blob: 5036b8321084438cb64eef54f28f34ba8284e230 [file] [log] [blame]
Zang MingJie76e0d7b2020-10-29 12:26:25 +08001/*
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 Wangcb23e0c2021-01-07 12:36:21 -080026#include <array>
Zang MingJie76e0d7b2020-10-29 12:26:25 +080027#include <stdint.h>
28
Zang MingJie53dd5832021-09-03 03:05:16 +080029#include <lib/core/CHIPError.h>
Boris Zbarsky1c203012024-03-12 10:28:02 -040030#include <lib/core/Optional.h>
Zang MingJie53dd5832021-09-03 03:05:16 +080031#include <lib/support/BitFlags.h>
32#include <lib/support/Pool.h>
Zang MingJie4ec0e4e2021-12-02 15:20:06 +080033#include <messaging/ExchangeContext.h>
34#include <messaging/ReliableMessageProtocolConfig.h>
Zang MingJie76e0d7b2020-10-29 12:26:25 +080035#include <system/SystemLayer.h>
36#include <system/SystemPacketBuffer.h>
Terence Hampsonb94e1a12022-08-12 13:46:49 -040037#include <transport/SessionUpdateDelegate.h>
Zang MingJie76e0d7b2020-10-29 12:26:25 +080038#include <transport/raw/MessageHeader.h>
39
40namespace chip {
Yufeng Wang01031e72020-12-01 09:57:42 -080041namespace Messaging {
Zang MingJie76e0d7b2020-10-29 12:26:25 +080042
43enum class SendMessageFlags : uint16_t;
44class ReliableMessageContext;
45
Yufeng Wang02b31c02021-02-02 15:15:54 -080046class ReliableMessageMgr
Zang MingJie76e0d7b2020-10-29 12:26:25 +080047{
48public:
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 MingJie6145b342021-09-30 06:14:57 +080061 RetransTableEntry(ReliableMessageContext * rc);
62 ~RetransTableEntry();
Zang MingJie76e0d7b2020-10-29 12:26:25 +080063
Zang MingJie4ec0e4e2021-12-02 15:20:06 +080064 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 MingJie76e0d7b2020-10-29 12:26:25 +080069 };
70
Boris Zbarskyd4bb6ee2022-06-28 19:10:26 -040071 ReliableMessageMgr(ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & contextPool);
Yufeng Wang02b31c02021-02-02 15:15:54 -080072 ~ReliableMessageMgr();
Zang MingJie76e0d7b2020-10-29 12:26:25 +080073
Zang MingJie4ec0e4e2021-12-02 15:20:06 +080074 void Init(chip::System::Layer * systemLayer);
Yufeng Wangcb23e0c2021-01-07 12:36:21 -080075 void Shutdown();
Zang MingJie76e0d7b2020-10-29 12:26:25 +080076
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080077 /**
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080078 * 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 MingJie76e0d7b2020-10-29 12:26:25 +080082 void ExecuteActions();
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080083
84 /**
85 * Handle physical wakeup of system due to ReliableMessageProtocol wakeup.
86 *
87 */
Kevin Schoedel7359d192021-08-11 17:26:23 -040088 static void Timeout(System::Layer * aSystemLayer, void * aAppState);
Zang MingJie76e0d7b2020-10-29 12:26:25 +080089
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -080090 /**
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 Wangcb23e0c2021-01-07 12:36:21 -0800101 CHIP_ERROR AddToRetransTable(ReliableMessageContext * rc, RetransTableEntry ** rEntry);
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800102
103 /**
Martin Turonfb8d9dc2022-03-30 14:36:36 -0700104 * Calculate the backoff timer for the retransmission.
105 *
Vivien Nicolas911d5f42022-10-26 11:39:55 +0200106 * @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 Turonfb8d9dc2022-03-30 14:36:36 -0700112 *
113 * @retval The backoff time value, including jitter.
114 */
Damian Królikffaeaa12024-04-30 08:59:22 +0200115 static System::Clock::Timeout GetBackoff(System::Clock::Timeout baseInterval, uint8_t sendCount,
116 bool computeMaxPossible = false);
Martin Turonfb8d9dc2022-03-30 14:36:36 -0700117
118 /**
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800119 * 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 Wangcb23e0c2021-01-07 12:36:21 -0800125 void StartRetransmision(RetransTableEntry * entry);
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800126
127 /**
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800128 * 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 MingJie2dcb61c2021-09-16 11:12:47 +0800131 * @param[in] rc A pointer to the ExchangeContext object.
132 * @param[in] ackMessageCounter The acknowledged message counter of the received packet.
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800133 *
134 * @retval #CHIP_NO_ERROR On success.
135 */
Zang MingJie2dcb61c2021-09-16 11:12:47 +0800136 bool CheckAndRemRetransTable(ReliableMessageContext * rc, uint32_t ackMessageCounter);
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800137
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 MingJie76e0d7b2020-10-29 12:26:25 +0800145 CHIP_ERROR SendFromRetransTable(RetransTableEntry * entry);
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800146
147 /**
148 * Clear entries matching a specified ExchangeContext.
149 *
150 * @param[in] rc A pointer to the ExchangeContext object.
151 *
152 */
Yufeng Wang6c949412021-01-12 15:56:30 -0800153 void ClearRetransTable(ReliableMessageContext * rc);
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800154
155 /**
156 * Clear an entry in the retransmission table.
157 *
158 * @param[in] rEntry A reference to the RetransTableEntry object.
159 *
160 */
Yufeng Wang6c949412021-01-12 15:56:30 -0800161 void ClearRetransTable(RetransTableEntry & rEntry);
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800162
163 /**
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800164 * 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 MingJie76e0d7b2020-10-29 12:26:25 +0800170 void StartTimer();
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800171
172 /**
173 * Stop the timer for retransmistion on current node.
174 *
175 */
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800176 void StopTimer();
Yufeng Wang9fb9d7f2021-02-09 12:16:15 -0800177
Terence Hampsonb94e1a12022-08-12 13:46:49 -0400178 /**
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 Zbarsky20b2b192022-09-06 19:57:43 -0400188 /**
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 Zbarskyf95637b2021-05-25 16:43:02 -0400195#if CHIP_CONFIG_TEST
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800196 // Functions for testing
197 int TestGetCountRetransTable();
Boris Zbarskyd30cff32022-10-25 08:23:30 -0400198
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 Zbarskyf95637b2021-05-25 16:43:02 -0400207#endif // CHIP_CONFIG_TEST
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800208
Boris Zbarsky1c203012024-03-12 10:28:02 -0400209 /**
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ólikbc0f5ee2024-05-07 11:44:16 +0200222 static void SetAdditionalMRPBackoffTime(const Optional<System::Clock::Timeout> & additionalTime);
Boris Zbarsky1c203012024-03-12 10:28:02 -0400223
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800224private:
mkardous-silabsa8a96592023-10-19 15:01:58 -0400225 /**
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 Zbarskyd4bb6ee2022-06-28 19:10:26 -0400233 ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & mContextPool;
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800234 chip::System::Layer * mSystemLayer;
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800235
236 /* Placeholder function to run a function for all exchanges */
237 template <typename Function>
238 void ExecuteForAllContext(Function function)
Yufeng Wangcb23e0c2021-01-07 12:36:21 -0800239 {
Zang MingJie1b5d2a72021-05-15 04:13:32 +0800240 mContextPool.ForEachActiveObject([&](auto * ec) {
241 function(ec->GetReliableMessageContext());
Zang MingJiee2e4c172021-12-03 01:15:02 +0800242 return Loop::Continue;
Zang MingJie1b5d2a72021-05-15 04:13:32 +0800243 });
Yufeng Wangcb23e0c2021-01-07 12:36:21 -0800244 }
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800245
246 void TicklessDebugDumpRetransTable(const char * log);
247
248 // ReliableMessageProtocol Global tables for timer context
Boris Zbarskyd4bb6ee2022-06-28 19:10:26 -0400249 ObjectPool<RetransTableEntry, CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE> mRetransTable;
Terence Hampsonb94e1a12022-08-12 13:46:49 -0400250
251 SessionUpdateDelegate * mSessionUpdateDelegate = nullptr;
Boris Zbarsky1c203012024-03-12 10:28:02 -0400252
Damian Królikbc0f5ee2024-05-07 11:44:16 +0200253 static System::Clock::Timeout sAdditionalMRPBackoffTime;
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800254};
255
Yufeng Wang01031e72020-12-01 09:57:42 -0800256} // namespace Messaging
Zang MingJie76e0d7b2020-10-29 12:26:25 +0800257} // namespace chip