Line data Source code
1 : /* 2 : * Copyright (c) 2020 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 classes corresponding to CHIP reliable message 21 : * protocol. 22 : */ 23 : 24 : #pragma once 25 : 26 : #include <array> 27 : #include <stdint.h> 28 : 29 : #include <lib/core/CHIPError.h> 30 : #include <lib/support/BitFlags.h> 31 : #include <lib/support/Pool.h> 32 : #include <messaging/ExchangeContext.h> 33 : #include <messaging/ReliableMessageProtocolConfig.h> 34 : #include <system/SystemLayer.h> 35 : #include <system/SystemPacketBuffer.h> 36 : #include <transport/SessionUpdateDelegate.h> 37 : #include <transport/raw/MessageHeader.h> 38 : 39 : namespace chip { 40 : namespace Messaging { 41 : 42 : enum class SendMessageFlags : uint16_t; 43 : class ReliableMessageContext; 44 : 45 : class ReliableMessageMgr 46 : { 47 : public: 48 : /** 49 : * @class RetransTableEntry 50 : * 51 : * @brief 52 : * This class is part of the CHIP Reliable Messaging Protocol and is used 53 : * to keep track of CHIP messages that have been sent and are expecting an 54 : * acknowledgment back. If the acknowledgment is not received within a 55 : * specific timeout, the message would be retransmitted from this table. 56 : * 57 : */ 58 : struct RetransTableEntry 59 : { 60 : RetransTableEntry(ReliableMessageContext * rc); 61 : ~RetransTableEntry(); 62 : 63 : ExchangeHandle ec; /**< The context for the stored CHIP message. */ 64 : EncryptedPacketBufferHandle retainedBuf; /**< The packet buffer holding the CHIP message. */ 65 : System::Clock::Timestamp nextRetransTime; /**< A counter representing the next retransmission time for the message. */ 66 : uint8_t sendCount; /**< The number of times we have tried to send this entry, 67 : including both successfully and failure send. */ 68 : }; 69 : 70 : ReliableMessageMgr(ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & contextPool); 71 : ~ReliableMessageMgr(); 72 : 73 : void Init(chip::System::Layer * systemLayer); 74 : void Shutdown(); 75 : 76 : /** 77 : * Iterate through active exchange contexts and retrans table entries. If an 78 : * action needs to be triggered by ReliableMessageProtocol time facilities, 79 : * execute that action. 80 : */ 81 : void ExecuteActions(); 82 : 83 : /** 84 : * Handle physical wakeup of system due to ReliableMessageProtocol wakeup. 85 : * 86 : */ 87 : static void Timeout(System::Layer * aSystemLayer, void * aAppState); 88 : 89 : /** 90 : * Add a CHIP message into the retransmission table to be subsequently resent if a corresponding acknowledgment 91 : * is not received within the retransmission timeout. 92 : * 93 : * @param[in] rc A pointer to the ExchangeContext object. 94 : * 95 : * @param[out] rEntry A pointer to a pointer of a retransmission table entry added into the table. 96 : * 97 : * @retval #CHIP_ERROR_RETRANS_TABLE_FULL If there is no empty slot left in the table for addition. 98 : * @retval #CHIP_NO_ERROR On success. 99 : */ 100 : CHIP_ERROR AddToRetransTable(ReliableMessageContext * rc, RetransTableEntry ** rEntry); 101 : 102 : /** 103 : * Calculate the backoff timer for the retransmission. 104 : * 105 : * @param[in] baseInterval The base interval to use for the backoff calculation, either the active or idle interval. 106 : * @param[in] sendCount Count of how many times this message 107 : * has been retransmitted so far (0 if it has 108 : * been sent only once with no retransmits, 109 : * 1 if it has been sent twice, etc). 110 : * @param[in] computeMaxPossible Disable randomness such that the maximum value is used instead. 111 : * 112 : * @retval The backoff time value, including jitter. 113 : */ 114 : static System::Clock::Timestamp GetBackoff(System::Clock::Timestamp baseInterval, uint8_t sendCount, 115 : bool computeMaxPossible = false); 116 : 117 : /** 118 : * Start retranmisttion of cached encryped packet for current entry. 119 : * 120 : * @param[in] entry A pointer to a retransmission table entry added into the table. 121 : * 122 : * @retval #CHIP_NO_ERROR On success. 123 : */ 124 : void StartRetransmision(RetransTableEntry * entry); 125 : 126 : /** 127 : * Iterate through active exchange contexts and retrans table entries. Clear the entry matching 128 : * the specified ExchangeContext and the message ID from the retransmision table. 129 : * 130 : * @param[in] rc A pointer to the ExchangeContext object. 131 : * @param[in] ackMessageCounter The acknowledged message counter of the received packet. 132 : * 133 : * @retval #CHIP_NO_ERROR On success. 134 : */ 135 : bool CheckAndRemRetransTable(ReliableMessageContext * rc, uint32_t ackMessageCounter); 136 : 137 : /** 138 : * Send the specified entry from the retransmission table. 139 : * 140 : * @param[in] entry A pointer to a retransmission table entry object that needs to be sent. 141 : * 142 : * @return #CHIP_NO_ERROR On success, else corresponding CHIP_ERROR returned from SendMessage. 143 : */ 144 : CHIP_ERROR SendFromRetransTable(RetransTableEntry * entry); 145 : 146 : /** 147 : * Clear entries matching a specified ExchangeContext. 148 : * 149 : * @param[in] rc A pointer to the ExchangeContext object. 150 : * 151 : */ 152 : void ClearRetransTable(ReliableMessageContext * rc); 153 : 154 : /** 155 : * Clear an entry in the retransmission table. 156 : * 157 : * @param[in] rEntry A reference to the RetransTableEntry object. 158 : * 159 : */ 160 : void ClearRetransTable(RetransTableEntry & rEntry); 161 : 162 : /** 163 : * Iterate through active exchange contexts and retrans table entries. 164 : * Determine how many ReliableMessageProtocol ticks we need to sleep before we 165 : * need to physically wake the CPU to perform an action. Set a timer to go off 166 : * when we next need to wake the system. 167 : * 168 : */ 169 : void StartTimer(); 170 : 171 : /** 172 : * Stop the timer for retransmistion on current node. 173 : * 174 : */ 175 : void StopTimer(); 176 : 177 : /** 178 : * Registers a delegate to perform an address lookup and update all active sessions. 179 : * 180 : * @param[in] sessionUpdateDelegate - Pointer to delegate to perform address lookup 181 : * that will update all active session. A null pointer is allowed if you 182 : * no longer have a valid delegate. 183 : * 184 : */ 185 : void RegisterSessionUpdateDelegate(SessionUpdateDelegate * sessionUpdateDelegate); 186 : 187 : /** 188 : * Map a send error code to the error code we should actually use for 189 : * success checks. This maps some error codes to CHIP_NO_ERROR as 190 : * appropriate. 191 : */ 192 : static CHIP_ERROR MapSendError(CHIP_ERROR error, uint16_t exchangeId, bool isInitiator); 193 : 194 : #if CHIP_CONFIG_TEST 195 : // Functions for testing 196 : int TestGetCountRetransTable(); 197 : 198 : // Enumerate the retransmission table. Clearing an entry while enumerating 199 : // that entry is allowed. F must take a RetransTableEntry as an argument 200 : // and return Loop::Continue or Loop::Break. 201 : template <typename F> 202 : void EnumerateRetransTable(F && functor) 203 : { 204 : mRetransTable.ForEachActiveObject(std::forward<F>(functor)); 205 : } 206 : #endif // CHIP_CONFIG_TEST 207 : 208 : private: 209 : /** 210 : * Calculates the next retransmission time for the entry 211 : * Function sets the nextRetransTime of the entry 212 : * 213 : * @param[in,out] entry RetransTableEntry for which we need to calculate the nextRetransTime 214 : */ 215 : void CalculateNextRetransTime(RetransTableEntry & entry); 216 : 217 : ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & mContextPool; 218 : chip::System::Layer * mSystemLayer; 219 : 220 : /* Placeholder function to run a function for all exchanges */ 221 : template <typename Function> 222 23827 : void ExecuteForAllContext(Function function) 223 : { 224 176769 : mContextPool.ForEachActiveObject([&](auto * ec) { 225 152942 : function(ec->GetReliableMessageContext()); 226 152942 : return Loop::Continue; 227 : }); 228 23827 : } 229 : 230 : void TicklessDebugDumpRetransTable(const char * log); 231 : 232 : // ReliableMessageProtocol Global tables for timer context 233 : ObjectPool<RetransTableEntry, CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE> mRetransTable; 234 : 235 : SessionUpdateDelegate * mSessionUpdateDelegate = nullptr; 236 : }; 237 : 238 : } // namespace Messaging 239 : } // namespace chip