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