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 * Defines the CHIP ExchangeManager class and its supporting types
21 * for Exchange management.
29 #include <messaging/Channel.h>
30 #include <messaging/ChannelContext.h>
31 #include <messaging/ExchangeContext.h>
32 #include <messaging/MessageCounterSync.h>
33 #include <messaging/ReliableMessageMgr.h>
34 #include <protocols/Protocols.h>
35 #include <support/DLLUtil.h>
36 #include <support/Pool.h>
37 #include <transport/SecureSessionMgr.h>
38 #include <transport/TransportMgr.h>
43 class ExchangeContext;
44 class ExchangeDelegate;
46 static constexpr int16_t kAnyMessageType = -1;
50 * This class is used to manage ExchangeContexts with other CHIP nodes.
51 * It works on be behalf of higher layers, creating ExchangeContexts and
52 * handling the registration/unregistration of unsolicited message handlers.
54 class DLL_EXPORT ExchangeManager : public SecureSessionMgrDelegate, public TransportMgrDelegate
58 ExchangeManager(const ExchangeManager &) = delete;
59 ExchangeManager operator=(const ExchangeManager &) = delete;
62 * Initialize the ExchangeManager object. Within the lifetime
63 * of this instance, this method is invoked once after object
64 * construction until a call to Shutdown is made to terminate the
67 * @param[in] sessionMgr A pointer to the SecureSessionMgr object.
69 * @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to
70 * kState_NotInitialized.
71 * @retval #CHIP_NO_ERROR On success.
74 CHIP_ERROR Init(SecureSessionMgr * sessionMgr);
77 * Shutdown the ExchangeManager. This terminates this instance
78 * of the object and releases all held resources.
81 * The protocol should only call this function after ensuring that
82 * there are no active ExchangeContext objects. Furthermore, it is the
83 * onus of the application to de-allocate the ExchangeManager
84 * object after calling ExchangeManager::Shutdown().
86 * @return #CHIP_NO_ERROR unconditionally.
88 CHIP_ERROR Shutdown();
91 * Creates a new ExchangeContext with a given peer CHIP node specified by the peer node identifier.
93 * @param[in] peerNodeId The node identifier of the peer with which the ExchangeContext is being set up.
95 * @param[in] delegate A pointer to ExchangeDelegate.
97 * @return A pointer to the created ExchangeContext object On success. Otherwise NULL if no object
98 * can be allocated or is available.
100 ExchangeContext * NewContext(SecureSessionHandle session, ExchangeDelegate * delegate);
103 * Register an unsolicited message handler for a given protocol identifier. This handler would be
104 * invoked for all messages of the given protocol.
106 * @param[in] protocolId The protocol identifier of the received message.
108 * @param[in] handler The unsolicited message handler.
110 * @param[in] delegate A pointer to ExchangeDelegate.
112 * @retval #CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS If the unsolicited message handler pool
113 * is full and a new one cannot be allocated.
114 * @retval #CHIP_NO_ERROR On success.
116 CHIP_ERROR RegisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId, ExchangeDelegate * delegate);
119 * Register an unsolicited message handler for a given protocol identifier and message type.
121 * @param[in] protocolId The protocol identifier of the received message.
123 * @param[in] msgType The message type of the corresponding protocol.
125 * @param[in] delegate A pointer to ExchangeDelegate.
127 * @retval #CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS If the unsolicited message handler pool
128 * is full and a new one cannot be allocated.
129 * @retval #CHIP_NO_ERROR On success.
131 CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType, ExchangeDelegate * delegate);
134 * A strongly-message-typed version of RegisterUnsolicitedMessageHandlerForType.
136 template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
137 CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(MessageType msgType, ExchangeDelegate * delegate)
139 static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
140 return RegisterUnsolicitedMessageHandlerForType(Protocols::MessageTypeTraits<MessageType>::ProtocolId(),
141 static_cast<uint8_t>(msgType), delegate);
145 * Unregister an unsolicited message handler for a given protocol identifier.
147 * @param[in] protocolId The protocol identifier of the received message.
149 * @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER If the matching unsolicited message handler
151 * @retval #CHIP_NO_ERROR On success.
153 CHIP_ERROR UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId);
156 * Unregister an unsolicited message handler for a given protocol identifier and message type.
158 * @param[in] protocolId The protocol identifier of the received message.
160 * @param[in] msgType The message type of the corresponding protocol.
162 * @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER If the matching unsolicited message handler
164 * @retval #CHIP_NO_ERROR On success.
166 CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType);
169 * A strongly-message-typed version of UnregisterUnsolicitedMessageHandlerForType.
171 template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
172 CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(MessageType msgType)
174 static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
175 return UnregisterUnsolicitedMessageHandlerForType(Protocols::MessageTypeTraits<MessageType>::ProtocolId(),
176 static_cast<uint8_t>(msgType));
181 * Called when a cached group message that was waiting for message counter
182 * sync shold be reprocessed.
184 * @param packetHeader The message header
185 * @param payloadHeader The payload header
186 * @param session The handle to the secure session
187 * @param msgBuf The received message
189 void HandleGroupMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
190 const SecureSessionHandle & session, System::PacketBufferHandle msgBuf);
192 // Channel public APIs
193 ChannelHandle EstablishChannel(const ChannelBuilder & builder, ChannelDelegate * delegate);
195 // Internal APIs used for channel
196 void ReleaseChannelContext(ChannelContext * channel) { mChannelContexts.ReleaseObject(channel); }
198 void ReleaseChannelHandle(ChannelContextHandleAssociation * association) { mChannelHandles.ReleaseObject(association); }
200 template <typename Event>
201 void NotifyChannelEvent(ChannelContext * channel, Event event)
203 mChannelHandles.ForEachActiveObject([&](ChannelContextHandleAssociation * association) {
204 if (association->mChannelContext == channel)
205 event(association->mChannelDelegate);
210 void IncrementContextsInUse();
211 void DecrementContextsInUse();
213 SecureSessionMgr * GetSessionMgr() const { return mSessionMgr; }
215 ReliableMessageMgr * GetReliableMessageMgr() { return &mReliableMessageMgr; };
217 MessageCounterSyncMgr * GetMessageCounterSyncMgr() { return &mMessageCounterSyncMgr; };
218 Transport::AdminId GetAdminId() { return mAdminId; }
220 uint16_t GetNextKeyId() { return ++mNextKeyId; }
221 size_t GetContextsInUse() const { return mContextsInUse; }
226 kState_NotInitialized = 0, // Used to indicate that the ExchangeManager is not initialized.
227 kState_Initialized = 1 // Used to indicate that the ExchangeManager is initialized.
230 struct UnsolicitedMessageHandler
232 UnsolicitedMessageHandler() : ProtocolId(Protocols::NotSpecified) {}
234 constexpr void Reset() { Delegate = nullptr; }
235 constexpr bool IsInUse() const { return Delegate != nullptr; }
236 // Matches() only returns a sensible value if IsInUse() is true.
237 constexpr bool Matches(Protocols::Id aProtocolId, int16_t aMessageType) const
239 return ProtocolId == aProtocolId && MessageType == aMessageType;
242 ExchangeDelegate * Delegate;
243 Protocols::Id ProtocolId;
244 // Message types are normally 8-bit unsigned ints, but we use
245 // kAnyMessageType, which is negative, to represent a wildcard handler,
246 // so need a type that can store both that and all valid message type
251 uint16_t mNextExchangeId;
254 SecureSessionMgr * mSessionMgr;
255 ReliableMessageMgr mReliableMessageMgr;
256 MessageCounterSyncMgr mMessageCounterSyncMgr;
258 Transport::AdminId mAdminId = 0;
260 std::array<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> mContextPool;
261 size_t mContextsInUse;
263 UnsolicitedMessageHandler UMHandlerPool[CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS];
264 BitMapObjectPool<ChannelContext, CHIP_CONFIG_MAX_ACTIVE_CHANNELS> mChannelContexts;
265 BitMapObjectPool<ChannelContextHandleAssociation, CHIP_CONFIG_MAX_CHANNEL_HANDLES> mChannelHandles;
267 ExchangeContext * AllocContext(uint16_t ExchangeId, SecureSessionHandle session, bool Initiator, ExchangeDelegate * delegate);
269 CHIP_ERROR RegisterUMH(Protocols::Id protocolId, int16_t msgType, ExchangeDelegate * delegate);
270 CHIP_ERROR UnregisterUMH(Protocols::Id protocolId, int16_t msgType);
272 static bool IsMsgCounterSyncMessage(const PayloadHeader & payloadHeader);
274 void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * msgLayer) override;
276 void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, SecureSessionHandle session,
277 System::PacketBufferHandle msgBuf, SecureSessionMgr * msgLayer) override;
279 void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override;
280 void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override;
282 // TransportMgrDelegate interface for rendezvous sessions
283 void OnMessageReceived(const PacketHeader & header, const Transport::PeerAddress & source,
284 System::PacketBufferHandle msgBuf) override;
287 } // namespace Messaging