/src/connectedhomeip/src/messaging/ReliableMessageContext.h
Line | Count | Source (jump to first uncovered line) |
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 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 | | |
29 | | #include <messaging/ReliableMessageProtocolConfig.h> |
30 | | |
31 | | #include <lib/core/CHIPError.h> |
32 | | #include <lib/core/ReferenceCounted.h> |
33 | | #include <lib/support/DLLUtil.h> |
34 | | #include <messaging/ReliableMessageProtocolConfig.h> |
35 | | #include <system/SystemLayer.h> |
36 | | #include <transport/raw/MessageHeader.h> |
37 | | |
38 | | namespace chip { |
39 | | namespace app { |
40 | | class TestCommandInteraction; |
41 | | class TestReadInteraction; |
42 | | class TestWriteInteraction; |
43 | | } // namespace app |
44 | | namespace Messaging { |
45 | | |
46 | | class ChipMessageInfo; |
47 | | class ExchangeContext; |
48 | | enum class MessageFlagValues : uint32_t; |
49 | | class ReliableMessageMgr; |
50 | | |
51 | | class ReliableMessageContext |
52 | | { |
53 | | public: |
54 | | ReliableMessageContext(); |
55 | | |
56 | | /** |
57 | | * Flush the pending Ack for current exchange. |
58 | | * |
59 | | */ |
60 | | CHIP_ERROR FlushAcks(); |
61 | | |
62 | | /** |
63 | | * 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. |
67 | | */ |
68 | | uint32_t TakePendingPeerAckMessageCounter() |
69 | 296 | { |
70 | 296 | SetAckPending(false); |
71 | 296 | return mPendingPeerAckMessageCounter; |
72 | 296 | } |
73 | | |
74 | | /** |
75 | | * 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. |
78 | | */ |
79 | | bool HasPiggybackAckPending() const; |
80 | | |
81 | | /** |
82 | | * 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 | | */ |
92 | | CHIP_ERROR SendStandaloneAckMessage(); |
93 | | |
94 | | /** |
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 | | */ |
99 | | bool AutoRequestAck() const; |
100 | | |
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 | | */ |
108 | | void SetAutoRequestAck(bool autoReqAck); |
109 | | |
110 | | /** |
111 | | * 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 | | */ |
115 | | bool IsAckPending() const; |
116 | | |
117 | | /// Determine whether the reliable message context is waiting for an ack. |
118 | | bool IsWaitingForAck() const; |
119 | | |
120 | | /// Set whether the reliable message context is waiting for an ack. |
121 | | void SetWaitingForAck(bool waitingForAck); |
122 | | |
123 | | /// Set if this exchange is requesting Sleepy End Device active mode |
124 | | void SetRequestingActiveMode(bool activeMode); |
125 | | |
126 | | /// Determine whether this exchange is a EphemeralExchange for replying a StandaloneAck |
127 | | bool IsEphemeralExchange() const; |
128 | | |
129 | | /** |
130 | | * Get the reliable message manager that corresponds to this reliable |
131 | | * message context. |
132 | | */ |
133 | | ReliableMessageMgr * GetReliableMessageMgr(); |
134 | | |
135 | | protected: |
136 | | bool WaitingForResponseOrAck() const; |
137 | | void SetWaitingForResponseOrAck(bool waitingForResponseOrAck); |
138 | | |
139 | | enum class Flags : uint16_t |
140 | | { |
141 | | /// When set, signifies that this context is the initiator of the exchange. |
142 | | kFlagInitiator = (1u << 0), |
143 | | |
144 | | /// When set, signifies that a response is expected for a message that is being sent. |
145 | | kFlagResponseExpected = (1u << 1), |
146 | | |
147 | | /// When set, automatically request an acknowledgment whenever a message is sent via UDP. |
148 | | kFlagAutoRequestAck = (1u << 2), |
149 | | |
150 | | /// 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), |
154 | | |
155 | | /// When set, signifies that there is an acknowledgment pending to be sent back. |
156 | | kFlagAckPending = (1u << 4), |
157 | | |
158 | | /// 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), |
162 | | |
163 | | /// When set, signifies that this exchange is waiting for a call to SendMessage. |
164 | | kFlagWillSendMessage = (1u << 6), |
165 | | |
166 | | /// When set, we have had Close() or Abort() called on us already. |
167 | | kFlagClosed = (1u << 7), |
168 | | |
169 | | /// When set, signifies that the exchange created sorely for replying a StandaloneAck |
170 | | kFlagEphemeralExchange = (1u << 8), |
171 | | |
172 | | /// When set, ignore session being released, because we are releasing it ourselves. |
173 | | 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), |
180 | | |
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), |
187 | | }; |
188 | | |
189 | | BitFlags<Flags> mFlags; // Internal state flags |
190 | | |
191 | | private: |
192 | | void HandleRcvdAck(uint32_t ackMessageCounter); |
193 | | CHIP_ERROR HandleNeedsAck(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags); |
194 | | CHIP_ERROR HandleNeedsAckInner(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags); |
195 | | ExchangeContext * GetExchangeContext(); |
196 | | |
197 | | /** |
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 | | |
206 | | // Set our pending peer ack message counter and any other state needed to ensure that we |
207 | | // will send that ack at some point. |
208 | | void SetPendingPeerAckMessageCounter(uint32_t aPeerAckMessageCounter); |
209 | | |
210 | | friend class ReliableMessageMgr; |
211 | | friend class ExchangeContext; |
212 | | friend class ExchangeMessageDispatch; |
213 | | friend class ::chip::app::TestCommandInteraction; |
214 | | friend class ::chip::app::TestReadInteraction; |
215 | | friend class ::chip::app::TestWriteInteraction; |
216 | | |
217 | | System::Clock::Timestamp mNextAckTime; // Next time for triggering Solo Ack |
218 | | uint32_t mPendingPeerAckMessageCounter; |
219 | | }; |
220 | | |
221 | | inline bool ReliableMessageContext::AutoRequestAck() const |
222 | 343 | { |
223 | 343 | return mFlags.Has(Flags::kFlagAutoRequestAck); |
224 | 343 | } |
225 | | |
226 | | inline bool ReliableMessageContext::IsAckPending() const |
227 | 2.88k | { |
228 | 2.88k | return mFlags.Has(Flags::kFlagAckPending); |
229 | 2.88k | } |
230 | | |
231 | | inline bool ReliableMessageContext::IsWaitingForAck() const |
232 | 570 | { |
233 | 570 | return mFlags.Has(Flags::kFlagWaitingForAck); |
234 | 570 | } |
235 | | |
236 | | inline bool ReliableMessageContext::HasPiggybackAckPending() const |
237 | 343 | { |
238 | 343 | return mFlags.Has(Flags::kFlagAckMessageCounterIsValid); |
239 | 343 | } |
240 | | |
241 | | inline void ReliableMessageContext::SetAutoRequestAck(bool autoReqAck) |
242 | 1.60k | { |
243 | 1.60k | mFlags.Set(Flags::kFlagAutoRequestAck, autoReqAck); |
244 | 1.60k | } |
245 | | |
246 | | inline void ReliableMessageContext::SetAckPending(bool inAckPending) |
247 | 2.20k | { |
248 | 2.20k | mFlags.Set(Flags::kFlagAckPending, inAckPending); |
249 | 2.20k | } |
250 | | |
251 | | inline bool ReliableMessageContext::IsEphemeralExchange() const |
252 | 285 | { |
253 | 285 | return mFlags.Has(Flags::kFlagEphemeralExchange); |
254 | 285 | } |
255 | | |
256 | | inline bool ReliableMessageContext::WaitingForResponseOrAck() const |
257 | 0 | { |
258 | 0 | return mFlags.Has(Flags::kFlagWaitingForResponseOrAck); |
259 | 0 | } |
260 | | |
261 | | inline void ReliableMessageContext::SetWaitingForResponseOrAck(bool waitingForResponseOrAck) |
262 | 0 | { |
263 | 0 | mFlags.Set(Flags::kFlagWaitingForResponseOrAck, waitingForResponseOrAck); |
264 | 0 | } |
265 | | |
266 | | } // namespace Messaging |
267 | | } // namespace chip |