3 * Copyright (c) 2020-2021 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * This file defines the classes corresponding to CHIP Exchange Context.
26 #include <lib/core/ReferenceCounted.h>
27 #include <messaging/ExchangeACL.h>
28 #include <messaging/ExchangeDelegate.h>
29 #include <messaging/Flags.h>
30 #include <messaging/ReliableMessageContext.h>
31 #include <protocols/Protocols.h>
32 #include <support/BitFlags.h>
33 #include <support/DLLUtil.h>
34 #include <system/SystemTimer.h>
35 #include <transport/SecureSessionMgr.h>
39 constexpr uint16_t kMsgCounterChallengeSize = 8; // The size of the message counter synchronization request message.
43 class ExchangeManager;
44 class ExchangeContext;
46 class ExchangeContextDeletor
49 static void Release(ExchangeContext * obj);
54 * This class represents an ongoing conversation (ExchangeContext) between two or more nodes.
55 * It defines methods for encoding and communicating CHIP messages within an ExchangeContext
56 * over various transport mechanisms, for example, TCP, UDP, or CHIP Reliable Messaging.
58 class DLL_EXPORT ExchangeContext : public ReferenceCounted<ExchangeContext, ExchangeContextDeletor, 0>
60 friend class ExchangeManager;
61 friend class ExchangeContextDeletor;
62 friend class MessageCounterSyncMgr;
65 typedef uint32_t Timeout; // Type used to express the timeout in this ExchangeContext, in milliseconds
68 * Determine whether the context is the initiator of the exchange.
70 * @return Returns 'true' if it is the initiator, else 'false'.
72 bool IsInitiator() const;
75 * Determine whether a response is expected for messages sent over
78 * @return Returns 'true' if response expected, else 'false'.
80 bool IsResponseExpected() const;
83 * Set whether a response is expected on this exchange.
85 * @param[in] inResponseExpected A Boolean indicating whether (true) or not
86 * (false) a response is expected on this
89 void SetResponseExpected(bool inResponseExpected);
92 * Send a CHIP message on this exchange.
94 * @param[in] protocolId The protocol identifier of the CHIP message to be sent.
96 * @param[in] msgType The message type of the corresponding protocol.
98 * @param[in] msgPayload A handle to the packet buffer holding the CHIP message.
100 * @param[in] sendFlags Flags set by the application for the CHIP message being sent.
102 * @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this SendMessage API.
103 * @retval #CHIP_ERROR_WRONG_MSG_VERSION_FOR_EXCHANGE if there is a mismatch in the specific send operation and the
104 * CHIP message protocol version that is supported.
105 * @retval #CHIP_ERROR_NOT_CONNECTED if the context was associated with a connection that is now
107 * @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
108 * @retval #CHIP_NO_ERROR if the CHIP layer successfully sent the message down to the
111 CHIP_ERROR SendMessage(Protocols::Id protocolId, uint8_t msgType, System::PacketBufferHandle msgPayload,
112 const SendFlags & sendFlags);
115 * A strongly-message-typed version of SendMessage.
117 template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
118 CHIP_ERROR SendMessage(MessageType msgType, System::PacketBufferHandle && msgPayload, const SendFlags & sendFlags)
120 static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
121 return SendMessage(Protocols::MessageTypeTraits<MessageType>::ProtocolId(), static_cast<uint8_t>(msgType),
122 std::move(msgPayload), sendFlags);
126 * Handle a received CHIP message on this exchange.
128 * @param[in] packetHeader A reference to the PacketHeader object.
130 * @param[in] payloadHeader A reference to the PayloadHeader object.
132 * @param[in] msgBuf A handle to the packet buffer holding the CHIP message.
134 * @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this HandleMessage API.
135 * @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
136 * @retval #CHIP_NO_ERROR if the CHIP layer successfully delivered the message up to the
139 CHIP_ERROR HandleMessage(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
140 System::PacketBufferHandle msgBuf);
142 ExchangeDelegate * GetDelegate() const { return mDelegate; }
143 void SetDelegate(ExchangeDelegate * delegate) { mDelegate = delegate; }
144 void SetReliableMessageDelegate(ReliableMessageDelegate * delegate) { mReliableMessageContext.SetDelegate(delegate); }
146 ExchangeManager * GetExchangeMgr() const { return mExchangeMgr; }
148 ReliableMessageContext * GetReliableMessageContext() { return &mReliableMessageContext; };
150 ExchangeACL * GetExchangeACL(Transport::AdminPairingTable & table)
152 if (mExchangeACL == nullptr)
154 Transport::AdminPairingInfo * admin = table.FindAdmin(mSecureSession.GetAdminId());
155 if (admin != nullptr)
157 mExchangeACL = chip::Platform::New<CASEExchangeACL>(admin);
164 SecureSessionHandle GetSecureSession() { return mSecureSession; }
166 uint16_t GetExchangeId() const { return mExchangeId; }
168 void SetChallenge(const uint8_t * value) { memcpy(&mChallenge[0], value, kMsgCounterChallengeSize); }
170 const uint8_t * GetChallenge() const { return mChallenge; }
172 SecureSessionHandle GetSecureSessionHandle() const { return mSecureSession; }
175 * In order to use reference counting (see refCount below) we use a hold/free paradigm where users of the exchange
176 * can hold onto it while it's out of their direct control to make sure it isn't closed before everyone's ready.
177 * A customized version of reference counting is used since there are some extra stuff to do within Release.
182 ExchangeContext * Alloc(ExchangeManager * em, uint16_t ExchangeId, SecureSessionHandle session, bool Initiator,
183 ExchangeDelegate * delegate);
187 void SetResponseTimeout(Timeout timeout);
190 enum class ExFlagValues : uint16_t
192 kFlagInitiator = 0x0001, // This context is the initiator of the exchange.
193 kFlagResponseExpected = 0x0002, // If a response is expected for a message that is being sent.
196 Timeout mResponseTimeout; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
197 ReliableMessageContext mReliableMessageContext;
198 ExchangeDelegate * mDelegate = nullptr;
199 ExchangeManager * mExchangeMgr = nullptr;
200 ExchangeACL * mExchangeACL = nullptr;
202 SecureSessionHandle mSecureSession; // The connection state
203 uint16_t mExchangeId; // Assigned exchange ID.
205 // [TODO: #4711]: this field need to be moved to appState object which implement 'exchange-specific' contextual
206 // actions with a delegate pattern.
207 uint8_t mChallenge[kMsgCounterChallengeSize]; // Challenge number to identify the sychronization request cryptographically.
209 BitFlags<ExFlagValues> mFlags; // Internal state flags
212 * Search for an existing exchange that the message applies to.
214 * @param[in] session The secure session of the received message.
216 * @param[in] packetHeader A reference to the PacketHeader object.
218 * @param[in] payloadHeader A reference to the PayloadHeader object.
220 * @retval true If a match is found.
221 * @retval false If a match is not found.
223 bool MatchExchange(SecureSessionHandle session, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader);
225 CHIP_ERROR StartResponseTimer();
228 * A subset of SendMessage functionality that does not perform message
229 * counter sync for group keys.
231 CHIP_ERROR SendMessageImpl(Protocols::Id protocolId, uint8_t msgType, System::PacketBufferHandle msgBuf,
232 const SendFlags & sendFlags, Transport::PeerConnectionState * state = nullptr);
233 void CancelResponseTimer();
234 static void HandleResponseTimeout(System::Layer * aSystemLayer, void * aAppState, System::Error aError);
236 void DoClose(bool clearRetransTable);
239 inline void ExchangeContextDeletor::Release(ExchangeContext * obj)
244 } // namespace Messaging