Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 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 | |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 26 | #include <array> |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 27 | #include <stdint.h> |
| 28 | |
Zang MingJie | 53dd583 | 2021-09-03 03:05:16 +0800 | [diff] [blame] | 29 | #include <lib/core/CHIPError.h> |
Boris Zbarsky | 1c20301 | 2024-03-12 10:28:02 -0400 | [diff] [blame] | 30 | #include <lib/core/Optional.h> |
Zang MingJie | 53dd583 | 2021-09-03 03:05:16 +0800 | [diff] [blame] | 31 | #include <lib/support/BitFlags.h> |
| 32 | #include <lib/support/Pool.h> |
Zang MingJie | 4ec0e4e | 2021-12-02 15:20:06 +0800 | [diff] [blame] | 33 | #include <messaging/ExchangeContext.h> |
| 34 | #include <messaging/ReliableMessageProtocolConfig.h> |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 35 | #include <system/SystemLayer.h> |
| 36 | #include <system/SystemPacketBuffer.h> |
Terence Hampson | b94e1a1 | 2022-08-12 13:46:49 -0400 | [diff] [blame] | 37 | #include <transport/SessionUpdateDelegate.h> |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 38 | #include <transport/raw/MessageHeader.h> |
| 39 | |
| 40 | namespace chip { |
Yufeng Wang | 01031e7 | 2020-12-01 09:57:42 -0800 | [diff] [blame] | 41 | namespace Messaging { |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 42 | |
| 43 | enum class SendMessageFlags : uint16_t; |
| 44 | class ReliableMessageContext; |
| 45 | |
Yufeng Wang | 02b31c0 | 2021-02-02 15:15:54 -0800 | [diff] [blame] | 46 | class ReliableMessageMgr |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 47 | { |
| 48 | public: |
| 49 | /** |
| 50 | * @class RetransTableEntry |
| 51 | * |
| 52 | * @brief |
| 53 | * This class is part of the CHIP Reliable Messaging Protocol and is used |
| 54 | * to keep track of CHIP messages that have been sent and are expecting an |
| 55 | * acknowledgment back. If the acknowledgment is not received within a |
| 56 | * specific timeout, the message would be retransmitted from this table. |
| 57 | * |
| 58 | */ |
| 59 | struct RetransTableEntry |
| 60 | { |
Zang MingJie | 6145b34 | 2021-09-30 06:14:57 +0800 | [diff] [blame] | 61 | RetransTableEntry(ReliableMessageContext * rc); |
| 62 | ~RetransTableEntry(); |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 63 | |
Zang MingJie | 4ec0e4e | 2021-12-02 15:20:06 +0800 | [diff] [blame] | 64 | ExchangeHandle ec; /**< The context for the stored CHIP message. */ |
| 65 | EncryptedPacketBufferHandle retainedBuf; /**< The packet buffer holding the CHIP message. */ |
| 66 | System::Clock::Timestamp nextRetransTime; /**< A counter representing the next retransmission time for the message. */ |
| 67 | uint8_t sendCount; /**< The number of times we have tried to send this entry, |
| 68 | including both successfully and failure send. */ |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 69 | }; |
| 70 | |
Boris Zbarsky | d4bb6ee | 2022-06-28 19:10:26 -0400 | [diff] [blame] | 71 | ReliableMessageMgr(ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & contextPool); |
Yufeng Wang | 02b31c0 | 2021-02-02 15:15:54 -0800 | [diff] [blame] | 72 | ~ReliableMessageMgr(); |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 73 | |
Zang MingJie | 4ec0e4e | 2021-12-02 15:20:06 +0800 | [diff] [blame] | 74 | void Init(chip::System::Layer * systemLayer); |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 75 | void Shutdown(); |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 76 | |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 77 | /** |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 78 | * Iterate through active exchange contexts and retrans table entries. If an |
| 79 | * action needs to be triggered by ReliableMessageProtocol time facilities, |
| 80 | * execute that action. |
| 81 | */ |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 82 | void ExecuteActions(); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 83 | |
| 84 | /** |
| 85 | * Handle physical wakeup of system due to ReliableMessageProtocol wakeup. |
| 86 | * |
| 87 | */ |
Kevin Schoedel | 7359d19 | 2021-08-11 17:26:23 -0400 | [diff] [blame] | 88 | static void Timeout(System::Layer * aSystemLayer, void * aAppState); |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 89 | |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 90 | /** |
| 91 | * Add a CHIP message into the retransmission table to be subsequently resent if a corresponding acknowledgment |
| 92 | * is not received within the retransmission timeout. |
| 93 | * |
| 94 | * @param[in] rc A pointer to the ExchangeContext object. |
| 95 | * |
| 96 | * @param[out] rEntry A pointer to a pointer of a retransmission table entry added into the table. |
| 97 | * |
| 98 | * @retval #CHIP_ERROR_RETRANS_TABLE_FULL If there is no empty slot left in the table for addition. |
| 99 | * @retval #CHIP_NO_ERROR On success. |
| 100 | */ |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 101 | CHIP_ERROR AddToRetransTable(ReliableMessageContext * rc, RetransTableEntry ** rEntry); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 102 | |
| 103 | /** |
Martin Turon | fb8d9dc | 2022-03-30 14:36:36 -0700 | [diff] [blame] | 104 | * Calculate the backoff timer for the retransmission. |
| 105 | * |
Vivien Nicolas | 911d5f4 | 2022-10-26 11:39:55 +0200 | [diff] [blame] | 106 | * @param[in] baseInterval The base interval to use for the backoff calculation, either the active or idle interval. |
| 107 | * @param[in] sendCount Count of how many times this message |
| 108 | * has been retransmitted so far (0 if it has |
| 109 | * been sent only once with no retransmits, |
| 110 | * 1 if it has been sent twice, etc). |
| 111 | * @param[in] computeMaxPossible Disable randomness such that the maximum value is used instead. |
Martin Turon | fb8d9dc | 2022-03-30 14:36:36 -0700 | [diff] [blame] | 112 | * |
| 113 | * @retval The backoff time value, including jitter. |
| 114 | */ |
Damian Królik | ffaeaa1 | 2024-04-30 08:59:22 +0200 | [diff] [blame] | 115 | static System::Clock::Timeout GetBackoff(System::Clock::Timeout baseInterval, uint8_t sendCount, |
| 116 | bool computeMaxPossible = false); |
Martin Turon | fb8d9dc | 2022-03-30 14:36:36 -0700 | [diff] [blame] | 117 | |
| 118 | /** |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 119 | * Start retranmisttion of cached encryped packet for current entry. |
| 120 | * |
| 121 | * @param[in] entry A pointer to a retransmission table entry added into the table. |
| 122 | * |
| 123 | * @retval #CHIP_NO_ERROR On success. |
| 124 | */ |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 125 | void StartRetransmision(RetransTableEntry * entry); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 126 | |
| 127 | /** |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 128 | * Iterate through active exchange contexts and retrans table entries. Clear the entry matching |
| 129 | * the specified ExchangeContext and the message ID from the retransmision table. |
| 130 | * |
Zang MingJie | 2dcb61c | 2021-09-16 11:12:47 +0800 | [diff] [blame] | 131 | * @param[in] rc A pointer to the ExchangeContext object. |
| 132 | * @param[in] ackMessageCounter The acknowledged message counter of the received packet. |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 133 | * |
| 134 | * @retval #CHIP_NO_ERROR On success. |
| 135 | */ |
Zang MingJie | 2dcb61c | 2021-09-16 11:12:47 +0800 | [diff] [blame] | 136 | bool CheckAndRemRetransTable(ReliableMessageContext * rc, uint32_t ackMessageCounter); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 137 | |
| 138 | /** |
| 139 | * Send the specified entry from the retransmission table. |
| 140 | * |
| 141 | * @param[in] entry A pointer to a retransmission table entry object that needs to be sent. |
| 142 | * |
| 143 | * @return #CHIP_NO_ERROR On success, else corresponding CHIP_ERROR returned from SendMessage. |
| 144 | */ |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 145 | CHIP_ERROR SendFromRetransTable(RetransTableEntry * entry); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 146 | |
| 147 | /** |
| 148 | * Clear entries matching a specified ExchangeContext. |
| 149 | * |
| 150 | * @param[in] rc A pointer to the ExchangeContext object. |
| 151 | * |
| 152 | */ |
Yufeng Wang | 6c94941 | 2021-01-12 15:56:30 -0800 | [diff] [blame] | 153 | void ClearRetransTable(ReliableMessageContext * rc); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 154 | |
| 155 | /** |
| 156 | * Clear an entry in the retransmission table. |
| 157 | * |
| 158 | * @param[in] rEntry A reference to the RetransTableEntry object. |
| 159 | * |
| 160 | */ |
Yufeng Wang | 6c94941 | 2021-01-12 15:56:30 -0800 | [diff] [blame] | 161 | void ClearRetransTable(RetransTableEntry & rEntry); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 162 | |
| 163 | /** |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 164 | * Iterate through active exchange contexts and retrans table entries. |
| 165 | * Determine how many ReliableMessageProtocol ticks we need to sleep before we |
| 166 | * need to physically wake the CPU to perform an action. Set a timer to go off |
| 167 | * when we next need to wake the system. |
| 168 | * |
| 169 | */ |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 170 | void StartTimer(); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 171 | |
| 172 | /** |
| 173 | * Stop the timer for retransmistion on current node. |
| 174 | * |
| 175 | */ |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 176 | void StopTimer(); |
Yufeng Wang | 9fb9d7f | 2021-02-09 12:16:15 -0800 | [diff] [blame] | 177 | |
Terence Hampson | b94e1a1 | 2022-08-12 13:46:49 -0400 | [diff] [blame] | 178 | /** |
| 179 | * Registers a delegate to perform an address lookup and update all active sessions. |
| 180 | * |
| 181 | * @param[in] sessionUpdateDelegate - Pointer to delegate to perform address lookup |
| 182 | * that will update all active session. A null pointer is allowed if you |
| 183 | * no longer have a valid delegate. |
| 184 | * |
| 185 | */ |
| 186 | void RegisterSessionUpdateDelegate(SessionUpdateDelegate * sessionUpdateDelegate); |
| 187 | |
Boris Zbarsky | 20b2b19 | 2022-09-06 19:57:43 -0400 | [diff] [blame] | 188 | /** |
| 189 | * Map a send error code to the error code we should actually use for |
| 190 | * success checks. This maps some error codes to CHIP_NO_ERROR as |
| 191 | * appropriate. |
| 192 | */ |
| 193 | static CHIP_ERROR MapSendError(CHIP_ERROR error, uint16_t exchangeId, bool isInitiator); |
| 194 | |
Boris Zbarsky | f95637b | 2021-05-25 16:43:02 -0400 | [diff] [blame] | 195 | #if CHIP_CONFIG_TEST |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 196 | // Functions for testing |
| 197 | int TestGetCountRetransTable(); |
Boris Zbarsky | d30cff3 | 2022-10-25 08:23:30 -0400 | [diff] [blame] | 198 | |
| 199 | // Enumerate the retransmission table. Clearing an entry while enumerating |
| 200 | // that entry is allowed. F must take a RetransTableEntry as an argument |
| 201 | // and return Loop::Continue or Loop::Break. |
| 202 | template <typename F> |
| 203 | void EnumerateRetransTable(F && functor) |
| 204 | { |
| 205 | mRetransTable.ForEachActiveObject(std::forward<F>(functor)); |
| 206 | } |
Boris Zbarsky | f95637b | 2021-05-25 16:43:02 -0400 | [diff] [blame] | 207 | #endif // CHIP_CONFIG_TEST |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 208 | |
Boris Zbarsky | 1c20301 | 2024-03-12 10:28:02 -0400 | [diff] [blame] | 209 | /** |
| 210 | * Set the value to add to the MRP backoff time we compute. This is meant to |
| 211 | * account for high network latency on the sending side (us) that can't be |
| 212 | * known to the message recipient and hence is not captured in the MRP |
| 213 | * parameters the message recipient communicates to us. |
| 214 | * |
| 215 | * If set to NullOptional falls back to the compile-time |
| 216 | * CHIP_CONFIG_MRP_RETRY_INTERVAL_SENDER_BOOST. |
| 217 | * |
| 218 | * This is a static, not a regular member, because API consumers may need to |
| 219 | * set this before actually bringing up the stack and having access to a |
| 220 | * ReliableMessageMgr. |
| 221 | */ |
Damian Królik | bc0f5ee | 2024-05-07 11:44:16 +0200 | [diff] [blame] | 222 | static void SetAdditionalMRPBackoffTime(const Optional<System::Clock::Timeout> & additionalTime); |
Boris Zbarsky | 1c20301 | 2024-03-12 10:28:02 -0400 | [diff] [blame] | 223 | |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 224 | private: |
mkardous-silabs | a8a9659 | 2023-10-19 15:01:58 -0400 | [diff] [blame] | 225 | /** |
| 226 | * Calculates the next retransmission time for the entry |
| 227 | * Function sets the nextRetransTime of the entry |
| 228 | * |
| 229 | * @param[in,out] entry RetransTableEntry for which we need to calculate the nextRetransTime |
| 230 | */ |
| 231 | void CalculateNextRetransTime(RetransTableEntry & entry); |
| 232 | |
Boris Zbarsky | d4bb6ee | 2022-06-28 19:10:26 -0400 | [diff] [blame] | 233 | ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & mContextPool; |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 234 | chip::System::Layer * mSystemLayer; |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 235 | |
| 236 | /* Placeholder function to run a function for all exchanges */ |
| 237 | template <typename Function> |
| 238 | void ExecuteForAllContext(Function function) |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 239 | { |
Zang MingJie | 1b5d2a7 | 2021-05-15 04:13:32 +0800 | [diff] [blame] | 240 | mContextPool.ForEachActiveObject([&](auto * ec) { |
| 241 | function(ec->GetReliableMessageContext()); |
Zang MingJie | e2e4c17 | 2021-12-03 01:15:02 +0800 | [diff] [blame] | 242 | return Loop::Continue; |
Zang MingJie | 1b5d2a7 | 2021-05-15 04:13:32 +0800 | [diff] [blame] | 243 | }); |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 244 | } |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 245 | |
| 246 | void TicklessDebugDumpRetransTable(const char * log); |
| 247 | |
| 248 | // ReliableMessageProtocol Global tables for timer context |
Boris Zbarsky | d4bb6ee | 2022-06-28 19:10:26 -0400 | [diff] [blame] | 249 | ObjectPool<RetransTableEntry, CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE> mRetransTable; |
Terence Hampson | b94e1a1 | 2022-08-12 13:46:49 -0400 | [diff] [blame] | 250 | |
| 251 | SessionUpdateDelegate * mSessionUpdateDelegate = nullptr; |
Boris Zbarsky | 1c20301 | 2024-03-12 10:28:02 -0400 | [diff] [blame] | 252 | |
Damian Królik | bc0f5ee | 2024-05-07 11:44:16 +0200 | [diff] [blame] | 253 | static System::Clock::Timeout sAdditionalMRPBackoffTime; |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 254 | }; |
| 255 | |
Yufeng Wang | 01031e7 | 2020-12-01 09:57:42 -0800 | [diff] [blame] | 256 | } // namespace Messaging |
Zang MingJie | 76e0d7b | 2020-10-29 12:26:25 +0800 | [diff] [blame] | 257 | } // namespace chip |