Matter SDK Coverage Report
Current view: top level - messaging - ExchangeMgr.h (source / functions) Coverage Total Hit
Test: SHA:6c8f029dd2432dc900f1c9245c324e69bd79e40a Lines: 100.0 % 15 15
Test Date: 2026-08-08 07:40:09 Functions: 85.7 % 14 12

            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              : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
      43              : class TestOnlyReceivedMessageObserver;
      44              : #endif
      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 SessionMessageDelegate
      55              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
      56              :     ,
      57              :                                    public SessionConnectionDelegate
      58              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
      59              : {
      60              :     friend class ExchangeContext;
      61              : 
      62              : public:
      63              :     ExchangeManager();
      64              :     ExchangeManager(const ExchangeManager &)           = delete;
      65              :     ExchangeManager operator=(const ExchangeManager &) = delete;
      66              : 
      67              :     /**
      68              :      *  Initialize the ExchangeManager object. Within the lifetime
      69              :      *  of this instance, this method is invoked once after object
      70              :      *  construction until a call to Shutdown is made to terminate the
      71              :      *  instance.
      72              :      *
      73              :      *  @param[in]    sessionManager    A pointer to the SessionManager object.
      74              :      *
      75              :      *  @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to
      76              :      *          kState_NotInitialized.
      77              :      *  @retval #CHIP_NO_ERROR On success.
      78              :      *
      79              :      */
      80              :     CHIP_ERROR Init(SessionManager * sessionManager);
      81              : 
      82              :     /**
      83              :      *  Shutdown the ExchangeManager. This terminates this instance
      84              :      *  of the object and releases all held resources.
      85              :      *
      86              :      * Please see documentation for SessionManager::Shutdown() for ordering
      87              :      * dependecies between that and this Shutdown() method.
      88              :      *
      89              :      *  @note
      90              :      *     The protocol should only call this function after ensuring that
      91              :      *     there are no active ExchangeContext objects (again, see
      92              :      *     SessionManager::Shutdown() documentation). Furthermore, it is the
      93              :      *     onus of the application to de-allocate the ExchangeManager
      94              :      *     object after calling ExchangeManager::Shutdown().
      95              :      */
      96              :     void Shutdown();
      97              : 
      98              :     /**
      99              :      *  Creates a new ExchangeContext with a given peer CHIP node specified by the peer node identifier.
     100              :      *
     101              :      *  @param[in]    session       The identifier of the secure session (possibly
     102              :      *                              the empty session for a non-secure exchange)
     103              :      *                              for which the ExchangeContext is being set up.
     104              :      *
     105              :      *  @param[in]    delegate      A pointer to ExchangeDelegate.
     106              :      *  @param[in]    isInitiator   Set to true if the exchange is created on the initiator. This is generally true
     107              :      *                              except in unit tests.
     108              :      *
     109              :      *  @return   A pointer to the created ExchangeContext object On success. Otherwise NULL if no object
     110              :      *            can be allocated or is available.
     111              :      */
     112              :     ExchangeContext * NewContext(const SessionHandle & session, ExchangeDelegate * delegate, bool isInitiator = true);
     113              : 
     114         4788 :     void ReleaseContext(ExchangeContext * ec) { mContextPool.ReleaseObject(ec); }
     115              : 
     116              :     /**
     117              :      *  Register an unsolicited message handler for a given protocol identifier. This handler would be
     118              :      *  invoked for all messages of the given protocol.
     119              :      *
     120              :      *  @param[in]    protocolId      The protocol identifier of the received message.
     121              :      *
     122              :      *  @param[in]    handler         A pointer to UnsolicitedMessageHandler.
     123              :      *
     124              :      *  @retval #CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS If the unsolicited message handler pool
     125              :      *                                                             is full and a new one cannot be allocated.
     126              :      *  @retval #CHIP_NO_ERROR On success.
     127              :      */
     128              :     CHIP_ERROR RegisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId, UnsolicitedMessageHandler * handler);
     129              : 
     130              :     /**
     131              :      *  Register an unsolicited message handler for a given protocol identifier and message type.
     132              :      *
     133              :      *  @param[in]    protocolId      The protocol identifier of the received message.
     134              :      *
     135              :      *  @param[in]    msgType         The message type of the corresponding protocol.
     136              :      *
     137              :      *  @param[in]    handler         A pointer to UnsolicitedMessageHandler.
     138              :      *
     139              :      *  @retval #CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS If the unsolicited message handler pool
     140              :      *                                                             is full and a new one cannot be allocated.
     141              :      *  @retval #CHIP_NO_ERROR On success.
     142              :      */
     143              :     CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType,
     144              :                                                         UnsolicitedMessageHandler * handler);
     145              : 
     146              :     /**
     147              :      * A strongly-message-typed version of RegisterUnsolicitedMessageHandlerForType.
     148              :      */
     149              :     template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
     150          508 :     CHIP_ERROR RegisterUnsolicitedMessageHandlerForType(MessageType msgType, UnsolicitedMessageHandler * handler)
     151              :     {
     152          508 :         return RegisterUnsolicitedMessageHandlerForType(Protocols::MessageTypeTraits<MessageType>::ProtocolId(),
     153         1016 :                                                         to_underlying(msgType), handler);
     154              :     }
     155              : 
     156              :     /**
     157              :      *  Unregister an unsolicited message handler for a given protocol identifier.
     158              :      *
     159              :      *  @param[in]    protocolId     The protocol identifier of the received message.
     160              :      *
     161              :      *  @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER  If the matching unsolicited message handler
     162              :      *                                                       is not found.
     163              :      *  @retval #CHIP_NO_ERROR On success.
     164              :      */
     165              :     CHIP_ERROR UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId);
     166              : 
     167              :     /**
     168              :      *  Unregister an unsolicited message handler for a given protocol identifier and message type.
     169              :      *
     170              :      *  @param[in]    protocolId     The protocol identifier of the received message.
     171              :      *
     172              :      *  @param[in]    msgType       The message type of the corresponding protocol.
     173              :      *
     174              :      *  @param[out]   outHandler   If non-null, receives the handler that was unregistered. If no
     175              :      *                             handler matched, *outHandler is set to nullptr. Callers may pass
     176              :      *                             nullptr if they do not need this information.
     177              :      *
     178              :      *  @retval #CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER  If the matching unsolicited message handler
     179              :      *                                                       is not found.
     180              :      *  @retval #CHIP_NO_ERROR On success.
     181              :      */
     182              :     CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType,
     183              :                                                           Messaging::UnsolicitedMessageHandler ** outHandler = nullptr);
     184              : 
     185              :     /**
     186              :      * A strongly-message-typed version of UnregisterUnsolicitedMessageHandlerForType.
     187              :      */
     188              :     template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
     189          492 :     CHIP_ERROR UnregisterUnsolicitedMessageHandlerForType(MessageType msgType,
     190              :                                                           Messaging::UnsolicitedMessageHandler ** outHandler = nullptr)
     191              :     {
     192          492 :         return UnregisterUnsolicitedMessageHandlerForType(Protocols::MessageTypeTraits<MessageType>::ProtocolId(),
     193          984 :                                                           to_underlying(msgType), outHandler);
     194              :     }
     195              : 
     196              :     /**
     197              :      * A method to call Close() on all contexts that have a given delegate as
     198              :      * their delegate.  To be used if the delegate is being destroyed.  This
     199              :      * method will guarantee that it does not call into the delegate.
     200              :      */
     201              :     void CloseAllContextsForDelegate(const ExchangeDelegate * delegate);
     202              : 
     203        40254 :     SessionManager * GetSessionManager() const { return mSessionManager; }
     204              : 
     205        53627 :     ReliableMessageMgr * GetReliableMessageMgr() { return &mReliableMessageMgr; };
     206              : 
     207              :     FabricIndex GetFabricIndex() const { return mFabricIndex; }
     208              : 
     209              :     uint16_t GetNextKeyId() { return ++mNextKeyId; }
     210              : 
     211     27560680 :     size_t GetNumActiveExchanges() { return mContextPool.Allocated(); }
     212              : 
     213              : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
     214              :     void SetTestOnlyReceivedMessageObserver(TestOnlyReceivedMessageObserver * observer) { mTestOnlyReceivedObserver = observer; }
     215              :     TestOnlyReceivedMessageObserver * GetTestOnlyReceivedMessageObserver() const { return mTestOnlyReceivedObserver; }
     216              : #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
     217              : 
     218              : private:
     219              :     enum class State
     220              :     {
     221              :         kState_NotInitialized = 0, // Used to indicate that the ExchangeManager is not initialized.
     222              :         kState_Initialized    = 1  // Used to indicate that the ExchangeManager is initialized.
     223              :     };
     224              : 
     225              :     struct UnsolicitedMessageHandlerSlot
     226              :     {
     227         5336 :         UnsolicitedMessageHandlerSlot() : ProtocolId(Protocols::NotSpecified) {}
     228              : 
     229         4537 :         constexpr void Reset() { Handler = nullptr; }
     230        27236 :         constexpr bool IsInUse() const { return Handler != nullptr; }
     231              :         // Matches() only returns a sensible value if IsInUse() is true.
     232         2107 :         constexpr bool Matches(Protocols::Id aProtocolId, int16_t aMessageType) const
     233              :         {
     234         2107 :             return ProtocolId == aProtocolId && MessageType == aMessageType;
     235              :         }
     236              : 
     237              :         Protocols::Id ProtocolId;
     238              :         // Message types are normally 8-bit unsigned ints, but we use
     239              :         // kAnyMessageType, which is negative, to represent a wildcard handler,
     240              :         // so need a type that can store both that and all valid message type
     241              :         // values.
     242              :         int16_t MessageType;
     243              : 
     244              :         UnsolicitedMessageHandler * Handler;
     245              :     };
     246              : 
     247              :     uint16_t mNextExchangeId;
     248              :     uint16_t mNextKeyId;
     249              :     State mState;
     250              : 
     251              :     FabricIndex mFabricIndex = 0;
     252              : 
     253              :     ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> mContextPool;
     254              : 
     255              :     SessionManager * mSessionManager;
     256              :     ReliableMessageMgr mReliableMessageMgr;
     257              : 
     258              : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
     259              :     TestOnlyReceivedMessageObserver * mTestOnlyReceivedObserver = nullptr;
     260              : #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
     261              : 
     262              :     UnsolicitedMessageHandlerSlot UMHandlerPool[CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS];
     263              : 
     264              :     CHIP_ERROR RegisterUMH(Protocols::Id protocolId, int16_t msgType, UnsolicitedMessageHandler * handler);
     265              :     CHIP_ERROR UnregisterUMH(Protocols::Id protocolId, int16_t msgType,
     266              :                              Messaging::UnsolicitedMessageHandler ** outHandler = nullptr);
     267              : 
     268              :     void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, const SessionHandle & session,
     269              :                            DuplicateMessage isDuplicate, System::PacketBufferHandle && msgBuf) override;
     270              :     void SendStandaloneAckIfNeeded(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
     271              :                                    const SessionHandle & session, MessageFlags msgFlags, System::PacketBufferHandle && msgBuf);
     272              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     273              :     void OnTCPConnectionClosed(const Transport::ActiveTCPConnectionState & conn, const SessionHandle & session,
     274              :                                CHIP_ERROR conErr) override;
     275              :     bool OnTCPConnectionAttemptComplete(Transport::ActiveTCPConnectionHandle & conn, CHIP_ERROR conErr) override;
     276              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     277              : };
     278              : 
     279              : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
     280              : /**
     281              :  * Test-only observer invoked for every inbound message on the ExchangeManager, just before dispatch.
     282              :  * Subclass and register an instance via ExchangeManager::SetTestOnlyReceivedMessageObserver to inspect inbound headers and message
     283              :  * bytes (e.g. to assert on Message/Exchange flags in Python integration tests).
     284              :  *
     285              :  * Lifetime: the ExchangeManager only holds a raw pointer to the observer and does not own it. The observer must outlive its
     286              :  * registration. The pointer is cleared on Init() and Shutdown(), so it does not survive a Shutdown()/re-Init() cycle; for any
     287              :  * other teardown the caller is responsible for unregistering (passing nullptr) before the observer is destroyed.
     288              :  *
     289              :  * OnMessageReceived must not consume or retain msgBuf beyond the call; call msgBuf.Retain() if a handle needs to outlive it.
     290              :  */
     291              : class TestOnlyReceivedMessageObserver
     292              : {
     293              : public:
     294              :     virtual ~TestOnlyReceivedMessageObserver() = default;
     295              : 
     296              :     virtual void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
     297              :                                    const System::PacketBufferHandle & msgBuf) = 0;
     298              : };
     299              : #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
     300              : 
     301              : } // namespace Messaging
     302              : } // namespace chip
        

Generated by: LCOV version 2.0-1