3 * Copyright (c) 2020 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 <support/BitFlags.h>
32 #include <support/DLLUtil.h>
33 #include <system/SystemTimer.h>
34 #include <transport/SecureSessionMgr.h>
38 constexpr uint16_t kMsgCounterChallengeSize = 8; // The size of the message counter synchronization request message.
42 class ExchangeManager;
43 class ExchangeContext;
45 class ExchangeContextDeletor
48 static void Release(ExchangeContext * obj);
53 * This class represents an ongoing conversation (ExchangeContext) between two or more nodes.
54 * It defines methods for encoding and communicating CHIP messages within an ExchangeContext
55 * over various transport mechanisms, for example, TCP, UDP, or CHIP Reliable Messaging.
57 class DLL_EXPORT ExchangeContext : public ReferenceCounted<ExchangeContext, ExchangeContextDeletor, 0>
59 friend class ExchangeManager;
60 friend class ExchangeContextDeletor;
61 friend class MessageCounterSyncMgr;
64 typedef uint32_t Timeout; // Type used to express the timeout in this ExchangeContext, in milliseconds
67 * Determine whether the context is the initiator of the exchange.
69 * @return Returns 'true' if it is the initiator, else 'false'.
71 bool IsInitiator() const;
74 * Determine whether a response is expected for messages sent over
77 * @return Returns 'true' if response expected, else 'false'.
79 bool IsResponseExpected() const;
82 * Set whether a response is expected on this exchange.
84 * @param[in] inResponseExpected A Boolean indicating whether (true) or not
85 * (false) a response is expected on this
88 void SetResponseExpected(bool inResponseExpected);
91 * Send a CHIP message on this exchange.
93 * @param[in] protocolId The protocol identifier of the CHIP message to be sent.
95 * @param[in] msgType The message type of the corresponding protocol.
97 * @param[in] msgPayload A handle to the packet buffer holding the CHIP message.
99 * @param[in] sendFlags Flags set by the application for the CHIP message being sent.
101 * @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this SendMessage API.
102 * @retval #CHIP_ERROR_WRONG_MSG_VERSION_FOR_EXCHANGE if there is a mismatch in the specific send operation and the
103 * CHIP message protocol version that is supported.
104 * @retval #CHIP_ERROR_NOT_CONNECTED if the context was associated with a connection that is now
106 * @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
107 * @retval #CHIP_NO_ERROR if the CHIP layer successfully sent the message down to the
110 CHIP_ERROR SendMessage(uint16_t protocolId, uint8_t msgType, System::PacketBufferHandle msgPayload,
111 const SendFlags & sendFlags);
114 * A strongly-message-typed version of SendMessage.
116 template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
117 CHIP_ERROR SendMessage(MessageType msgType, System::PacketBufferHandle && msgPayload, const SendFlags & sendFlags)
119 static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
120 return SendMessage(Protocols::MessageTypeTraits<MessageType>::ProtocolId, static_cast<uint8_t>(msgType),
121 std::move(msgPayload), sendFlags);
125 * Handle a received CHIP message on this exchange.
127 * @param[in] packetHeader A reference to the PacketHeader object.
129 * @param[in] payloadHeader A reference to the PayloadHeader object.
131 * @param[in] msgBuf A handle to the packet buffer holding the CHIP message.
133 * @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this HandleMessage API.
134 * @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
135 * @retval #CHIP_NO_ERROR if the CHIP layer successfully delivered the message up to the
138 CHIP_ERROR HandleMessage(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
139 System::PacketBufferHandle msgBuf);
141 ExchangeDelegate * GetDelegate() const { return mDelegate; }
142 void SetDelegate(ExchangeDelegate * delegate) { mDelegate = delegate; }
143 void SetReliableMessageDelegate(ReliableMessageDelegate * delegate) { mReliableMessageContext.SetDelegate(delegate); }
145 ExchangeManager * GetExchangeMgr() const { return mExchangeMgr; }
147 ReliableMessageContext * GetReliableMessageContext() { return &mReliableMessageContext; };
149 ExchangeACL * GetExchangeACL(Transport::AdminPairingTable & table)
151 if (mExchangeACL == nullptr)
153 Transport::AdminPairingInfo * admin = table.FindAdmin(mSecureSession.GetAdminId());
154 if (admin != nullptr)
156 mExchangeACL = chip::Platform::New<CASEExchangeACL>(admin);
163 SecureSessionHandle GetSecureSession() { return mSecureSession; }
165 uint16_t GetExchangeId() const { return mExchangeId; }
167 void SetChallenge(const uint8_t * value) { memcpy(&mChallenge[0], value, kMsgCounterChallengeSize); }
169 const uint8_t * GetChallenge() const { return mChallenge; }
171 SecureSessionHandle GetSecureSessionHandle() const { return mSecureSession; }
174 * In order to use reference counting (see refCount below) we use a hold/free paradigm where users of the exchange
175 * can hold onto it while it's out of their direct control to make sure it isn't closed before everyone's ready.
176 * A customized version of reference counting is used since there are some extra stuff to do within Release.
181 ExchangeContext * Alloc(ExchangeManager * em, uint16_t ExchangeId, SecureSessionHandle session, bool Initiator,
182 ExchangeDelegate * delegate);
186 void SetResponseTimeout(Timeout timeout);
189 enum class ExFlagValues : uint16_t
191 kFlagInitiator = 0x0001, // This context is the initiator of the exchange.
192 kFlagResponseExpected = 0x0002, // If a response is expected for a message that is being sent.
195 Timeout mResponseTimeout; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
196 ReliableMessageContext mReliableMessageContext;
197 ExchangeDelegate * mDelegate = nullptr;
198 ExchangeManager * mExchangeMgr = nullptr;
199 ExchangeACL * mExchangeACL = nullptr;
201 SecureSessionHandle mSecureSession; // The connection state
202 uint16_t mExchangeId; // Assigned exchange ID.
204 // [TODO: #4711]: this field need to be moved to appState object which implement 'exchange-specific' contextual
205 // actions with a delegate pattern.
206 uint8_t mChallenge[kMsgCounterChallengeSize]; // Challenge number to identify the sychronization request cryptographically.
208 BitFlags<uint16_t, ExFlagValues> mFlags; // Internal state flags
211 * Search for an existing exchange that the message applies to.
213 * @param[in] session The secure session of the received message.
215 * @param[in] packetHeader A reference to the PacketHeader object.
217 * @param[in] payloadHeader A reference to the PayloadHeader object.
219 * @retval true If a match is found.
220 * @retval false If a match is not found.
222 bool MatchExchange(SecureSessionHandle session, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader);
224 CHIP_ERROR StartResponseTimer();
227 * A subset of SendMessage functionality that does not perform message
228 * counter sync for group keys.
230 CHIP_ERROR SendMessageImpl(uint16_t protocolId, uint8_t msgType, System::PacketBufferHandle msgBuf, const SendFlags & sendFlags,
231 Transport::PeerConnectionState * state = nullptr);
232 void CancelResponseTimer();
233 static void HandleResponseTimeout(System::Layer * aSystemLayer, void * aAppState, System::Error aError);
235 void DoClose(bool clearRetransTable);
238 inline void ExchangeContextDeletor::Release(ExchangeContext * obj)
243 } // namespace Messaging