Matter SDK Coverage Report
Current view: top level - transport - SessionManager.cpp (source / functions) Coverage Total Hit
Test: SHA:5853f10e345717417494f970a7d13b422d94af51 Lines: 70.5 % 577 407
Test Date: 2025-06-30 07:09:23 Functions: 50.0 % 46 23

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       5              :  *    All rights reserved.
       6              :  *
       7              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       8              :  *    you may not use this file except in compliance with the License.
       9              :  *    You may obtain a copy of the License at
      10              :  *
      11              :  *        http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  *    Unless required by applicable law or agreed to in writing, software
      14              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      15              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  *    See the License for the specific language governing permissions and
      17              :  *    limitations under the License.
      18              :  */
      19              : 
      20              : /**
      21              :  *    @file
      22              :  *      This file implements the CHIP Connection object that maintains a UDP connection.
      23              :  *      TODO This class should be extended to support TCP as well...
      24              :  *
      25              :  */
      26              : 
      27              : #include "SessionManager.h"
      28              : 
      29              : #include <inttypes.h>
      30              : #include <string.h>
      31              : 
      32              : #include "transport/TraceMessage.h"
      33              : #include <app/util/basic-types.h>
      34              : #include <credentials/GroupDataProvider.h>
      35              : #include <inttypes.h>
      36              : #include <lib/core/CHIPKeyIds.h>
      37              : #include <lib/core/Global.h>
      38              : #include <lib/support/AutoRelease.h>
      39              : #include <lib/support/CodeUtils.h>
      40              : #include <lib/support/SafeInt.h>
      41              : #include <lib/support/logging/CHIPLogging.h>
      42              : #include <platform/CHIPDeviceLayer.h>
      43              : #include <protocols/Protocols.h>
      44              : #include <protocols/secure_channel/Constants.h>
      45              : #include <tracing/macros.h>
      46              : #include <transport/GroupPeerMessageCounter.h>
      47              : #include <transport/GroupSession.h>
      48              : #include <transport/SecureMessageCodec.h>
      49              : #include <transport/TracingStructs.h>
      50              : #include <transport/TransportMgr.h>
      51              : 
      52              : namespace chip {
      53              : 
      54              : using System::PacketBufferHandle;
      55              : using Transport::GroupPeerTable;
      56              : using Transport::PeerAddress;
      57              : using Transport::SecureSession;
      58              : 
      59              : namespace {
      60              : Global<GroupPeerTable> gGroupPeerTable;
      61              : 
      62              : // Helper function that strips off the interface ID from a peer address that is
      63              : // not an IPv6 link-local address.  For any other address type we should rely on
      64              : // the device's routing table to route messages sent.  Forcing messages down a
      65              : // specific interface might fail with "no route to host".
      66        14919 : void CorrectPeerAddressInterfaceID(Transport::PeerAddress & peerAddress)
      67              : {
      68        14919 :     if (peerAddress.GetIPAddress().IsIPv6LinkLocal())
      69              :     {
      70            0 :         return;
      71              :     }
      72        14919 :     peerAddress.SetInterface(Inet::InterfaceId::Null());
      73              : }
      74              : 
      75              : } // namespace
      76              : 
      77        25381 : uint32_t EncryptedPacketBufferHandle::GetMessageCounter() const
      78              : {
      79        25381 :     PacketHeader header;
      80        25381 :     uint16_t headerSize = 0;
      81        25381 :     CHIP_ERROR err      = header.Decode((*this)->Start(), (*this)->DataLength(), &headerSize);
      82              : 
      83        25381 :     if (err == CHIP_NO_ERROR)
      84              :     {
      85        25381 :         return header.GetMessageCounter();
      86              :     }
      87              : 
      88            0 :     ChipLogError(Inet, "Failed to decode EncryptedPacketBufferHandle header with error: %" CHIP_ERROR_FORMAT, err.Format());
      89              : 
      90            0 :     return 0;
      91              : }
      92              : 
      93          466 : SessionManager::SessionManager() : mState(State::kNotReady) {}
      94              : 
      95          466 : SessionManager::~SessionManager()
      96              : {
      97          466 :     this->Shutdown();
      98          466 : }
      99              : 
     100          403 : CHIP_ERROR SessionManager::Init(System::Layer * systemLayer, TransportMgrBase * transportMgr,
     101              :                                 Transport::MessageCounterManagerInterface * messageCounterManager,
     102              :                                 chip::PersistentStorageDelegate * storageDelegate, FabricTable * fabricTable,
     103              :                                 Crypto::SessionKeystore & sessionKeystore)
     104              : {
     105          403 :     VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE);
     106          403 :     VerifyOrReturnError(transportMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     107          403 :     VerifyOrReturnError(storageDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     108          403 :     VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     109          403 :     ReturnErrorOnFailure(fabricTable->AddFabricDelegate(this));
     110              : 
     111          403 :     mState                 = State::kInitialized;
     112          403 :     mSystemLayer           = systemLayer;
     113          403 :     mTransportMgr          = transportMgr;
     114          403 :     mMessageCounterManager = messageCounterManager;
     115          403 :     mFabricTable           = fabricTable;
     116          403 :     mSessionKeystore       = &sessionKeystore;
     117              : 
     118          403 :     mSecureSessions.Init();
     119              : 
     120          403 :     mGlobalUnencryptedMessageCounter.Init();
     121              : 
     122          403 :     ReturnErrorOnFailure(mGroupClientCounter.Init(storageDelegate));
     123              : 
     124          403 :     mTransportMgr->SetSessionManager(this);
     125              : 
     126              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     127          403 :     mConnCompleteCb = nullptr;
     128          403 :     mConnClosedCb   = nullptr;
     129              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     130              : 
     131          403 :     return CHIP_NO_ERROR;
     132              : }
     133              : 
     134          868 : void SessionManager::Shutdown()
     135              : {
     136          868 :     if (mFabricTable != nullptr)
     137              :     {
     138          403 :         mFabricTable->RemoveFabricDelegate(this);
     139          403 :         mFabricTable = nullptr;
     140              :     }
     141              : 
     142              :     // Ensure that we don't create new sessions as we iterate our session table.
     143          868 :     mState = State::kNotReady;
     144              : 
     145              :     // Just in case some consumer forgot to do it, expire all our secure
     146              :     // sessions.  Note that this stands a good chance of crashing with a
     147              :     // null-deref if there are in fact any secure sessions left, since they will
     148              :     // try to notify their exchanges, which will then try to operate on
     149              :     // partially-shut-down objects.
     150          868 :     ExpireAllSecureSessions();
     151              : 
     152              :     // We don't have a safe way to check or affect the state of our
     153              :     // mUnauthenticatedSessions.  We can only hope they got shut down properly.
     154              : 
     155          868 :     mMessageCounterManager = nullptr;
     156              : 
     157          868 :     mSystemLayer  = nullptr;
     158          868 :     mTransportMgr = nullptr;
     159          868 :     mCB           = nullptr;
     160          868 : }
     161              : 
     162              : /**
     163              :  * @brief Notification that a fabric was removed.
     164              :  *        This function doesn't call ExpireAllSessionsForFabric
     165              :  *        since the CASE session might still be open to send a response
     166              :  *        on the removed fabric.
     167              :  */
     168            7 : void SessionManager::FabricRemoved(FabricIndex fabricIndex)
     169              : {
     170            7 :     gGroupPeerTable->FabricRemoved(fabricIndex);
     171            7 : }
     172              : 
     173        15018 : CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, PayloadHeader & payloadHeader,
     174              :                                           System::PacketBufferHandle && message, EncryptedPacketBufferHandle & preparedMessage)
     175              : {
     176              :     MATTER_TRACE_SCOPE("PrepareMessage", "SessionManager");
     177              : 
     178        15018 :     PacketHeader packetHeader;
     179        15018 :     bool isControlMsg = IsControlMessage(payloadHeader);
     180        15018 :     if (isControlMsg)
     181              :     {
     182            0 :         packetHeader.SetSecureSessionControlMsg(true);
     183              :     }
     184              : 
     185        15018 :     if (sessionHandle->AllowsLargePayload())
     186              :     {
     187            0 :         VerifyOrReturnError(message->TotalLength() <= kMaxLargeAppMessageLen, CHIP_ERROR_MESSAGE_TOO_LONG);
     188              :     }
     189              :     else
     190              :     {
     191        15018 :         VerifyOrReturnError(message->TotalLength() <= kMaxAppMessageLen, CHIP_ERROR_MESSAGE_TOO_LONG);
     192              :     }
     193              : 
     194              : #if CHIP_PROGRESS_LOGGING
     195              :     NodeId destination;
     196              :     FabricIndex fabricIndex;
     197              : #endif // CHIP_PROGRESS_LOGGING
     198              : 
     199        15017 :     NodeId sourceNodeId = kUndefinedNodeId;
     200        15017 :     PeerAddress destination_address;
     201              : 
     202        15017 :     switch (sessionHandle->GetSessionType())
     203              :     {
     204            2 :     case Transport::Session::SessionType::kGroupOutgoing: {
     205            2 :         auto groupSession = sessionHandle->AsOutgoingGroupSession();
     206            2 :         auto * groups     = Credentials::GetGroupDataProvider();
     207            2 :         VerifyOrReturnError(nullptr != groups, CHIP_ERROR_INTERNAL);
     208              : 
     209            2 :         const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
     210            2 :         VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     211              : 
     212            2 :         packetHeader.SetDestinationGroupId(groupSession->GetGroupId());
     213            2 :         packetHeader.SetMessageCounter(mGroupClientCounter.GetCounter(isControlMsg));
     214            2 :         mGroupClientCounter.IncrementCounter(isControlMsg);
     215            2 :         packetHeader.SetSessionType(Header::SessionType::kGroupSession);
     216            2 :         sourceNodeId = fabric->GetNodeId();
     217            2 :         packetHeader.SetSourceNodeId(sourceNodeId);
     218              : 
     219            2 :         if (!packetHeader.IsValidGroupMsg())
     220              :         {
     221            0 :             return CHIP_ERROR_INTERNAL;
     222              :         }
     223              : 
     224            2 :         destination_address = Transport::PeerAddress::Multicast(fabric->GetFabricId(), groupSession->GetGroupId());
     225              : 
     226              :         // Trace before any encryption
     227              :         MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kGroupMessage, &payloadHeader, &packetHeader,
     228              :                                 chip::ByteSpan(message->Start(), message->TotalLength()));
     229              : 
     230            2 :         CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
     231              : 
     232              :         Crypto::SymmetricKeyContext * keyContext =
     233            2 :             groups->GetKeyContext(groupSession->GetFabricIndex(), groupSession->GetGroupId());
     234            2 :         VerifyOrReturnError(nullptr != keyContext, CHIP_ERROR_INTERNAL);
     235              : 
     236            2 :         packetHeader.SetSessionId(keyContext->GetKeyHash());
     237              :         CryptoContext::NonceStorage nonce;
     238            2 :         CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), sourceNodeId);
     239            2 :         CHIP_ERROR err = SecureMessageCodec::Encrypt(CryptoContext(keyContext), nonce, payloadHeader, packetHeader, message);
     240            2 :         keyContext->Release();
     241            2 :         ReturnErrorOnFailure(err);
     242              : 
     243              : #if CHIP_PROGRESS_LOGGING
     244            2 :         destination = NodeIdFromGroupId(groupSession->GetGroupId());
     245            2 :         fabricIndex = groupSession->GetFabricIndex();
     246              : #endif // CHIP_PROGRESS_LOGGING
     247              :     }
     248            2 :     break;
     249        14906 :     case Transport::Session::SessionType::kSecure: {
     250        14906 :         SecureSession * session = sessionHandle->AsSecureSession();
     251        14906 :         if (session == nullptr)
     252              :         {
     253            1 :             return CHIP_ERROR_NOT_CONNECTED;
     254              :         }
     255              : 
     256        14906 :         MessageCounter & counter = session->GetSessionMessageCounter().GetLocalMessageCounter();
     257              :         uint32_t messageCounter;
     258        14906 :         ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
     259              :         packetHeader
     260        14905 :             .SetMessageCounter(messageCounter)         //
     261        14905 :             .SetSessionId(session->GetPeerSessionId()) //
     262        14905 :             .SetSessionType(Header::SessionType::kUnicastSession);
     263              : 
     264        14905 :         destination_address = session->GetPeerAddress();
     265              : 
     266              :         // Trace before any encryption
     267              :         MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kSecureSession, &payloadHeader, &packetHeader,
     268              :                                 chip::ByteSpan(message->Start(), message->TotalLength()));
     269        14905 :         CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
     270              : 
     271              :         CryptoContext::NonceStorage nonce;
     272        14905 :         sourceNodeId = session->GetLocalScopedNodeId().GetNodeId();
     273        14905 :         CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), messageCounter, sourceNodeId);
     274              : 
     275        14905 :         ReturnErrorOnFailure(SecureMessageCodec::Encrypt(session->GetCryptoContext(), nonce, payloadHeader, packetHeader, message));
     276              : 
     277              : #if CHIP_PROGRESS_LOGGING
     278        14905 :         destination = session->GetPeerNodeId();
     279        14905 :         fabricIndex = session->GetFabricIndex();
     280              : #endif // CHIP_PROGRESS_LOGGING
     281              :     }
     282        14905 :     break;
     283          109 :     case Transport::Session::SessionType::kUnauthenticated: {
     284          109 :         MessageCounter & counter = mGlobalUnencryptedMessageCounter;
     285              :         uint32_t messageCounter;
     286          109 :         ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
     287          109 :         packetHeader.SetMessageCounter(messageCounter);
     288          109 :         Transport::UnauthenticatedSession * session = sessionHandle->AsUnauthenticatedSession();
     289          109 :         switch (session->GetSessionRole())
     290              :         {
     291           64 :         case Transport::UnauthenticatedSession::SessionRole::kInitiator:
     292           64 :             packetHeader.SetSourceNodeId(session->GetEphemeralInitiatorNodeID());
     293           64 :             break;
     294           45 :         case Transport::UnauthenticatedSession::SessionRole::kResponder:
     295           45 :             packetHeader.SetDestinationNodeId(session->GetEphemeralInitiatorNodeID());
     296           45 :             break;
     297              :         }
     298              : 
     299          109 :         auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
     300          109 :         destination_address  = unauthenticated->GetPeerAddress();
     301              : 
     302              :         // Trace after all headers are settled.
     303              :         MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
     304              :                                 chip::ByteSpan(message->Start(), message->TotalLength()));
     305          109 :         CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
     306              : 
     307          109 :         ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(message));
     308              : 
     309              : #if CHIP_PROGRESS_LOGGING
     310          109 :         destination = kUndefinedNodeId;
     311          109 :         fabricIndex = kUndefinedFabricIndex;
     312          109 :         if (session->GetSessionRole() == Transport::UnauthenticatedSession::SessionRole::kResponder)
     313              :         {
     314           45 :             destination = session->GetEphemeralInitiatorNodeID();
     315              :         }
     316           64 :         else if (session->GetSessionRole() == Transport::UnauthenticatedSession::SessionRole::kInitiator)
     317              :         {
     318           64 :             sourceNodeId = session->GetEphemeralInitiatorNodeID();
     319              :         }
     320              : #endif // CHIP_PROGRESS_LOGGING
     321              :     }
     322          109 :     break;
     323            0 :     default:
     324            0 :         return CHIP_ERROR_INTERNAL;
     325              :     }
     326              : 
     327        15016 :     ReturnErrorOnFailure(packetHeader.EncodeBeforeData(message));
     328              : 
     329              : #if CHIP_PROGRESS_LOGGING
     330        15016 :     CompressedFabricId compressedFabricId = kUndefinedCompressedFabricId;
     331              : 
     332        15016 :     if (fabricIndex != kUndefinedFabricIndex && mFabricTable != nullptr)
     333              :     {
     334        14860 :         auto fabricInfo = mFabricTable->FindFabricWithIndex(fabricIndex);
     335        14860 :         if (fabricInfo)
     336              :         {
     337        14860 :             compressedFabricId = fabricInfo->GetCompressedFabricId();
     338              :         }
     339              :     }
     340              : 
     341        15016 :     auto * protocolName = Protocols::GetProtocolName(payloadHeader.GetProtocolID());
     342        15016 :     auto * msgTypeName  = Protocols::GetMessageTypeName(payloadHeader.GetProtocolID(), payloadHeader.GetMessageType());
     343              : 
     344              :     //
     345              :     // 32-bit value maximum = 10 chars + text preamble (6) + trailer (1) + null (1) + 2 buffer = 20
     346              :     //
     347              :     char ackBuf[20];
     348        15016 :     ackBuf[0] = '\0';
     349        15016 :     if (payloadHeader.GetAckMessageCounter().HasValue())
     350              :     {
     351        12614 :         snprintf(ackBuf, sizeof(ackBuf), " (Ack:" ChipLogFormatMessageCounter ")", payloadHeader.GetAckMessageCounter().Value());
     352              :     }
     353              : 
     354        15016 :     char addressStr[Transport::PeerAddress::kMaxToStringSize] = { 0 };
     355        15016 :     destination_address.ToString(addressStr);
     356              : 
     357              :     // Work around pigweed not allowing more than 14 format args in a log
     358              :     // message when using tokenized logs.
     359              :     char typeStr[4 + 1 + 2 + 1];
     360        15016 :     snprintf(typeStr, sizeof(typeStr), "%04X:%02X", payloadHeader.GetProtocolID().GetProtocolId(), payloadHeader.GetMessageType());
     361              : 
     362              :     // More work around pigweed not allowing more than 14 format args in a log
     363              :     // message when using tokenized logs.
     364              :     // ChipLogFormatExchangeId logs the numeric exchange ID (at most 5 chars,
     365              :     // since it's a uint16_t) and one char for initiator/responder.  Plus we
     366              :     // need a null-terminator.
     367              :     char exchangeStr[5 + 1 + 1];
     368        15016 :     snprintf(exchangeStr, sizeof(exchangeStr), ChipLogFormatExchangeId, ChipLogValueExchangeIdFromSentHeader(payloadHeader));
     369              : 
     370              :     // More work around pigweed not allowing more than 14 format args in a log
     371              :     // message when using tokenized logs.
     372              :     // text(5) + source(16) + text(4) + fabricIndex(uint16_t, at most 5 chars) + text(1) + destination(16) + text(2) + compressed
     373              :     // fabric id(4) + text(1) + null-terminator
     374              :     char sourceDestinationStr[5 + 16 + 4 + 5 + 1 + 16 + 2 + 4 + 1 + 1];
     375        15016 :     snprintf(sourceDestinationStr, sizeof(sourceDestinationStr), "from " ChipLogFormatX64 " to %u:" ChipLogFormatX64 " [%04X]",
     376        15016 :              ChipLogValueX64(sourceNodeId), fabricIndex, ChipLogValueX64(destination), static_cast<uint16_t>(compressedFabricId));
     377              : 
     378              :     //
     379              :     // Legend that can be used to decode this log line can be found in messaging/README.md
     380              :     //
     381        15016 :     ChipLogProgress(ExchangeManager,
     382              :                     "<<< [E:%s S:%u M:" ChipLogFormatMessageCounter "%s] (%s) Msg TX %s [%s] --- Type %s (%s:%s) (B:%u)",
     383              :                     exchangeStr, sessionHandle->SessionIdForLogging(), packetHeader.GetMessageCounter(), ackBuf,
     384              :                     Transport::GetSessionTypeString(sessionHandle), sourceDestinationStr, addressStr, typeStr, protocolName,
     385              :                     msgTypeName, static_cast<unsigned>(message->TotalLength()));
     386              : #endif
     387              : 
     388        15016 :     preparedMessage = EncryptedPacketBufferHandle::MarkEncrypted(std::move(message));
     389              : 
     390        15016 :     return CHIP_NO_ERROR;
     391              : }
     392              : 
     393        15070 : CHIP_ERROR SessionManager::SendPreparedMessage(const SessionHandle & sessionHandle,
     394              :                                                const EncryptedPacketBufferHandle & preparedMessage)
     395              : {
     396        15070 :     VerifyOrReturnError(mState == State::kInitialized, CHIP_ERROR_INCORRECT_STATE);
     397        15070 :     VerifyOrReturnError(!preparedMessage.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
     398              : 
     399        15070 :     Transport::PeerAddress multicastAddress; // Only used for the group case
     400              :     const Transport::PeerAddress * destination;
     401              : 
     402        15070 :     switch (sessionHandle->GetSessionType())
     403              :     {
     404            2 :     case Transport::Session::SessionType::kGroupOutgoing: {
     405            2 :         auto groupSession = sessionHandle->AsOutgoingGroupSession();
     406              : 
     407            2 :         const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
     408            2 :         VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     409              : 
     410            2 :         multicastAddress = Transport::PeerAddress::Multicast(fabric->GetFabricId(), groupSession->GetGroupId());
     411            2 :         destination      = &multicastAddress;
     412              :     }
     413            2 :     break;
     414        14956 :     case Transport::Session::SessionType::kSecure: {
     415              :         // Find an active connection to the specified peer node
     416        14956 :         SecureSession * secure = sessionHandle->AsSecureSession();
     417              : 
     418              :         // This marks any connection where we send data to as 'active'
     419        14956 :         secure->MarkActive();
     420              : 
     421        14956 :         destination = &secure->GetPeerAddress();
     422              :     }
     423        14956 :     break;
     424          112 :     case Transport::Session::SessionType::kUnauthenticated: {
     425          112 :         auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
     426          112 :         unauthenticated->MarkActive();
     427          112 :         destination = &unauthenticated->GetPeerAddress();
     428              :     }
     429          112 :     break;
     430            0 :     default:
     431            0 :         return CHIP_ERROR_INTERNAL;
     432              :     }
     433              : 
     434        30140 :     PacketBufferHandle msgBuf = preparedMessage.CastToWritable();
     435        15070 :     VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
     436        15070 :     VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
     437              : 
     438              : #if CHIP_SYSTEM_CONFIG_MULTICAST_HOMING
     439        15070 :     if (sessionHandle->GetSessionType() == Transport::Session::SessionType::kGroupOutgoing)
     440              :     {
     441            2 :         chip::Inet::InterfaceIterator interfaceIt;
     442            2 :         chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId::Null();
     443              :         chip::Inet::IPAddress addr;
     444            2 :         bool interfaceFound = false;
     445              : 
     446            6 :         while (interfaceIt.Next())
     447              :         {
     448              :             char name[Inet::InterfaceId::kMaxIfNameLength];
     449            4 :             interfaceIt.GetInterfaceName(name, Inet::InterfaceId::kMaxIfNameLength);
     450            4 :             if (interfaceIt.SupportsMulticast() && interfaceIt.IsUp())
     451              :             {
     452            2 :                 interfaceId = interfaceIt.GetInterfaceId();
     453            2 :                 if (CHIP_NO_ERROR == interfaceId.GetLinkLocalAddr(&addr))
     454              :                 {
     455            2 :                     ChipLogDetail(Inet, "Interface %s has a link local address", name);
     456              : 
     457            2 :                     interfaceFound             = true;
     458            2 :                     PacketBufferHandle tempBuf = msgBuf.CloneData();
     459            2 :                     VerifyOrReturnError(!tempBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
     460            2 :                     VerifyOrReturnError(!tempBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
     461              : 
     462            2 :                     destination = &(multicastAddress.SetInterface(interfaceId));
     463            2 :                     if (mTransportMgr != nullptr)
     464              :                     {
     465            2 :                         if (CHIP_NO_ERROR != mTransportMgr->SendMessage(*destination, std::move(tempBuf)))
     466              :                         {
     467            0 :                             ChipLogError(Inet, "Failed to send Multicast message on interface %s", name);
     468              :                         }
     469              :                         else
     470              :                         {
     471            2 :                             ChipLogDetail(Inet, "Successfully send Multicast message on interface %s", name);
     472              :                         }
     473              :                     }
     474            2 :                 }
     475              :             }
     476              :         }
     477              : 
     478            2 :         if (!interfaceFound)
     479              :         {
     480            0 :             ChipLogError(Inet, "No valid Interface found.. Sending to the default one.. ");
     481              :         }
     482              :         else
     483              :         {
     484              :             // Always return No error, because we expect some interface to fails and others to always succeed (e.g. lo interface)
     485            2 :             return CHIP_NO_ERROR;
     486              :         }
     487            2 :     }
     488              : 
     489              : #endif // CHIP_SYSTEM_CONFIG_MULTICAST_HOMING
     490              : 
     491        15068 :     if (mTransportMgr != nullptr)
     492              :     {
     493        15068 :         CHIP_ERROR err = mTransportMgr->SendMessage(*destination, std::move(msgBuf));
     494              : #if CHIP_ERROR_LOGGING
     495        15068 :         if (err != CHIP_NO_ERROR)
     496              :         {
     497            5 :             char addressStr[Transport::PeerAddress::kMaxToStringSize] = { 0 };
     498            5 :             destination->ToString(addressStr);
     499            5 :             ChipLogError(Inet, "SendMessage() to %s failed: %" CHIP_ERROR_FORMAT, addressStr, err.Format());
     500              :         }
     501              : #endif // CHIP_ERROR_LOGGING
     502        15068 :         return err;
     503              :     }
     504              : 
     505            0 :     ChipLogError(Inet, "The transport manager is not initialized. Unable to send the message");
     506            0 :     return CHIP_ERROR_INCORRECT_STATE;
     507              : }
     508              : 
     509            0 : void SessionManager::ExpireAllSessions(const ScopedNodeId & node)
     510              : {
     511            0 :     ChipLogDetail(Inet, "Expiring all sessions for node " ChipLogFormatScopedNodeId "!!", ChipLogValueScopedNodeId(node));
     512              : 
     513            0 :     ForEachMatchingSession(node, [](auto * session) { session->MarkForEviction(); });
     514            0 : }
     515              : 
     516            2 : void SessionManager::ExpireAllSessionsForFabric(FabricIndex fabricIndex)
     517              : {
     518            2 :     ChipLogDetail(Inet, "Expiring all sessions for fabric 0x%x!!", static_cast<unsigned>(fabricIndex));
     519              : 
     520            8 :     ForEachMatchingSession(fabricIndex, [](auto * session) { session->MarkForEviction(); });
     521            2 : }
     522              : 
     523            0 : CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(const ScopedNodeId & node)
     524              : {
     525            0 :     ChipLogDetail(Inet, "Expiring all sessions to peer " ChipLogFormatScopedNodeId " that are on the same logical fabric!!",
     526              :                   ChipLogValueScopedNodeId(node));
     527              : 
     528            0 :     return ForEachMatchingSessionOnLogicalFabric(node, [](auto * session) { session->MarkForEviction(); });
     529              : }
     530              : 
     531            0 : CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(FabricIndex fabricIndex)
     532              : {
     533            0 :     ChipLogDetail(Inet, "Expiring all sessions on the same logical fabric as fabric 0x%x!!", static_cast<unsigned>(fabricIndex));
     534              : 
     535            0 :     return ForEachMatchingSessionOnLogicalFabric(fabricIndex, [](auto * session) { session->MarkForEviction(); });
     536              : }
     537              : 
     538            0 : void SessionManager::ExpireAllPASESessions()
     539              : {
     540            0 :     ChipLogDetail(Inet, "Expiring all PASE sessions");
     541            0 :     mSecureSessions.ForEachSession([&](auto session) {
     542            0 :         if (session->GetSecureSessionType() == Transport::SecureSession::Type::kPASE)
     543              :         {
     544            0 :             session->MarkForEviction();
     545              :         }
     546            0 :         return Loop::Continue;
     547              :     });
     548            0 : }
     549              : 
     550          869 : void SessionManager::ExpireAllSecureSessions()
     551              : {
     552          869 :     mSecureSessions.ForEachSession([&](auto session) {
     553         1433 :         session->MarkForEviction();
     554         1433 :         return Loop::Continue;
     555              :     });
     556          869 : }
     557              : 
     558            0 : void SessionManager::MarkSessionsAsDefunct(const ScopedNodeId & node, const Optional<Transport::SecureSession::Type> & type)
     559              : {
     560            0 :     mSecureSessions.ForEachSession([&node, &type](auto session) {
     561            0 :         if (session->IsActiveSession() && session->GetPeer() == node &&
     562            0 :             (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
     563              :         {
     564            0 :             session->MarkAsDefunct();
     565              :         }
     566            0 :         return Loop::Continue;
     567              :     });
     568            0 : }
     569              : 
     570            0 : void SessionManager::UpdateAllSessionsPeerAddress(const ScopedNodeId & node, const Transport::PeerAddress & addr)
     571              : {
     572            0 :     mSecureSessions.ForEachSession([&node, &addr](auto session) {
     573              :         // Arguably we should only be updating active and defunct sessions, but there is no harm
     574              :         // in updating evicted sessions.
     575            0 :         if (session->GetPeer() == node && Transport::SecureSession::Type::kCASE == session->GetSecureSessionType())
     576              :         {
     577            0 :             session->SetPeerAddress(addr);
     578              :         }
     579            0 :         return Loop::Continue;
     580              :     });
     581            0 : }
     582              : 
     583       133657 : Optional<SessionHandle> SessionManager::AllocateSession(SecureSession::Type secureSessionType,
     584              :                                                         const ScopedNodeId & sessionEvictionHint)
     585              : {
     586       133657 :     VerifyOrReturnValue(mState == State::kInitialized, NullOptional);
     587       133657 :     return mSecureSessions.CreateNewSecureSession(secureSessionType, sessionEvictionHint);
     588              : }
     589              : 
     590         1503 : CHIP_ERROR SessionManager::InjectPaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, NodeId peerNodeId,
     591              :                                                         uint16_t peerSessionId, FabricIndex fabric,
     592              :                                                         const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role)
     593              : {
     594         1503 :     NodeId localNodeId              = kUndefinedNodeId;
     595              :     Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
     596              :         chip::Transport::SecureSession::Type::kPASE, localSessionId, localNodeId, peerNodeId, CATValues{}, peerSessionId, fabric,
     597         1503 :         GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
     598         1503 :     VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
     599         1503 :     SecureSession * secureSession = session.Value()->AsSecureSession();
     600         1503 :     secureSession->SetPeerAddress(peerAddress);
     601              : 
     602         1503 :     size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
     603         1503 :     ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
     604         1503 :     ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
     605              :         *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
     606         1503 :     secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
     607         1503 :     sessionHolder.Grab(session.Value());
     608         1503 :     return CHIP_NO_ERROR;
     609         1503 : }
     610              : 
     611           23 : CHIP_ERROR SessionManager::InjectCaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId,
     612              :                                                         uint16_t peerSessionId, NodeId localNodeId, NodeId peerNodeId,
     613              :                                                         FabricIndex fabric, const Transport::PeerAddress & peerAddress,
     614              :                                                         CryptoContext::SessionRole role, const CATValues & cats)
     615              : {
     616              :     Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
     617              :         chip::Transport::SecureSession::Type::kCASE, localSessionId, localNodeId, peerNodeId, cats, peerSessionId, fabric,
     618           23 :         GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
     619           23 :     VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
     620           23 :     SecureSession * secureSession = session.Value()->AsSecureSession();
     621           23 :     secureSession->SetPeerAddress(peerAddress);
     622              : 
     623           23 :     size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
     624           23 :     ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
     625           23 :     ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
     626              :         *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
     627           23 :     secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
     628           23 :     sessionHolder.Grab(session.Value());
     629           23 :     return CHIP_NO_ERROR;
     630           23 : }
     631              : 
     632        14936 : void SessionManager::OnMessageReceived(const PeerAddress & peerAddress, System::PacketBufferHandle && msg,
     633              :                                        Transport::MessageTransportContext * ctxt)
     634              : {
     635        14936 :     PacketHeader partialPacketHeader;
     636              : 
     637        14936 :     CHIP_ERROR err = partialPacketHeader.DecodeFixed(msg);
     638        14936 :     if (err != CHIP_NO_ERROR)
     639              :     {
     640            0 :         ChipLogError(Inet, "Failed to decode packet header: %" CHIP_ERROR_FORMAT, err.Format());
     641            0 :         return;
     642              :     }
     643              : 
     644        14936 :     if (partialPacketHeader.IsEncrypted())
     645              :     {
     646        14829 :         if (partialPacketHeader.IsGroupSession())
     647              :         {
     648            7 :             SecureGroupMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
     649              :         }
     650              :         else
     651              :         {
     652        14822 :             SecureUnicastMessageDispatch(partialPacketHeader, peerAddress, std::move(msg), ctxt);
     653              :         }
     654              :     }
     655              :     else
     656              :     {
     657          107 :         UnauthenticatedMessageDispatch(partialPacketHeader, peerAddress, std::move(msg), ctxt);
     658              :     }
     659              : }
     660              : 
     661              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     662            0 : void SessionManager::HandleConnectionReceived(Transport::ActiveTCPConnectionState * conn)
     663              : {
     664              :     char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     665              : 
     666            0 :     VerifyOrReturn(conn != nullptr);
     667            0 :     conn->mPeerAddr.ToString(peerAddrBuf);
     668            0 :     ChipLogProgress(Inet, "Received TCP connection request from %s.", peerAddrBuf);
     669              : 
     670            0 :     Transport::AppTCPConnectionCallbackCtxt * appTCPConnCbCtxt = conn->mAppState;
     671            0 :     if (appTCPConnCbCtxt != nullptr && appTCPConnCbCtxt->connReceivedCb != nullptr)
     672              :     {
     673            0 :         appTCPConnCbCtxt->connReceivedCb(conn);
     674              :     }
     675              : }
     676              : 
     677            0 : void SessionManager::HandleConnectionAttemptComplete(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr)
     678              : {
     679            0 :     VerifyOrReturn(conn != nullptr);
     680              : 
     681            0 :     Transport::AppTCPConnectionCallbackCtxt * appTCPConnCbCtxt = conn->mAppState;
     682            0 :     if (appTCPConnCbCtxt == nullptr)
     683              :     {
     684            0 :         TCPDisconnect(conn, /* shouldAbort = */ true);
     685            0 :         return;
     686              :     }
     687              : 
     688            0 :     if (appTCPConnCbCtxt->connCompleteCb != nullptr)
     689              :     {
     690            0 :         appTCPConnCbCtxt->connCompleteCb(conn, conErr);
     691              :     }
     692              :     else
     693              :     {
     694              :         char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     695            0 :         conn->mPeerAddr.ToString(peerAddrBuf);
     696              : 
     697            0 :         ChipLogProgress(Inet, "TCP Connection established with peer %s, but no registered handler. Disconnecting.", peerAddrBuf);
     698              : 
     699              :         // Close the connection
     700            0 :         TCPDisconnect(conn, /* shouldAbort = */ true);
     701              :     }
     702              : }
     703              : 
     704            0 : void SessionManager::HandleConnectionClosed(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr)
     705              : {
     706            0 :     VerifyOrReturn(conn != nullptr);
     707              : 
     708            0 :     MarkSecureSessionOverTCPForEviction(conn, conErr);
     709              : 
     710              :     // TODO: A mechanism to mark an unauthenticated session as unusable when
     711              :     // the underlying connection is broken. Issue #32323
     712              : 
     713            0 :     Transport::AppTCPConnectionCallbackCtxt * appTCPConnCbCtxt = conn->mAppState;
     714            0 :     VerifyOrReturn(appTCPConnCbCtxt != nullptr);
     715              : 
     716            0 :     if (appTCPConnCbCtxt->connClosedCb != nullptr)
     717              :     {
     718            0 :         appTCPConnCbCtxt->connClosedCb(conn, conErr);
     719              :     }
     720              : }
     721              : 
     722            0 : CHIP_ERROR SessionManager::TCPConnect(const PeerAddress & peerAddress, Transport::AppTCPConnectionCallbackCtxt * appState,
     723              :                                       Transport::ActiveTCPConnectionState ** peerConnState)
     724              : {
     725              :     char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     726            0 :     peerAddress.ToString(peerAddrBuf);
     727            0 :     if (mTransportMgr != nullptr)
     728              :     {
     729            0 :         ChipLogProgress(Inet, "Connecting over TCP with peer at %s.", peerAddrBuf);
     730            0 :         return mTransportMgr->TCPConnect(peerAddress, appState, peerConnState);
     731              :     }
     732              : 
     733            0 :     ChipLogError(Inet, "The transport manager is not initialized. Unable to connect to peer at %s.", peerAddrBuf);
     734              : 
     735            0 :     return CHIP_ERROR_INCORRECT_STATE;
     736              : }
     737              : 
     738            0 : CHIP_ERROR SessionManager::TCPDisconnect(const PeerAddress & peerAddress)
     739              : {
     740            0 :     if (mTransportMgr != nullptr)
     741              :     {
     742              :         char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     743            0 :         peerAddress.ToString(peerAddrBuf);
     744            0 :         ChipLogProgress(Inet, "Disconnecting TCP connection from peer at %s.", peerAddrBuf);
     745            0 :         mTransportMgr->TCPDisconnect(peerAddress);
     746              :     }
     747              : 
     748            0 :     return CHIP_NO_ERROR;
     749              : }
     750              : 
     751            0 : void SessionManager::TCPDisconnect(Transport::ActiveTCPConnectionState * conn, bool shouldAbort)
     752              : {
     753            0 :     if (mTransportMgr != nullptr && conn != nullptr)
     754              :     {
     755              :         char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     756            0 :         conn->mPeerAddr.ToString(peerAddrBuf);
     757            0 :         ChipLogProgress(Inet, "Disconnecting TCP connection from peer at %s.", peerAddrBuf);
     758            0 :         mTransportMgr->TCPDisconnect(conn, shouldAbort);
     759              : 
     760            0 :         MarkSecureSessionOverTCPForEviction(conn, CHIP_NO_ERROR);
     761              :     }
     762            0 : }
     763              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     764              : 
     765          107 : void SessionManager::UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader,
     766              :                                                     const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg,
     767              :                                                     Transport::MessageTransportContext * ctxt)
     768              : {
     769              :     MATTER_TRACE_SCOPE("Unauthenticated Message Dispatch", "SessionManager");
     770              : 
     771              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     772          107 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp && ctxt->conn == nullptr)
     773              :     {
     774            0 :         ChipLogError(Inet, "Connection object is missing for received message.");
     775            0 :         return;
     776              :     }
     777              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     778              : 
     779              :     // Drop unsecured messages with privacy enabled.
     780          107 :     if (partialPacketHeader.HasPrivacyFlag())
     781              :     {
     782            0 :         ChipLogError(Inet, "Dropping unauthenticated message with privacy flag set");
     783            0 :         return;
     784              :     }
     785              : 
     786          107 :     PacketHeader packetHeader;
     787          107 :     ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
     788              : 
     789          107 :     Optional<NodeId> source      = packetHeader.GetSourceNodeId();
     790          107 :     Optional<NodeId> destination = packetHeader.GetDestinationNodeId();
     791              : 
     792          107 :     if ((source.HasValue() && destination.HasValue()) || (!source.HasValue() && !destination.HasValue()))
     793              :     {
     794            0 :         ChipLogProgress(Inet,
     795              :                         "Received malformed unsecure packet with source 0x" ChipLogFormatX64 " destination 0x" ChipLogFormatX64,
     796              :                         ChipLogValueX64(source.ValueOr(kUndefinedNodeId)), ChipLogValueX64(destination.ValueOr(kUndefinedNodeId)));
     797            0 :         return; // ephemeral node id is only assigned to the initiator, there should be one and only one node id exists.
     798              :     }
     799              : 
     800          107 :     Optional<SessionHandle> optionalSession;
     801          107 :     if (source.HasValue())
     802              :     {
     803              :         // Assume peer is the initiator, we are the responder.
     804           62 :         optionalSession = mUnauthenticatedSessions.FindOrAllocateResponder(source.Value(), GetDefaultMRPConfig(), peerAddress);
     805           62 :         if (!optionalSession.HasValue())
     806              :         {
     807            0 :             ChipLogError(Inet, "UnauthenticatedSession exhausted");
     808            0 :             return;
     809              :         }
     810              :     }
     811              :     else
     812              :     {
     813              :         // Assume peer is the responder, we are the initiator.
     814           45 :         optionalSession = mUnauthenticatedSessions.FindInitiator(destination.Value(), peerAddress);
     815           45 :         if (!optionalSession.HasValue())
     816              :         {
     817            0 :             ChipLogProgress(Inet, "Received unknown unsecure packet for initiator 0x" ChipLogFormatX64,
     818              :                             ChipLogValueX64(destination.Value()));
     819            0 :             return;
     820              :         }
     821              :     }
     822              : 
     823          107 :     const SessionHandle & session                        = optionalSession.Value();
     824          107 :     Transport::UnauthenticatedSession * unsecuredSession = session->AsUnauthenticatedSession();
     825          107 :     Transport::PeerAddress mutablePeerAddress            = peerAddress;
     826          107 :     CorrectPeerAddressInterfaceID(mutablePeerAddress);
     827          107 :     unsecuredSession->SetPeerAddress(mutablePeerAddress);
     828          107 :     SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
     829              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     830              :     // Associate the unauthenticated session with the connection, if not done already.
     831          107 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp)
     832              :     {
     833            0 :         Transport::ActiveTCPConnectionState * sessionConn = unsecuredSession->GetTCPConnection();
     834            0 :         if (sessionConn == nullptr)
     835              :         {
     836            0 :             unsecuredSession->SetTCPConnection(ctxt->conn);
     837              :         }
     838              :         else
     839              :         {
     840            0 :             if (sessionConn != ctxt->conn)
     841              :             {
     842            0 :                 ChipLogError(Inet, "Data received over wrong connection %p. Dropping it!", ctxt->conn);
     843            0 :                 return;
     844              :             }
     845              :         }
     846              :     }
     847              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     848              : 
     849          107 :     unsecuredSession->MarkActiveRx();
     850              : 
     851          107 :     PayloadHeader payloadHeader;
     852          107 :     ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));
     853              : 
     854              :     // Verify message counter
     855          107 :     CHIP_ERROR err = unsecuredSession->GetPeerMessageCounter().VerifyUnencrypted(packetHeader.GetMessageCounter());
     856          107 :     if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
     857              :     {
     858            0 :         ChipLogDetail(Inet,
     859              :                       "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
     860              :                       " on exchange " ChipLogFormatExchangeId,
     861              :                       packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
     862            0 :         isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
     863            0 :         err         = CHIP_NO_ERROR;
     864              :     }
     865              :     else
     866              :     {
     867              :         // VerifyUnencrypted always returns one of CHIP_NO_ERROR or
     868              :         // CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED.
     869          107 :         unsecuredSession->GetPeerMessageCounter().CommitUnencrypted(packetHeader.GetMessageCounter());
     870              :     }
     871          107 :     if (mCB != nullptr)
     872              :     {
     873              :         MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
     874              :                                     unsecuredSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));
     875              : 
     876          107 :         CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, unsecuredSession, peerAddress, msg->Start(), msg->TotalLength());
     877          107 :         mCB->OnMessageReceived(packetHeader, payloadHeader, session, isDuplicate, std::move(msg));
     878              :     }
     879              :     else
     880              :     {
     881            0 :         ChipLogError(Inet, "Received UNSECURED message was not processed.");
     882              :     }
     883          107 : }
     884              : 
     885        14822 : void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader,
     886              :                                                   const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg,
     887              :                                                   Transport::MessageTransportContext * ctxt)
     888              : {
     889              :     MATTER_TRACE_SCOPE("Secure Unicast Message Dispatch", "SessionManager");
     890              : 
     891        14822 :     CHIP_ERROR err = CHIP_NO_ERROR;
     892              : 
     893              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     894        14822 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp && ctxt->conn == nullptr)
     895              :     {
     896            0 :         ChipLogError(Inet, "Connection object is missing for received message.");
     897           16 :         return;
     898              :     }
     899              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     900              : 
     901        14822 :     Optional<SessionHandle> session = mSecureSessions.FindSecureSessionByLocalKey(partialPacketHeader.GetSessionId());
     902        14822 :     if (!session.HasValue())
     903              :     {
     904           10 :         ChipLogError(Inet, "Data received on an unknown session (LSID=%d). Dropping it!", partialPacketHeader.GetSessionId());
     905           10 :         return;
     906              :     }
     907              : 
     908        14812 :     Transport::SecureSession * secureSession  = session.Value()->AsSecureSession();
     909        14812 :     Transport::PeerAddress mutablePeerAddress = peerAddress;
     910        14812 :     CorrectPeerAddressInterfaceID(mutablePeerAddress);
     911        14812 :     if (secureSession->GetPeerAddress() != mutablePeerAddress)
     912              :     {
     913            5 :         secureSession->SetPeerAddress(mutablePeerAddress);
     914              :     }
     915              : 
     916              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     917              :     // Associate the secure session with the connection, if not done already.
     918        14812 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp)
     919              :     {
     920            0 :         Transport::ActiveTCPConnectionState * sessionConn = secureSession->GetTCPConnection();
     921            0 :         if (sessionConn == nullptr)
     922              :         {
     923            0 :             secureSession->SetTCPConnection(ctxt->conn);
     924              :         }
     925              :         else
     926              :         {
     927            0 :             if (sessionConn != ctxt->conn)
     928              :             {
     929            0 :                 ChipLogError(Inet, "Data received over wrong connection %p. Dropping it!", ctxt->conn);
     930            0 :                 return;
     931              :             }
     932              :         }
     933              :     }
     934              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     935              : 
     936        14812 :     PayloadHeader payloadHeader;
     937              : 
     938              :     // Drop secure unicast messages with privacy enabled.
     939        14812 :     if (partialPacketHeader.HasPrivacyFlag())
     940              :     {
     941            1 :         ChipLogError(Inet, "Dropping secure unicast message with privacy flag set");
     942            1 :         return;
     943              :     }
     944              : 
     945        14811 :     PacketHeader packetHeader;
     946        14811 :     ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
     947              : 
     948        14811 :     SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
     949              : 
     950        14811 :     if (msg.IsNull())
     951              :     {
     952            0 :         ChipLogError(Inet, "Secure transport received Unicast NULL packet, discarding");
     953            0 :         return;
     954              :     }
     955              : 
     956              :     // We need to allow through messages even on sessions that are pending
     957              :     // evictions, because for some cases (UpdateNOC, RemoveFabric, etc) there
     958              :     // can be a single exchange alive on the session waiting for a MRP ack, and
     959              :     // we need to make sure to send the ack through.  The exchange manager is
     960              :     // responsible for ensuring that such messages do not lead to new exchange
     961              :     // creation.
     962        14811 :     if (!secureSession->IsDefunct() && !secureSession->IsActiveSession() && !secureSession->IsPendingEviction())
     963              :     {
     964            0 :         ChipLogError(Inet, "Secure transport received message on a session in an invalid state (state = '%s')",
     965              :                      secureSession->GetStateStr());
     966            0 :         return;
     967              :     }
     968              : 
     969              :     // Decrypt and verify the message before message counter verification or any further processing.
     970              :     CryptoContext::NonceStorage nonce;
     971              :     // PASE Sessions use the undefined node ID of all zeroes, since there is no node ID to use
     972              :     // and the key is short-lived and always different for each PASE session.
     973        14821 :     CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(),
     974        14821 :                               secureSession->GetSecureSessionType() == SecureSession::Type::kCASE ? secureSession->GetPeerNodeId()
     975              :                                                                                                   : kUndefinedNodeId);
     976        14811 :     if (SecureMessageCodec::Decrypt(secureSession->GetCryptoContext(), nonce, payloadHeader, packetHeader, msg) != CHIP_NO_ERROR)
     977              :     {
     978            3 :         ChipLogError(Inet, "Secure transport received message, but failed to decode/authenticate it, discarding");
     979            3 :         return;
     980              :     }
     981              : 
     982        14808 :     err =
     983        14808 :         secureSession->GetSessionMessageCounter().GetPeerMessageCounter().VerifyEncryptedUnicast(packetHeader.GetMessageCounter());
     984        14808 :     if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
     985              :     {
     986            8 :         ChipLogDetail(Inet,
     987              :                       "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
     988              :                       " on exchange " ChipLogFormatExchangeId,
     989              :                       packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
     990            8 :         isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
     991            8 :         err         = CHIP_NO_ERROR;
     992              :     }
     993        14808 :     if (err != CHIP_NO_ERROR)
     994              :     {
     995            0 :         ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     996            0 :         return;
     997              :     }
     998              : 
     999        14808 :     secureSession->MarkActiveRx();
    1000              : 
    1001        14808 :     if (isDuplicate == SessionMessageDelegate::DuplicateMessage::Yes && !payloadHeader.NeedsAck())
    1002              :     {
    1003              :         // If it's a duplicate message, but doesn't require an ack, let's drop it right here to save CPU
    1004              :         // cycles on further message processing.
    1005            2 :         return;
    1006              :     }
    1007              : 
    1008        14806 :     if (isDuplicate == SessionMessageDelegate::DuplicateMessage::No)
    1009              :     {
    1010        14800 :         secureSession->GetSessionMessageCounter().GetPeerMessageCounter().CommitEncryptedUnicast(packetHeader.GetMessageCounter());
    1011              :     }
    1012              : 
    1013        14806 :     if (mCB != nullptr)
    1014              :     {
    1015              :         MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kSecureUnicast, &payloadHeader, &packetHeader,
    1016              :                                     secureSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));
    1017        14806 :         CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, secureSession, peerAddress, msg->Start(), msg->TotalLength());
    1018              : 
    1019              :         // Always recompute whether a message is for a commissioning session based on the latest knowledge of
    1020              :         // the fabric table.
    1021        14806 :         if (secureSession->IsCASESession())
    1022              :         {
    1023           20 :             secureSession->SetCaseCommissioningSessionStatus(secureSession->GetFabricIndex() ==
    1024           10 :                                                              mFabricTable->GetPendingNewFabricIndex());
    1025              :         }
    1026        14806 :         mCB->OnMessageReceived(packetHeader, payloadHeader, session.Value(), isDuplicate, std::move(msg));
    1027              :     }
    1028              :     else
    1029              :     {
    1030            0 :         ChipLogError(Inet, "Received SECURED message was not processed.");
    1031              :     }
    1032        14822 : }
    1033              : 
    1034              : /**
    1035              :  * Helper function to implement a single attempt to decrypt a groupcast message
    1036              :  * using the given group key and privacy setting.
    1037              :  *
    1038              :  * @param[in] partialPacketHeader The partial packet header with non-obfuscated message fields (result of calling DecodeFixed).
    1039              :  * @param[out] packetHeaderCopy A copy of the packet header, to be filled with privacy decrypted fields
    1040              :  * @param[out] payloadHeader The payload header of the decrypted message
    1041              :  * @param[in] applyPrivacy Whether to apply privacy deobfuscation
    1042              :  * @param[out] msgCopy A copy of the message, to be filled with the decrypted message
    1043              :  * @param[in] mac The MAC of the message
    1044              :  * @param[in] groupContext The group context to use for decryption key material
    1045              :  *
    1046              :  * @return true if the message was decrypted successfully
    1047              :  * @return false if the message could not be decrypted
    1048              :  */
    1049            9 : static bool GroupKeyDecryptAttempt(const PacketHeader & partialPacketHeader, PacketHeader & packetHeaderCopy,
    1050              :                                    PayloadHeader & payloadHeader, bool applyPrivacy, System::PacketBufferHandle & msgCopy,
    1051              :                                    const MessageAuthenticationCode & mac,
    1052              :                                    const Credentials::GroupDataProvider::GroupSession & groupContext)
    1053              : {
    1054            9 :     bool decrypted = false;
    1055            9 :     CryptoContext context(groupContext.keyContext);
    1056              : 
    1057            9 :     if (applyPrivacy)
    1058              :     {
    1059              :         // Perform privacy deobfuscation, if applicable.
    1060            3 :         uint8_t * privacyHeader = partialPacketHeader.PrivacyHeader(msgCopy->Start());
    1061            3 :         size_t privacyLength    = partialPacketHeader.PrivacyHeaderLength();
    1062            3 :         if (CHIP_NO_ERROR != context.PrivacyDecrypt(privacyHeader, privacyLength, privacyHeader, partialPacketHeader, mac))
    1063              :         {
    1064            0 :             return false;
    1065              :         }
    1066              :     }
    1067              : 
    1068            9 :     if (packetHeaderCopy.DecodeAndConsume(msgCopy) != CHIP_NO_ERROR)
    1069              :     {
    1070            0 :         ChipLogError(Inet, "Failed to decode Groupcast packet header. Discarding.");
    1071            0 :         return false;
    1072              :     }
    1073              : 
    1074              :     // Optimization to reduce number of decryption attempts
    1075            9 :     GroupId groupId = packetHeaderCopy.GetDestinationGroupId().Value();
    1076            9 :     if (groupId != groupContext.group_id)
    1077              :     {
    1078            3 :         return false;
    1079              :     }
    1080              : 
    1081              :     CryptoContext::NonceStorage nonce;
    1082            6 :     CryptoContext::BuildNonce(nonce, packetHeaderCopy.GetSecurityFlags(), packetHeaderCopy.GetMessageCounter(),
    1083            6 :                               packetHeaderCopy.GetSourceNodeId().Value());
    1084            6 :     decrypted = (CHIP_NO_ERROR == SecureMessageCodec::Decrypt(context, nonce, payloadHeader, packetHeaderCopy, msgCopy));
    1085              : 
    1086            6 :     return decrypted;
    1087            9 : }
    1088              : 
    1089            7 : void SessionManager::SecureGroupMessageDispatch(const PacketHeader & partialPacketHeader,
    1090              :                                                 const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
    1091              : {
    1092              :     MATTER_TRACE_SCOPE("Group Message Dispatch", "SessionManager");
    1093              : 
    1094            7 :     PayloadHeader payloadHeader;
    1095            7 :     PacketHeader packetHeaderCopy; /// Packet header decoded per group key, with privacy decrypted fields
    1096            7 :     System::PacketBufferHandle msgCopy;
    1097            7 :     Credentials::GroupDataProvider * groups = Credentials::GetGroupDataProvider();
    1098            7 :     VerifyOrReturn(nullptr != groups);
    1099            7 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1100              : 
    1101            7 :     if (!partialPacketHeader.HasDestinationGroupId())
    1102              :     {
    1103            0 :         return; // malformed packet
    1104              :     }
    1105              : 
    1106              :     // Check if Message Header is valid first
    1107            7 :     if (!(partialPacketHeader.IsValidMCSPMsg() || partialPacketHeader.IsValidGroupMsg()))
    1108              :     {
    1109            0 :         ChipLogError(Inet, "Invalid condition found in packet header");
    1110            0 :         return;
    1111              :     }
    1112              : 
    1113              :     // Trial decryption with GroupDataProvider
    1114            7 :     Credentials::GroupDataProvider::GroupSession groupContext;
    1115              : 
    1116              :     AutoRelease<Credentials::GroupDataProvider::GroupSessionIterator> iter(
    1117            7 :         groups->IterateGroupSessions(partialPacketHeader.GetSessionId()));
    1118              : 
    1119            7 :     if (iter.IsNull())
    1120              :     {
    1121            0 :         ChipLogError(Inet, "Failed to retrieve Groups iterator. Discarding everything");
    1122            0 :         return;
    1123              :     }
    1124              : 
    1125              :     // Extract MIC from the end of the message.
    1126            7 :     uint8_t * data     = msg->Start();
    1127            7 :     size_t len         = msg->DataLength();
    1128            7 :     uint16_t footerLen = partialPacketHeader.MICTagLength();
    1129            7 :     VerifyOrReturn(footerLen <= len);
    1130              : 
    1131            7 :     uint16_t taglen = 0;
    1132              :     MessageAuthenticationCode mac;
    1133            7 :     ReturnOnFailure(mac.Decode(partialPacketHeader, &data[len - footerLen], footerLen, &taglen));
    1134            7 :     VerifyOrReturn(taglen == footerLen);
    1135              : 
    1136            7 :     bool decrypted = false;
    1137           14 :     while (!decrypted && iter->Next(groupContext))
    1138              :     {
    1139            7 :         CryptoContext context(groupContext.keyContext);
    1140            7 :         msgCopy = msg.CloneData();
    1141            7 :         if (msgCopy.IsNull())
    1142              :         {
    1143            0 :             ChipLogError(Inet, "Failed to clone Groupcast message buffer. Discarding.");
    1144            0 :             return;
    1145              :         }
    1146              : 
    1147            7 :         bool privacy = partialPacketHeader.HasPrivacyFlag();
    1148              :         decrypted =
    1149            7 :             GroupKeyDecryptAttempt(partialPacketHeader, packetHeaderCopy, payloadHeader, privacy, msgCopy, mac, groupContext);
    1150              : 
    1151              : #if CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2
    1152            7 :         if (privacy && !decrypted)
    1153              :         {
    1154              :             // Try processing the P=1 message again without privacy as a work-around for invalid early-SVE2 nodes.
    1155            2 :             msgCopy = msg.CloneData();
    1156            2 :             if (msgCopy.IsNull())
    1157              :             {
    1158            0 :                 ChipLogError(Inet, "Failed to clone Groupcast message buffer. Discarding.");
    1159            0 :                 return;
    1160              :             }
    1161              :             decrypted =
    1162            2 :                 GroupKeyDecryptAttempt(partialPacketHeader, packetHeaderCopy, payloadHeader, false, msgCopy, mac, groupContext);
    1163              :         }
    1164              : #endif // CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2
    1165            7 :     }
    1166            7 :     iter.Release();
    1167              : 
    1168            7 :     if (!decrypted)
    1169              :     {
    1170            1 :         ChipLogError(Inet, "Failed to decrypt group message. Discarding everything");
    1171            1 :         return;
    1172              :     }
    1173            6 :     msg = std::move(msgCopy);
    1174              : 
    1175              :     // MCSP check
    1176            6 :     if (packetHeaderCopy.IsValidMCSPMsg())
    1177              :     {
    1178              :         // TODO: When MCSP Msg, create Secure Session instead of a Group session
    1179              : 
    1180              :         // TODO
    1181              :         // if (packetHeaderCopy.GetDestinationNodeId().Value() == ThisDeviceNodeID)
    1182              :         // {
    1183              :         //     MCSP processing..
    1184              :         // }
    1185              : 
    1186            0 :         return;
    1187              :     }
    1188              : 
    1189              :     // Group Messages should never send an Ack
    1190            6 :     if (payloadHeader.NeedsAck())
    1191              :     {
    1192            0 :         ChipLogError(Inet, "Unexpected ACK requested for group message");
    1193            0 :         return;
    1194              :     }
    1195              : 
    1196              :     // Handle Group message counter here spec 4.7.3
    1197              :     // spec 4.5.1.2 for msg counter
    1198            6 :     Transport::PeerMessageCounter * counter = nullptr;
    1199              : 
    1200            6 :     if (CHIP_NO_ERROR ==
    1201           18 :         gGroupPeerTable->FindOrAddPeer(groupContext.fabric_index, packetHeaderCopy.GetSourceNodeId().Value(),
    1202           12 :                                        packetHeaderCopy.IsSecureSessionControlMsg(), counter))
    1203              :     {
    1204            6 :         if (Credentials::GroupDataProvider::SecurityPolicy::kTrustFirst == groupContext.security_policy)
    1205              :         {
    1206            4 :             err = counter->VerifyOrTrustFirstGroup(packetHeaderCopy.GetMessageCounter());
    1207              :         }
    1208              :         else
    1209              :         {
    1210              : 
    1211              :             // TODO support cache and sync with MCSP. Issue  #11689
    1212            2 :             ChipLogError(Inet, "Received Group Msg with key policy Cache and Sync, but MCSP is not implemented");
    1213            2 :             return;
    1214              : 
    1215              :             // cache and sync
    1216              :             // err = counter->VerifyGroup(packetHeaderCopy.GetMessageCounter());
    1217              :         }
    1218              : 
    1219            4 :         if (err != CHIP_NO_ERROR)
    1220              :         {
    1221              :             // Exit now, since Group Messages don't have acks or responses of any kind.
    1222            1 :             ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
    1223            1 :             return;
    1224              :         }
    1225              :     }
    1226              :     else
    1227              :     {
    1228            0 :         ChipLogError(Inet,
    1229              :                      "Group Counter Tables full or invalid NodeId/FabricIndex after decryption of message, dropping everything");
    1230            0 :         return;
    1231              :     }
    1232              : 
    1233            3 :     counter->CommitGroup(packetHeaderCopy.GetMessageCounter());
    1234              : 
    1235            3 :     if (mCB != nullptr)
    1236              :     {
    1237              :         // TODO : When MCSP is done, clean up session creation logic
    1238            3 :         Transport::IncomingGroupSession groupSession(groupContext.group_id, groupContext.fabric_index,
    1239            3 :                                                      packetHeaderCopy.GetSourceNodeId().Value());
    1240              : 
    1241              :         MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kGroupMessage, &payloadHeader, &packetHeaderCopy,
    1242              :                                     &groupSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));
    1243              : 
    1244            3 :         CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeaderCopy, &groupSession, peerAddress, msg->Start(), msg->TotalLength());
    1245            3 :         mCB->OnMessageReceived(packetHeaderCopy, payloadHeader, SessionHandle(groupSession),
    1246            3 :                                SessionMessageDelegate::DuplicateMessage::No, std::move(msg));
    1247            3 :     }
    1248              :     else
    1249              :     {
    1250            0 :         ChipLogError(Inet, "Received GROUP message was not processed.");
    1251              :     }
    1252           11 : }
    1253              : 
    1254            1 : Optional<SessionHandle> SessionManager::FindSecureSessionForNode(ScopedNodeId peerNodeId,
    1255              :                                                                  const Optional<Transport::SecureSession::Type> & type,
    1256              :                                                                  TransportPayloadCapability transportPayloadCapability)
    1257              : {
    1258            1 :     SecureSession * mrpSession = nullptr;
    1259              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1260            1 :     SecureSession * tcpSession = nullptr;
    1261              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1262              : 
    1263            1 :     mSecureSessions.ForEachSession([&peerNodeId, &type, &mrpSession,
    1264              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1265              :                                     &tcpSession,
    1266              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1267           15 :                                     &transportPayloadCapability](auto session) {
    1268            4 :         if (session->IsActiveSession() && session->GetPeer() == peerNodeId &&
    1269            2 :             (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
    1270              :         {
    1271            2 :             if (transportPayloadCapability == TransportPayloadCapability::kMRPOrTCPCompatiblePayload ||
    1272            2 :                 transportPayloadCapability == TransportPayloadCapability::kLargePayload)
    1273              :             {
    1274              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1275              :                 // Set up a TCP transport based session as standby
    1276            0 :                 if ((tcpSession == nullptr || tcpSession->GetLastPeerActivityTime() < session->GetLastPeerActivityTime()) &&
    1277            0 :                     session->GetTCPConnection() != nullptr)
    1278              :                 {
    1279            0 :                     tcpSession = session;
    1280              :                 }
    1281              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1282              :             }
    1283              : 
    1284            2 :             if ((mrpSession == nullptr) || (mrpSession->GetLastPeerActivityTime() < session->GetLastPeerActivityTime()))
    1285              :             {
    1286            2 :                 mrpSession = session;
    1287              :             }
    1288              :         }
    1289              : 
    1290            2 :         return Loop::Continue;
    1291              :     });
    1292              : 
    1293              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1294            1 :     if (transportPayloadCapability == TransportPayloadCapability::kLargePayload)
    1295              :     {
    1296            0 :         return tcpSession != nullptr ? MakeOptional<SessionHandle>(*tcpSession) : Optional<SessionHandle>::Missing();
    1297              :     }
    1298              : 
    1299            1 :     if (transportPayloadCapability == TransportPayloadCapability::kMRPOrTCPCompatiblePayload)
    1300              :     {
    1301              :         // If MRP-based session is available, use it.
    1302            0 :         if (mrpSession != nullptr)
    1303              :         {
    1304            0 :             return MakeOptional<SessionHandle>(*mrpSession);
    1305              :         }
    1306              : 
    1307              :         // Otherwise, look for a tcp-based session
    1308            0 :         if (tcpSession != nullptr)
    1309              :         {
    1310            0 :             return MakeOptional<SessionHandle>(*tcpSession);
    1311              :         }
    1312              : 
    1313            0 :         return Optional<SessionHandle>::Missing();
    1314              :     }
    1315              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1316              : 
    1317            1 :     return mrpSession != nullptr ? MakeOptional<SessionHandle>(*mrpSession) : Optional<SessionHandle>::Missing();
    1318              : }
    1319              : 
    1320              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1321            0 : void SessionManager::MarkSecureSessionOverTCPForEviction(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr)
    1322              : {
    1323              :     // Mark the corresponding secure sessions for eviction
    1324            0 :     mSecureSessions.ForEachSession([&](auto session) {
    1325            0 :         if (session->IsActiveSession() && session->GetTCPConnection() == conn)
    1326              :         {
    1327            0 :             SessionHandle handle(*session);
    1328              :             // Notify the SessionConnection delegate of the connection
    1329              :             // closure.
    1330            0 :             if (mConnDelegate != nullptr)
    1331              :             {
    1332            0 :                 mConnDelegate->OnTCPConnectionClosed(handle, conErr);
    1333              :             }
    1334              : 
    1335              :             // Dis-associate the connection from session by setting it to a
    1336              :             // nullptr.
    1337            0 :             session->SetTCPConnection(nullptr);
    1338              :             // Mark session for eviction.
    1339            0 :             session->MarkForEviction();
    1340            0 :         }
    1341              : 
    1342            0 :         return Loop::Continue;
    1343              :     });
    1344            0 : }
    1345              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1346              : 
    1347              : /**
    1348              :  * Provides a means to get diagnostic information such as number of sessions.
    1349              :  */
    1350            0 : [[maybe_unused]] CHIP_ERROR SessionManager::ForEachSessionHandle(void * context, SessionHandleCallback lambda)
    1351              : {
    1352            0 :     mSecureSessions.ForEachSession([&](auto session) {
    1353            0 :         SessionHandle handle(*session);
    1354            0 :         lambda(context, handle);
    1355            0 :         return Loop::Continue;
    1356            0 :     });
    1357            0 :     return CHIP_NO_ERROR;
    1358              : }
    1359              : 
    1360              : } // namespace chip
        

Generated by: LCOV version 2.0-1