Matter SDK Coverage Report
Current view: top level - app/server - CommissioningWindowManager.cpp (source / functions) Coverage Total Hit
Test: SHA:3108862db59e5fa02f4a254cea1d5089c60155eb Lines: 57.9 % 261 151
Test Date: 2025-10-12 07:08:15 Functions: 58.8 % 34 20

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

Generated by: LCOV version 2.0-1