Matter SDK Coverage Report
Current view: top level - app - CASESessionManager.cpp (source / functions) Coverage Total Hit
Test: SHA:f1767a8b0a3778fdf31b1d979afbdf544892fd94 Lines: 30.0 % 80 24
Test Date: 2026-06-03 07:35:21 Functions: 40.0 % 15 6

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : #include <app/CASESessionManager.h>
      20              : #include <lib/address_resolve/AddressResolve.h>
      21              : 
      22              : namespace chip {
      23              : 
      24            1 : CHIP_ERROR CASESessionManager::Init(chip::System::Layer * systemLayer, const CASESessionManagerConfig & params)
      25              : {
      26            1 :     ReturnErrorOnFailure(params.sessionInitParams.Validate());
      27            1 :     mConfig = params;
      28            1 :     params.sessionInitParams.exchangeMgr->GetReliableMessageMgr()->RegisterSessionUpdateDelegate(this);
      29            1 :     return AddressResolve::Resolver::Instance().Init(systemLayer);
      30              : }
      31              : 
      32            1 : void CASESessionManager::Shutdown()
      33              : {
      34            1 :     AddressResolve::Resolver::Instance().Shutdown();
      35            1 : }
      36              : 
      37            0 : void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
      38              :                                                 Callback::Callback<OnDeviceConnectionFailure> * onFailure,
      39              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      40              :                                                 uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
      41              : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      42              :                                                 TransportPayloadCapability transportPayloadCapability,
      43              :                                                 const Optional<AddressResolve::ResolveResult> & fallbackResolveResult)
      44              : {
      45            0 :     FindOrEstablishSessionHelper(peerId, onConnection, onFailure, nullptr,
      46              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      47              :                                  attemptCount, onRetry,
      48              : #endif
      49              :                                  transportPayloadCapability, fallbackResolveResult);
      50            0 : }
      51              : 
      52            0 : void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
      53              :                                                 Callback::Callback<OperationalSessionSetup::OnSetupFailure> * onSetupFailure,
      54              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      55              :                                                 uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
      56              : #endif
      57              :                                                 TransportPayloadCapability transportPayloadCapability)
      58              : {
      59            0 :     FindOrEstablishSessionHelper(peerId, onConnection, nullptr, onSetupFailure,
      60              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      61              :                                  attemptCount, onRetry,
      62              : #endif
      63              :                                  transportPayloadCapability);
      64            0 : }
      65              : 
      66            0 : void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
      67              :                                                 std::nullptr_t,
      68              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      69              :                                                 uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
      70              : #endif
      71              :                                                 TransportPayloadCapability transportPayloadCapability)
      72              : {
      73            0 :     FindOrEstablishSessionHelper(peerId, onConnection, nullptr, nullptr,
      74              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      75              :                                  attemptCount, onRetry,
      76              : #endif
      77              :                                  transportPayloadCapability);
      78            0 : }
      79              : 
      80            0 : void CASESessionManager::FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
      81              :                                                 Callback::Callback<OnDeviceConnectionFailure> * onFailure,
      82              :                                                 TransportPayloadCapability transportPayloadCapability)
      83              : {
      84            0 :     FindOrEstablishSessionHelper(peerId, onConnection, onFailure, nullptr,
      85              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      86              :                                  1 /* attemptCount */, nullptr /* onRetry */,
      87              : #endif
      88              :                                  transportPayloadCapability);
      89            0 : }
      90              : 
      91            0 : void CASESessionManager::FindOrEstablishSessionHelper(const ScopedNodeId & peerId,
      92              :                                                       Callback::Callback<OnDeviceConnected> * onConnection,
      93              :                                                       Callback::Callback<OnDeviceConnectionFailure> * onFailure,
      94              :                                                       Callback::Callback<OperationalSessionSetup::OnSetupFailure> * onSetupFailure,
      95              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
      96              :                                                       uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
      97              : #endif
      98              :                                                       TransportPayloadCapability transportPayloadCapability,
      99              :                                                       const Optional<AddressResolve::ResolveResult> & fallbackResolveResult)
     100              : {
     101            0 :     ChipLogDetail(CASESessionManager, "FindOrEstablishSession: PeerId = [%d:" ChipLogFormatX64 "]", peerId.GetFabricIndex(),
     102              :                   ChipLogValueX64(peerId.GetNodeId()));
     103              : 
     104            0 :     bool forAddressUpdate             = false;
     105            0 :     OperationalSessionSetup * session = FindExistingSessionSetup(peerId, forAddressUpdate);
     106            0 :     if (session == nullptr)
     107              :     {
     108            0 :         ChipLogDetail(CASESessionManager, "FindOrEstablishSession: No existing OperationalSessionSetup instance found");
     109            0 :         session = mConfig.sessionSetupPool->Allocate(mConfig.sessionInitParams, mConfig.clientPool, peerId, this);
     110              : 
     111            0 :         if (session == nullptr)
     112              :         {
     113            0 :             if (onFailure != nullptr)
     114              :             {
     115            0 :                 onFailure->mCall(onFailure->mContext, peerId, CHIP_ERROR_NO_MEMORY);
     116              :             }
     117              : 
     118            0 :             if (onSetupFailure != nullptr)
     119              :             {
     120              :                 OperationalSessionSetup::ConnectionFailureInfo failureInfo(peerId, CHIP_ERROR_NO_MEMORY,
     121            0 :                                                                            SessionEstablishmentStage::kUnknown);
     122            0 :                 onSetupFailure->mCall(onSetupFailure->mContext, failureInfo);
     123              :             }
     124            0 :             return;
     125              :         }
     126              :     }
     127              : 
     128              : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
     129            0 :     session->UpdateAttemptCount(attemptCount);
     130            0 :     if (onRetry)
     131              :     {
     132            0 :         session->AddRetryHandler(onRetry);
     133              :     }
     134              : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
     135              : 
     136              : #if CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK
     137              :     // Set fallback resolve result if provided
     138              :     if (fallbackResolveResult.HasValue())
     139              :     {
     140              :         session->SetFallbackResolveResult(fallbackResolveResult.Value());
     141              :     }
     142              : #endif // CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK
     143              : 
     144            0 :     if (onFailure != nullptr)
     145              :     {
     146            0 :         session->Connect(onConnection, onFailure, transportPayloadCapability);
     147              :     }
     148              : 
     149            0 :     if (onSetupFailure != nullptr)
     150              :     {
     151            0 :         session->Connect(onConnection, onSetupFailure, transportPayloadCapability);
     152              :     }
     153              : }
     154              : 
     155            1 : void CASESessionManager::ReleaseSessionsForFabric(FabricIndex fabricIndex)
     156              : {
     157              :     // Intentionally bypasses the IsEstablishingSession() in-flight guard used by
     158              :     // ReleaseSession(peerId). Fabric removal is irreversible; all setups for the fabric
     159              :     // -- including mid-handshake ones -- must be torn down unconditionally to avoid
     160              :     // dangling references to a removed fabric.
     161            1 :     mConfig.sessionSetupPool->ReleaseAllSessionSetupsForFabric(fabricIndex);
     162            1 : }
     163              : 
     164            1 : void CASESessionManager::ReleaseAllSessions()
     165              : {
     166              :     // Intentionally bypasses the IsEstablishingSession() in-flight guard used by
     167              :     // ReleaseSession(peerId). Shutdown is terminal; every setup must be destroyed
     168              :     // regardless of handshake state. Safe because the caller is tearing down the entire
     169              :     // stack, not trimming individual peers.
     170            1 :     mConfig.sessionSetupPool->ReleaseAllSessionSetup();
     171            1 : }
     172              : 
     173            0 : CHIP_ERROR CASESessionManager::GetPeerAddress(const ScopedNodeId & peerId, Transport::PeerAddress & addr,
     174              :                                               TransportPayloadCapability transportPayloadCapability)
     175              : {
     176            0 :     ReturnErrorOnFailure(mConfig.sessionInitParams.Validate());
     177            0 :     auto optionalSessionHandle = FindExistingSession(peerId, transportPayloadCapability);
     178            0 :     VerifyOrReturnError(optionalSessionHandle.HasValue(), CHIP_ERROR_NOT_CONNECTED);
     179            0 :     addr = optionalSessionHandle.Value()->AsSecureSession()->GetPeerAddress();
     180            0 :     return CHIP_NO_ERROR;
     181            0 : }
     182              : 
     183            0 : void CASESessionManager::UpdatePeerAddress(ScopedNodeId peerId)
     184              : {
     185            0 :     bool forAddressUpdate             = true;
     186            0 :     OperationalSessionSetup * session = FindExistingSessionSetup(peerId, forAddressUpdate);
     187            0 :     if (session == nullptr)
     188              :     {
     189            0 :         ChipLogDetail(CASESessionManager, "UpdatePeerAddress: No existing OperationalSessionSetup instance found");
     190              : 
     191            0 :         session = mConfig.sessionSetupPool->Allocate(mConfig.sessionInitParams, mConfig.clientPool, peerId, this);
     192            0 :         if (session == nullptr)
     193              :         {
     194            0 :             ChipLogDetail(CASESessionManager, "UpdatePeerAddress: Failed to allocate OperationalSessionSetup instance");
     195            0 :             return;
     196              :         }
     197              :     }
     198              :     else
     199              :     {
     200            0 :         ChipLogDetail(CASESessionManager,
     201              :                       "UpdatePeerAddress: Found existing OperationalSessionSetup instance for peerId[" ChipLogFormatX64 "]",
     202              :                       ChipLogValueX64(peerId.GetNodeId()));
     203              :     }
     204              : 
     205            0 :     session->PerformAddressUpdate();
     206              : }
     207              : 
     208            0 : OperationalSessionSetup * CASESessionManager::FindExistingSessionSetup(const ScopedNodeId & peerId, bool forAddressUpdate) const
     209              : {
     210            0 :     return mConfig.sessionSetupPool->FindSessionSetup(peerId, forAddressUpdate);
     211              : }
     212              : 
     213            0 : Optional<SessionHandle> CASESessionManager::FindExistingSession(const ScopedNodeId & peerId,
     214              :                                                                 const TransportPayloadCapability transportPayloadCapability) const
     215              : {
     216            0 :     return mConfig.sessionInitParams.sessionManager->FindSecureSessionForNode(
     217            0 :         peerId, MakeOptional(Transport::SecureSession::Type::kCASE), transportPayloadCapability);
     218              : }
     219              : 
     220           22 : void CASESessionManager::ReleaseSession(const ScopedNodeId & peerId)
     221              : {
     222           22 :     auto * session = mConfig.sessionSetupPool->FindSessionSetup(peerId, false);
     223           22 :     if (session != nullptr && session->IsEstablishingSession())
     224              :     {
     225              :         // Don't tear down a setup that's actively trying to establish.
     226              :         // The OperationalSessionSetup owns retry state (mAttemptsDone,
     227              :         // mRequestedBusyDelay, exponential backoff); destroying it resets
     228              :         // that state and produces a churn of fresh Sigma1 attempts against
     229              :         // a slow/busy accessory each time a higher layer
     230              :         // calls ReleaseSession during cold-start.
     231              :         // Let the in-flight attempt complete or hit its own retry cycle
     232              :         // naturally.
     233           17 :         ChipLogDetail(Discovery,
     234              :                       "CASESessionManager::ReleaseSession for " ChipLogFormatScopedNodeId
     235              :                       ": setup is establishing a session, skipping release",
     236              :                       ChipLogValueScopedNodeId(peerId));
     237           17 :         return;
     238              :     }
     239            5 :     ReleaseSession(session);
     240              : }
     241              : 
     242            5 : void CASESessionManager::ReleaseSession(OperationalSessionSetup * session)
     243              : {
     244              :     // OperationalSessionReleaseDelegate override. No IsEstablishingSession() guard here:
     245              :     // this overload's only callers are (1) OperationalSessionSetup itself, requesting
     246              :     // self-destruction after its handshake has finished (success or terminal failure)
     247              :     // -- by which point the setup is no longer "establishing" -- and (2) the peerId
     248              :     // overload above, which has already applied the guard. A check here would be
     249              :     // redundant with (2) and incorrect for (1), since (1) needs the release to happen.
     250            5 :     if (session != nullptr)
     251              :     {
     252            4 :         mConfig.sessionSetupPool->Release(session);
     253              :     }
     254            5 : }
     255              : 
     256              : } // namespace chip
        

Generated by: LCOV version 2.0-1