-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
ExchangeContext.h
224 lines (186 loc) · 9.25 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
/*
*
* Copyright (c) 2020 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 <messaging/ExchangeDelegate.h>
#include <messaging/Flags.h>
#include <messaging/ReliableMessageContext.h>
#include <support/BitFlags.h>
#include <support/DLLUtil.h>
#include <system/SystemTimer.h>
#include <transport/SecureSessionMgr.h>
namespace chip {
constexpr uint16_t kMsgCounterChallengeSize = 8; // The size of the message counter synchronization request message.
namespace Messaging {
class ExchangeManager;
class 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 ReferenceCounted<ExchangeContext, ExchangeContextDeletor, 0>
{
friend class ExchangeManager;
friend class ExchangeContextDeletor;
public:
typedef uint32_t Timeout; // Type used to express the timeout in this ExchangeContext, in milliseconds
/**
* Determine whether the context is the initiator of the exchange.
*
* @return Returns 'true' if it is the initiator, else 'false'.
*/
bool IsInitiator() const;
/**
* Determine whether a response is expected for messages sent over
* this exchange.
*
* @return Returns 'true' if response expected, else 'false'.
*/
bool IsResponseExpected() const;
/**
* Set whether a response is expected on this exchange.
*
* @param[in] inResponseExpected A Boolean indicating whether (true) or not
* (false) a response is expected on this
* exchange.
*/
void SetResponseExpected(bool inResponseExpected);
/**
* Send a CHIP message on this exchange.
*
* @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.
*
* @param[in] msgCtxt A pointer to an application-specific context object to be associated
* with the 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(uint16_t protocolId, uint8_t msgType, System::PacketBufferHandle msgPayload, const SendFlags & sendFlags,
void * msgCtxt = nullptr);
/**
* 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,
void * msgCtxt = nullptr)
{
static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
return SendMessage(Protocols::MessageTypeTraits<MessageType>::ProtocolId, static_cast<uint8_t>(msgType),
std::move(msgPayload), sendFlags, msgCtxt);
}
/**
* Handle a received CHIP message on this exchange.
*
* @param[in] packetHeader A reference to the PacketHeader object.
*
* @param[in] payloadHeader A reference to the PayloadHeader object.
*
* @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(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
System::PacketBufferHandle msgBuf);
ExchangeDelegate * GetDelegate() const { return mDelegate; }
void SetDelegate(ExchangeDelegate * delegate) { mDelegate = delegate; }
void SetReliableMessageDelegate(ReliableMessageDelegate * delegate) { mReliableMessageContext.SetDelegate(delegate); }
ExchangeManager * GetExchangeMgr() const { return mExchangeMgr; }
ReliableMessageContext * GetReliableMessageContext() { return &mReliableMessageContext; };
SecureSessionHandle GetSecureSession() { return mSecureSession; }
uint16_t GetExchangeId() const { return mExchangeId; }
void SetChallenge(const uint8_t * value) { memcpy(&mChallenge[0], value, kMsgCounterChallengeSize); }
const uint8_t * GetChallenge() const { return mChallenge; }
SecureSessionHandle GetSecureSessionHandle() const { return mSecureSession; }
/*
* 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();
ExchangeContext * Alloc(ExchangeManager * em, uint16_t ExchangeId, SecureSessionHandle session, bool Initiator,
ExchangeDelegate * delegate);
void Free();
void Reset();
void SetResponseTimeout(Timeout timeout);
private:
enum class ExFlagValues : uint16_t
{
kFlagInitiator = 0x0001, // This context is the initiator of the exchange.
kFlagResponseExpected = 0x0002, // If a response is expected for a message that is being sent.
};
Timeout mResponseTimeout; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
ReliableMessageContext mReliableMessageContext;
ExchangeDelegate * mDelegate = nullptr;
ExchangeManager * mExchangeMgr = nullptr;
SecureSessionHandle mSecureSession; // The connection state
uint16_t mExchangeId; // Assigned exchange ID.
// [TODO: #4711]: this field need to be moved to appState object which implement 'exchange-specific' contextual
// actions with a delegate pattern.
uint8_t mChallenge[kMsgCounterChallengeSize]; // Challenge number to identify the sychronization request cryptographically.
BitFlags<uint16_t, ExFlagValues> mFlags; // Internal state flags
/**
* 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(SecureSessionHandle session, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader);
CHIP_ERROR StartResponseTimer();
void CancelResponseTimer();
static void HandleResponseTimeout(System::Layer * aSystemLayer, void * aAppState, System::Error aError);
void DoClose(bool clearRetransTable);
};
inline void ExchangeContextDeletor::Release(ExchangeContext * obj)
{
obj->Free();
}
} // namespace Messaging
} // namespace chip