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