Matter SDK Coverage Report
Current view: top level - controller - SetUpCodePairer.cpp (source / functions) Coverage Total Hit
Test: SHA:704d97f9c619242ad76fcf75aeabc67802fa72d4 Lines: 19.8 % 414 82
Test Date: 2026-05-18 07:37:39 Functions: 33.3 % 42 14

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

Generated by: LCOV version 2.0-1