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