Matter SDK Coverage Report
Current view: top level - transport - SessionManager.cpp (source / functions) Coverage Total Hit
Test: SHA:2a48c1efeab1c0f76f3adb3a0940b0f7de706453 Lines: 77.3 % 586 453
Test Date: 2026-01-31 08:14:20 Functions: 63.0 % 46 29

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

Generated by: LCOV version 2.0-1