Matter SDK Coverage Report
Current view: top level - app/server - CommissioningWindowManager.cpp (source / functions) Coverage Total Hit
Test: SHA:e021a368d10ac6f3f201c101585146211fdcdaa2 Lines: 85.7 % 266 228
Test Date: 2026-02-13 08:13:38 Functions: 88.6 % 35 31

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

Generated by: LCOV version 2.0-1