Matter SDK Coverage Report
Current view: top level - transport - SessionManager.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 71.1 % 588 418
Test Date: 2025-01-17 19:00:11 Functions: 54.9 % 51 28

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

Generated by: LCOV version 2.0-1