LCOV - code coverage report
Current view: top level - app/server - CommissioningWindowManager.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 174 254 68.5 %
Date: 2024-02-15 08:20:41 Functions: 23 32 71.9 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2021-2022 Project CHIP Authors
       4             :  *
       5             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6             :  *    you may not use this file except in compliance with the License.
       7             :  *    You may obtain a copy of the License at
       8             :  *
       9             :  *        http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  *    Unless required by applicable law or agreed to in writing, software
      12             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  *    See the License for the specific language governing permissions and
      15             :  *    limitations under the License.
      16             :  */
      17             : 
      18             : #include <app/icd/server/ICDServerConfig.h>
      19             : #include <app/server/CommissioningWindowManager.h>
      20             : #if CHIP_CONFIG_ENABLE_ICD_SERVER
      21             : #include <app/icd/server/ICDNotifier.h> // nogncheck
      22             : #endif
      23             : #include <app/reporting/reporting.h>
      24             : #include <app/server/Dnssd.h>
      25             : #include <app/server/Server.h>
      26             : #include <lib/dnssd/Advertiser.h>
      27             : #include <lib/support/CodeUtils.h>
      28             : #include <platform/CHIPDeviceLayer.h>
      29             : #include <platform/CommissionableDataProvider.h>
      30             : #include <platform/DeviceControlServer.h>
      31             : 
      32             : using namespace chip::app::Clusters;
      33             : using namespace chip::System::Clock;
      34             : 
      35             : using AdministratorCommissioning::CommissioningWindowStatusEnum;
      36             : using chip::app::DataModel::MakeNullable;
      37             : using chip::app::DataModel::Nullable;
      38             : using chip::app::DataModel::NullNullable;
      39             : 
      40             : namespace {
      41             : 
      42             : // As per specifications (Section 13.3), Nodes SHALL exit commissioning mode after 20 failed commission attempts.
      43             : constexpr uint8_t kMaxFailedCommissioningAttempts = 20;
      44             : 
      45           0 : void HandleSessionEstablishmentTimeout(chip::System::Layer * aSystemLayer, void * aAppState)
      46             : {
      47           0 :     chip::CommissioningWindowManager * commissionMgr = static_cast<chip::CommissioningWindowManager *>(aAppState);
      48           0 :     commissionMgr->OnSessionEstablishmentError(CHIP_ERROR_TIMEOUT);
      49           0 : }
      50             : 
      51           0 : void OnPlatformEventWrapper(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
      52             : {
      53           0 :     chip::CommissioningWindowManager * commissionMgr = reinterpret_cast<chip::CommissioningWindowManager *>(arg);
      54           0 :     commissionMgr->OnPlatformEvent(event);
      55           0 : }
      56             : } // namespace
      57             : 
      58             : namespace chip {
      59             : 
      60           0 : void CommissioningWindowManager::OnPlatformEvent(const DeviceLayer::ChipDeviceEvent * event)
      61             : {
      62           0 :     if (event->Type == DeviceLayer::DeviceEventType::kCommissioningComplete)
      63             :     {
      64           0 :         ChipLogProgress(AppServer, "Commissioning completed successfully");
      65           0 :         DeviceLayer::SystemLayer().CancelTimer(HandleCommissioningWindowTimeout, this);
      66           0 :         mCommissioningTimeoutTimerArmed = false;
      67           0 :         Cleanup();
      68           0 :         mServer->GetSecureSessionManager().ExpireAllPASESessions();
      69             :         // That should have cleared out mPASESession.
      70             : #if CONFIG_NETWORK_LAYER_BLE && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
      71             :         // If in NonConcurrentConnection, this will already have been completed
      72           0 :         mServer->GetBleLayerObject()->CloseAllBleConnections();
      73             : #endif
      74             :     }
      75           0 :     else if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired)
      76             :     {
      77           0 :         ChipLogError(AppServer, "Failsafe timer expired");
      78           0 :         if (mPASESession)
      79             :         {
      80           0 :             mPASESession->AsSecureSession()->MarkForEviction();
      81             :         }
      82           0 :         HandleFailedAttempt(CHIP_ERROR_TIMEOUT);
      83             :     }
      84           0 :     else if (event->Type == DeviceLayer::DeviceEventType::kOperationalNetworkEnabled)
      85             :     {
      86           0 :         app::DnssdServer::Instance().AdvertiseOperational();
      87           0 :         ChipLogProgress(AppServer, "Operational advertising enabled");
      88             :     }
      89             : #if CONFIG_NETWORK_LAYER_BLE
      90           0 :     else if (event->Type == DeviceLayer::DeviceEventType::kCloseAllBleConnections)
      91             :     {
      92           0 :         ChipLogProgress(AppServer, "Received kCloseAllBleConnections:%d", static_cast<int>(event->Type));
      93           0 :         mServer->GetBleLayerObject()->Shutdown();
      94             :     }
      95             : #endif
      96           0 : }
      97             : 
      98           1 : void CommissioningWindowManager::Shutdown()
      99             : {
     100           1 :     StopAdvertisement(/* aShuttingDown = */ true);
     101             : 
     102           1 :     ResetState();
     103           1 : }
     104             : 
     105           7 : void CommissioningWindowManager::ResetState()
     106             : {
     107           7 :     mUseECM = false;
     108             : 
     109           7 :     mECMDiscriminator = 0;
     110           7 :     mECMIterations    = 0;
     111           7 :     mECMSaltLength    = 0;
     112             : 
     113           7 :     UpdateWindowStatus(CommissioningWindowStatusEnum::kWindowNotOpen);
     114             : 
     115           7 :     UpdateOpenerFabricIndex(NullNullable);
     116           7 :     UpdateOpenerVendorId(NullNullable);
     117             : 
     118           7 :     memset(&mECMPASEVerifier, 0, sizeof(mECMPASEVerifier));
     119           7 :     memset(mECMSalt, 0, sizeof(mECMSalt));
     120             : 
     121           7 :     DeviceLayer::SystemLayer().CancelTimer(HandleCommissioningWindowTimeout, this);
     122           7 :     mCommissioningTimeoutTimerArmed = false;
     123             : 
     124           7 :     DeviceLayer::PlatformMgr().RemoveEventHandler(OnPlatformEventWrapper, reinterpret_cast<intptr_t>(this));
     125           7 : }
     126             : 
     127           6 : void CommissioningWindowManager::Cleanup()
     128             : {
     129           6 :     StopAdvertisement(/* aShuttingDown = */ false);
     130           6 :     ResetState();
     131           6 : }
     132             : 
     133           1 : void CommissioningWindowManager::OnSessionEstablishmentError(CHIP_ERROR err)
     134             : {
     135           1 :     DeviceLayer::SystemLayer().CancelTimer(HandleSessionEstablishmentTimeout, this);
     136           1 :     HandleFailedAttempt(err);
     137           1 : }
     138             : 
     139           1 : void CommissioningWindowManager::HandleFailedAttempt(CHIP_ERROR err)
     140             : {
     141           1 :     mFailedCommissioningAttempts++;
     142           1 :     ChipLogError(AppServer, "Commissioning failed (attempt %d): %" CHIP_ERROR_FORMAT, mFailedCommissioningAttempts, err.Format());
     143             : #if CONFIG_NETWORK_LAYER_BLE
     144           1 :     mServer->GetBleLayerObject()->CloseAllBleConnections();
     145             : #endif
     146             : 
     147           1 :     CHIP_ERROR prevErr = err;
     148           1 :     if (mFailedCommissioningAttempts < kMaxFailedCommissioningAttempts)
     149             :     {
     150             :         // If the number of commissioning attempts has not exceeded maximum
     151             :         // retries, let's start listening for commissioning connections again.
     152           1 :         err = AdvertiseAndListenForPASE();
     153             :     }
     154             : 
     155           1 :     if (mAppDelegate != nullptr)
     156             :     {
     157           0 :         mAppDelegate->OnCommissioningSessionEstablishmentError(prevErr);
     158             :     }
     159             : 
     160           1 :     if (err != CHIP_NO_ERROR)
     161             :     {
     162             :         // The commissioning attempts limit was exceeded, or listening for
     163             :         // commmissioning connections failed.
     164           0 :         Cleanup();
     165             : 
     166           0 :         if (mAppDelegate != nullptr)
     167             :         {
     168           0 :             mAppDelegate->OnCommissioningSessionStopped();
     169             :         }
     170             :     }
     171           1 : }
     172             : 
     173           1 : void CommissioningWindowManager::OnSessionEstablishmentStarted()
     174             : {
     175             :     // As per specifications, section 5.5: Commissioning Flows
     176           1 :     constexpr System::Clock::Timeout kPASESessionEstablishmentTimeout = System::Clock::Seconds16(60);
     177           1 :     DeviceLayer::SystemLayer().StartTimer(kPASESessionEstablishmentTimeout, HandleSessionEstablishmentTimeout, this);
     178             : 
     179           1 :     ChipLogProgress(AppServer, "Commissioning session establishment step started");
     180           1 :     if (mAppDelegate != nullptr)
     181             :     {
     182           0 :         mAppDelegate->OnCommissioningSessionEstablishmentStarted();
     183             :     }
     184           1 : }
     185             : 
     186           0 : void CommissioningWindowManager::OnSessionEstablished(const SessionHandle & session)
     187             : {
     188           0 :     DeviceLayer::SystemLayer().CancelTimer(HandleSessionEstablishmentTimeout, this);
     189             : 
     190           0 :     ChipLogProgress(AppServer, "Commissioning completed session establishment step");
     191           0 :     if (mAppDelegate != nullptr)
     192             :     {
     193           0 :         mAppDelegate->OnCommissioningSessionStarted();
     194             :     }
     195             : 
     196           0 :     DeviceLayer::PlatformMgr().AddEventHandler(OnPlatformEventWrapper, reinterpret_cast<intptr_t>(this));
     197             : 
     198           0 :     StopAdvertisement(/* aShuttingDown = */ false);
     199             : 
     200           0 :     auto & failSafeContext = Server::GetInstance().GetFailSafeContext();
     201             :     // This should never be armed because we don't allow CASE sessions to arm the failsafe when the commissioning window is open and
     202             :     // we check that the failsafe is not armed before opening the commissioning window. None the less, it is good to double-check.
     203           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     204           0 :     if (failSafeContext.IsFailSafeArmed())
     205             :     {
     206           0 :         ChipLogError(AppServer, "Error - arm failsafe is already armed on PASE session establishment completion");
     207             :     }
     208             :     else
     209             :     {
     210           0 :         err = failSafeContext.ArmFailSafe(kUndefinedFabricIndex, System::Clock::Seconds16(60));
     211           0 :         if (err != CHIP_NO_ERROR)
     212             :         {
     213           0 :             ChipLogError(AppServer, "Error arming failsafe on PASE session establishment completion");
     214             :             // Don't allow a PASE session to hang around without a fail-safe.
     215           0 :             session->AsSecureSession()->MarkForEviction();
     216           0 :             HandleFailedAttempt(err);
     217             :         }
     218             :     }
     219             : 
     220           0 :     ChipLogProgress(AppServer, "Device completed Rendezvous process");
     221             : 
     222           0 :     if (err == CHIP_NO_ERROR)
     223             :     {
     224             :         // When the now-armed fail-safe is disarmed or expires it will handle
     225             :         // clearing out mPASESession.
     226           0 :         mPASESession.Grab(session);
     227             :     }
     228           0 : }
     229             : 
     230           6 : CHIP_ERROR CommissioningWindowManager::OpenCommissioningWindow(Seconds16 commissioningTimeout)
     231             : {
     232           6 :     VerifyOrReturnError(commissioningTimeout <= MaxCommissioningTimeout() && commissioningTimeout >= MinCommissioningTimeout(),
     233             :                         CHIP_ERROR_INVALID_ARGUMENT);
     234           6 :     auto & failSafeContext = Server::GetInstance().GetFailSafeContext();
     235           6 :     VerifyOrReturnError(failSafeContext.IsFailSafeFullyDisarmed(), CHIP_ERROR_INCORRECT_STATE);
     236             : 
     237           6 :     ReturnErrorOnFailure(Dnssd::ServiceAdvertiser::Instance().UpdateCommissionableInstanceName());
     238             : 
     239           6 :     ReturnErrorOnFailure(DeviceLayer::SystemLayer().StartTimer(commissioningTimeout, HandleCommissioningWindowTimeout, this));
     240             : 
     241           6 :     mCommissioningTimeoutTimerArmed = true;
     242             : 
     243           6 :     return AdvertiseAndListenForPASE();
     244             : }
     245             : 
     246           7 : CHIP_ERROR CommissioningWindowManager::AdvertiseAndListenForPASE()
     247             : {
     248           7 :     VerifyOrReturnError(mCommissioningTimeoutTimerArmed, CHIP_ERROR_INCORRECT_STATE);
     249             : 
     250           7 :     mPairingSession.Clear();
     251             : 
     252           7 :     ReturnErrorOnFailure(mServer->GetExchangeManager().RegisterUnsolicitedMessageHandlerForType(
     253             :         Protocols::SecureChannel::MsgType::PBKDFParamRequest, this));
     254           7 :     mListeningForPASE = true;
     255             : 
     256           7 :     if (mUseECM)
     257             :     {
     258           1 :         ReturnErrorOnFailure(SetTemporaryDiscriminator(mECMDiscriminator));
     259           1 :         ReturnErrorOnFailure(mPairingSession.WaitForPairing(mServer->GetSecureSessionManager(), mECMPASEVerifier, mECMIterations,
     260             :                                                             ByteSpan(mECMSalt, mECMSaltLength), GetLocalMRPConfig(), this));
     261             :     }
     262             :     else
     263             :     {
     264           6 :         uint32_t iterationCount                      = 0;
     265           6 :         uint8_t salt[kSpake2p_Max_PBKDF_Salt_Length] = { 0 };
     266           6 :         Spake2pVerifierSerialized serializedVerifier = { 0 };
     267           6 :         size_t serializedVerifierLen                 = 0;
     268             :         Spake2pVerifier verifier;
     269           6 :         MutableByteSpan saltSpan{ salt };
     270           6 :         MutableByteSpan verifierSpan{ serializedVerifier };
     271             : 
     272           6 :         auto * commissionableDataProvider = DeviceLayer::GetCommissionableDataProvider();
     273           6 :         ReturnErrorOnFailure(commissionableDataProvider->GetSpake2pIterationCount(iterationCount));
     274           6 :         ReturnErrorOnFailure(commissionableDataProvider->GetSpake2pSalt(saltSpan));
     275           6 :         ReturnErrorOnFailure(commissionableDataProvider->GetSpake2pVerifier(verifierSpan, serializedVerifierLen));
     276           6 :         VerifyOrReturnError(Crypto::kSpake2p_VerifierSerialized_Length == serializedVerifierLen, CHIP_ERROR_INVALID_ARGUMENT);
     277           6 :         VerifyOrReturnError(verifierSpan.size() == serializedVerifierLen, CHIP_ERROR_INTERNAL);
     278             : 
     279           6 :         ReturnErrorOnFailure(verifier.Deserialize(ByteSpan(serializedVerifier)));
     280             : 
     281           6 :         ReturnErrorOnFailure(mPairingSession.WaitForPairing(mServer->GetSecureSessionManager(), verifier, iterationCount, saltSpan,
     282             :                                                             GetLocalMRPConfig(), this));
     283             :     }
     284             : 
     285           7 :     ReturnErrorOnFailure(StartAdvertisement());
     286             : 
     287           7 :     return CHIP_NO_ERROR;
     288             : }
     289             : 
     290           5 : CHIP_ERROR CommissioningWindowManager::OpenBasicCommissioningWindow(Seconds16 commissioningTimeout,
     291             :                                                                     CommissioningWindowAdvertisement advertisementMode)
     292             : {
     293           5 :     RestoreDiscriminator();
     294             : 
     295             : #if CONFIG_NETWORK_LAYER_BLE
     296             :     // Enable BLE advertisements if commissioning window is to be opened on all supported
     297             :     // transports, and BLE is supported on the current device.
     298           5 :     SetBLE(advertisementMode == chip::CommissioningWindowAdvertisement::kAllSupported);
     299             : #else
     300             :     SetBLE(false);
     301             : #endif // CONFIG_NETWORK_LAYER_BLE
     302             : 
     303           5 :     mFailedCommissioningAttempts = 0;
     304             : 
     305           5 :     mUseECM = false;
     306             : 
     307           5 :     CHIP_ERROR err = OpenCommissioningWindow(commissioningTimeout);
     308           5 :     if (err != CHIP_NO_ERROR)
     309             :     {
     310           0 :         Cleanup();
     311             :     }
     312             : 
     313           5 :     return err;
     314             : }
     315             : 
     316             : CHIP_ERROR
     317           1 : CommissioningWindowManager::OpenBasicCommissioningWindowForAdministratorCommissioningCluster(
     318             :     System::Clock::Seconds16 commissioningTimeout, FabricIndex fabricIndex, VendorId vendorId)
     319             : {
     320           1 :     ReturnErrorOnFailure(OpenBasicCommissioningWindow(commissioningTimeout, CommissioningWindowAdvertisement::kDnssdOnly));
     321             : 
     322           1 :     UpdateOpenerFabricIndex(MakeNullable(fabricIndex));
     323           1 :     UpdateOpenerVendorId(MakeNullable(vendorId));
     324             : 
     325           1 :     return CHIP_NO_ERROR;
     326             : }
     327             : 
     328           1 : CHIP_ERROR CommissioningWindowManager::OpenEnhancedCommissioningWindow(Seconds16 commissioningTimeout, uint16_t discriminator,
     329             :                                                                        Spake2pVerifier & verifier, uint32_t iterations,
     330             :                                                                        ByteSpan salt, FabricIndex fabricIndex, VendorId vendorId)
     331             : {
     332             :     // Once a device is operational, it shall be commissioned into subsequent fabrics using
     333             :     // the operational network only.
     334           1 :     SetBLE(false);
     335             : 
     336           1 :     VerifyOrReturnError(salt.size() <= sizeof(mECMSalt), CHIP_ERROR_INVALID_ARGUMENT);
     337             : 
     338           1 :     memcpy(mECMSalt, salt.data(), salt.size());
     339           1 :     mECMSaltLength = static_cast<uint32_t>(salt.size());
     340             : 
     341           1 :     mFailedCommissioningAttempts = 0;
     342             : 
     343           1 :     mECMDiscriminator = discriminator;
     344           1 :     mECMIterations    = iterations;
     345             : 
     346           1 :     memcpy(&mECMPASEVerifier, &verifier, sizeof(Spake2pVerifier));
     347             : 
     348           1 :     mUseECM = true;
     349             : 
     350           1 :     CHIP_ERROR err = OpenCommissioningWindow(commissioningTimeout);
     351           1 :     if (err != CHIP_NO_ERROR)
     352             :     {
     353           0 :         Cleanup();
     354             :     }
     355             :     else
     356             :     {
     357           1 :         UpdateOpenerFabricIndex(MakeNullable(fabricIndex));
     358           1 :         UpdateOpenerVendorId(MakeNullable(vendorId));
     359             :     }
     360             : 
     361           1 :     return err;
     362             : }
     363             : 
     364           6 : void CommissioningWindowManager::CloseCommissioningWindow()
     365             : {
     366           6 :     if (IsCommissioningWindowOpen())
     367             :     {
     368             : #if CONFIG_NETWORK_LAYER_BLE
     369           6 :         if (mListeningForPASE)
     370             :         {
     371             :             // We never established PASE, so never armed a fail-safe and hence
     372             :             // can't rely on it expiring to close our BLE connection.  Do that
     373             :             // manually here.
     374           6 :             mServer->GetBleLayerObject()->CloseAllBleConnections();
     375             :         }
     376             : #endif
     377           6 :         ChipLogProgress(AppServer, "Closing pairing window");
     378           6 :         Cleanup();
     379             :     }
     380           6 : }
     381             : 
     382          56 : CommissioningWindowStatusEnum CommissioningWindowManager::CommissioningWindowStatusForCluster() const
     383             : {
     384             :     // If the condition we use to determine whether we were opened via the
     385             :     // cluster ever changes, make sure whatever code affects that condition
     386             :     // marks calls MatterReportingAttributeChangeCallback for WindowStatus as
     387             :     // needed.
     388          56 :     if (mOpenerVendorId.IsNull())
     389             :     {
     390             :         // Not opened via the cluster.
     391          46 :         return CommissioningWindowStatusEnum::kWindowNotOpen;
     392             :     }
     393             : 
     394          10 :     return mWindowStatus;
     395             : }
     396             : 
     397          18 : bool CommissioningWindowManager::IsCommissioningWindowOpen() const
     398             : {
     399          18 :     return mWindowStatus != CommissioningWindowStatusEnum::kWindowNotOpen;
     400             : }
     401             : 
     402           0 : void CommissioningWindowManager::OnFabricRemoved(FabricIndex removedIndex)
     403             : {
     404           0 :     if (!mOpenerFabricIndex.IsNull() && mOpenerFabricIndex.Value() == removedIndex)
     405             :     {
     406             :         // Per spec, we should clear out the stale fabric index.
     407           0 :         UpdateOpenerFabricIndex(NullNullable);
     408             :     }
     409           0 : }
     410             : 
     411          15 : Dnssd::CommissioningMode CommissioningWindowManager::GetCommissioningMode() const
     412             : {
     413          15 :     if (!mListeningForPASE)
     414             :     {
     415             :         // We should not be advertising ourselves as in commissioning mode.
     416             :         // We need to check this before mWindowStatus, because we might have an
     417             :         // open window even while we are not listening for PASE.
     418           7 :         return Dnssd::CommissioningMode::kDisabled;
     419             :     }
     420             : 
     421           8 :     switch (mWindowStatus)
     422             :     {
     423           1 :     case CommissioningWindowStatusEnum::kEnhancedWindowOpen:
     424           1 :         return Dnssd::CommissioningMode::kEnabledEnhanced;
     425           7 :     case CommissioningWindowStatusEnum::kBasicWindowOpen:
     426           7 :         return Dnssd::CommissioningMode::kEnabledBasic;
     427           0 :     default:
     428           0 :         return Dnssd::CommissioningMode::kDisabled;
     429             :     }
     430             : }
     431             : 
     432           7 : CHIP_ERROR CommissioningWindowManager::StartAdvertisement()
     433             : {
     434             : #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
     435             :     // notify device layer that advertisement is beginning (to do work such as increment rotating id)
     436             :     DeviceLayer::ConfigurationMgr().NotifyOfAdvertisementStart();
     437             : #endif
     438             : 
     439             : #if CONFIG_NETWORK_LAYER_BLE
     440           7 :     if (mIsBLE)
     441             :     {
     442           1 :         CHIP_ERROR err = chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true);
     443             :         // BLE advertising may just not be supported.  That should not prevent
     444             :         // us from opening a commissioning window and advertising over IP.
     445           1 :         if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE)
     446             :         {
     447           0 :             ChipLogProgress(AppServer, "BLE networking available but BLE advertising is not supported");
     448           0 :             err = CHIP_NO_ERROR;
     449             :         }
     450           1 :         ReturnErrorOnFailure(err);
     451             :     }
     452             : #endif // CONFIG_NETWORK_LAYER_BLE
     453             : 
     454           7 :     if (mUseECM)
     455             :     {
     456           1 :         UpdateWindowStatus(CommissioningWindowStatusEnum::kEnhancedWindowOpen);
     457             :     }
     458             :     else
     459             :     {
     460           6 :         UpdateWindowStatus(CommissioningWindowStatusEnum::kBasicWindowOpen);
     461             :     }
     462             : 
     463           7 :     if (mAppDelegate != nullptr)
     464             :     {
     465           0 :         mAppDelegate->OnCommissioningWindowOpened();
     466             :     }
     467             : 
     468             :     // reset all advertising, switching to our new commissioning mode.
     469           7 :     app::DnssdServer::Instance().StartServer();
     470             : 
     471           7 :     return CHIP_NO_ERROR;
     472             : }
     473             : 
     474           7 : CHIP_ERROR CommissioningWindowManager::StopAdvertisement(bool aShuttingDown)
     475             : {
     476           7 :     RestoreDiscriminator();
     477             : 
     478           7 :     mServer->GetExchangeManager().UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::PBKDFParamRequest);
     479           7 :     mListeningForPASE = false;
     480           7 :     mPairingSession.Clear();
     481             : 
     482             :     // If aShuttingDown, don't try to change our DNS-SD advertisements.
     483           7 :     if (!aShuttingDown)
     484             :     {
     485             :         // Stop advertising commissioning mode, since we're not accepting PASE
     486             :         // connections right now.  If we start accepting them again (via
     487             :         // AdvertiseAndListenForPASE) that will call StartAdvertisement as needed.
     488           6 :         app::DnssdServer::Instance().StartServer();
     489             :     }
     490             : 
     491             : #if CONFIG_NETWORK_LAYER_BLE
     492           7 :     if (mIsBLE)
     493             :     {
     494             :         // Ignore errors from SetBLEAdvertisingEnabled (which could be due to
     495             :         // BLE advertising not being supported at all).  Our commissioning
     496             :         // window is now closed and we need to notify our delegate of that.
     497           1 :         (void) chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false);
     498             :     }
     499             : #endif // CONFIG_NETWORK_LAYER_BLE
     500             : 
     501           7 :     if (mAppDelegate != nullptr)
     502             :     {
     503           0 :         mAppDelegate->OnCommissioningWindowClosed();
     504             :     }
     505             : 
     506           7 :     return CHIP_NO_ERROR;
     507             : }
     508             : 
     509           1 : CHIP_ERROR CommissioningWindowManager::SetTemporaryDiscriminator(uint16_t discriminator)
     510             : {
     511           1 :     return app::DnssdServer::Instance().SetEphemeralDiscriminator(MakeOptional(discriminator));
     512             : }
     513             : 
     514          12 : CHIP_ERROR CommissioningWindowManager::RestoreDiscriminator()
     515             : {
     516          12 :     return app::DnssdServer::Instance().SetEphemeralDiscriminator(NullOptional);
     517             : }
     518             : 
     519           2 : void CommissioningWindowManager::HandleCommissioningWindowTimeout(chip::System::Layer * aSystemLayer, void * aAppState)
     520             : {
     521           2 :     auto * commissionMgr                           = static_cast<CommissioningWindowManager *>(aAppState);
     522           2 :     commissionMgr->mCommissioningTimeoutTimerArmed = false;
     523           2 :     commissionMgr->CloseCommissioningWindow();
     524           2 : }
     525             : 
     526           0 : void CommissioningWindowManager::OnSessionReleased()
     527             : {
     528             :     // The PASE session has died, probably due to CloseSession.  Immediately
     529             :     // expire the fail-safe, if it's still armed (which it might not be if the
     530             :     // PASE session is being released due to the fail-safe expiring or being
     531             :     // disarmed).
     532             :     //
     533             :     // Expiring the fail-safe will make us start listening for new PASE sessions
     534             :     // as needed.
     535             :     //
     536             :     // Note that at this point the fail-safe _must_ be associated with our PASE
     537             :     // session, since we arm it when the PASE session is set up, and anything
     538             :     // that disarms the fail-safe would also tear down the PASE session.
     539           0 :     ExpireFailSafeIfArmed();
     540           0 : }
     541             : 
     542           0 : void CommissioningWindowManager::ExpireFailSafeIfArmed()
     543             : {
     544           0 :     auto & failSafeContext = Server::GetInstance().GetFailSafeContext();
     545           0 :     if (failSafeContext.IsFailSafeArmed())
     546             :     {
     547           0 :         failSafeContext.ForceFailSafeTimerExpiry();
     548             :     }
     549           0 : }
     550             : 
     551          14 : void CommissioningWindowManager::UpdateWindowStatus(CommissioningWindowStatusEnum aNewStatus)
     552             : {
     553          14 :     CommissioningWindowStatusEnum oldClusterStatus = CommissioningWindowStatusForCluster();
     554          14 :     if (mWindowStatus != aNewStatus)
     555             :     {
     556          12 :         mWindowStatus = aNewStatus;
     557             : #if CHIP_CONFIG_ENABLE_ICD_SERVER
     558             :         app::ICDListener::KeepActiveFlags request = app::ICDListener::KeepActiveFlag::kCommissioningWindowOpen;
     559             :         if (mWindowStatus != CommissioningWindowStatusEnum::kWindowNotOpen)
     560             :         {
     561             :             app::ICDNotifier::GetInstance().NotifyActiveRequestNotification(request);
     562             :         }
     563             :         else
     564             :         {
     565             :             app::ICDNotifier::GetInstance().NotifyActiveRequestWithdrawal(request);
     566             :         }
     567             : #endif // CHIP_CONFIG_ENABLE_ICD_SERVER
     568             :     }
     569             : 
     570          14 :     if (CommissioningWindowStatusForCluster() != oldClusterStatus)
     571             :     {
     572             :         // The Administrator Commissioning cluster is always on the root endpoint.
     573           2 :         MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
     574             :                                                AdministratorCommissioning::Attributes::WindowStatus::Id);
     575             :     }
     576          14 : }
     577             : 
     578           9 : void CommissioningWindowManager::UpdateOpenerVendorId(Nullable<VendorId> aNewOpenerVendorId)
     579             : {
     580             :     // Changing the opener vendor id affects what
     581             :     // CommissioningWindowStatusForCluster() returns.
     582           9 :     CommissioningWindowStatusEnum oldClusterStatus = CommissioningWindowStatusForCluster();
     583             : 
     584           9 :     if (mOpenerVendorId != aNewOpenerVendorId)
     585             :     {
     586             :         // The Administrator Commissioning cluster is always on the root endpoint.
     587           4 :         MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
     588             :                                                AdministratorCommissioning::Attributes::AdminVendorId::Id);
     589             :     }
     590             : 
     591           9 :     mOpenerVendorId = aNewOpenerVendorId;
     592             : 
     593           9 :     if (CommissioningWindowStatusForCluster() != oldClusterStatus)
     594             :     {
     595             :         // The Administrator Commissioning cluster is always on the root endpoint.
     596           2 :         MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
     597             :                                                AdministratorCommissioning::Attributes::WindowStatus::Id);
     598             :     }
     599           9 : }
     600             : 
     601           9 : void CommissioningWindowManager::UpdateOpenerFabricIndex(Nullable<FabricIndex> aNewOpenerFabricIndex)
     602             : {
     603           9 :     if (mOpenerFabricIndex != aNewOpenerFabricIndex)
     604             :     {
     605             :         // The Administrator Commissioning cluster is always on the root endpoint.
     606           4 :         MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
     607             :                                                AdministratorCommissioning::Attributes::AdminFabricIndex::Id);
     608             :     }
     609             : 
     610           9 :     mOpenerFabricIndex = aNewOpenerFabricIndex;
     611           9 : }
     612             : 
     613           0 : CHIP_ERROR CommissioningWindowManager::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader,
     614             :                                                                     Messaging::ExchangeDelegate *& newDelegate)
     615             : {
     616             :     using Protocols::SecureChannel::MsgType;
     617             : 
     618             :     // Must be a PBKDFParamRequest message.  Stop listening to new
     619             :     // PBKDFParamRequest messages and hand it off to mPairingSession.  If
     620             :     // mPairingSession's OnMessageReceived fails, it will call our
     621             :     // OnSessionEstablishmentError, and that will either start listening for a
     622             :     // new PBKDFParamRequest or not, depending on how many failures we had seen.
     623             :     //
     624             :     // It's very important that we stop listening here, so that new incoming
     625             :     // PASE establishment attempts don't interrupt our existing establishment.
     626           0 :     mServer->GetExchangeManager().UnregisterUnsolicitedMessageHandlerForType(MsgType::PBKDFParamRequest);
     627           0 :     newDelegate = &mPairingSession;
     628           0 :     return CHIP_NO_ERROR;
     629             : }
     630             : 
     631           0 : void CommissioningWindowManager::OnExchangeCreationFailed(Messaging::ExchangeDelegate * delegate)
     632             : {
     633             :     using Protocols::SecureChannel::MsgType;
     634             : 
     635             :     // We couldn't create an exchange, so didn't manage to call
     636             :     // OnMessageReceived on mPairingSession.  Just go back to listening for
     637             :     // PBKDFParamRequest messages.
     638           0 :     mServer->GetExchangeManager().RegisterUnsolicitedMessageHandlerForType(MsgType::PBKDFParamRequest, this);
     639           0 : }
     640             : 
     641             : } // namespace chip

Generated by: LCOV version 1.14