blob: 7e8f725cbed15b190298b06e7d70a717d84fe908 [file] [log] [blame]
Zang MingJie76e0d7b2020-10-29 12:26:25 +08001/*
Kevin Schoedel8ea423a2021-03-11 11:49:18 -05002 * Copyright (c) 2020-2021 Project CHIP Authors
Zang MingJie76e0d7b2020-10-29 12:26:25 +08003 * 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 defines the reliable message context for the CHIP Message
21 * Layer. The context is one-on-one relationship with a chip session.
22 */
23
24#pragma once
25
26#include <stdint.h>
27#include <string.h>
28
Kevin Schoedel8e5eb8a2021-12-09 11:07:45 -050029#include <messaging/ReliableMessageProtocolConfig.h>
30
Zang MingJie53dd5832021-09-03 03:05:16 +080031#include <lib/core/CHIPError.h>
Zang MingJie76e0d7b2020-10-29 12:26:25 +080032#include <lib/core/ReferenceCounted.h>
Zang MingJie53dd5832021-09-03 03:05:16 +080033#include <lib/support/DLLUtil.h>
Zang MingJie619b7262021-11-24 02:33:30 +080034#include <messaging/ReliableMessageProtocolConfig.h>
Zang MingJie76e0d7b2020-10-29 12:26:25 +080035#include <system/SystemLayer.h>
36#include <transport/raw/MessageHeader.h>
37
38namespace chip {
Boris Zbarskyd30cff32022-10-25 08:23:30 -040039namespace app {
40class TestCommandInteraction;
41class TestReadInteraction;
42class TestWriteInteraction;
43} // namespace app
Yufeng Wang01031e72020-12-01 09:57:42 -080044namespace Messaging {
Zang MingJie76e0d7b2020-10-29 12:26:25 +080045
46class ChipMessageInfo;
Yufeng Wangcb23e0c2021-01-07 12:36:21 -080047class ExchangeContext;
Zang MingJie76e0d7b2020-10-29 12:26:25 +080048enum class MessageFlagValues : uint32_t;
Yufeng Wang02b31c02021-02-02 15:15:54 -080049class ReliableMessageMgr;
Zang MingJie76e0d7b2020-10-29 12:26:25 +080050
Yufeng Wangcb23e0c2021-01-07 12:36:21 -080051class ReliableMessageContext
Zang MingJie76e0d7b2020-10-29 12:26:25 +080052{
53public:
Zang MingJie76e0d7b2020-10-29 12:26:25 +080054 ReliableMessageContext();
55
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080056 /**
57 * Flush the pending Ack for current exchange.
58 *
59 */
Zang MingJie76e0d7b2020-10-29 12:26:25 +080060 CHIP_ERROR FlushAcks();
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080061
Boris Zbarsky233ec0f2021-06-28 17:30:29 -040062 /**
Boris Zbarskyfa43d002021-09-28 11:52:23 -040063 * Take the pending peer ack message counter from the context. This must
64 * only be called when HasPiggybackAckPending() is true. After this call,
65 * IsAckPending() will be false; it's the caller's responsibility to send
66 * the ack.
Boris Zbarsky233ec0f2021-06-28 17:30:29 -040067 */
Zang MingJiefa0ef982021-09-15 00:32:01 +080068 uint32_t TakePendingPeerAckMessageCounter()
Boris Zbarsky233ec0f2021-06-28 17:30:29 -040069 {
70 SetAckPending(false);
Zang MingJiefa0ef982021-09-15 00:32:01 +080071 return mPendingPeerAckMessageCounter;
Boris Zbarsky233ec0f2021-06-28 17:30:29 -040072 }
Yufeng Wang2d43a7f2021-04-19 11:10:27 -070073
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080074 /**
Zang MingJie3a5d0862022-06-09 02:03:18 +080075 * Check whether we have a mPendingPeerAckMessageCounter. The counter is
76 * valid once we receive a message which requests an ack. Once
77 * mPendingPeerAckMessageCounter is valid, it never stops being valid.
Boris Zbarskyfa43d002021-09-28 11:52:23 -040078 */
79 bool HasPiggybackAckPending() const;
80
81 /**
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080082 * Send a SecureChannel::StandaloneAck message.
83 *
84 * @note When sent via UDP, the null message is sent *without* requesting an acknowledgment,
85 * even in the case where the auto-request acknowledgment feature has been enabled on the
86 * exchange.
87 *
88 * @retval #CHIP_ERROR_NO_MEMORY If no available PacketBuffers.
89 * @retval #CHIP_NO_ERROR If the method succeeded or the error wasn't critical.
90 * @retval other Another critical error returned by SendMessage().
91 */
Yufeng Wang7efa6572021-01-11 12:28:39 -080092 CHIP_ERROR SendStandaloneAckMessage();
Zang MingJie76e0d7b2020-10-29 12:26:25 +080093
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080094 /**
95 * Determine whether an acknowledgment will be requested whenever a message is sent for the exchange.
96 *
97 * @return Returns 'true' an acknowledgment will be requested whenever a message is sent, else 'false'.
98 */
Yufeng Wangcb23e0c2021-01-07 12:36:21 -080099 bool AutoRequestAck() const;
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800100
101 /**
102 * Set whether an acknowledgment should be requested whenever a message is sent.
103 *
104 * @param[in] autoReqAck A Boolean indicating whether or not an
105 * acknowledgment should be requested whenever a
106 * message is sent.
107 */
Yufeng Wangcb23e0c2021-01-07 12:36:21 -0800108 void SetAutoRequestAck(bool autoReqAck);
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800109
110 /**
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800111 * Determine whether there is already an acknowledgment pending to be sent to the peer on this exchange.
112 *
113 * @return Returns 'true' if there is already an acknowledgment pending on this exchange, else 'false'.
114 */
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800115 bool IsAckPending() const;
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800116
Boris Zbarsky58875c32023-10-09 14:59:53 -0400117 /// Determine whether the reliable message context is waiting for an ack.
118 bool IsWaitingForAck() const;
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700119
Boris Zbarsky58875c32023-10-09 14:59:53 -0400120 /// Set whether the reliable message context is waiting for an ack.
121 void SetWaitingForAck(bool waitingForAck);
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700122
Kamil Kasperczyk10bb2fd2022-04-28 03:21:18 +0200123 /// Set if this exchange is requesting Sleepy End Device active mode
124 void SetRequestingActiveMode(bool activeMode);
Damian Królik73e3c832022-02-03 14:23:55 +0100125
Zang MingJied2a2f072022-06-10 22:09:05 +0800126 /// Determine whether this exchange is a EphemeralExchange for replying a StandaloneAck
127 bool IsEphemeralExchange() const;
128
Boris Zbarsky8e8efc32021-06-03 17:22:09 -0400129 /**
130 * Get the reliable message manager that corresponds to this reliable
131 * message context.
132 */
133 ReliableMessageMgr * GetReliableMessageMgr();
134
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700135protected:
Boris Zbarsky58875c32023-10-09 14:59:53 -0400136 bool WaitingForResponseOrAck() const;
137 void SetWaitingForResponseOrAck(bool waitingForResponseOrAck);
138
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800139 enum class Flags : uint16_t
140 {
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700141 /// When set, signifies that this context is the initiator of the exchange.
Boris Zbarskyfa43d002021-09-28 11:52:23 -0400142 kFlagInitiator = (1u << 0),
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700143
144 /// When set, signifies that a response is expected for a message that is being sent.
Boris Zbarskyfa43d002021-09-28 11:52:23 -0400145 kFlagResponseExpected = (1u << 1),
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700146
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800147 /// When set, automatically request an acknowledgment whenever a message is sent via UDP.
Boris Zbarskyfa43d002021-09-28 11:52:23 -0400148 kFlagAutoRequestAck = (1u << 2),
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800149
Boris Zbarsky58875c32023-10-09 14:59:53 -0400150 /// When set, signifies the reliable message context is waiting for an
151 /// ack: a message that needs an ack has been sent, no ack has been
152 /// received, and we have not yet run out of MRP retries.
153 kFlagWaitingForAck = (1u << 3),
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800154
155 /// When set, signifies that there is an acknowledgment pending to be sent back.
Zang MingJie3a5d0862022-06-09 02:03:18 +0800156 kFlagAckPending = (1u << 4),
Boris Zbarskyfa43d002021-09-28 11:52:23 -0400157
Zang MingJie3a5d0862022-06-09 02:03:18 +0800158 /// When set, signifies that mPendingPeerAckMessageCounter is valid.
159 /// The counter is valid once we receive a message which requests an ack.
160 /// Once mPendingPeerAckMessageCounter is valid, it never stops being valid.
161 kFlagAckMessageCounterIsValid = (1u << 5),
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800162
Boris Zbarsky6c172a22021-07-09 17:08:55 -0400163 /// When set, signifies that this exchange is waiting for a call to SendMessage.
Zang MingJie3a5d0862022-06-09 02:03:18 +0800164 kFlagWillSendMessage = (1u << 6),
Boris Zbarsky6c172a22021-07-09 17:08:55 -0400165
Boris Zbarsky6c172a22021-07-09 17:08:55 -0400166 /// When set, we have had Close() or Abort() called on us already.
Zang MingJie3a5d0862022-06-09 02:03:18 +0800167 kFlagClosed = (1u << 7),
Damian Królik73e3c832022-02-03 14:23:55 +0100168
Zang MingJied2a2f072022-06-10 22:09:05 +0800169 /// When set, signifies that the exchange created sorely for replying a StandaloneAck
mkardous-silabsa8a96592023-10-19 15:01:58 -0400170 kFlagEphemeralExchange = (1u << 8),
Zang MingJiec9971a52022-06-18 10:42:58 +0800171
Boris Zbarsky03de7002022-06-22 19:19:30 -0400172 /// When set, ignore session being released, because we are releasing it ourselves.
mkardous-silabsa8a96592023-10-19 15:01:58 -0400173 kFlagIgnoreSessionRelease = (1u << 9),
174
175 // This flag is used to determine if the peer (receiver) should be considered active or not.
176 // When set, sender knows it has received at least one application-level message
177 // from the peer and can assume the peer (receiver) is active.
178 // If the flag is not set, we don't know if the peer (receiver) is active or not.
179 kFlagReceivedAtLeastOneMessage = (1u << 10),
Boris Zbarsky58875c32023-10-09 14:59:53 -0400180
181 /// When set:
182 ///
183 /// (1) We sent a message that expected a response (hence
184 /// IsResponseExpected() is true).
185 /// (2) We have received neither a response nor an ack for that message.
186 kFlagWaitingForResponseOrAck = (1u << 11),
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800187 };
188
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500189 BitFlags<Flags> mFlags; // Internal state flags
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800190
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700191private:
Boris Zbarskya62ee312021-09-22 14:36:37 -0400192 void HandleRcvdAck(uint32_t ackMessageCounter);
Zang MingJiefa0ef982021-09-15 00:32:01 +0800193 CHIP_ERROR HandleNeedsAck(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags);
194 CHIP_ERROR HandleNeedsAckInner(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags);
Yufeng Wang2d43a7f2021-04-19 11:10:27 -0700195 ExchangeContext * GetExchangeContext();
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800196
Boris Zbarsky233ec0f2021-06-28 17:30:29 -0400197 /**
198 * Set if an acknowledgment needs to be sent back to the peer on this exchange.
199 *
200 * @param[in] inAckPending A Boolean indicating whether (true) or not
201 * (false) an acknowledgment should be sent back
202 * in response to a received message.
203 */
204 void SetAckPending(bool inAckPending);
205
Zang MingJiefa0ef982021-09-15 00:32:01 +0800206 // Set our pending peer ack message counter and any other state needed to ensure that we
Boris Zbarsky233ec0f2021-06-28 17:30:29 -0400207 // will send that ack at some point.
Zang MingJiefa0ef982021-09-15 00:32:01 +0800208 void SetPendingPeerAckMessageCounter(uint32_t aPeerAckMessageCounter);
Boris Zbarsky233ec0f2021-06-28 17:30:29 -0400209
Yufeng Wang02b31c02021-02-02 15:15:54 -0800210 friend class ReliableMessageMgr;
Yufeng Wangcb23e0c2021-01-07 12:36:21 -0800211 friend class ExchangeContext;
Pankaj Garg362c5f22021-04-14 16:35:15 -0700212 friend class ExchangeMessageDispatch;
Boris Zbarskyd30cff32022-10-25 08:23:30 -0400213 friend class ::chip::app::TestCommandInteraction;
214 friend class ::chip::app::TestReadInteraction;
215 friend class ::chip::app::TestWriteInteraction;
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800216
Zang MingJie4ec0e4e2021-12-02 15:20:06 +0800217 System::Clock::Timestamp mNextAckTime; // Next time for triggering Solo Ack
Zang MingJiefa0ef982021-09-15 00:32:01 +0800218 uint32_t mPendingPeerAckMessageCounter;
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800219};
220
Damian Królik48563902022-01-24 18:27:21 +0100221inline bool ReliableMessageContext::AutoRequestAck() const
222{
223 return mFlags.Has(Flags::kFlagAutoRequestAck);
224}
225
226inline bool ReliableMessageContext::IsAckPending() const
227{
228 return mFlags.Has(Flags::kFlagAckPending);
229}
230
Boris Zbarsky58875c32023-10-09 14:59:53 -0400231inline bool ReliableMessageContext::IsWaitingForAck() const
Damian Królik48563902022-01-24 18:27:21 +0100232{
Boris Zbarsky58875c32023-10-09 14:59:53 -0400233 return mFlags.Has(Flags::kFlagWaitingForAck);
Damian Królik48563902022-01-24 18:27:21 +0100234}
235
Damian Królik48563902022-01-24 18:27:21 +0100236inline bool ReliableMessageContext::HasPiggybackAckPending() const
237{
238 return mFlags.Has(Flags::kFlagAckMessageCounterIsValid);
239}
240
241inline void ReliableMessageContext::SetAutoRequestAck(bool autoReqAck)
242{
243 mFlags.Set(Flags::kFlagAutoRequestAck, autoReqAck);
244}
245
Damian Królik48563902022-01-24 18:27:21 +0100246inline void ReliableMessageContext::SetAckPending(bool inAckPending)
247{
248 mFlags.Set(Flags::kFlagAckPending, inAckPending);
249}
250
Zang MingJied2a2f072022-06-10 22:09:05 +0800251inline bool ReliableMessageContext::IsEphemeralExchange() const
252{
253 return mFlags.Has(Flags::kFlagEphemeralExchange);
254}
255
Boris Zbarsky58875c32023-10-09 14:59:53 -0400256inline bool ReliableMessageContext::WaitingForResponseOrAck() const
257{
258 return mFlags.Has(Flags::kFlagWaitingForResponseOrAck);
259}
260
261inline void ReliableMessageContext::SetWaitingForResponseOrAck(bool waitingForResponseOrAck)
262{
263 mFlags.Set(Flags::kFlagWaitingForResponseOrAck, waitingForResponseOrAck);
264}
265
Yufeng Wang01031e72020-12-01 09:57:42 -0800266} // namespace Messaging
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800267} // namespace chip