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 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 7850 : uint32_t TakePendingPeerAckMessageCounter() 69 : { 70 7850 : SetAckPending(false); 71 7850 : return mPendingPeerAckMessageCounter; 72 : } 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 9490 : inline bool ReliableMessageContext::AutoRequestAck() const 222 : { 223 9490 : return mFlags.Has(Flags::kFlagAutoRequestAck); 224 : } 225 : 226 173098 : inline bool ReliableMessageContext::IsAckPending() const 227 : { 228 173098 : return mFlags.Has(Flags::kFlagAckPending); 229 : } 230 : 231 15799 : inline bool ReliableMessageContext::IsWaitingForAck() const 232 : { 233 15799 : return mFlags.Has(Flags::kFlagWaitingForAck); 234 : } 235 : 236 9411 : inline bool ReliableMessageContext::HasPiggybackAckPending() const 237 : { 238 9411 : return mFlags.Has(Flags::kFlagAckMessageCounterIsValid); 239 : } 240 : 241 3268 : inline void ReliableMessageContext::SetAutoRequestAck(bool autoReqAck) 242 : { 243 3268 : mFlags.Set(Flags::kFlagAutoRequestAck, autoReqAck); 244 3268 : } 245 : 246 18863 : inline void ReliableMessageContext::SetAckPending(bool inAckPending) 247 : { 248 18863 : mFlags.Set(Flags::kFlagAckPending, inAckPending); 249 18863 : } 250 : 251 7888 : inline bool ReliableMessageContext::IsEphemeralExchange() const 252 : { 253 7888 : return mFlags.Has(Flags::kFlagEphemeralExchange); 254 : } 255 : 256 38 : inline bool ReliableMessageContext::WaitingForResponseOrAck() const 257 : { 258 38 : return mFlags.Has(Flags::kFlagWaitingForResponseOrAck); 259 : } 260 : 261 20457 : inline void ReliableMessageContext::SetWaitingForResponseOrAck(bool waitingForResponseOrAck) 262 : { 263 20457 : mFlags.Set(Flags::kFlagWaitingForResponseOrAck, waitingForResponseOrAck); 264 20457 : } 265 : 266 : } // namespace Messaging 267 : } // namespace chip