Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / messaging / ReliableMessageContext.cpp
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 <messaging/ExchangeContext.h>
27 #include <messaging/ReliableMessageContext.h>
28
29 #include <core/CHIPEncoding.h>
30 #include <messaging/ErrorCategory.h>
31 #include <messaging/Flags.h>
32 #include <messaging/ReliableMessageMgr.h>
33 #include <protocols/Protocols.h>
34 #include <protocols/secure_channel/Constants.h>
35 #include <support/CodeUtils.h>
36
37 namespace chip {
38 namespace Messaging {
39
40 ReliableMessageContext::ReliableMessageContext() :
41     mManager(nullptr), mExchange(nullptr), mDelegate(nullptr), mConfig(gDefaultReliableMessageProtocolConfig), mNextAckTimeTick(0),
42     mPendingPeerAckId(0)
43 {}
44
45 void ReliableMessageContext::Init(ReliableMessageMgr * manager, ExchangeContext * exchange)
46 {
47     mManager  = manager;
48     mExchange = exchange;
49     mDelegate = nullptr;
50
51     SetDropAckDebug(false);
52     SetAckPending(false);
53     SetPeerRequestedAck(false);
54     SetMsgRcvdFromPeer(false);
55     SetAutoRequestAck(true);
56 }
57
58 void ReliableMessageContext::Retain()
59 {
60     mExchange->Retain();
61 }
62
63 void ReliableMessageContext::Release()
64 {
65     mExchange->Release();
66 }
67
68 bool ReliableMessageContext::AutoRequestAck() const
69 {
70     return mFlags.Has(Flags::kFlagAutoRequestAck);
71 }
72
73 bool ReliableMessageContext::IsAckPending() const
74 {
75     return mFlags.Has(Flags::kFlagAckPending);
76 }
77
78 bool ReliableMessageContext::HasPeerRequestedAck() const
79 {
80     return mFlags.Has(Flags::kFlagPeerRequestedAck);
81 }
82
83 bool ReliableMessageContext::HasRcvdMsgFromPeer() const
84 {
85     return mFlags.Has(Flags::kFlagMsgRcvdFromPeer);
86 }
87
88 void ReliableMessageContext::SetAutoRequestAck(bool autoReqAck)
89 {
90     mFlags.Set(Flags::kFlagAutoRequestAck, autoReqAck);
91 }
92
93 void ReliableMessageContext::SetMsgRcvdFromPeer(bool inMsgRcvdFromPeer)
94 {
95     mFlags.Set(Flags::kFlagMsgRcvdFromPeer, inMsgRcvdFromPeer);
96 }
97
98 void ReliableMessageContext::SetAckPending(bool inAckPending)
99 {
100     mFlags.Set(Flags::kFlagAckPending, inAckPending);
101 }
102
103 void ReliableMessageContext::SetPeerRequestedAck(bool inPeerRequestedAck)
104 {
105     mFlags.Set(Flags::kFlagPeerRequestedAck, inPeerRequestedAck);
106 }
107
108 void ReliableMessageContext::SetDropAckDebug(bool inDropAckDebug)
109 {
110     mFlags.Set(Flags::kFlagDropAckDebug, inDropAckDebug);
111 }
112
113 bool ReliableMessageContext::ShouldDropAckDebug() const
114 {
115     return mFlags.Has(Flags::kFlagDropAckDebug);
116 }
117
118 CHIP_ERROR ReliableMessageContext::FlushAcks()
119 {
120     CHIP_ERROR err = CHIP_NO_ERROR;
121
122     if (IsAckPending())
123     {
124         // Send the acknowledgment as a SecureChannel::StandStandaloneAck message
125         err = SendStandaloneAckMessage();
126
127         if (err == CHIP_NO_ERROR)
128         {
129 #if !defined(NDEBUG)
130             ChipLogProgress(ExchangeManager, "Flushed pending ack for MsgId:%08" PRIX32, mPendingPeerAckId);
131 #endif
132         }
133     }
134
135     return err;
136 }
137
138 uint64_t ReliableMessageContext::GetCurrentRetransmitTimeoutTick()
139 {
140     return (HasRcvdMsgFromPeer() ? mConfig.mActiveRetransTimeoutTick : mConfig.mInitialRetransTimeoutTick);
141 }
142
143 /**
144  *  Process received Ack. Remove the corresponding message context from the RetransTable and execute the application
145  *  callback
146  *
147  *  @note
148  *    This message is part of the CHIP Reliable Messaging protocol.
149  *
150  *  @param[in]    AckMsgId         The msgId of incoming Ack message.
151  *
152  *  @retval  #CHIP_ERROR_INVALID_ACK_ID                 if the msgId of received Ack is not in the RetransTable.
153  *  @retval  #CHIP_NO_ERROR                             if the context was removed.
154  *
155  */
156 CHIP_ERROR ReliableMessageContext::HandleRcvdAck(uint32_t AckMsgId)
157 {
158     CHIP_ERROR err = CHIP_NO_ERROR;
159
160     // Msg is an Ack; Check Retrans Table and remove message context
161     if (!mManager->CheckAndRemRetransTable(this, AckMsgId))
162     {
163 #if !defined(NDEBUG)
164         ChipLogError(ExchangeManager, "CHIP MsgId:%08" PRIX32 " not in RetransTable", AckMsgId);
165 #endif
166         err = CHIP_ERROR_INVALID_ACK_ID;
167         // Optionally call an application callback with this error.
168     }
169     else
170     {
171         if (mDelegate)
172         {
173             mDelegate->OnAckRcvd();
174         }
175
176 #if !defined(NDEBUG)
177         ChipLogProgress(ExchangeManager, "Removed CHIP MsgId:%08" PRIX32 " from RetransTable", AckMsgId);
178 #endif
179     }
180
181     return err;
182 }
183
184 CHIP_ERROR ReliableMessageContext::HandleNeedsAck(uint32_t MessageId, BitFlags<MessageFlagValues> MsgFlags)
185
186 {
187     CHIP_ERROR err = CHIP_NO_ERROR;
188
189     // Skip processing ack if drop ack debug is enabled.
190     if (ShouldDropAckDebug())
191         return err;
192
193     // Expire any virtual ticks that have expired so all wakeup sources reflect the current time
194     mManager->ExpireTicks();
195
196     // If the message IS a duplicate.
197     if (MsgFlags.Has(MessageFlagValues::kDuplicateMessage))
198     {
199 #if !defined(NDEBUG)
200         ChipLogProgress(ExchangeManager, "Forcing tx of solitary ack for duplicate MsgId:%08" PRIX32, MessageId);
201 #endif
202         // Is there pending ack for a different message id.
203         bool wasAckPending = IsAckPending() && mPendingPeerAckId != MessageId;
204
205         // Temporary store currently pending ack id (even if there is none).
206         uint32_t tempAckId = mPendingPeerAckId;
207
208         // Set the pending ack id.
209         mPendingPeerAckId = MessageId;
210
211         // Send the Ack for the duplication message in a SecureChannel::StandaloneAck message.
212         err = SendStandaloneAckMessage();
213
214         // If there was pending ack for a different message id.
215         if (wasAckPending)
216         {
217             // Restore previously pending ack id.
218             mPendingPeerAckId = tempAckId;
219             SetAckPending(true);
220         }
221
222         SuccessOrExit(err);
223     }
224     // Otherwise, the message IS NOT a duplicate.
225     else
226     {
227         if (IsAckPending())
228         {
229 #if !defined(NDEBUG)
230             ChipLogProgress(ExchangeManager, "Pending ack queue full; forcing tx of solitary ack for MsgId:%08" PRIX32,
231                             mPendingPeerAckId);
232 #endif
233             // Send the Ack for the currently pending Ack in a SecureChannel::StandaloneAck message.
234             err = SendStandaloneAckMessage();
235             SuccessOrExit(err);
236         }
237
238         // Replace the Pending ack id.
239         mPendingPeerAckId = MessageId;
240         mNextAckTimeTick  = static_cast<uint16_t>(mConfig.mAckPiggybackTimeoutTick +
241                                                  mManager->GetTickCounterFromTimeDelta(System::Timer::GetCurrentEpoch()));
242         SetAckPending(true);
243     }
244
245 exit:
246     // Schedule next physical wakeup
247     mManager->StartTimer();
248     return err;
249 }
250
251 CHIP_ERROR ReliableMessageContext::SendStandaloneAckMessage()
252 {
253     CHIP_ERROR err = CHIP_NO_ERROR;
254
255     // Allocate a buffer for the null message
256     System::PacketBufferHandle msgBuf = MessagePacketBuffer::New(0);
257     VerifyOrExit(!msgBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
258
259     // Send the null message
260     if (mExchange != nullptr)
261     {
262         err = mExchange->SendMessage(Protocols::SecureChannel::MsgType::StandaloneAck, std::move(msgBuf),
263                                      BitFlags<SendMessageFlags>{ SendMessageFlags::kNoAutoRequestAck });
264     }
265     else
266     {
267         ChipLogError(ExchangeManager, "ExchangeContext is not initilized in ReliableMessageContext");
268         err = CHIP_ERROR_NOT_CONNECTED;
269     }
270
271 exit:
272     if (IsSendErrorNonCritical(err))
273     {
274         ChipLogError(ExchangeManager, "Non-crit err %ld sending solitary ack", long(err));
275         err = CHIP_NO_ERROR;
276     }
277     if (err != CHIP_NO_ERROR)
278     {
279         ChipLogError(ExchangeManager, "Failed to send Solitary ack for MsgId:%08" PRIX32 ":%ld", mPendingPeerAckId, (long) err);
280     }
281
282     return err;
283 }
284
285 } // namespace Messaging
286 } // namespace chip