Matter SDK Coverage Report
Current view: top level - messaging - ExchangeMgr.cpp (source / functions) Coverage Total Hit
Test: SHA:2a48c1efeab1c0f76f3adb3a0940b0f7de706453 Lines: 83.1 % 177 147
Test Date: 2026-01-31 08:14:20 Functions: 78.9 % 19 15

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 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              :  *      This file implements the ExchangeManager class.
      21              :  *
      22              :  */
      23              : 
      24              : #include <cstring>
      25              : #include <inttypes.h>
      26              : #include <stddef.h>
      27              : 
      28              : #include <crypto/RandUtils.h>
      29              : #include <lib/core/CHIPCore.h>
      30              : #include <lib/core/CHIPEncoding.h>
      31              : #include <lib/support/CHIPFaultInjection.h>
      32              : #include <lib/support/CodeUtils.h>
      33              : #include <lib/support/logging/CHIPLogging.h>
      34              : #include <messaging/ExchangeContext.h>
      35              : #include <messaging/ExchangeMgr.h>
      36              : #include <protocols/Protocols.h>
      37              : 
      38              : using namespace chip::Encoding;
      39              : using namespace chip::Inet;
      40              : using namespace chip::System;
      41              : 
      42              : namespace chip {
      43              : namespace Messaging {
      44              : 
      45              : /**
      46              :  *  Constructor for the ExchangeManager class.
      47              :  *  It sets the state to kState_NotInitialized.
      48              :  *
      49              :  *  @note
      50              :  *    The class must be initialized via ExchangeManager::Init()
      51              :  *    prior to use.
      52              :  *
      53              :  */
      54         5031 : ExchangeManager::ExchangeManager() : mReliableMessageMgr(mContextPool)
      55              : {
      56          559 :     mState = State::kState_NotInitialized;
      57          559 : }
      58              : 
      59          427 : CHIP_ERROR ExchangeManager::Init(SessionManager * sessionManager)
      60              : {
      61          427 :     CHIP_ERROR err = CHIP_NO_ERROR;
      62              : 
      63          427 :     VerifyOrReturnError(mState == State::kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE);
      64              : 
      65          427 :     mSessionManager = sessionManager;
      66              : 
      67          427 :     mNextExchangeId = chip::Crypto::GetRandU16();
      68          427 :     mNextKeyId      = 0;
      69              : 
      70         3843 :     for (auto & handler : UMHandlerPool)
      71              :     {
      72              :         // Mark all handlers as unallocated.  This handles both initial
      73              :         // initialization and the case when the consumer shuts us down and
      74              :         // then re-initializes without removing registered handlers.
      75         3416 :         handler.Reset();
      76              :     }
      77              : 
      78          427 :     sessionManager->SetMessageDelegate(this);
      79              : 
      80              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
      81          427 :     sessionManager->SetConnectionDelegate(this);
      82              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
      83          427 :     mReliableMessageMgr.Init(sessionManager->SystemLayer());
      84              : 
      85          427 :     mState = State::kState_Initialized;
      86              : 
      87          427 :     return err;
      88              : }
      89              : 
      90          427 : void ExchangeManager::Shutdown()
      91              : {
      92          427 :     VerifyOrReturn(mState != State::kState_NotInitialized);
      93              : 
      94          427 :     mReliableMessageMgr.Shutdown();
      95              : 
      96          427 :     if (mSessionManager != nullptr)
      97              :     {
      98          427 :         mSessionManager->SetMessageDelegate(nullptr);
      99          427 :         mSessionManager = nullptr;
     100              :     }
     101              : 
     102          427 :     mState = State::kState_NotInitialized;
     103              : }
     104              : 
     105         2396 : ExchangeContext * ExchangeManager::NewContext(const SessionHandle & session, ExchangeDelegate * delegate, bool isInitiator)
     106              : {
     107         2396 :     if (!session->IsActiveSession())
     108              :     {
     109              : #if CHIP_ERROR_LOGGING
     110            6 :         const ScopedNodeId & peer = session->GetPeer();
     111            6 :         ChipLogError(ExchangeManager, "NewContext failed: session %u to " ChipLogFormatScopedNodeId " is inactive",
     112              :                      session->SessionIdForLogging(), ChipLogValueScopedNodeId(peer));
     113              : #endif // CHIP_ERROR_LOGGING
     114              : 
     115              :         // Disallow creating exchange on an inactive session
     116            6 :         return nullptr;
     117              :     }
     118         2390 :     return mContextPool.CreateObject(this, mNextExchangeId++, session, isInitiator, delegate);
     119              : }
     120              : 
     121          489 : CHIP_ERROR ExchangeManager::RegisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId,
     122              :                                                                          UnsolicitedMessageHandler * handler)
     123              : {
     124          489 :     return RegisterUMH(protocolId, kAnyMessageType, handler);
     125              : }
     126              : 
     127          480 : CHIP_ERROR ExchangeManager::RegisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType,
     128              :                                                                      UnsolicitedMessageHandler * handler)
     129              : {
     130          480 :     return RegisterUMH(protocolId, static_cast<int16_t>(msgType), handler);
     131              : }
     132              : 
     133          362 : CHIP_ERROR ExchangeManager::UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId)
     134              : {
     135          362 :     return UnregisterUMH(protocolId, kAnyMessageType);
     136              : }
     137              : 
     138          466 : CHIP_ERROR ExchangeManager::UnregisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType,
     139              :                                                                        Messaging::UnsolicitedMessageHandler ** outHandler)
     140              : {
     141          466 :     return UnregisterUMH(protocolId, static_cast<int16_t>(msgType), outHandler);
     142              : }
     143              : 
     144          969 : CHIP_ERROR ExchangeManager::RegisterUMH(Protocols::Id protocolId, int16_t msgType, UnsolicitedMessageHandler * handler)
     145              : {
     146          969 :     UnsolicitedMessageHandlerSlot * selected = nullptr;
     147              : 
     148         7806 :     for (auto & umh : UMHandlerPool)
     149              :     {
     150         6968 :         if (!umh.IsInUse())
     151              :         {
     152         6270 :             if (selected == nullptr)
     153          838 :                 selected = &umh;
     154              :         }
     155          698 :         else if (umh.Matches(protocolId, msgType))
     156              :         {
     157          131 :             umh.Handler = handler;
     158          131 :             return CHIP_NO_ERROR;
     159              :         }
     160              :     }
     161              : 
     162          838 :     if (selected == nullptr)
     163            0 :         return CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS;
     164              : 
     165          838 :     selected->Handler     = handler;
     166          838 :     selected->ProtocolId  = protocolId;
     167          838 :     selected->MessageType = msgType;
     168              : 
     169          838 :     SYSTEM_STATS_INCREMENT(chip::System::Stats::kExchangeMgr_NumUMHandlers);
     170              : 
     171          838 :     return CHIP_NO_ERROR;
     172              : }
     173              : 
     174          828 : CHIP_ERROR ExchangeManager::UnregisterUMH(Protocols::Id protocolId, int16_t msgType,
     175              :                                           Messaging::UnsolicitedMessageHandler ** outHandler)
     176              : {
     177         1305 :     for (auto & umh : UMHandlerPool)
     178              :     {
     179         1296 :         if (umh.IsInUse() && umh.Matches(protocolId, msgType))
     180              :         {
     181              :             // Store the handler before unregistering.
     182          819 :             if (outHandler != nullptr)
     183              :             {
     184           16 :                 *outHandler = umh.Handler;
     185              :             }
     186          819 :             umh.Reset();
     187          819 :             SYSTEM_STATS_DECREMENT(chip::System::Stats::kExchangeMgr_NumUMHandlers);
     188          819 :             return CHIP_NO_ERROR;
     189              :         }
     190              :     }
     191              : 
     192            9 :     if (outHandler != nullptr)
     193              :     {
     194            1 :         *outHandler = nullptr;
     195              :     }
     196              : 
     197            9 :     return CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER;
     198              : }
     199              : 
     200        14995 : void ExchangeManager::OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
     201              :                                         const SessionHandle & session, DuplicateMessage isDuplicate,
     202              :                                         System::PacketBufferHandle && msgBuf)
     203              : {
     204        14995 :     UnsolicitedMessageHandlerSlot * matchingUMH = nullptr;
     205              : 
     206              : #if CHIP_PROGRESS_LOGGING
     207        14995 :     auto * protocolName = Protocols::GetProtocolName(payloadHeader.GetProtocolID());
     208        14995 :     auto * msgTypeName  = Protocols::GetMessageTypeName(payloadHeader.GetProtocolID(), payloadHeader.GetMessageType());
     209              : 
     210        14995 :     auto destination = kUndefinedNodeId;
     211        14995 :     if (packetHeader.GetDestinationNodeId().HasValue())
     212              :     {
     213           51 :         destination = packetHeader.GetDestinationNodeId().Value();
     214              :     }
     215        14944 :     else if (session->IsSecureSession())
     216              :     {
     217        14874 :         destination = session->AsSecureSession()->GetLocalNodeId();
     218              :     }
     219              : 
     220              :     //
     221              :     // 32-bit value maximum = 10 chars + text preamble (6) + trailer (1) + null (1) + 2 buffer = 20
     222              :     //
     223              :     char ackBuf[20];
     224        14995 :     ackBuf[0] = '\0';
     225        14995 :     if (payloadHeader.GetAckMessageCounter().HasValue())
     226              :     {
     227        12638 :         snprintf(ackBuf, sizeof(ackBuf), " (Ack:" ChipLogFormatMessageCounter ")", payloadHeader.GetAckMessageCounter().Value());
     228              :     }
     229              : 
     230        14995 :     CompressedFabricId compressedFabricId = 0;
     231        14995 :     if (session->IsSecureSession() && mSessionManager->GetFabricTable() != nullptr)
     232              :     {
     233        14874 :         auto fabricInfo = mSessionManager->GetFabricTable()->FindFabricWithIndex(session->AsSecureSession()->GetFabricIndex());
     234        14874 :         if (fabricInfo)
     235              :         {
     236        14827 :             compressedFabricId = fabricInfo->GetCompressedFabricId();
     237              :         }
     238              :     }
     239              : 
     240              :     // Work around pigweed not allowing more than 14 format args in a log
     241              :     // message when using tokenized logs.
     242              :     char typeStr[4 + 1 + 2 + 1];
     243        14995 :     snprintf(typeStr, sizeof(typeStr), "%04X:%02X", payloadHeader.GetProtocolID().GetProtocolId(), payloadHeader.GetMessageType());
     244              : 
     245              :     // More work around pigweed not allowing more than 14 format args in a log
     246              :     // message when using tokenized logs.
     247              :     // text(5) + fabricIndex (uint16_t, at most 5 chars) + text (1) + source (16) + text (2) + compressed fabric id (4) + text (5) +
     248              :     // destination + null-terminator
     249              :     char sourceDestinationStr[5 + 5 + 1 + 16 + 2 + 4 + 5 + 16 + 1];
     250        59980 :     snprintf(sourceDestinationStr, sizeof(sourceDestinationStr), "from %u:" ChipLogFormatX64 " [%04X] to " ChipLogFormatX64,
     251        14995 :              session->GetFabricIndex(), ChipLogValueX64(session->GetPeer().GetNodeId()), static_cast<uint16_t>(compressedFabricId),
     252        14995 :              ChipLogValueX64(destination));
     253              : 
     254              :     //
     255              :     // Legend that can be used to decode this log line can be found in README.md
     256              :     //
     257        14995 :     ChipLogProgress(
     258              :         ExchangeManager,
     259              :         ">>> [E:" ChipLogFormatExchangeId " S:%u M:" ChipLogFormatMessageCounter "%s] (%s) Msg RX %s --- Type %s (%s:%s) (B:%u)",
     260              :         ChipLogValueExchangeIdFromReceivedHeader(payloadHeader), session->SessionIdForLogging(), packetHeader.GetMessageCounter(),
     261              :         ackBuf, Transport::GetSessionTypeString(session), sourceDestinationStr, typeStr, protocolName, msgTypeName,
     262              :         static_cast<unsigned>(msgBuf->TotalLength() + packetHeader.EncodeSizeBytes() + packetHeader.MICTagLength() +
     263              :                               payloadHeader.EncodeSizeBytes()));
     264              : #endif
     265              : 
     266        14995 :     MessageFlags msgFlags;
     267        14995 :     if (isDuplicate == DuplicateMessage::Yes)
     268              :     {
     269            5 :         msgFlags.Set(MessageFlagValues::kDuplicateMessage);
     270              :     }
     271              : 
     272              :     // Skip retrieval of exchange for group message since no exchange is stored
     273              :     // for group msg (optimization)
     274        14995 :     if (!packetHeader.IsGroupSession())
     275              :     {
     276              :         // Search for an existing exchange that the message applies to. If a match is found...
     277        14995 :         bool found = false;
     278        14995 :         mContextPool.ForEachActiveObject([&](auto * ec) {
     279        52438 :             if (ec->MatchExchange(session, packetHeader, payloadHeader))
     280              :             {
     281        12611 :                 ChipLogDetail(ExchangeManager, "Found matching exchange: " ChipLogFormatExchange ", Delegate: %p",
     282              :                               ChipLogValueExchange(ec), ec->GetDelegate());
     283              : 
     284              :                 // Matched ExchangeContext; send to message handler.
     285        12611 :                 TEMPORARY_RETURN_IGNORED ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, msgFlags,
     286        12611 :                                                            std::move(msgBuf));
     287        12611 :                 found = true;
     288        12611 :                 return Loop::Break;
     289              :             }
     290        39827 :             return Loop::Continue;
     291              :         });
     292              : 
     293        14995 :         if (found)
     294              :         {
     295        12611 :             return;
     296              :         }
     297              :     }
     298              :     else
     299              :     {
     300            0 :         if (packetHeader.GetDestinationGroupId().HasValue())
     301              :         {
     302            0 :             ChipLogProgress(ExchangeManager, "Received Groupcast Message with GroupId 0x%04X (%d)",
     303              :                             packetHeader.GetDestinationGroupId().Value(), packetHeader.GetDestinationGroupId().Value());
     304              :         }
     305              :         else
     306              :         {
     307            0 :             ChipLogProgress(ExchangeManager, "Received Groupcast Message without GroupId");
     308              :         }
     309              :     }
     310              : 
     311              :     // Do not handle messages that don't match an existing exchange on an
     312              :     // inactive session, since we should not be creating new exchanges there.
     313         2384 :     if (!session->IsActiveSession())
     314              :     {
     315            0 :         ChipLogProgress(ExchangeManager, "Dropping message on inactive session that does not match an existing exchange");
     316            0 :         return;
     317              :     }
     318              : 
     319              :     // If it's not a duplicate message, search for an unsolicited message handler if it is marked as being sent by an initiator.
     320              :     // Since we didn't find an existing exchange that matches the message, it must be an unsolicited message. However all
     321              :     // unsolicited messages must be marked as being from an initiator.
     322         2384 :     if (!msgFlags.Has(MessageFlagValues::kDuplicateMessage) && payloadHeader.IsInitiator())
     323              :     {
     324              :         // Search for an unsolicited message handler that can handle the message. Prefer handlers that can explicitly
     325              :         // handle the message type over handlers that handle all messages for a profile.
     326         2322 :         matchingUMH = nullptr;
     327              : 
     328        20366 :         for (auto & umh : UMHandlerPool)
     329              :         {
     330        18120 :             if (umh.IsInUse() && payloadHeader.HasProtocol(umh.ProtocolId))
     331              :             {
     332         2339 :                 if (umh.MessageType == payloadHeader.GetMessageType())
     333              :                 {
     334           76 :                     matchingUMH = &umh;
     335           76 :                     break;
     336              :                 }
     337              : 
     338         2263 :                 if (umh.MessageType == kAnyMessageType)
     339         2231 :                     matchingUMH = &umh;
     340              :             }
     341              :         }
     342              :     }
     343              :     // Discard the message if it isn't marked as being sent by an initiator and the message does not need to send
     344              :     // an ack to the peer.
     345           62 :     else if (!payloadHeader.NeedsAck())
     346              :     {
     347              :         // We can easily get standalone acks here: any time we fail to get a
     348              :         // timely ack for the last message in an exchange and retransmit it,
     349              :         // then get acks for both the message and the retransmit, the second ack
     350              :         // will end up in this block.  That's not really an error condition, so
     351              :         // there is no need to log an error in that case.
     352           48 :         if (!payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::StandaloneAck))
     353              :         {
     354              :             // Using same error message for all errors to reduce code size.
     355            2 :             ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT,
     356              :                          CHIP_ERROR_UNSOLICITED_MSG_NO_ORIGINATOR.Format());
     357              :         }
     358           48 :         return;
     359              :     }
     360              : 
     361              :     // If we found a handler, create an exchange to handle the message.
     362         2336 :     if (matchingUMH != nullptr)
     363              :     {
     364         2307 :         ExchangeDelegate * delegate = nullptr;
     365              : 
     366              :         // Fetch delegate from the handler
     367         2307 :         CHIP_ERROR err = matchingUMH->Handler->OnUnsolicitedMessageReceived(payloadHeader, session, delegate);
     368         4614 :         if (err != CHIP_NO_ERROR)
     369              :         {
     370              :             // Using same error message for all errors to reduce code size.
     371            0 :             ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     372            0 :             SendStandaloneAckIfNeeded(packetHeader, payloadHeader, session, msgFlags, std::move(msgBuf));
     373            0 :             return;
     374              :         }
     375              : 
     376         2307 :         ExchangeContext * ec = mContextPool.CreateObject(this, payloadHeader.GetExchangeID(), session, false, delegate);
     377              : 
     378         2307 :         if (ec == nullptr)
     379              :         {
     380            0 :             if (delegate != nullptr)
     381              :             {
     382            0 :                 matchingUMH->Handler->OnExchangeCreationFailed(delegate);
     383              :             }
     384              : 
     385              :             // Using same error message for all errors to reduce code size.
     386            0 :             ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, CHIP_ERROR_NO_MEMORY.Format());
     387              :             // No resource for creating new exchange, SendStandaloneAckIfNeeded probably also fails, so do not try it here
     388            0 :             return;
     389              :         }
     390              : 
     391         2307 :         ChipLogDetail(ExchangeManager, "Handling via exchange: " ChipLogFormatExchange ", Delegate: %p", ChipLogValueExchange(ec),
     392              :                       ec->GetDelegate());
     393              : 
     394         2307 :         if (ec->IsEncryptionRequired() != packetHeader.IsEncrypted())
     395              :         {
     396            1 :             ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT,
     397              :                          CHIP_ERROR_INVALID_MESSAGE_TYPE.Format());
     398            1 :             ec->Close();
     399            1 :             SendStandaloneAckIfNeeded(packetHeader, payloadHeader, session, msgFlags, std::move(msgBuf));
     400            1 :             return;
     401              :         }
     402              : 
     403         2306 :         err = ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, msgFlags, std::move(msgBuf));
     404         4612 :         if (err != CHIP_NO_ERROR)
     405              :         {
     406              :             // Using same error message for all errors to reduce code size.
     407            3 :             ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     408              :         }
     409         2306 :         return;
     410              :     }
     411              : 
     412           29 :     SendStandaloneAckIfNeeded(packetHeader, payloadHeader, session, msgFlags, std::move(msgBuf));
     413              : }
     414              : 
     415           30 : void ExchangeManager::SendStandaloneAckIfNeeded(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
     416              :                                                 const SessionHandle & session, MessageFlags msgFlags,
     417              :                                                 System::PacketBufferHandle && msgBuf)
     418              : {
     419              : 
     420              :     // If using the MRP protocol and we need to send a StandaloneAck, create an EphemeralExchange to send
     421              :     // the StandaloneAck.
     422           30 :     if (!session->AllowsMRP() || !payloadHeader.NeedsAck())
     423            8 :         return;
     424              : 
     425              :     // If rcvd msg is from initiator then this exchange is created as not Initiator.
     426              :     // If rcvd msg is not from initiator then this exchange is created as Initiator.
     427              :     // Create a EphemeralExchange to generate a StandaloneAck
     428           22 :     ExchangeContext * ec = mContextPool.CreateObject(this, payloadHeader.GetExchangeID(), session, !payloadHeader.IsInitiator(),
     429           22 :                                                      nullptr, true /* IsEphemeralExchange */);
     430              : 
     431           22 :     if (ec == nullptr)
     432              :     {
     433              :         // Using same error message for all errors to reduce code size.
     434            0 :         ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, CHIP_ERROR_NO_MEMORY.Format());
     435            0 :         return;
     436              :     }
     437              : 
     438           22 :     ChipLogDetail(ExchangeManager, "Generating StandaloneAck via exchange: " ChipLogFormatExchange, ChipLogValueExchange(ec));
     439              : 
     440              :     // No need to verify packet encryption type, the EphemeralExchange can handle both secure and insecure messages.
     441              : 
     442           22 :     CHIP_ERROR err = ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, msgFlags, std::move(msgBuf));
     443           44 :     if (err != CHIP_NO_ERROR)
     444              :     {
     445              :         // Using same error message for all errors to reduce code size.
     446            0 :         ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     447              :     }
     448              : 
     449              :     // The exchange should be closed inside HandleMessage function. So don't bother close it here.
     450              : }
     451              : 
     452          428 : void ExchangeManager::CloseAllContextsForDelegate(const ExchangeDelegate * delegate)
     453              : {
     454          428 :     mContextPool.ForEachActiveObject([&](auto * ec) {
     455           31 :         if (ec->GetDelegate() == delegate)
     456              :         {
     457              :             // Make sure to null out the delegate before closing the context, so
     458              :             // we don't notify the delegate that the context is closing.  We
     459              :             // have to do this, because the delegate might be partially
     460              :             // destroyed by this point.
     461            1 :             ec->SetDelegate(nullptr);
     462            1 :             ec->Close();
     463              :         }
     464           31 :         return Loop::Continue;
     465              :     });
     466          428 : }
     467              : 
     468              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     469            0 : void ExchangeManager::OnTCPConnectionClosed(const Transport::ActiveTCPConnectionState & conn, const SessionHandle & session,
     470              :                                             CHIP_ERROR conErr)
     471              : {
     472            0 :     mContextPool.ForEachActiveObject([&](auto * ec) {
     473            0 :         if (ec->HasSessionHandle() && ec->GetSessionHandle() == session)
     474              :         {
     475            0 :             ec->OnSessionConnectionClosed(conn, conErr);
     476              :         }
     477            0 :         return Loop::Continue;
     478              :     });
     479            0 : }
     480              : 
     481            0 : bool ExchangeManager::OnTCPConnectionAttemptComplete(Transport::ActiveTCPConnectionHandle & conn, CHIP_ERROR conErr)
     482              : {
     483            0 :     bool foundHandler = false;
     484            0 :     mContextPool.ForEachActiveObject([&](auto * ec) {
     485            0 :         if (ec->HasSessionHandle())
     486              :         {
     487            0 :             ec->OnConnectionAttemptComplete(conn, conErr);
     488            0 :             foundHandler = true;
     489              :         }
     490            0 :         return Loop::Continue;
     491              :     });
     492              : 
     493            0 :     return foundHandler;
     494              : }
     495              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     496              : 
     497              : } // namespace Messaging
     498              : } // namespace chip
        

Generated by: LCOV version 2.0-1