Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / messaging / ExchangeMgr.h
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 /**
19  *    @file
20  *      Defines the CHIP ExchangeManager class and its supporting types
21  *      for Exchange management.
22  *
23  */
24
25 #pragma once
26
27 #include <array>
28
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>
39
40 namespace chip {
41 namespace Messaging {
42
43 class ExchangeContext;
44 class ExchangeDelegate;
45
46 static constexpr int16_t kAnyMessageType = -1;
47
48 /**
49  *  @brief
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.
53  */
54 class DLL_EXPORT ExchangeManager : public SecureSessionMgrDelegate, public TransportMgrDelegate
55 {
56 public:
57     ExchangeManager();
58     ExchangeManager(const ExchangeManager &) = delete;
59     ExchangeManager operator=(const ExchangeManager &) = delete;
60
61     /**
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
65      *  instance.
66      *
67      *  @param[in]    sessionMgr    A pointer to the SecureSessionMgr object.
68      *
69      *  @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to
70      *          kState_NotInitialized.
71      *  @retval #CHIP_NO_ERROR On success.
72      *
73      */
74     CHIP_ERROR Init(SecureSessionMgr * sessionMgr);
75
76     /**
77      *  Shutdown the ExchangeManager. This terminates this instance
78      *  of the object and releases all held resources.
79      *
80      *  @note
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().
85      *
86      *  @return #CHIP_NO_ERROR unconditionally.
87      */
88     CHIP_ERROR Shutdown();
89
90     /**
91      *  Creates a new ExchangeContext with a given peer CHIP node specified by the peer node identifier.
92      *
93      *  @param[in]    peerNodeId    The node identifier of the peer with which the ExchangeContext is being set up.
94      *
95      *  @param[in]    delegate      A pointer to ExchangeDelegate.
96      *
97      *  @return   A pointer to the created ExchangeContext object On success. Otherwise NULL if no object
98      *            can be allocated or is available.
99      */
100     ExchangeContext * NewContext(SecureSessionHandle session, ExchangeDelegate * delegate);
101
102     /**
103      *  Register an unsolicited message handler for a given protocol identifier. This handler would be
104      *  invoked for all messages of the given protocol.
105      *
106      *  @param[in]    protocolId      The protocol identifier of the received message.
107      *
108      *  @param[in]    handler         The unsolicited message handler.
109      *
110      *  @param[in]    delegate        A pointer to ExchangeDelegate.
111      *
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.
115      */
116     CHIP_ERROR RegisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId, ExchangeDelegate * delegate);
117
118     /**
119      *  Register an unsolicited message handler for a given protocol identifier and message type.
120      *
121      *  @param[in]    protocolId      The protocol identifier of the received message.
122      *
123      *  @param[in]    msgType         The message type of the corresponding protocol.
124      *
125      *  @param[in]    delegate        A pointer to ExchangeDelegate.
126      *
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.
130      */
131     CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType, ExchangeDelegate * delegate);
132
133     /**
134      * A strongly-message-typed version of RegisterUnsolicitedMessageHandlerForType.
135      */
136     template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
137     CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(MessageType msgType, ExchangeDelegate * delegate)
138     {
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);
142     }
143
144     /**
145      *  Unregister an unsolicited message handler for a given protocol identifier.
146      *
147      *  @param[in]    protocolId     The protocol identifier of the received message.
148      *
149      *  @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER  If the matching unsolicited message handler
150      *                                                       is not found.
151      *  @retval #CHIP_NO_ERROR On success.
152      */
153     CHIP_ERROR UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId);
154
155     /**
156      *  Unregister an unsolicited message handler for a given protocol identifier and message type.
157      *
158      *  @param[in]    protocolId     The protocol identifier of the received message.
159      *
160      *  @param[in]    msgType       The message type of the corresponding protocol.
161      *
162      *  @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER  If the matching unsolicited message handler
163      *                                                       is not found.
164      *  @retval #CHIP_NO_ERROR On success.
165      */
166     CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType);
167
168     /**
169      * A strongly-message-typed version of UnregisterUnsolicitedMessageHandlerForType.
170      */
171     template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
172     CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(MessageType msgType)
173     {
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));
177     }
178
179     /**
180      * @brief
181      *   Called when a cached group message that was waiting for message counter
182      *   sync shold be reprocessed.
183      *
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
188      */
189     void HandleGroupMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
190                                     const SecureSessionHandle & session, System::PacketBufferHandle msgBuf);
191
192     // Channel public APIs
193     ChannelHandle EstablishChannel(const ChannelBuilder & builder, ChannelDelegate * delegate);
194
195     // Internal APIs used for channel
196     void ReleaseChannelContext(ChannelContext * channel) { mChannelContexts.ReleaseObject(channel); }
197
198     void ReleaseChannelHandle(ChannelContextHandleAssociation * association) { mChannelHandles.ReleaseObject(association); }
199
200     template <typename Event>
201     void NotifyChannelEvent(ChannelContext * channel, Event event)
202     {
203         mChannelHandles.ForEachActiveObject([&](ChannelContextHandleAssociation * association) {
204             if (association->mChannelContext == channel)
205                 event(association->mChannelDelegate);
206             return true;
207         });
208     }
209
210     void IncrementContextsInUse();
211     void DecrementContextsInUse();
212
213     SecureSessionMgr * GetSessionMgr() const { return mSessionMgr; }
214
215     ReliableMessageMgr * GetReliableMessageMgr() { return &mReliableMessageMgr; };
216
217     MessageCounterSyncMgr * GetMessageCounterSyncMgr() { return &mMessageCounterSyncMgr; };
218     Transport::AdminId GetAdminId() { return mAdminId; }
219
220     uint16_t GetNextKeyId() { return ++mNextKeyId; }
221     size_t GetContextsInUse() const { return mContextsInUse; }
222
223 private:
224     enum class State
225     {
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.
228     };
229
230     struct UnsolicitedMessageHandler
231     {
232         UnsolicitedMessageHandler() : ProtocolId(Protocols::NotSpecified) {}
233
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
238         {
239             return ProtocolId == aProtocolId && MessageType == aMessageType;
240         }
241
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
247         // values.
248         int16_t MessageType;
249     };
250
251     uint16_t mNextExchangeId;
252     uint16_t mNextKeyId;
253     State mState;
254     SecureSessionMgr * mSessionMgr;
255     ReliableMessageMgr mReliableMessageMgr;
256     MessageCounterSyncMgr mMessageCounterSyncMgr;
257
258     Transport::AdminId mAdminId = 0;
259
260     std::array<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> mContextPool;
261     size_t mContextsInUse;
262
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;
266
267     ExchangeContext * AllocContext(uint16_t ExchangeId, SecureSessionHandle session, bool Initiator, ExchangeDelegate * delegate);
268
269     CHIP_ERROR RegisterUMH(Protocols::Id protocolId, int16_t msgType, ExchangeDelegate * delegate);
270     CHIP_ERROR UnregisterUMH(Protocols::Id protocolId, int16_t msgType);
271
272     static bool IsMsgCounterSyncMessage(const PayloadHeader & payloadHeader);
273
274     void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * msgLayer) override;
275
276     void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, SecureSessionHandle session,
277                            System::PacketBufferHandle msgBuf, SecureSessionMgr * msgLayer) override;
278
279     void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override;
280     void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override;
281
282     // TransportMgrDelegate interface for rendezvous sessions
283     void OnMessageReceived(const PacketHeader & header, const Transport::PeerAddress & source,
284                            System::PacketBufferHandle msgBuf) override;
285 };
286
287 } // namespace Messaging
288 } // namespace chip