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/ReliableMessageProtocolConfig.h>
35 : #include <system/SystemLayer.h>
36 : #include <system/SystemPacketBuffer.h>
37 : #include <transport/SessionUpdateDelegate.h>
38 : #include <transport/raw/MessageHeader.h>
39 :
40 : namespace chip {
41 : namespace Messaging {
42 :
43 : enum class SendMessageFlags : uint16_t;
44 : class ReliableMessageContext;
45 :
46 : class ReliableMessageMgr
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 : {
61 : RetransTableEntry(ReliableMessageContext * rc);
62 : ~RetransTableEntry();
63 :
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. */
69 : };
70 :
71 : ReliableMessageMgr(ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & contextPool);
72 : ~ReliableMessageMgr();
73 :
74 : void Init(chip::System::Layer * systemLayer);
75 : void Shutdown();
76 :
77 : /**
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 : */
82 : void ExecuteActions();
83 :
84 : /**
85 : * Handle physical wakeup of system due to ReliableMessageProtocol wakeup.
86 : *
87 : */
88 : static void Timeout(System::Layer * aSystemLayer, void * aAppState);
89 :
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 : */
101 : CHIP_ERROR AddToRetransTable(ReliableMessageContext * rc, RetransTableEntry ** rEntry);
102 :
103 : /**
104 : * Calculate the backoff timer for the retransmission.
105 : *
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.
112 : *
113 : * @retval The backoff time value, including jitter.
114 : */
115 : static System::Clock::Timeout GetBackoff(System::Clock::Timeout baseInterval, uint8_t sendCount,
116 : bool computeMaxPossible = false);
117 :
118 : /**
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 : */
125 : void StartRetransmision(RetransTableEntry * entry);
126 :
127 : /**
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 : *
131 : * @param[in] rc A pointer to the ExchangeContext object.
132 : * @param[in] ackMessageCounter The acknowledged message counter of the received packet.
133 : *
134 : * @retval #CHIP_NO_ERROR On success.
135 : */
136 : bool CheckAndRemRetransTable(ReliableMessageContext * rc, uint32_t ackMessageCounter);
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 : */
145 : CHIP_ERROR SendFromRetransTable(RetransTableEntry * entry);
146 :
147 : /**
148 : * Clear entries matching a specified ExchangeContext.
149 : *
150 : * @param[in] rc A pointer to the ExchangeContext object.
151 : *
152 : */
153 : void ClearRetransTable(ReliableMessageContext * rc);
154 :
155 : /**
156 : * Clear an entry in the retransmission table.
157 : *
158 : * @param[in] rEntry A reference to the RetransTableEntry object.
159 : *
160 : */
161 : void ClearRetransTable(RetransTableEntry & rEntry);
162 :
163 : /**
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 : */
170 : void StartTimer();
171 :
172 : /**
173 : * Stop the timer for retransmistion on current node.
174 : *
175 : */
176 : void StopTimer();
177 :
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 :
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 :
195 : #if CHIP_CONFIG_TEST
196 : // Functions for testing
197 : int TestGetCountRetransTable();
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 : }
207 : #endif // CHIP_CONFIG_TEST
208 :
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 : */
222 : static void SetAdditionalMRPBackoffTime(const Optional<System::Clock::Timeout> & additionalTime);
223 :
224 : private:
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 :
233 : ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & mContextPool;
234 : chip::System::Layer * mSystemLayer;
235 :
236 : /* Placeholder function to run a function for all exchanges */
237 : template <typename Function>
238 24298 : void ExecuteForAllContext(Function function)
239 : {
240 178020 : mContextPool.ForEachActiveObject([&](auto * ec) {
241 153722 : function(ec->GetReliableMessageContext());
242 153722 : return Loop::Continue;
243 : });
244 24298 : }
245 :
246 : void TicklessDebugDumpRetransTable(const char * log);
247 :
248 : // ReliableMessageProtocol Global tables for timer context
249 : ObjectPool<RetransTableEntry, CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE> mRetransTable;
250 :
251 : SessionUpdateDelegate * mSessionUpdateDelegate = nullptr;
252 :
253 : static System::Clock::Timeout sAdditionalMRPBackoffTime;
254 : };
255 :
256 : } // namespace Messaging
257 : } // namespace chip
|