-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathExchangeContext.h
269 lines (226 loc) · 11 KB
/
ExchangeContext.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
267
268
269
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
*
* 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 Exchange Context.
*
*/
#pragma once
#include <lib/core/ReferenceCounted.h>
#include <lib/support/BitFlags.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/ReferenceCountedHandle.h>
#include <lib/support/TypeTraits.h>
#include <messaging/ExchangeDelegate.h>
#include <messaging/Flags.h>
#include <messaging/ReliableMessageContext.h>
#include <protocols/Protocols.h>
#include <transport/SessionManager.h>
namespace chip {
namespace Messaging {
class ExchangeManager;
class ExchangeContext;
class ExchangeMessageDispatch;
using ExchangeHandle = ReferenceCountedHandle<ExchangeContext>;
class ExchangeContextDeletor
{
public:
static void Release(ExchangeContext * obj);
};
/**
* @brief
* This class represents an ongoing conversation (ExchangeContext) between two or more nodes.
* It defines methods for encoding and communicating CHIP messages within an ExchangeContext
* over various transport mechanisms, for example, TCP, UDP, or CHIP Reliable Messaging.
*/
class DLL_EXPORT ExchangeContext : public ReliableMessageContext, public ReferenceCounted<ExchangeContext, ExchangeContextDeletor>
{
friend class ExchangeManager;
friend class ExchangeContextDeletor;
public:
typedef System::Clock::Timeout Timeout; // Type used to express the timeout in this ExchangeContext
ExchangeContext(ExchangeManager * em, uint16_t ExchangeId, SessionHandle session, bool Initiator, ExchangeDelegate * delegate);
~ExchangeContext();
/**
* Determine whether the context is the initiator of the exchange.
*
* @return Returns 'true' if it is the initiator, else 'false'.
*/
bool IsInitiator() const;
bool IsEncryptionRequired() const { return mDispatch->IsEncryptionRequired(); }
bool IsGroupExchangeContext() const { return (mSession.HasValue() && mSession.Value().IsGroupSession()); }
/**
* Send a CHIP message on this exchange.
*
* If SendMessage returns success and the message was not expecting a
* response, the exchange will close itself before returning, unless the
* message being sent is a standalone ack. If SendMessage returns failure,
* the caller is responsible for deciding what to do (e.g. closing the
* exchange, trying to re-establish a secure session, etc).
*
* @param[in] protocolId The protocol identifier of the CHIP message to be sent.
*
* @param[in] msgType The message type of the corresponding protocol.
*
* @param[in] msgPayload A handle to the packet buffer holding the CHIP message.
*
* @param[in] sendFlags Flags set by the application for the CHIP message being sent.
*
* @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this SendMessage API.
* @retval #CHIP_ERROR_WRONG_MSG_VERSION_FOR_EXCHANGE if there is a mismatch in the specific send operation and the
* CHIP message protocol version that is supported.
* @retval #CHIP_ERROR_NOT_CONNECTED if the context was associated with a connection that is now
* closed.
* @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
* @retval #CHIP_NO_ERROR if the CHIP layer successfully sent the message down to the
* network layer.
*/
CHIP_ERROR SendMessage(Protocols::Id protocolId, uint8_t msgType, System::PacketBufferHandle && msgPayload,
const SendFlags & sendFlags = SendFlags(SendMessageFlags::kNone));
/**
* A strongly-message-typed version of SendMessage.
*/
template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
CHIP_ERROR SendMessage(MessageType msgType, System::PacketBufferHandle && msgPayload,
const SendFlags & sendFlags = SendFlags(SendMessageFlags::kNone))
{
return SendMessage(Protocols::MessageTypeTraits<MessageType>::ProtocolId(), to_underlying(msgType), std::move(msgPayload),
sendFlags);
}
/**
* A notification that we will have SendMessage called on us in the future
* (and should stay open until that happens).
*/
void WillSendMessage() { mFlags.Set(Flags::kFlagWillSendMessage); }
/**
* Handle a received CHIP message on this exchange.
*
* @param[in] messageCounter The message counter of the packet.
* @param[in] payloadHeader A reference to the PayloadHeader object.
* @param[in] peerAddress The address of the sender
* @param[in] msgFlags The message flags corresponding to the received message
* @param[in] msgBuf A handle to the packet buffer holding the CHIP message.
*
* @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this HandleMessage API.
* @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
* @retval #CHIP_NO_ERROR if the CHIP layer successfully delivered the message up to the
* protocol layer.
*/
CHIP_ERROR HandleMessage(uint32_t messageCounter, const PayloadHeader & payloadHeader,
const Transport::PeerAddress & peerAddress, MessageFlags msgFlags,
System::PacketBufferHandle && msgBuf);
ExchangeDelegate * GetDelegate() const { return mDelegate; }
void SetDelegate(ExchangeDelegate * delegate) { mDelegate = delegate; }
ExchangeManager * GetExchangeMgr() const { return mExchangeMgr; }
ReliableMessageContext * GetReliableMessageContext() { return static_cast<ReliableMessageContext *>(this); };
ExchangeMessageDispatch * GetMessageDispatch() { return mDispatch; }
SessionHandle GetSessionHandle() const { return mSession.Value(); }
bool HasSessionHandle() const { return mSession.HasValue(); }
uint16_t GetExchangeId() const { return mExchangeId; }
/*
* In order to use reference counting (see refCount below) we use a hold/free paradigm where users of the exchange
* can hold onto it while it's out of their direct control to make sure it isn't closed before everyone's ready.
* A customized version of reference counting is used since there are some extra stuff to do within Release.
*/
void Close();
void Abort();
void SetResponseTimeout(Timeout timeout);
// TODO: move following 5 functions into SessionHandle once we can access session vars w/o using a SessionManager
/*
* Get the overall acknowledge timeout period for the underneath transport(MRP+UDP/TCP)
*/
System::Clock::Milliseconds32 GetAckTimeout();
bool IsUDPTransport();
bool IsTCPTransport();
bool IsBLETransport();
// Helper function for easily accessing MRP config
const ReliableMessageProtocolConfig & GetMRPConfig() const;
private:
Timeout mResponseTimeout{ 0 }; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
ExchangeDelegate * mDelegate = nullptr;
ExchangeManager * mExchangeMgr = nullptr;
ExchangeMessageDispatch * mDispatch = nullptr;
Optional<SessionHandle> mSession; // The connection state
uint16_t mExchangeId; // Assigned exchange ID.
/**
* Determine whether a response is currently expected for a message that was sent over
* this exchange. While this is true, attempts to send other messages that expect a response
* will fail.
*
* @return Returns 'true' if response expected, else 'false'.
*/
bool IsResponseExpected() const;
/**
* Determine whether we are expecting our consumer to send a message on
* this exchange (i.e. WillSendMessage was called and the message has not
* yet been sent).
*/
bool IsSendExpected() const { return mFlags.Has(Flags::kFlagWillSendMessage); }
/**
* Track whether we are now expecting a response to a message sent via this exchange (because that
* message had the kExpectResponse flag set in its sendFlags).
*
* @param[in] inResponseExpected A Boolean indicating whether (true) or not
* (false) a response is currently expected on this
* exchange.
*/
void SetResponseExpected(bool inResponseExpected);
/**
* Search for an existing exchange that the message applies to.
*
* @param[in] session The secure session of the received message.
*
* @param[in] packetHeader A reference to the PacketHeader object.
*
* @param[in] payloadHeader A reference to the PayloadHeader object.
*
* @retval true If a match is found.
* @retval false If a match is not found.
*/
bool MatchExchange(SessionHandle session, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader);
/**
* Notify the exchange that its connection has expired.
*/
void OnConnectionExpired();
/**
* Notify our delegate, if any, that we have timed out waiting for a
* response.
*/
void NotifyResponseTimeout();
CHIP_ERROR StartResponseTimer();
void CancelResponseTimer();
static void HandleResponseTimeout(System::Layer * aSystemLayer, void * aAppState);
void DoClose(bool clearRetransTable);
/**
* We have handled an application-level message in some way and should
* re-evaluate out state to see whether we should still be open.
*/
void MessageHandled();
/**
* Updates Sleepy End Device polling interval in the following way:
* - does nothing for exchanges over Bluetooth LE
* - set IDLE polling mode if all conditions are met:
* - device doesn't expect getting response nor sending message
* - there is no other active exchange than the current one
* - set ACTIVE polling mode if any of the conditions is met:
* - device expects getting response or sending message
* - there is another active exchange
*/
void UpdateSEDPollingMode();
};
} // namespace Messaging
} // namespace chip