Line data Source code
1 : /*
2 : * Copyright (c) 2020-2021 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : /**
19 : * @file
20 : * This file implements the CHIP reliable message protocol.
21 : *
22 : */
23 :
24 : #include <inttypes.h>
25 :
26 : #include <lib/core/CHIPEncoding.h>
27 : #include <lib/support/CodeUtils.h>
28 : #include <lib/support/Defer.h>
29 : #include <messaging/ErrorCategory.h>
30 : #include <messaging/ExchangeContext.h>
31 : #include <messaging/ExchangeMgr.h>
32 : #include <messaging/Flags.h>
33 : #include <messaging/ReliableMessageContext.h>
34 : #include <messaging/ReliableMessageMgr.h>
35 : #include <platform/PlatformManager.h>
36 : #include <protocols/Protocols.h>
37 : #include <protocols/secure_channel/Constants.h>
38 :
39 : using namespace chip::DeviceLayer;
40 :
41 : namespace chip {
42 : namespace Messaging {
43 :
44 3561 : ReliableMessageContext::ReliableMessageContext() : mNextAckTime(0), mPendingPeerAckMessageCounter(0) {}
45 :
46 29763 : ExchangeContext * ReliableMessageContext::GetExchangeContext()
47 : {
48 29763 : return static_cast<ExchangeContext *>(this);
49 : }
50 :
51 34883 : ReliableMessageMgr * ReliableMessageContext::GetReliableMessageMgr()
52 : {
53 34883 : return static_cast<ExchangeContext *>(this)->GetExchangeMgr()->GetReliableMessageMgr();
54 : }
55 :
56 16678 : void ReliableMessageContext::SetWaitingForAck(bool waitingForAck)
57 : {
58 16678 : mFlags.Set(Flags::kFlagWaitingForAck, waitingForAck);
59 16678 : }
60 :
61 3654 : CHIP_ERROR ReliableMessageContext::FlushAcks()
62 : {
63 3654 : CHIP_ERROR err = CHIP_NO_ERROR;
64 :
65 3654 : if (IsAckPending())
66 : {
67 1665 : err = SendStandaloneAckMessage();
68 :
69 1665 : if (err == CHIP_NO_ERROR)
70 : {
71 1662 : ChipLogDetail(ExchangeManager,
72 : "Flushed pending ack for MessageCounter:" ChipLogFormatMessageCounter
73 : " on exchange " ChipLogFormatExchange,
74 : mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()));
75 : }
76 : }
77 :
78 3654 : return err;
79 : }
80 :
81 : /**
82 : * Process received Ack. Remove the corresponding message context from the RetransTable and execute the application
83 : * callback
84 : *
85 : * @note
86 : * This message is part of the CHIP Reliable Messaging protocol.
87 : *
88 : * @param[in] ackMessageCounter The acknowledged message counter of the incoming message.
89 : */
90 8206 : void ReliableMessageContext::HandleRcvdAck(uint32_t ackMessageCounter)
91 : {
92 : // Msg is an Ack; Check Retrans Table and remove message context
93 8206 : if (GetReliableMessageMgr()->CheckAndRemRetransTable(this, ackMessageCounter))
94 : {
95 8194 : SetWaitingForResponseOrAck(false);
96 : }
97 : else
98 : {
99 : // This can happen quite easily due to a packet with a piggyback ack
100 : // being lost and retransmitted.
101 12 : ChipLogDetail(ExchangeManager,
102 : "CHIP MessageCounter:" ChipLogFormatMessageCounter " not in RetransTable on exchange " ChipLogFormatExchange,
103 : ackMessageCounter, ChipLogValueExchange(GetExchangeContext()));
104 : }
105 8206 : }
106 :
107 8277 : CHIP_ERROR ReliableMessageContext::HandleNeedsAck(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags)
108 : {
109 8277 : CHIP_ERROR err = HandleNeedsAckInner(messageCounter, messageFlags);
110 :
111 : // Schedule next physical wakeup on function exit
112 8277 : GetReliableMessageMgr()->StartTimer();
113 :
114 8277 : return err;
115 : }
116 :
117 8277 : CHIP_ERROR ReliableMessageContext::HandleNeedsAckInner(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags)
118 :
119 : {
120 : // If the message IS a duplicate there will never be a response to it, so we
121 : // should not wait for one and just immediately send a standalone ack.
122 8277 : if (messageFlags.Has(MessageFlagValues::kDuplicateMessage))
123 : {
124 5 : ChipLogDetail(ExchangeManager,
125 : "Forcing tx of solitary ack for duplicate MessageCounter:" ChipLogFormatMessageCounter
126 : " on exchange " ChipLogFormatExchange,
127 : messageCounter, ChipLogValueExchange(GetExchangeContext()));
128 :
129 5 : bool wasAckPending = IsAckPending() && mPendingPeerAckMessageCounter != messageCounter;
130 :
131 5 : bool messageCounterWasValid = HasPiggybackAckPending();
132 :
133 : // Temporary store currently pending ack message counter (even if there is none).
134 5 : uint32_t tempAckMessageCounter = mPendingPeerAckMessageCounter;
135 :
136 5 : SetPendingPeerAckMessageCounter(messageCounter);
137 5 : CHIP_ERROR err = SendStandaloneAckMessage();
138 :
139 5 : if (wasAckPending)
140 : {
141 : // Restore previously pending ack message counter.
142 0 : SetPendingPeerAckMessageCounter(tempAckMessageCounter);
143 : }
144 5 : else if (messageCounterWasValid)
145 : {
146 : // Restore the previous value, so later piggybacks will pick it up,
147 : // but don't set out "ack is pending" state, because we didn't use
148 : // to have it set.
149 2 : mPendingPeerAckMessageCounter = tempAckMessageCounter;
150 : }
151 : // Otherwise don't restore the invalid old mPendingPeerAckMessageCounter
152 : // value, so we preserve the invariant that once we have had an ack
153 : // pending we always have a valid mPendingPeerAckMessageCounter.
154 :
155 5 : return err;
156 : }
157 : // Otherwise, the message IS NOT a duplicate.
158 :
159 8272 : if (IsAckPending())
160 : {
161 0 : ChipLogDetail(ExchangeManager,
162 : "Pending ack queue full; forcing tx of solitary ack for MessageCounter:" ChipLogFormatMessageCounter
163 : " on exchange " ChipLogFormatExchange,
164 : mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()));
165 : // Send the Ack for the currently pending Ack in a SecureChannel::StandaloneAck message.
166 0 : ReturnErrorOnFailure(SendStandaloneAckMessage());
167 : }
168 :
169 : // Replace the Pending ack message counter.
170 8272 : SetPendingPeerAckMessageCounter(messageCounter);
171 : using namespace System::Clock::Literals;
172 8272 : mNextAckTime = System::SystemClock().GetMonotonicTimestamp() + CHIP_CONFIG_RMP_DEFAULT_ACK_TIMEOUT;
173 8272 : return CHIP_NO_ERROR;
174 : }
175 :
176 1672 : CHIP_ERROR ReliableMessageContext::SendStandaloneAckMessage()
177 : {
178 : // Allocate a buffer for the null message
179 1672 : System::PacketBufferHandle msgBuf = MessagePacketBuffer::New(0);
180 1672 : if (msgBuf.IsNull())
181 : {
182 0 : return CHIP_ERROR_NO_MEMORY;
183 : }
184 :
185 3344 : CHIP_ERROR err = GetExchangeContext()->SendMessage(Protocols::SecureChannel::MsgType::StandaloneAck, std::move(msgBuf),
186 1672 : BitFlags<SendMessageFlags>{ SendMessageFlags::kNoAutoRequestAck });
187 1672 : if (IsSendErrorNonCritical(err))
188 : {
189 0 : ChipLogError(ExchangeManager,
190 : "Non-crit err %" CHIP_ERROR_FORMAT " sending solitary ack for MessageCounter:" ChipLogFormatMessageCounter
191 : " on exchange " ChipLogFormatExchange,
192 : err.Format(), mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()));
193 0 : return CHIP_NO_ERROR;
194 : }
195 1672 : if (err != CHIP_NO_ERROR)
196 : {
197 3 : ChipLogError(ExchangeManager,
198 : "Failed to send Solitary ack for MessageCounter:" ChipLogFormatMessageCounter
199 : " on exchange " ChipLogFormatExchange ":%" CHIP_ERROR_FORMAT,
200 : mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()), err.Format());
201 : }
202 :
203 1672 : return err;
204 1672 : }
205 :
206 8301 : void ReliableMessageContext::SetPendingPeerAckMessageCounter(uint32_t aPeerAckMessageCounter)
207 : {
208 8301 : mPendingPeerAckMessageCounter = aPeerAckMessageCounter;
209 8301 : SetAckPending(true);
210 8301 : mFlags.Set(Flags::kFlagAckMessageCounterIsValid);
211 8301 : }
212 :
213 : } // namespace Messaging
214 : } // namespace chip
|