Line data Source code
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 <lib/support/DLLUtil.h>
30 : #include <lib/support/Pool.h>
31 : #include <lib/support/TypeTraits.h>
32 : #include <messaging/ExchangeContext.h>
33 : #include <messaging/ReliableMessageMgr.h>
34 : #include <protocols/Protocols.h>
35 : #include <transport/SessionManager.h>
36 :
37 : namespace chip {
38 : namespace Messaging {
39 :
40 : class ExchangeContext;
41 : class ExchangeDelegate;
42 :
43 : static constexpr int16_t kAnyMessageType = -1;
44 :
45 : /**
46 : * @brief
47 : * This class is used to manage ExchangeContexts with other CHIP nodes.
48 : * It works on be behalf of higher layers, creating ExchangeContexts and
49 : * handling the registration/unregistration of unsolicited message handlers.
50 : */
51 : class DLL_EXPORT ExchangeManager : public SessionMessageDelegate
52 : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
53 : ,
54 : public SessionConnectionDelegate
55 : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
56 : {
57 : friend class ExchangeContext;
58 :
59 : public:
60 : ExchangeManager();
61 : ExchangeManager(const ExchangeManager &) = delete;
62 : ExchangeManager operator=(const ExchangeManager &) = delete;
63 :
64 : /**
65 : * Initialize the ExchangeManager object. Within the lifetime
66 : * of this instance, this method is invoked once after object
67 : * construction until a call to Shutdown is made to terminate the
68 : * instance.
69 : *
70 : * @param[in] sessionManager A pointer to the SessionManager object.
71 : *
72 : * @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to
73 : * kState_NotInitialized.
74 : * @retval #CHIP_NO_ERROR On success.
75 : *
76 : */
77 : CHIP_ERROR Init(SessionManager * sessionManager);
78 :
79 : /**
80 : * Shutdown the ExchangeManager. This terminates this instance
81 : * of the object and releases all held resources.
82 : *
83 : * Please see documentation for SessionManager::Shutdown() for ordering
84 : * dependecies between that and this Shutdown() method.
85 : *
86 : * @note
87 : * The protocol should only call this function after ensuring that
88 : * there are no active ExchangeContext objects (again, see
89 : * SessionManager::Shutdown() documentation). Furthermore, it is the
90 : * onus of the application to de-allocate the ExchangeManager
91 : * object after calling ExchangeManager::Shutdown().
92 : */
93 : void Shutdown();
94 :
95 : /**
96 : * Creates a new ExchangeContext with a given peer CHIP node specified by the peer node identifier.
97 : *
98 : * @param[in] session The identifier of the secure session (possibly
99 : * the empty session for a non-secure exchange)
100 : * for which the ExchangeContext is being set up.
101 : *
102 : * @param[in] delegate A pointer to ExchangeDelegate.
103 : * @param[in] isInitiator Set to true if the exchange is created on the initiator. This is generally true
104 : * except in unit tests.
105 : *
106 : * @return A pointer to the created ExchangeContext object On success. Otherwise NULL if no object
107 : * can be allocated or is available.
108 : */
109 : ExchangeContext * NewContext(const SessionHandle & session, ExchangeDelegate * delegate, bool isInitiator = true);
110 :
111 3429 : void ReleaseContext(ExchangeContext * ec) { mContextPool.ReleaseObject(ec); }
112 :
113 : /**
114 : * Register an unsolicited message handler for a given protocol identifier. This handler would be
115 : * invoked for all messages of the given protocol.
116 : *
117 : * @param[in] protocolId The protocol identifier of the received message.
118 : *
119 : * @param[in] handler A pointer to UnsolicitedMessageHandler.
120 : *
121 : * @retval #CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS If the unsolicited message handler pool
122 : * is full and a new one cannot be allocated.
123 : * @retval #CHIP_NO_ERROR On success.
124 : */
125 : CHIP_ERROR RegisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId, UnsolicitedMessageHandler * handler);
126 :
127 : /**
128 : * Register an unsolicited message handler for a given protocol identifier and message type.
129 : *
130 : * @param[in] protocolId The protocol identifier of the received message.
131 : *
132 : * @param[in] msgType The message type of the corresponding protocol.
133 : *
134 : * @param[in] handler A pointer to UnsolicitedMessageHandler.
135 : *
136 : * @retval #CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS If the unsolicited message handler pool
137 : * is full and a new one cannot be allocated.
138 : * @retval #CHIP_NO_ERROR On success.
139 : */
140 : CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType,
141 : UnsolicitedMessageHandler * handler);
142 :
143 : /**
144 : * A strongly-message-typed version of RegisterUnsolicitedMessageHandlerForType.
145 : */
146 : template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
147 336 : CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(MessageType msgType, UnsolicitedMessageHandler * handler)
148 : {
149 336 : return RegisterUnsolicitedMessageHandlerForType(Protocols::MessageTypeTraits<MessageType>::ProtocolId(),
150 672 : to_underlying(msgType), handler);
151 : }
152 :
153 : /**
154 : * Unregister an unsolicited message handler for a given protocol identifier.
155 : *
156 : * @param[in] protocolId The protocol identifier of the received message.
157 : *
158 : * @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER If the matching unsolicited message handler
159 : * is not found.
160 : * @retval #CHIP_NO_ERROR On success.
161 : */
162 : CHIP_ERROR UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId);
163 :
164 : /**
165 : * Unregister an unsolicited message handler for a given protocol identifier and message type.
166 : *
167 : * @param[in] protocolId The protocol identifier of the received message.
168 : *
169 : * @param[in] msgType The message type of the corresponding protocol.
170 : *
171 : * @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER If the matching unsolicited message handler
172 : * is not found.
173 : * @retval #CHIP_NO_ERROR On success.
174 : */
175 : CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType);
176 :
177 : /**
178 : * A strongly-message-typed version of UnregisterUnsolicitedMessageHandlerForType.
179 : */
180 : template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
181 342 : CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(MessageType msgType)
182 : {
183 342 : return UnregisterUnsolicitedMessageHandlerForType(Protocols::MessageTypeTraits<MessageType>::ProtocolId(),
184 684 : to_underlying(msgType));
185 : }
186 :
187 : /**
188 : * A method to call Close() on all contexts that have a given delegate as
189 : * their delegate. To be used if the delegate is being destroyed. This
190 : * method will guarantee that it does not call into the delegate.
191 : */
192 : void CloseAllContextsForDelegate(const ExchangeDelegate * delegate);
193 :
194 27355 : SessionManager * GetSessionManager() const { return mSessionManager; }
195 :
196 25642 : ReliableMessageMgr * GetReliableMessageMgr() { return &mReliableMessageMgr; };
197 :
198 : FabricIndex GetFabricIndex() const { return mFabricIndex; }
199 :
200 : uint16_t GetNextKeyId() { return ++mNextKeyId; }
201 :
202 : size_t GetNumActiveExchanges() { return mContextPool.Allocated(); }
203 :
204 : private:
205 : enum class State
206 : {
207 : kState_NotInitialized = 0, // Used to indicate that the ExchangeManager is not initialized.
208 : kState_Initialized = 1 // Used to indicate that the ExchangeManager is initialized.
209 : };
210 :
211 : struct UnsolicitedMessageHandlerSlot
212 : {
213 3152 : UnsolicitedMessageHandlerSlot() : ProtocolId(Protocols::NotSpecified) {}
214 :
215 3432 : constexpr void Reset() { Handler = nullptr; }
216 19818 : constexpr bool IsInUse() const { return Handler != nullptr; }
217 : // Matches() only returns a sensible value if IsInUse() is true.
218 1620 : constexpr bool Matches(Protocols::Id aProtocolId, int16_t aMessageType) const
219 : {
220 1620 : return ProtocolId == aProtocolId && MessageType == aMessageType;
221 : }
222 :
223 : Protocols::Id ProtocolId;
224 : // Message types are normally 8-bit unsigned ints, but we use
225 : // kAnyMessageType, which is negative, to represent a wildcard handler,
226 : // so need a type that can store both that and all valid message type
227 : // values.
228 : int16_t MessageType;
229 :
230 : UnsolicitedMessageHandler * Handler;
231 : };
232 :
233 : uint16_t mNextExchangeId;
234 : uint16_t mNextKeyId;
235 : State mState;
236 :
237 : FabricIndex mFabricIndex = 0;
238 :
239 : ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> mContextPool;
240 :
241 : SessionManager * mSessionManager;
242 : ReliableMessageMgr mReliableMessageMgr;
243 :
244 : UnsolicitedMessageHandlerSlot UMHandlerPool[CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS];
245 :
246 : CHIP_ERROR RegisterUMH(Protocols::Id protocolId, int16_t msgType, UnsolicitedMessageHandler * handler);
247 : CHIP_ERROR UnregisterUMH(Protocols::Id protocolId, int16_t msgType);
248 :
249 : void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, const SessionHandle & session,
250 : DuplicateMessage isDuplicate, System::PacketBufferHandle && msgBuf) override;
251 : void SendStandaloneAckIfNeeded(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
252 : const SessionHandle & session, MessageFlags msgFlags, System::PacketBufferHandle && msgBuf);
253 : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
254 : void OnTCPConnectionClosed(const SessionHandle & session, CHIP_ERROR conErr) override;
255 : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
256 : };
257 :
258 : } // namespace Messaging
259 : } // namespace chip
|