Matter SDK Coverage Report
Current view: top level - controller - SetUpCodePairer.cpp (source / functions) Coverage Total Hit
Test: SHA:6c8f029dd2432dc900f1c9245c324e69bd79e40a Lines: 25.2 % 420 106
Test Date: 2026-08-08 07:40:09 Functions: 39.5 % 43 17

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      21              :  *      Implementation of SetUp Code Pairer, a class that parses a given
      22              :  *      setup code and uses the extracted informations to discover and
      23              :  *      filter commissionables nodes, before initiating the pairing process.
      24              :  *
      25              :  */
      26              : 
      27              : #include <controller/SetUpCodePairer.h>
      28              : 
      29              : #include <controller/CHIPDeviceController.h>
      30              : #include <lib/dnssd/Resolver.h>
      31              : #include <lib/support/CodeUtils.h>
      32              : #include <memory>
      33              : #include <platform/internal/NFCCommissioningManager.h>
      34              : #include <system/SystemClock.h>
      35              : #include <tracing/metric_event.h>
      36              : #include <utility>
      37              : #include <vector>
      38              : 
      39              : constexpr uint32_t kDeviceDiscoveredTimeout = CHIP_CONFIG_SETUP_CODE_PAIRER_DISCOVERY_TIMEOUT_SECS * chip::kMillisecondsPerSecond;
      40              : 
      41              : using namespace chip::Tracing;
      42              : 
      43              : namespace chip {
      44              : namespace Controller {
      45              : 
      46            0 : CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour commission,
      47              :                                        DiscoveryType discoveryType, Optional<Dnssd::CommonResolutionData> resolutionData)
      48              : {
      49            0 :     VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE);
      50            0 :     VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, remoteId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
      51              : 
      52            0 :     std::vector<SetupPayload> payloads;
      53            0 :     ReturnErrorOnFailure(SetupPayload::FromStringRepresentation(setUpCode, payloads));
      54              : 
      55              :     // If the caller has provided a specific single resolution data, and we were
      56              :     // only looking for one commissionee, and the caller says that the provided
      57              :     // data matches that one commissionee, just go ahead and use the provided data.
      58              :     //
      59              :     // If we were looking for more than one device (i.e. if either of the
      60              :     // payload arrays involved does not have length 1), we can't make use of the
      61              :     // incoming resolution data, since it does not contain the long
      62              :     // discriminator of the thing that was discovered, and therefore we can't
      63              :     // tell which setup passcode to use for it.
      64            0 :     if (resolutionData.HasValue() && payloads.size() == 1 && mSetupPayloads.size() == 1)
      65              :     {
      66            0 :         VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, discoveryType != DiscoveryType::kAll,
      67              :                                       CHIP_ERROR_INVALID_ARGUMENT);
      68            0 :         if (mRemoteId == remoteId && mSetupPayloads[0].setUpPINCode == payloads[0].setUpPINCode && mConnectionType == commission &&
      69            0 :             mDiscoveryType == discoveryType)
      70              :         {
      71              :             // Not passing a discriminator is ok, since we have only one payload.
      72            0 :             NotifyCommissionableDeviceDiscovered(resolutionData.Value(), /* matchedLongDiscriminator = */ std::nullopt);
      73            0 :             return CHIP_NO_ERROR;
      74              :         }
      75              :     }
      76              : 
      77            0 :     ResetDiscoveryState();
      78              : 
      79            0 :     mConnectionType = commission;
      80            0 :     mDiscoveryType  = discoveryType;
      81            0 :     mRemoteId       = remoteId;
      82            0 :     mSetupPayloads  = std::move(payloads);
      83              : 
      84            0 :     if (resolutionData.HasValue() && mSetupPayloads.size() == 1)
      85              :     {
      86              :         // No need to pass in a discriminator if we have only one payload, which
      87              :         // is good because we don't have a full discriminator here anyway.
      88            0 :         NotifyCommissionableDeviceDiscovered(resolutionData.Value(), /* matchedLongDiscriminator = */ std::nullopt);
      89            0 :         return CHIP_NO_ERROR;
      90              :     }
      91              : 
      92            0 :     ReturnErrorOnFailureWithMetric(kMetricSetupCodePairerPairDevice, Connect());
      93              :     auto errorCode =
      94            0 :         mSystemLayer->StartTimer(System::Clock::Milliseconds32(kDeviceDiscoveredTimeout), OnDeviceDiscoveredTimeoutCallback, this);
      95            0 :     if (CHIP_NO_ERROR == errorCode)
      96              :     {
      97              :         MATTER_LOG_METRIC_BEGIN(kMetricSetupCodePairerPairDevice);
      98              :     }
      99            0 :     return errorCode;
     100            0 : }
     101              : 
     102            0 : CHIP_ERROR SetUpCodePairer::Connect()
     103              : {
     104            0 :     if (mDiscoveryType == DiscoveryType::kAll)
     105              :     {
     106            0 :         if (ShouldDiscoverUsing(RendezvousInformationFlag::kBLE))
     107              :         {
     108            0 :             CHIP_ERROR err = StartDiscoveryOverBLE();
     109            0 :             if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
     110              :             {
     111            0 :                 ChipLogProgress(Controller,
     112              :                                 "Skipping commissionable node discovery over BLE since not supported by the controller!");
     113              :             }
     114            0 :             else if (err != CHIP_NO_ERROR)
     115              :             {
     116            0 :                 ChipLogError(Controller, "Failed to start commissionable node discovery over BLE: %" CHIP_ERROR_FORMAT,
     117              :                              err.Format());
     118              :             }
     119              :         }
     120            0 :         if (ShouldDiscoverUsing(RendezvousInformationFlag::kWiFiPAF))
     121              :         {
     122            0 :             CHIP_ERROR err = StartDiscoveryOverWiFiPAF();
     123            0 :             if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
     124              :             {
     125            0 :                 ChipLogProgress(Controller,
     126              :                                 "Skipping commissionable node discovery over Wi-Fi PAF since not supported by the controller!");
     127              :             }
     128            0 :             else if (err != CHIP_NO_ERROR)
     129              :             {
     130            0 :                 ChipLogError(Controller, "Failed to start commissionable node discovery over Wi-Fi PAF: %" CHIP_ERROR_FORMAT,
     131              :                              err.Format());
     132              :             }
     133              :         }
     134            0 :         if (ShouldDiscoverUsing(RendezvousInformationFlag::kNFC))
     135              :         {
     136            0 :             CHIP_ERROR err = StartDiscoveryOverNFC();
     137            0 :             if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
     138              :             {
     139            0 :                 ChipLogProgress(Controller,
     140              :                                 "Skipping commissionable node discovery over NFC since not supported by the controller!");
     141              :             }
     142            0 :             else if (err == CHIP_ERROR_NOT_FOUND)
     143              :             {
     144            0 :                 ChipLogProgress(Controller,
     145              :                                 "Skipping commissionable node discovery over NFC since no NFC Reader Transport is present");
     146              :             }
     147            0 :             else if (err != CHIP_NO_ERROR)
     148              :             {
     149            0 :                 ChipLogError(Controller, "Failed to start commissionable node discovery over NFC: %" CHIP_ERROR_FORMAT,
     150              :                              err.Format());
     151              :             }
     152              :         }
     153            0 :         if (ShouldDiscoverUsing(RendezvousInformationFlag::kThread))
     154              :         {
     155            0 :             CHIP_ERROR err = StartDiscoveryOverThreadMeshcop();
     156            0 :             if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
     157              :             {
     158            0 :                 ChipLogProgress(Controller,
     159              :                                 "Skipping commissionable node discovery over ThreadMeshcop since not supported by the controller!");
     160              :             }
     161            0 :             else if (err != CHIP_NO_ERROR)
     162              :             {
     163            0 :                 ChipLogError(Controller, "Failed to start commissionable node discovery over ThreadMeshcop: %" CHIP_ERROR_FORMAT,
     164              :                              err.Format());
     165              :             }
     166              :         }
     167              :     }
     168              : 
     169              :     // We always want to search on network because any node that has already been commissioned will use on-network regardless of the
     170              :     // QR code flag.
     171            0 :     CHIP_ERROR err = StartDiscoveryOverDNSSD();
     172            0 :     if (err != CHIP_NO_ERROR)
     173              :     {
     174            0 :         ChipLogError(Controller, "Failed to start commissionable node discovery over DNS-SD: %" CHIP_ERROR_FORMAT, err.Format());
     175              :     }
     176            0 :     return err;
     177              : }
     178              : 
     179            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverBLE()
     180              : {
     181              : #if CONFIG_NETWORK_LAYER_BLE
     182              : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     183              :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     184              :     mCommissioner->ConnectBleTransportToSelf();
     185              : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     186            0 :     VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
     187              : 
     188            0 :     ChipLogProgress(Controller, "Starting commissionable node discovery over BLE");
     189              : 
     190              :     // Handle possibly-sync callbacks.
     191            0 :     mWaitingForDiscovery[kBLETransport] = true;
     192              :     CHIP_ERROR err;
     193              :     // Not all BLE backends support the new NewBleConnectionByDiscriminators
     194              :     // API, so use the old one when we can (i.e. when we only have one setup
     195              :     // payload), to avoid breaking existing API consumers.
     196            0 :     if (mSetupPayloads.size() == 1)
     197              :     {
     198            0 :         err = mBleLayer->NewBleConnectionByDiscriminator(mSetupPayloads[0].discriminator, this, OnDiscoveredDeviceOverBleSuccess,
     199              :                                                          OnDiscoveredDeviceOverBleError);
     200              :     }
     201              :     else
     202              :     {
     203            0 :         std::vector<SetupDiscriminator> discriminators;
     204            0 :         discriminators.reserve(mSetupPayloads.size());
     205            0 :         for (auto & payload : mSetupPayloads)
     206              :         {
     207            0 :             discriminators.emplace_back(payload.discriminator);
     208              :         }
     209            0 :         err = mBleLayer->NewBleConnectionByDiscriminators(Span(discriminators.data(), discriminators.size()), this,
     210              :                                                           OnDiscoveredDeviceWithDiscriminatorOverBleSuccess,
     211              :                                                           OnDiscoveredDeviceOverBleError);
     212            0 :     }
     213            0 :     if (err != CHIP_NO_ERROR)
     214              :     {
     215            0 :         mWaitingForDiscovery[kBLETransport] = false;
     216              :     }
     217            0 :     return err;
     218              : #else
     219              :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     220              : #endif // CONFIG_NETWORK_LAYER_BLE
     221              : }
     222              : 
     223            1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverBLE()
     224              : {
     225              :     // Make sure to not call CancelBleIncompleteConnection unless we are in fact
     226              :     // waiting on BLE discovery.  It will cancel connections that are in fact
     227              :     // completed. In particular, if we just established PASE over BLE calling
     228              :     // CancelBleIncompleteConnection here unconditionally would cancel the BLE
     229              :     // connection underlying the PASE session.  So make sure to only call
     230              :     // CancelBleIncompleteConnection if we're still waiting to hear back on the
     231              :     // BLE discovery bits.
     232            1 :     if (!mWaitingForDiscovery[kBLETransport])
     233              :     {
     234            0 :         return CHIP_NO_ERROR;
     235              :     }
     236              : 
     237            1 :     mWaitingForDiscovery[kBLETransport] = false;
     238              : #if CONFIG_NETWORK_LAYER_BLE
     239            1 :     VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
     240            0 :     ChipLogProgress(Controller, "Stopping commissionable node discovery over BLE");
     241            0 :     return mBleLayer->CancelBleIncompleteConnection();
     242              : #else
     243              :     return CHIP_NO_ERROR;
     244              : #endif // CONFIG_NETWORK_LAYER_BLE
     245              : }
     246              : 
     247            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverDNSSD()
     248              : {
     249            0 :     ChipLogProgress(Controller, "Starting commissionable node discovery over DNS-SD");
     250              : 
     251            0 :     Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kNone);
     252            0 :     if (mSetupPayloads.size() == 1)
     253              :     {
     254            0 :         auto & discriminator = mSetupPayloads[0].discriminator;
     255            0 :         if (discriminator.IsShortDiscriminator())
     256              :         {
     257            0 :             filter.type = Dnssd::DiscoveryFilterType::kShortDiscriminator;
     258            0 :             filter.code = discriminator.GetShortValue();
     259              :         }
     260              :         else
     261              :         {
     262            0 :             filter.type = Dnssd::DiscoveryFilterType::kLongDiscriminator;
     263            0 :             filter.code = discriminator.GetLongValue();
     264              :         }
     265              :     }
     266              : 
     267              :     // In theory we could try to filter on the vendor ID if it's the same across all the setup
     268              :     // payloads, but DNS-SD advertisements are not required to include the Vendor ID subtype, so in
     269              :     // practice that's not doable.
     270              : 
     271              :     // Handle possibly-sync callbacks.
     272            0 :     mWaitingForDiscovery[kIPTransport] = true;
     273            0 :     CHIP_ERROR err                     = mCommissioner->DiscoverCommissionableNodes(filter);
     274            0 :     if (err != CHIP_NO_ERROR)
     275              :     {
     276            0 :         mWaitingForDiscovery[kIPTransport] = false;
     277              :     }
     278            0 :     return err;
     279              : }
     280              : 
     281            2 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverDNSSD()
     282              : {
     283            2 :     ChipLogProgress(Controller, "Stopping commissionable node discovery over DNS-SD");
     284              : 
     285            2 :     mWaitingForDiscovery[kIPTransport] = false;
     286              : 
     287            2 :     return mCommissioner->StopCommissionableDiscovery();
     288              : }
     289              : 
     290            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverWiFiPAF()
     291              : {
     292              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     293            0 :     if (mSetupPayloads.size() != 1)
     294              :     {
     295            0 :         ChipLogError(Controller, "Wi-Fi PAF commissioning does not support concatenated QR codes yet.");
     296            0 :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     297              :     }
     298              : 
     299            0 :     auto & payload = mSetupPayloads[0];
     300              : 
     301            0 :     ChipLogProgress(Controller, "Starting commissionable node discovery over Wi-Fi PAF");
     302            0 :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     303              : 
     304            0 :     const SetupDiscriminator connDiscriminator(payload.discriminator);
     305            0 :     VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
     306              :                         ChipLogError(Controller, "Error, Long discriminator is required"));
     307            0 :     uint16_t discriminator              = connDiscriminator.GetLongValue();
     308            0 :     WiFiPAF::WiFiPAFSession sessionInfo = { .role          = WiFiPAF::WiFiPafRole::kWiFiPafRole_Subscriber,
     309            0 :                                             .nodeId        = mRemoteId,
     310            0 :                                             .discriminator = discriminator };
     311            0 :     ReturnErrorOnFailure(
     312              :         DeviceLayer::ConnectivityMgr().GetWiFiPAF()->AddPafSession(WiFiPAF::PafInfoAccess::kAccNodeInfo, sessionInfo));
     313              : 
     314            0 :     mWaitingForDiscovery[kWiFiPAFTransport] = true;
     315            0 :     CHIP_ERROR err = DeviceLayer::ConnectivityMgr().WiFiPAFSubscribe(discriminator, (void *) this, OnWiFiPAFSubscribeComplete,
     316              :                                                                      OnWiFiPAFSubscribeError);
     317            0 :     if (err != CHIP_NO_ERROR)
     318              :     {
     319            0 :         ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     320            0 :         mWaitingForDiscovery[kWiFiPAFTransport] = false;
     321              :     }
     322            0 :     return err;
     323              : #else
     324              :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     325              : #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     326              : }
     327              : 
     328            1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverWiFiPAF()
     329              : {
     330            1 :     mWaitingForDiscovery[kWiFiPAFTransport] = false;
     331              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     332            1 :     return DeviceLayer::ConnectivityMgr().WiFiPAFCancelIncompleteSubscribe();
     333              : #else
     334              :     return CHIP_NO_ERROR;
     335              : #endif
     336              : }
     337              : 
     338            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverNFC()
     339              : {
     340              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     341              :     if (mSetupPayloads.size() != 1)
     342              :     {
     343              :         ChipLogError(Controller, "NFC commissioning does not support concatenated QR codes yet.");
     344              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     345              :     }
     346              : 
     347              :     auto & payload = mSetupPayloads[0];
     348              : 
     349              :     ChipLogProgress(Controller, "Starting commissionable node discovery over NFC");
     350              :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     351              : 
     352              :     const SetupDiscriminator connDiscriminator(payload.discriminator);
     353              :     VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
     354              :                         ChipLogError(Controller, "Error, Long discriminator is required"));
     355              :     chip::Nfc::NFCTag::Identifier identifier  = { .discriminator = payload.discriminator.GetLongValue() };
     356              :     Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
     357              :     if (!readerTransport)
     358              :     {
     359              :         // No valid NFC reader transport
     360              :         return CHIP_ERROR_NOT_FOUND;
     361              :     }
     362              : 
     363              :     readerTransport->SetDelegate(this);
     364              :     CHIP_ERROR err = readerTransport->StartDiscoveringTagMatchingAddress(identifier);
     365              :     if (err != CHIP_NO_ERROR)
     366              :     {
     367              :         ChipLogError(Controller, "Commissionable node discovery over NFC failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     368              :     }
     369              :     else
     370              :     {
     371              :         mWaitingForDiscovery[kNFCTransport] = true;
     372              :     }
     373              :     return err;
     374              : #else
     375            0 :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     376              : #endif // CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     377              : }
     378              : 
     379            1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverNFC()
     380              : {
     381              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     382              :     mWaitingForDiscovery[kNFCTransport] = false;
     383              : 
     384              :     Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
     385              :     if (!readerTransport)
     386              :     {
     387              :         // No valid NFC reader transport.
     388              :         return CHIP_ERROR_NOT_FOUND;
     389              :     }
     390              : 
     391              :     ChipLogProgress(Controller, "Stopping commissionable node discovery over NFC by removing delegate");
     392              :     readerTransport->SetDelegate(nullptr);
     393              : #endif
     394            1 :     return CHIP_NO_ERROR;
     395              : }
     396              : 
     397            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverThreadMeshcop()
     398              : {
     399              : #if CHIP_SUPPORT_THREAD_MESHCOP
     400            0 :     if (mSetupPayloads.size() != 1)
     401              :     {
     402            0 :         ChipLogError(Controller, "Thread Meshcop commissioning does not support concatenated QR codes yet.");
     403            0 :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     404              :     }
     405              : 
     406            0 :     if (!mThreadMeshcopCommissionProxy)
     407              :     {
     408            0 :         ChipLogError(Controller, "The meshcopCommissioningProxy is not set");
     409            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     410              :     }
     411              : 
     412            0 :     if (!mThreadMeshcopCommissionParams.HasValue() ||
     413            0 :         mThreadMeshcopCommissionParams.Value().mBorderAgentAddress.GetTransportType() != Transport::Type::kThreadMeshcop)
     414              :     {
     415            0 :         ChipLogError(Controller, "The meshcopCommissioningParams is not set");
     416            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     417              :     }
     418              : 
     419            0 :     auto & payload = mSetupPayloads[0];
     420              : 
     421            0 :     ChipLogProgress(Controller, "Starting commissionable node discovery over Thread Meshcop");
     422            0 :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     423              : 
     424            0 :     const SetupDiscriminator connDiscriminator(payload.discriminator);
     425            0 :     Thread::DiscoveryCode code;
     426            0 :     if (connDiscriminator.IsShortDiscriminator())
     427              :     {
     428            0 :         code = Thread::DiscoveryCode(connDiscriminator.GetShortValue());
     429            0 :         ChipLogProgress(Controller, "Discovery code from short discriminator: 0x%" PRIx64, code.AsUInt64());
     430              :     }
     431              :     else
     432              :     {
     433            0 :         code = Thread::DiscoveryCode(connDiscriminator.GetLongValue());
     434            0 :         ChipLogProgress(Controller, "Discovery code from long discriminator: 0x%" PRIx64, code.AsUInt64());
     435              :     }
     436              : 
     437            0 :     ByteSpan pskc(mThreadMeshcopCommissionParams.Value().mPSKcBuffer);
     438              :     {
     439            0 :         mWaitingForDiscovery[kThreadMeshcopTransport] = true;
     440            0 :         Dnssd::DiscoveredNodeData discoveredNodeData;
     441              : 
     442            0 :         CHIP_ERROR err = mThreadMeshcopCommissionProxy->Discover(pskc, mThreadMeshcopCommissionParams.Value().mBorderAgentAddress,
     443              :                                                                  code, connDiscriminator, discoveredNodeData, 30);
     444              : 
     445            0 :         mWaitingForDiscovery[kThreadMeshcopTransport] = false;
     446            0 :         ReturnErrorOnFailure(err);
     447            0 :         mCommissioner->OnNodeDiscovered(discoveredNodeData);
     448            0 :         ChipLogProgress(Controller, "Joiner discovered");
     449            0 :     }
     450            0 :     return CHIP_NO_ERROR;
     451              : #else
     452              :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     453              : #endif // CHIP_SUPPORT_THREAD_MESHCOP
     454              : }
     455              : 
     456            1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverThreadMeshcop()
     457              : {
     458              :     // Currently we don't have any methods to stop discovery Over Thread Meshcop.
     459              :     // Still return no error here to prevent error logs.
     460            1 :     return CHIP_NO_ERROR;
     461              : }
     462              : 
     463            6 : bool SetUpCodePairer::ConnectToDiscoveredDevice()
     464              : {
     465            6 :     if (mWaitingForPASE)
     466              :     {
     467              :         // Nothing to do.  Just wait until we either succeed or fail at that
     468              :         // PASE session establishment.
     469            4 :         return false;
     470              :     }
     471              : 
     472            2 :     while (!mDiscoveredParameters.empty())
     473              :     {
     474            0 :         mCurrentPASEPayload.reset();
     475              : 
     476              :         // Grab the first element from the queue and try connecting to it.
     477              :         // Remove it from the queue before we try to connect, in case the
     478              :         // connection attempt fails and calls right back into us to try the next
     479              :         // thing.
     480            0 :         SetUpCodePairerParameters params(mDiscoveredParameters.front());
     481            0 :         mDiscoveredParameters.pop_front();
     482              : 
     483            0 :         if (params.mLongDiscriminator)
     484              :         {
     485            0 :             auto longDiscriminator = *params.mLongDiscriminator;
     486              :             // Look for a matching setup passcode.
     487            0 :             for (auto & payload : mSetupPayloads)
     488              :             {
     489            0 :                 if (payload.discriminator.MatchesLongDiscriminator(longDiscriminator))
     490              :                 {
     491            0 :                     params.SetSetupPINCode(payload.setUpPINCode);
     492            0 :                     params.SetSetupDiscriminator(payload.discriminator);
     493            0 :                     mCurrentPASEPayload = payload;
     494            0 :                     break;
     495              :                 }
     496              :             }
     497            0 :             if (!mCurrentPASEPayload)
     498              :             {
     499            0 :                 ChipLogError(Controller, "SetUpCodePairer: Discovered discriminator %u does not match any of our setup payloads",
     500              :                              longDiscriminator);
     501              :                 // Move on to the the next discovered params; nothing we can do here.
     502            0 :                 continue;
     503              :             }
     504              :         }
     505              :         else
     506              :         {
     507              :             // No discriminator known for this discovered device.  This can work if we have only one
     508              :             // setup payload, but otherwise we have no idea what setup passcode to use for it.
     509            0 :             if (mSetupPayloads.size() == 1)
     510              :             {
     511            0 :                 params.SetSetupPINCode(mSetupPayloads[0].setUpPINCode);
     512            0 :                 params.SetSetupDiscriminator(mSetupPayloads[0].discriminator);
     513            0 :                 mCurrentPASEPayload = mSetupPayloads[0];
     514              :             }
     515              :             else
     516              :             {
     517            0 :                 ChipLogError(Controller,
     518              :                              "SetUpCodePairer: Unable to handle discovered parameters with no discriminator, because it has %u "
     519              :                              "possible payloads",
     520              :                              static_cast<unsigned>(mSetupPayloads.size()));
     521            0 :                 continue;
     522              :             }
     523              :         }
     524              : 
     525              : #if CHIP_PROGRESS_LOGGING
     526              :         char buf[Transport::PeerAddress::kMaxToStringSize];
     527            0 :         params.GetPeerAddress().ToString(buf);
     528            0 :         ChipLogProgress(Controller, "Attempting PASE connection to %s", buf);
     529              : #endif // CHIP_PROGRESS_LOGGING
     530              : 
     531              :         // Handle possibly-sync call backs from attempts to establish PASE.
     532            0 :         ExpectPASEEstablishment();
     533              : 
     534            0 :         if (params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
     535              :         {
     536            0 :             mCurrentPASEParameters.SetValue(params);
     537              :         }
     538              : 
     539              :         CHIP_ERROR err;
     540            0 :         if (mConnectionType == SetupCodePairerBehaviour::kCommission)
     541              :         {
     542            0 :             err = mCommissioner->PairDevice(mRemoteId, params);
     543              :         }
     544              :         else
     545              :         {
     546            0 :             err = mCommissioner->EstablishPASEConnection(mRemoteId, params);
     547              :         }
     548              : 
     549            0 :         LogErrorOnFailure(err);
     550            0 :         if (err == CHIP_NO_ERROR)
     551              :         {
     552            0 :             return true;
     553              :         }
     554              : 
     555              :         // Failed to start establishing PASE.  Move on to the next item.
     556            0 :         mCurrentPASEParameters.ClearValue();
     557            0 :         mCurrentPASEPayload.reset();
     558            0 :         PASEEstablishmentComplete();
     559              :     }
     560              : 
     561            2 :     return false;
     562              : }
     563              : 
     564              : #if CONFIG_NETWORK_LAYER_BLE
     565            0 : void SetUpCodePairer::OnDiscoveredDeviceOverBle(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> matchedLongDiscriminator)
     566              : {
     567            0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over BLE");
     568              : 
     569            0 :     mWaitingForDiscovery[kBLETransport] = false;
     570              : 
     571              :     // In order to not wait for all the possible addresses discovered over mdns to
     572              :     // be tried before trying to connect over BLE, the discovered connection object is
     573              :     // inserted at the beginning of the list.
     574              :     //
     575              :     // It makes it the 'next' thing to try to connect to if there are already some
     576              :     // discovered parameters in the list.
     577              :     //
     578              :     // TODO: Consider implementing the SHOULD the spec has about commissioning things
     579              :     // in QR code order by waiting for a second or something before actually starting
     580              :     // the first PASE session when we have multiple setup payloads, and sorting the
     581              :     // results in setup payload order.  If we do this, we might want to restrict it to
     582              :     // cases when the different payloads have different vendor/product IDs, since if
     583              :     // they are all the same product presumably ordering really does not matter.
     584            0 :     mDiscoveredParameters.emplace_front(connObj, matchedLongDiscriminator);
     585            0 :     ConnectToDiscoveredDevice();
     586            0 : }
     587              : 
     588            0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
     589              : {
     590            0 :     (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::nullopt);
     591            0 : }
     592              : 
     593            0 : void SetUpCodePairer::OnDiscoveredDeviceWithDiscriminatorOverBleSuccess(void * appState, uint16_t matchedLongDiscriminator,
     594              :                                                                         BLE_CONNECTION_OBJECT connObj)
     595              : {
     596            0 :     (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::make_optional(matchedLongDiscriminator));
     597            0 : }
     598              : 
     599            0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
     600              : {
     601            0 :     static_cast<SetUpCodePairer *>(appState)->OnBLEDiscoveryError(err);
     602            0 : }
     603              : 
     604            0 : void SetUpCodePairer::OnBLEDiscoveryError(CHIP_ERROR err)
     605              : {
     606            0 :     ChipLogError(Controller, "Commissionable node discovery over BLE failed: %" CHIP_ERROR_FORMAT, err.Format());
     607            0 :     mWaitingForDiscovery[kBLETransport] = false;
     608            0 :     LogErrorOnFailure(err);
     609            0 :     StopPairingIfTransportsExhausted(err);
     610            0 : }
     611              : #endif // CONFIG_NETWORK_LAYER_BLE
     612              : 
     613              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     614            0 : void SetUpCodePairer::OnDiscoveredDeviceOverWifiPAF()
     615              : {
     616            0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over Wi-Fi PAF, RemoteId: %" PRIu64, mRemoteId);
     617              : 
     618            0 :     mWaitingForDiscovery[kWiFiPAFTransport] = false;
     619            0 :     auto param                              = SetUpCodePairerParameters();
     620            0 :     param.SetPeerAddress(Transport::PeerAddress(Transport::Type::kWiFiPAF, mRemoteId));
     621              :     // TODO: This needs to support concatenated QR codes and set the relevant
     622              :     // long discriminator on param.
     623              :     //
     624              :     // See https://github.com/project-chip/connectedhomeip/issues/39134
     625            0 :     mDiscoveredParameters.emplace_back(param);
     626            0 :     ConnectToDiscoveredDevice();
     627            0 : }
     628              : 
     629            0 : void SetUpCodePairer::OnWifiPAFDiscoveryError(CHIP_ERROR err)
     630              : {
     631            0 :     ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed: %" CHIP_ERROR_FORMAT, err.Format());
     632            0 :     mWaitingForDiscovery[kWiFiPAFTransport] = false;
     633            0 :     StopPairingIfTransportsExhausted(err);
     634            0 : }
     635              : 
     636            0 : void SetUpCodePairer::OnWiFiPAFSubscribeComplete(void * appState)
     637              : {
     638            0 :     auto self = reinterpret_cast<SetUpCodePairer *>(appState);
     639            0 :     self->OnDiscoveredDeviceOverWifiPAF();
     640            0 : }
     641              : 
     642            0 : void SetUpCodePairer::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err)
     643              : {
     644            0 :     auto self = reinterpret_cast<SetUpCodePairer *>(appState);
     645            0 :     self->OnWifiPAFDiscoveryError(err);
     646            0 : }
     647              : #endif
     648              : 
     649              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     650              : void SetUpCodePairer::OnTagDiscovered(const chip::Nfc::NFCTag::Identifier & identifier)
     651              : {
     652              :     ChipLogProgress(Controller, "Discovered device to be commissioned over NFC, Identifier: %u", identifier.discriminator);
     653              : 
     654              :     mWaitingForDiscovery[kNFCTransport] = false;
     655              :     auto param                          = SetUpCodePairerParameters();
     656              :     param.SetPeerAddress(Transport::PeerAddress(Transport::PeerAddress::NFC(identifier.discriminator)));
     657              :     // TODO: This needs to support concatenated QR codes and set the relevant
     658              :     // long discriminator on param.
     659              :     //
     660              :     // See https://github.com/project-chip/connectedhomeip/issues/39134
     661              :     mDiscoveredParameters.emplace_back(param);
     662              :     ConnectToDiscoveredDevice();
     663              : }
     664              : 
     665              : void SetUpCodePairer::OnTagDiscoveryFailed(CHIP_ERROR error)
     666              : {
     667              :     ChipLogError(Controller, "Commissionable node discovery over NFC failed: %" CHIP_ERROR_FORMAT, error.Format());
     668              :     mWaitingForDiscovery[kNFCTransport] = false;
     669              :     StopPairingIfTransportsExhausted(error);
     670              : }
     671              : #endif
     672              : 
     673            0 : bool SetUpCodePairer::IdIsPresent(uint16_t vendorOrProductID)
     674              : {
     675            0 :     return vendorOrProductID != kNotAvailable;
     676              : }
     677              : 
     678            0 : bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & discNodeData) const
     679              : {
     680            0 :     if (!discNodeData.Is<Dnssd::CommissionNodeData>())
     681              :     {
     682            0 :         return false;
     683              :     }
     684              : 
     685            0 :     const Dnssd::CommissionNodeData & nodeData = discNodeData.Get<Dnssd::CommissionNodeData>();
     686              : 
     687            0 :     VerifyOrReturnError(mCommissioner != nullptr, false);
     688            0 :     VerifyOrReturnError(mCommissioner->HasValidCommissioningMode(nodeData), false);
     689              : 
     690              :     // Check whether this matches one of our setup payloads.
     691            0 :     for (auto & payload : mSetupPayloads)
     692              :     {
     693              :         // The advertisement may not include a vendor id, and the payload may not have one either.
     694            0 :         if (IdIsPresent(payload.vendorID) && IdIsPresent(nodeData.vendorId) && payload.vendorID != nodeData.vendorId)
     695              :         {
     696            0 :             ChipLogProgress(Controller, "Discovered device vendor ID (%u) does not match our vendor ID (%u).", nodeData.vendorId,
     697              :                             payload.vendorID);
     698            0 :             continue;
     699              :         }
     700              : 
     701              :         // The advertisement may not include a product id, and the payload may not have one either.
     702            0 :         if (IdIsPresent(payload.productID) && IdIsPresent(nodeData.productId) && payload.productID != nodeData.productId)
     703              :         {
     704            0 :             ChipLogProgress(Controller, "Discovered device product ID (%u) does not match our product ID (%u).", nodeData.productId,
     705              :                             payload.productID);
     706            0 :             continue;
     707              :         }
     708              : 
     709            0 :         if (!payload.discriminator.MatchesLongDiscriminator(nodeData.longDiscriminator))
     710              :         {
     711            0 :             ChipLogProgress(Controller, "Discovered device discriminator (%u) does not match our discriminator.",
     712              :                             nodeData.longDiscriminator);
     713            0 :             continue;
     714              :         }
     715              : 
     716            0 :         ChipLogProgress(Controller, "Discovered device with discriminator %u matches one of our setup payloads",
     717              :                         nodeData.longDiscriminator);
     718            0 :         return true;
     719              :     }
     720              : 
     721            0 :     return false;
     722              : }
     723              : 
     724            0 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::DiscoveredNodeData & nodeData)
     725              : {
     726            0 :     if (!NodeMatchesCurrentFilter(nodeData))
     727              :     {
     728            0 :         return;
     729              :     }
     730              : 
     731            0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over DNS-SD");
     732              : 
     733            0 :     auto & commissionableNodeData = nodeData.Get<Dnssd::CommissionNodeData>();
     734              : 
     735            0 :     NotifyCommissionableDeviceDiscovered(commissionableNodeData, std::make_optional(commissionableNodeData.longDiscriminator));
     736              : }
     737              : 
     738            4 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::CommonResolutionData & resolutionData,
     739              :                                                            std::optional<uint16_t> matchedLongDiscriminator)
     740              : {
     741            4 :     if (mDiscoveryType == DiscoveryType::kDiscoveryNetworkOnlyWithoutPASEAutoRetry)
     742              :     {
     743              :         // If the discovery type does not want the PASE auto retry mechanism, we will just store
     744              :         // a single IP. So the discovery process is stopped as it won't be of any help anymore.
     745            0 :         TEMPORARY_RETURN_IGNORED StopDiscoveryOverDNSSD();
     746            0 :         EnqueueDiscoveredParametersIfNotDuplicate(SetUpCodePairerParameters(resolutionData, matchedLongDiscriminator, 0));
     747              :     }
     748              :     else
     749              :     {
     750            9 :         for (size_t i = 0; i < resolutionData.numIPs; i++)
     751              :         {
     752            5 :             EnqueueDiscoveredParametersIfNotDuplicate(SetUpCodePairerParameters(resolutionData, matchedLongDiscriminator, i));
     753              :         }
     754              :     }
     755              : 
     756            4 :     ConnectToDiscoveredDevice();
     757            4 : }
     758              : 
     759            5 : void SetUpCodePairer::EnqueueDiscoveredParametersIfNotDuplicate(SetUpCodePairerParameters && params)
     760              : {
     761              :     // The same device can be advertised more than once -- most notably the same non-link-local
     762              :     // address arriving on multiple interfaces -- producing candidates that would drive an identical
     763              :     // PASE attempt. Retrying the same attempt just wastes it and adds latency, so drop duplicates.
     764            6 :     for (const SetUpCodePairerParameters & existing : mDiscoveredParameters)
     765              :     {
     766            3 :         if (existing.CanCoalesceWith(params))
     767              :         {
     768            2 :             ChipLogDetail(Controller, "SetUpCodePairer: dropping duplicate discovered rendezvous parameters");
     769            2 :             return;
     770              :         }
     771              :     }
     772              : 
     773            3 :     mDiscoveredParameters.emplace_back(std::move(params));
     774              : }
     775              : 
     776            0 : bool SetUpCodePairer::StopPairing(NodeId remoteId)
     777              : {
     778            0 :     VerifyOrReturnValue(mRemoteId != kUndefinedNodeId, false);
     779            0 :     VerifyOrReturnValue(remoteId == kUndefinedNodeId || remoteId == mRemoteId, false);
     780              : 
     781            0 :     if (mWaitingForPASE)
     782              :     {
     783            0 :         PASEEstablishmentComplete();
     784              :     }
     785              : 
     786            0 :     ResetDiscoveryState();
     787            0 :     mRemoteId = kUndefinedNodeId;
     788            0 :     return true;
     789              : }
     790              : 
     791            2 : bool SetUpCodePairer::TryNextRendezvousParameters()
     792              : {
     793            2 :     if (ConnectToDiscoveredDevice())
     794              :     {
     795            0 :         ChipLogProgress(Controller, "Trying connection to commissionee over different transport");
     796            0 :         return true;
     797              :     }
     798              : 
     799            2 :     if (DiscoveryInProgress())
     800              :     {
     801            2 :         ChipLogProgress(Controller, "Waiting to discover commissionees that match our filters");
     802            2 :         return true;
     803              :     }
     804              : 
     805            0 :     return false;
     806              : }
     807              : 
     808            3 : bool SetUpCodePairer::DiscoveryInProgress() const
     809              : {
     810            8 :     for (const auto & waiting : mWaitingForDiscovery)
     811              :     {
     812            7 :         if (waiting)
     813              :         {
     814            2 :             return true;
     815              :         }
     816              :     }
     817              : 
     818            1 :     return false;
     819              : }
     820              : 
     821            1 : void SetUpCodePairer::StopPairingIfTransportsExhausted(CHIP_ERROR err)
     822              : {
     823            1 :     if (mWaitingForPASE || !mDiscoveredParameters.empty() || DiscoveryInProgress() || mRemoteId == kUndefinedNodeId)
     824              :     {
     825            0 :         return;
     826              :     }
     827              :     // Clear mRemoteId first to guard against re-entrant calls (e.g. from an async
     828              :     // cancel callback fired after StopAllDiscoveryAttempts already cleared the flags).
     829            1 :     mRemoteId          = kUndefinedNodeId;
     830            2 :     CHIP_ERROR failErr = mLastPASEError != CHIP_NO_ERROR ? mLastPASEError : err;
     831              :     MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, failErr);
     832            1 :     mCommissioner->OnSessionEstablishmentError(failErr);
     833              : }
     834              : 
     835            1 : void SetUpCodePairer::StopAllDiscoveryAttempts()
     836              : {
     837            1 :     LogErrorOnFailure(StopDiscoveryOverBLE());
     838            1 :     LogErrorOnFailure(StopDiscoveryOverDNSSD());
     839            1 :     LogErrorOnFailure(StopDiscoveryOverWiFiPAF());
     840            2 :     LogErrorOnFailure(StopDiscoveryOverNFC().NoErrorIf(CHIP_ERROR_NOT_FOUND));
     841            1 :     LogErrorOnFailure(StopDiscoveryOverThreadMeshcop());
     842              : 
     843              :     // Just in case any of those failed to reset the waiting state properly.
     844            5 :     for (auto & waiting : mWaitingForDiscovery)
     845              :     {
     846            4 :         waiting = false;
     847              :     }
     848            1 : }
     849              : 
     850            0 : void SetUpCodePairer::ResetDiscoveryState()
     851              : {
     852            0 :     StopAllDiscoveryAttempts();
     853              : 
     854            0 :     mDiscoveredParameters.clear();
     855            0 :     mCurrentPASEParameters.ClearValue();
     856            0 :     mLastPASEError = CHIP_NO_ERROR;
     857              : 
     858            0 :     mSetupPayloads.clear();
     859              : 
     860            0 :     mSystemLayer->CancelTimer(OnDeviceDiscoveredTimeoutCallback, this);
     861            0 : }
     862              : 
     863            2 : void SetUpCodePairer::ExpectPASEEstablishment()
     864              : {
     865            2 :     VerifyOrDie(!mWaitingForPASE);
     866            2 :     mWaitingForPASE = true;
     867            2 :     auto * delegate = mCommissioner->GetPairingDelegate();
     868            2 :     VerifyOrDie(delegate != this);
     869            2 :     mPairingDelegate = delegate;
     870            2 :     mCommissioner->RegisterPairingDelegate(this);
     871            2 : }
     872              : 
     873            2 : void SetUpCodePairer::PASEEstablishmentComplete()
     874              : {
     875            2 :     VerifyOrDie(mWaitingForPASE);
     876            2 :     mWaitingForPASE = false;
     877            2 :     mCommissioner->RegisterPairingDelegate(mPairingDelegate);
     878            2 :     mPairingDelegate = nullptr;
     879            2 : }
     880              : 
     881            0 : void SetUpCodePairer::OnStatusUpdate(DevicePairingDelegate::Status status)
     882              : {
     883            0 :     if (status == DevicePairingDelegate::Status::SecurePairingFailed)
     884              :     {
     885              :         // If we're still waiting on discovery, don't propagate this failure
     886              :         // (which is due to PASE failure with something we discovered, but the
     887              :         // "something" may not have been the right thing) for now.  Wait until
     888              :         // discovery completes.  Then we will either succeed and notify
     889              :         // accordingly or time out and land in OnStatusUpdate again, but at that
     890              :         // point we will not be waiting on discovery anymore.
     891            0 :         if (!mDiscoveredParameters.empty())
     892              :         {
     893            0 :             ChipLogProgress(Controller, "Ignoring SecurePairingFailed status for now; we have more discovered devices to try");
     894            0 :             return;
     895              :         }
     896              : 
     897            0 :         if (DiscoveryInProgress())
     898              :         {
     899            0 :             ChipLogProgress(Controller,
     900              :                             "Ignoring SecurePairingFailed status for now; we are waiting to see if we discover more devices");
     901            0 :             return;
     902              :         }
     903              :     }
     904              : 
     905            0 :     if (mPairingDelegate)
     906              :     {
     907            0 :         mPairingDelegate->OnStatusUpdate(status);
     908              :     }
     909              : }
     910              : 
     911            2 : void SetUpCodePairer::OnPairingComplete(CHIP_ERROR error, const std::optional<RendezvousParameters> & rendezvousParameters,
     912              :                                         const std::optional<SetupPayload> & setupPayload)
     913              : {
     914              :     // Save the pairing delegate so we can notify it.  We want to notify it
     915              :     // _after_ we restore the state on the commissioner, in case the delegate
     916              :     // ends up immediately calling back into the commissioner again when
     917              :     // notified.
     918            2 :     auto * pairingDelegate = mPairingDelegate;
     919            2 :     PASEEstablishmentComplete();
     920              : 
     921              :     // Make sure to clear out mCurrentPASEPayload whether we succeeded or failed.
     922            2 :     std::optional<SetupPayload> pasePayload;
     923            2 :     pasePayload.swap(mCurrentPASEPayload);
     924              : 
     925            4 :     if (CHIP_NO_ERROR == error)
     926              :     {
     927            0 :         ChipLogProgress(Controller, "PASE session established with commissionee. Stopping discovery.");
     928            0 :         ResetDiscoveryState();
     929            0 :         mRemoteId = kUndefinedNodeId;
     930              :         MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
     931            0 :         if (pairingDelegate != nullptr)
     932              :         {
     933              :             // We don't expect to have a setupPayload passed in here.
     934            0 :             if (setupPayload)
     935              :             {
     936            0 :                 ChipLogError(Controller,
     937              :                              "Unexpected setupPayload passed to SetUpCodePairer::OnPairingComplete.  Where did it come from?");
     938              :             }
     939            0 :             pairingDelegate->OnPairingComplete(error, rendezvousParameters, pasePayload);
     940              :         }
     941            0 :         return;
     942              :     }
     943              : 
     944              :     // It may happen that there is a stale DNS entry. If so, ReconfirmRecord will flush
     945              :     // the record from the daemon cache once it determines that it is invalid.
     946              :     // It may not help for this particular resolve, but may help subsequent resolves.
     947            4 :     if (CHIP_ERROR_TIMEOUT == error && mCurrentPASEParameters.HasValue())
     948              :     {
     949            1 :         const auto & params = mCurrentPASEParameters.Value();
     950            1 :         const auto & peer   = params.GetPeerAddress();
     951            1 :         const auto & ip     = peer.GetIPAddress();
     952            1 :         auto err            = Dnssd::Resolver::Instance().ReconfirmRecord(params.mHostName, ip, params.mInterfaceId);
     953            3 :         if (CHIP_NO_ERROR != err && CHIP_ERROR_NOT_IMPLEMENTED != err)
     954              :         {
     955            0 :             ChipLogError(Controller, "Error when verifying the validity of an address: %" CHIP_ERROR_FORMAT, err.Format());
     956              :         }
     957              :     }
     958            2 :     mCurrentPASEParameters.ClearValue();
     959              : 
     960              :     // We failed to establish PASE.  Try the next thing we have discovered, if
     961              :     // any.
     962            2 :     if (TryNextRendezvousParameters())
     963              :     {
     964              :         // Keep waiting until that finishes.  Don't call OnPairingComplete yet.
     965            2 :         mLastPASEError = error;
     966            2 :         return;
     967              :     }
     968              : 
     969              :     MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
     970            0 :     if (pairingDelegate != nullptr)
     971              :     {
     972            0 :         pairingDelegate->OnPairingComplete(error, rendezvousParameters, pasePayload);
     973              :     }
     974            2 : }
     975              : 
     976            0 : void SetUpCodePairer::OnPairingDeleted(CHIP_ERROR error)
     977              : {
     978            0 :     if (mPairingDelegate)
     979              :     {
     980            0 :         mPairingDelegate->OnPairingDeleted(error);
     981              :     }
     982            0 : }
     983              : 
     984            0 : void SetUpCodePairer::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error)
     985              : {
     986              :     // Not really expecting this, but handle it anyway.
     987            0 :     if (mPairingDelegate)
     988              :     {
     989            0 :         mPairingDelegate->OnCommissioningComplete(deviceId, error);
     990              :     }
     991            0 : }
     992              : 
     993            2 : void SetUpCodePairer::OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, void * context)
     994              : {
     995            2 :     ChipLogError(Controller, "Discovery timed out");
     996            2 :     auto * pairer = static_cast<SetUpCodePairer *>(context);
     997              : 
     998              :     // If a PASE attempt is in progress, do not stop physical-proximity
     999              :     // transports (BLE, Wi-Fi PAF, NFC) — they have their own completion/timeout
    1000              :     // mechanisms.  DNS-SD, however, runs indefinitely, so stop it now to
    1001              :     // prevent DiscoveryInProgress() from being true forever.
    1002            2 :     if (pairer->mWaitingForPASE)
    1003              :     {
    1004            1 :         LogErrorOnFailure(pairer->StopDiscoveryOverDNSSD());
    1005            1 :         return;
    1006              :     }
    1007              : 
    1008              :     // No PASE in progress — stop all remaining discovery and fail if nothing is left to try.
    1009            1 :     pairer->StopAllDiscoveryAttempts();
    1010            1 :     pairer->StopPairingIfTransportsExhausted(CHIP_ERROR_TIMEOUT);
    1011              : }
    1012              : 
    1013            0 : bool SetUpCodePairer::ShouldDiscoverUsing(RendezvousInformationFlag commissioningChannel) const
    1014              : {
    1015            0 :     for (auto & payload : mSetupPayloads)
    1016              :     {
    1017            0 :         auto & rendezvousInformation = payload.rendezvousInformation;
    1018            0 :         if (!rendezvousInformation.HasValue())
    1019              :         {
    1020              :             // No idea which commissioning channels this device supports, so we
    1021              :             // should be trying using all of them.
    1022            0 :             return true;
    1023              :         }
    1024              : 
    1025            0 :         if (rendezvousInformation.Value().Has(commissioningChannel))
    1026              :         {
    1027            0 :             return true;
    1028              :         }
    1029              :     }
    1030              : 
    1031              :     // None of the payloads claimed support for this commissioning channel.
    1032            0 :     return false;
    1033              : }
    1034              : 
    1035           15 : SetUpCodePairerParameters::SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data,
    1036           15 :                                                      std::optional<uint16_t> longDiscriminator, size_t index) :
    1037           15 :     mLongDiscriminator(longDiscriminator)
    1038              : {
    1039           15 :     mInterfaceId = data.interfaceId;
    1040           15 :     Platform::CopyString(mHostName, data.hostName);
    1041              : 
    1042           15 :     auto & ip = data.ipAddress[index];
    1043           15 :     SetPeerAddress(Transport::PeerAddress::UDP(ip, data.port, ip.IsIPv6LinkLocal() ? data.interfaceId : Inet::InterfaceId::Null()));
    1044              : 
    1045           15 :     if (data.mrpRetryIntervalIdle.has_value())
    1046              :     {
    1047            2 :         SetIdleInterval(*data.mrpRetryIntervalIdle);
    1048              :     }
    1049              : 
    1050           15 :     if (data.mrpRetryIntervalActive.has_value())
    1051              :     {
    1052            0 :         SetActiveInterval(*data.mrpRetryIntervalActive);
    1053              :     }
    1054           15 : }
    1055              : 
    1056              : #if CONFIG_NETWORK_LAYER_BLE
    1057            0 : SetUpCodePairerParameters::SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> longDiscriminator,
    1058            0 :                                                      bool connected) :
    1059            0 :     mLongDiscriminator(longDiscriminator)
    1060              : {
    1061            0 :     Transport::PeerAddress peerAddress = Transport::PeerAddress::BLE();
    1062            0 :     SetPeerAddress(peerAddress);
    1063            0 :     if (connected)
    1064              :     {
    1065            0 :         SetConnectionObject(connObj);
    1066              :     }
    1067              :     else
    1068              :     {
    1069            0 :         SetDiscoveredObject(connObj);
    1070              :     }
    1071            0 : }
    1072              : #endif // CONFIG_NETWORK_LAYER_BLE
    1073              : 
    1074              : } // namespace Controller
    1075              : } // namespace chip
        

Generated by: LCOV version 2.0-1