Matter SDK Coverage Report
Current view: top level - controller - SetUpCodePairer.cpp (source / functions) Coverage Total Hit
Test: SHA:3640a4f95bebd68003e5aea27c711ffe4cd39423 Lines: 0.0 % 358 0
Test Date: 2025-09-14 07:12:24 Functions: 0.0 % 39 0

            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_NO_ERROR)
     142              :             {
     143            0 :                 ChipLogError(Controller, "Failed to start commissionable node discovery over NFC: %" CHIP_ERROR_FORMAT,
     144              :                              err.Format());
     145              :             }
     146              :         }
     147              :     }
     148              : 
     149              :     // We always want to search on network because any node that has already been commissioned will use on-network regardless of the
     150              :     // QR code flag.
     151            0 :     CHIP_ERROR err = StartDiscoveryOverDNSSD();
     152            0 :     if (err != CHIP_NO_ERROR)
     153              :     {
     154            0 :         ChipLogError(Controller, "Failed to start commissionable node discovery over DNS-SD: %" CHIP_ERROR_FORMAT, err.Format());
     155              :     }
     156            0 :     return err;
     157              : }
     158              : 
     159            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverBLE()
     160              : {
     161              : #if CONFIG_NETWORK_LAYER_BLE
     162              : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     163              :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     164              :     mCommissioner->ConnectBleTransportToSelf();
     165              : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     166            0 :     VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
     167              : 
     168            0 :     ChipLogProgress(Controller, "Starting commissionable node discovery over BLE");
     169              : 
     170              :     // Handle possibly-sync callbacks.
     171            0 :     mWaitingForDiscovery[kBLETransport] = true;
     172              :     CHIP_ERROR err;
     173              :     // Not all BLE backends support the new NewBleConnectionByDiscriminators
     174              :     // API, so use the old one when we can (i.e. when we only have one setup
     175              :     // payload), to avoid breaking existing API consumers.
     176            0 :     if (mSetupPayloads.size() == 1)
     177              :     {
     178            0 :         err = mBleLayer->NewBleConnectionByDiscriminator(mSetupPayloads[0].discriminator, this, OnDiscoveredDeviceOverBleSuccess,
     179              :                                                          OnDiscoveredDeviceOverBleError);
     180              :     }
     181              :     else
     182              :     {
     183            0 :         std::vector<SetupDiscriminator> discriminators;
     184            0 :         discriminators.reserve(mSetupPayloads.size());
     185            0 :         for (auto & payload : mSetupPayloads)
     186              :         {
     187            0 :             discriminators.emplace_back(payload.discriminator);
     188              :         }
     189            0 :         err = mBleLayer->NewBleConnectionByDiscriminators(Span(discriminators.data(), discriminators.size()), this,
     190              :                                                           OnDiscoveredDeviceWithDiscriminatorOverBleSuccess,
     191              :                                                           OnDiscoveredDeviceOverBleError);
     192            0 :     }
     193            0 :     if (err != CHIP_NO_ERROR)
     194              :     {
     195            0 :         mWaitingForDiscovery[kBLETransport] = false;
     196              :     }
     197            0 :     return err;
     198              : #else
     199              :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     200              : #endif // CONFIG_NETWORK_LAYER_BLE
     201              : }
     202              : 
     203            0 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverBLE()
     204              : {
     205              :     // Make sure to not call CancelBleIncompleteConnection unless we are in fact
     206              :     // waiting on BLE discovery.  It will cancel connections that are in fact
     207              :     // completed. In particular, if we just established PASE over BLE calling
     208              :     // CancelBleIncompleteConnection here unconditionally would cancel the BLE
     209              :     // connection underlying the PASE session.  So make sure to only call
     210              :     // CancelBleIncompleteConnection if we're still waiting to hear back on the
     211              :     // BLE discovery bits.
     212            0 :     if (!mWaitingForDiscovery[kBLETransport])
     213              :     {
     214            0 :         return CHIP_NO_ERROR;
     215              :     }
     216              : 
     217            0 :     mWaitingForDiscovery[kBLETransport] = false;
     218              : #if CONFIG_NETWORK_LAYER_BLE
     219            0 :     VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
     220            0 :     ChipLogProgress(Controller, "Stopping commissionable node discovery over BLE");
     221            0 :     return mBleLayer->CancelBleIncompleteConnection();
     222              : #else
     223              :     return CHIP_NO_ERROR;
     224              : #endif // CONFIG_NETWORK_LAYER_BLE
     225              : }
     226              : 
     227            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverDNSSD()
     228              : {
     229            0 :     ChipLogProgress(Controller, "Starting commissionable node discovery over DNS-SD");
     230              : 
     231            0 :     Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kNone);
     232            0 :     if (mSetupPayloads.size() == 1)
     233              :     {
     234            0 :         auto & discriminator = mSetupPayloads[0].discriminator;
     235            0 :         if (discriminator.IsShortDiscriminator())
     236              :         {
     237            0 :             filter.type = Dnssd::DiscoveryFilterType::kShortDiscriminator;
     238            0 :             filter.code = discriminator.GetShortValue();
     239              :         }
     240              :         else
     241              :         {
     242            0 :             filter.type = Dnssd::DiscoveryFilterType::kLongDiscriminator;
     243            0 :             filter.code = discriminator.GetLongValue();
     244              :         }
     245              :     }
     246              : 
     247              :     // In theory we could try to filter on the vendor ID if it's the same across all the setup
     248              :     // payloads, but DNS-SD advertisements are not required to include the Vendor ID subtype, so in
     249              :     // practice that's not doable.
     250              : 
     251              :     // Handle possibly-sync callbacks.
     252            0 :     mWaitingForDiscovery[kIPTransport] = true;
     253            0 :     CHIP_ERROR err                     = mCommissioner->DiscoverCommissionableNodes(filter);
     254            0 :     if (err != CHIP_NO_ERROR)
     255              :     {
     256            0 :         mWaitingForDiscovery[kIPTransport] = false;
     257              :     }
     258            0 :     return err;
     259              : }
     260              : 
     261            0 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverDNSSD()
     262              : {
     263            0 :     ChipLogProgress(Controller, "Stopping commissionable node discovery over DNS-SD");
     264              : 
     265            0 :     mWaitingForDiscovery[kIPTransport] = false;
     266              : 
     267            0 :     mCommissioner->StopCommissionableDiscovery();
     268            0 :     return CHIP_NO_ERROR;
     269              : }
     270              : 
     271            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverWiFiPAF()
     272              : {
     273              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     274            0 :     if (mSetupPayloads.size() != 1)
     275              :     {
     276            0 :         ChipLogError(Controller, "Wi-Fi PAF commissioning does not support concatenated QR codes yet.");
     277            0 :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     278              :     }
     279              : 
     280            0 :     auto & payload = mSetupPayloads[0];
     281              : 
     282            0 :     ChipLogProgress(Controller, "Starting commissionable node discovery over Wi-Fi PAF");
     283            0 :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     284              : 
     285            0 :     const SetupDiscriminator connDiscriminator(payload.discriminator);
     286            0 :     VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
     287              :                         ChipLogError(Controller, "Error, Long discriminator is required"));
     288            0 :     uint16_t discriminator              = connDiscriminator.GetLongValue();
     289            0 :     WiFiPAF::WiFiPAFSession sessionInfo = { .role          = WiFiPAF::WiFiPafRole::kWiFiPafRole_Subscriber,
     290            0 :                                             .nodeId        = mRemoteId,
     291            0 :                                             .discriminator = discriminator };
     292            0 :     ReturnErrorOnFailure(
     293              :         DeviceLayer::ConnectivityMgr().GetWiFiPAF()->AddPafSession(WiFiPAF::PafInfoAccess::kAccNodeInfo, sessionInfo));
     294              : 
     295            0 :     mWaitingForDiscovery[kWiFiPAFTransport] = true;
     296            0 :     CHIP_ERROR err = DeviceLayer::ConnectivityMgr().WiFiPAFSubscribe(discriminator, (void *) this, OnWiFiPAFSubscribeComplete,
     297              :                                                                      OnWiFiPAFSubscribeError);
     298            0 :     if (err != CHIP_NO_ERROR)
     299              :     {
     300            0 :         ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     301            0 :         mWaitingForDiscovery[kWiFiPAFTransport] = false;
     302              :     }
     303            0 :     return err;
     304              : #else
     305              :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     306              : #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     307              : }
     308              : 
     309            0 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverWiFiPAF()
     310              : {
     311            0 :     mWaitingForDiscovery[kWiFiPAFTransport] = false;
     312              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     313            0 :     DeviceLayer::ConnectivityMgr().WiFiPAFCancelIncompleteSubscribe();
     314              : #endif
     315            0 :     return CHIP_NO_ERROR;
     316              : }
     317              : 
     318            0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverNFC()
     319              : {
     320              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     321              :     if (mSetupPayloads.size() != 1)
     322              :     {
     323              :         ChipLogError(Controller, "NFC commissioning does not support concatenated QR codes yet.");
     324              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     325              :     }
     326              : 
     327              :     auto & payload = mSetupPayloads[0];
     328              : 
     329              :     ChipLogProgress(Controller, "Starting commissionable node discovery over NFC");
     330              :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     331              : 
     332              :     const SetupDiscriminator connDiscriminator(payload.discriminator);
     333              :     VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
     334              :                         ChipLogError(Controller, "Error, Long discriminator is required"));
     335              :     chip::Nfc::NFCTag::Identifier identifier  = { .discriminator = payload.discriminator.GetLongValue() };
     336              :     Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
     337              :     if (!readerTransport)
     338              :     {
     339              :         ChipLogError(Controller, "Commissionable node discovery over NFC since there is no valid NFC reader transport");
     340              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     341              :     }
     342              : 
     343              :     readerTransport->SetDelegate(this);
     344              :     CHIP_ERROR err = readerTransport->StartDiscoveringTagMatchingAddress(identifier);
     345              :     if (err != CHIP_NO_ERROR)
     346              :     {
     347              :         ChipLogError(Controller, "Commissionable node discovery over NFC failed, err = %" CHIP_ERROR_FORMAT, err.Format());
     348              :     }
     349              :     else
     350              :     {
     351              :         mWaitingForDiscovery[kNFCTransport] = true;
     352              :     }
     353              :     return err;
     354              : #else
     355            0 :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     356              : #endif // CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     357              : }
     358              : 
     359            0 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverNFC()
     360              : {
     361              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     362              :     mWaitingForDiscovery[kNFCTransport] = false;
     363              : 
     364              :     Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
     365              :     if (!readerTransport)
     366              :     {
     367              :         ChipLogError(Controller,
     368              :                      "Failed to stop commissionable node discovery over NFC since there is no valid NFC reader transport");
     369              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     370              :     }
     371              : 
     372              :     ChipLogProgress(Controller, "Stopping commissionable node discovery over NFC by removing delegate");
     373              :     readerTransport->SetDelegate(nullptr);
     374              : #endif
     375            0 :     return CHIP_NO_ERROR;
     376              : }
     377              : 
     378            0 : bool SetUpCodePairer::ConnectToDiscoveredDevice()
     379              : {
     380            0 :     if (mWaitingForPASE)
     381              :     {
     382              :         // Nothing to do.  Just wait until we either succeed or fail at that
     383              :         // PASE session establishment.
     384            0 :         return false;
     385              :     }
     386              : 
     387            0 :     while (!mDiscoveredParameters.empty())
     388              :     {
     389              :         // Grab the first element from the queue and try connecting to it.
     390              :         // Remove it from the queue before we try to connect, in case the
     391              :         // connection attempt fails and calls right back into us to try the next
     392              :         // thing.
     393            0 :         SetUpCodePairerParameters params(mDiscoveredParameters.front());
     394            0 :         mDiscoveredParameters.pop_front();
     395              : 
     396            0 :         if (params.mLongDiscriminator)
     397              :         {
     398            0 :             auto longDiscriminator = *params.mLongDiscriminator;
     399              :             // Look for a matching setup passcode.
     400            0 :             bool found = false;
     401            0 :             for (auto & payload : mSetupPayloads)
     402              :             {
     403            0 :                 if (payload.discriminator.MatchesLongDiscriminator(longDiscriminator))
     404              :                 {
     405            0 :                     params.SetSetupPINCode(payload.setUpPINCode);
     406            0 :                     found = true;
     407            0 :                     break;
     408              :                 }
     409              :             }
     410            0 :             if (!found)
     411              :             {
     412            0 :                 ChipLogError(Controller, "SetUpCodePairer: Discovered discriminator %u does not match any of our setup payloads",
     413              :                              longDiscriminator);
     414              :                 // Move on to the the next discovered params; nothing we can do here.
     415            0 :                 continue;
     416              :             }
     417              :         }
     418              :         else
     419              :         {
     420              :             // No discriminator known for this discovered device.  This can work if we have only one
     421              :             // setup payload, but otherwise we have no idea what setup passcode to use for it.
     422            0 :             if (mSetupPayloads.size() == 1)
     423              :             {
     424            0 :                 params.SetSetupPINCode(mSetupPayloads[0].setUpPINCode);
     425              :             }
     426              :             else
     427              :             {
     428            0 :                 ChipLogError(Controller,
     429              :                              "SetUpCodePairer: Unable to handle discovered parameters with no discriminator, because it has %u "
     430              :                              "possible payloads",
     431              :                              static_cast<unsigned>(mSetupPayloads.size()));
     432            0 :                 continue;
     433              :             }
     434              :         }
     435              : 
     436              : #if CHIP_PROGRESS_LOGGING
     437              :         char buf[Transport::PeerAddress::kMaxToStringSize];
     438            0 :         params.GetPeerAddress().ToString(buf);
     439            0 :         ChipLogProgress(Controller, "Attempting PASE connection to %s", buf);
     440              : #endif // CHIP_PROGRESS_LOGGING
     441              : 
     442              :         // Handle possibly-sync call backs from attempts to establish PASE.
     443            0 :         ExpectPASEEstablishment();
     444              : 
     445            0 :         if (params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
     446              :         {
     447            0 :             mCurrentPASEParameters.SetValue(params);
     448              :         }
     449              : 
     450              :         CHIP_ERROR err;
     451            0 :         if (mConnectionType == SetupCodePairerBehaviour::kCommission)
     452              :         {
     453            0 :             err = mCommissioner->PairDevice(mRemoteId, params);
     454              :         }
     455              :         else
     456              :         {
     457            0 :             err = mCommissioner->EstablishPASEConnection(mRemoteId, params);
     458              :         }
     459              : 
     460            0 :         LogErrorOnFailure(err);
     461            0 :         if (err == CHIP_NO_ERROR)
     462              :         {
     463            0 :             return true;
     464              :         }
     465              : 
     466              :         // Failed to start establishing PASE.  Move on to the next item.
     467            0 :         PASEEstablishmentComplete();
     468              :     }
     469              : 
     470            0 :     return false;
     471              : }
     472              : 
     473              : #if CONFIG_NETWORK_LAYER_BLE
     474            0 : void SetUpCodePairer::OnDiscoveredDeviceOverBle(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> matchedLongDiscriminator)
     475              : {
     476            0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over BLE");
     477              : 
     478            0 :     mWaitingForDiscovery[kBLETransport] = false;
     479              : 
     480              :     // In order to not wait for all the possible addresses discovered over mdns to
     481              :     // be tried before trying to connect over BLE, the discovered connection object is
     482              :     // inserted at the beginning of the list.
     483              :     //
     484              :     // It makes it the 'next' thing to try to connect to if there are already some
     485              :     // discovered parameters in the list.
     486              :     //
     487              :     // TODO: Consider implementing the SHOULD the spec has about commissioning things
     488              :     // in QR code order by waiting for a second or something before actually starting
     489              :     // the first PASE session when we have multiple setup payloads, and sorting the
     490              :     // results in setup payload order.  If we do this, we might want to restrict it to
     491              :     // cases when the different payloads have different vendor/product IDs, since if
     492              :     // they are all the same product presumably ordering really does not matter.
     493            0 :     mDiscoveredParameters.emplace_front(connObj, matchedLongDiscriminator);
     494            0 :     ConnectToDiscoveredDevice();
     495            0 : }
     496              : 
     497            0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
     498              : {
     499            0 :     (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::nullopt);
     500            0 : }
     501              : 
     502            0 : void SetUpCodePairer::OnDiscoveredDeviceWithDiscriminatorOverBleSuccess(void * appState, uint16_t matchedLongDiscriminator,
     503              :                                                                         BLE_CONNECTION_OBJECT connObj)
     504              : {
     505            0 :     (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::make_optional(matchedLongDiscriminator));
     506            0 : }
     507              : 
     508            0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
     509              : {
     510            0 :     static_cast<SetUpCodePairer *>(appState)->OnBLEDiscoveryError(err);
     511            0 : }
     512              : 
     513            0 : void SetUpCodePairer::OnBLEDiscoveryError(CHIP_ERROR err)
     514              : {
     515            0 :     ChipLogError(Controller, "Commissionable node discovery over BLE failed: %" CHIP_ERROR_FORMAT, err.Format());
     516            0 :     mWaitingForDiscovery[kBLETransport] = false;
     517            0 :     LogErrorOnFailure(err);
     518            0 : }
     519              : #endif // CONFIG_NETWORK_LAYER_BLE
     520              : 
     521              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     522            0 : void SetUpCodePairer::OnDiscoveredDeviceOverWifiPAF()
     523              : {
     524            0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over Wi-Fi PAF, RemoteId: %lu", mRemoteId);
     525              : 
     526            0 :     mWaitingForDiscovery[kWiFiPAFTransport] = false;
     527            0 :     auto param                              = SetUpCodePairerParameters();
     528            0 :     param.SetPeerAddress(Transport::PeerAddress(Transport::Type::kWiFiPAF, mRemoteId));
     529              :     // TODO: This needs to support concatenated QR codes and set the relevant
     530              :     // long discriminator on param.
     531              :     //
     532              :     // See https://github.com/project-chip/connectedhomeip/issues/39134
     533            0 :     mDiscoveredParameters.emplace_back(param);
     534            0 :     ConnectToDiscoveredDevice();
     535            0 : }
     536              : 
     537            0 : void SetUpCodePairer::OnWifiPAFDiscoveryError(CHIP_ERROR err)
     538              : {
     539            0 :     ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed: %" CHIP_ERROR_FORMAT, err.Format());
     540            0 :     mWaitingForDiscovery[kWiFiPAFTransport] = false;
     541            0 : }
     542              : 
     543            0 : void SetUpCodePairer::OnWiFiPAFSubscribeComplete(void * appState)
     544              : {
     545            0 :     auto self = reinterpret_cast<SetUpCodePairer *>(appState);
     546            0 :     self->OnDiscoveredDeviceOverWifiPAF();
     547            0 : }
     548              : 
     549            0 : void SetUpCodePairer::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err)
     550              : {
     551            0 :     auto self = reinterpret_cast<SetUpCodePairer *>(appState);
     552            0 :     self->OnWifiPAFDiscoveryError(err);
     553            0 : }
     554              : #endif
     555              : 
     556              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     557              : void SetUpCodePairer::OnTagDiscovered(const chip::Nfc::NFCTag::Identifier & identifier)
     558              : {
     559              :     ChipLogProgress(Controller, "Discovered device to be commissioned over NFC, Identifier: %u", identifier.discriminator);
     560              : 
     561              :     mWaitingForDiscovery[kNFCTransport] = false;
     562              :     auto param                          = SetUpCodePairerParameters();
     563              :     param.SetPeerAddress(Transport::PeerAddress(Transport::PeerAddress::NFC(identifier.discriminator)));
     564              :     // TODO: This needs to support concatenated QR codes and set the relevant
     565              :     // long discriminator on param.
     566              :     //
     567              :     // See https://github.com/project-chip/connectedhomeip/issues/39134
     568              :     mDiscoveredParameters.emplace_back(param);
     569              :     ConnectToDiscoveredDevice();
     570              : }
     571              : 
     572              : void SetUpCodePairer::OnTagDiscoveryFailed(CHIP_ERROR error)
     573              : {
     574              :     ChipLogError(Controller, "Commissionable node discovery over NFC failed: %" CHIP_ERROR_FORMAT, error.Format());
     575              :     mWaitingForDiscovery[kNFCTransport] = false;
     576              : }
     577              : #endif
     578              : 
     579            0 : bool SetUpCodePairer::IdIsPresent(uint16_t vendorOrProductID)
     580              : {
     581            0 :     return vendorOrProductID != kNotAvailable;
     582              : }
     583              : 
     584            0 : bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & discNodeData) const
     585              : {
     586            0 :     if (!discNodeData.Is<Dnssd::CommissionNodeData>())
     587              :     {
     588            0 :         return false;
     589              :     }
     590              : 
     591            0 :     const Dnssd::CommissionNodeData & nodeData = discNodeData.Get<Dnssd::CommissionNodeData>();
     592              : 
     593            0 :     VerifyOrReturnError(mCommissioner != nullptr, false);
     594            0 :     VerifyOrReturnError(mCommissioner->HasValidCommissioningMode(nodeData), false);
     595              : 
     596              :     // Check whether this matches one of our setup payloads.
     597            0 :     for (auto & payload : mSetupPayloads)
     598              :     {
     599              :         // The advertisement may not include a vendor id, and the payload may not have one either.
     600            0 :         if (IdIsPresent(payload.vendorID) && IdIsPresent(nodeData.vendorId) && payload.vendorID != nodeData.vendorId)
     601              :         {
     602            0 :             ChipLogProgress(Controller, "Discovered device vendor ID (%u) does not match our vendor ID (%u).", nodeData.vendorId,
     603              :                             payload.vendorID);
     604            0 :             continue;
     605              :         }
     606              : 
     607              :         // The advertisement may not include a product id, and the payload may not have one either.
     608            0 :         if (IdIsPresent(payload.productID) && IdIsPresent(nodeData.productId) && payload.productID != nodeData.productId)
     609              :         {
     610            0 :             ChipLogProgress(Controller, "Discovered device product ID (%u) does not match our product ID (%u).", nodeData.productId,
     611              :                             payload.productID);
     612            0 :             continue;
     613              :         }
     614              : 
     615            0 :         if (!payload.discriminator.MatchesLongDiscriminator(nodeData.longDiscriminator))
     616              :         {
     617            0 :             ChipLogProgress(Controller, "Discovered device discriminator (%u) does not match our discriminator.",
     618              :                             nodeData.longDiscriminator);
     619            0 :             continue;
     620              :         }
     621              : 
     622            0 :         ChipLogProgress(Controller, "Discovered device with discriminator %u matches one of our setup payloads",
     623              :                         nodeData.longDiscriminator);
     624            0 :         return true;
     625              :     }
     626              : 
     627            0 :     return false;
     628              : }
     629              : 
     630            0 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::DiscoveredNodeData & nodeData)
     631              : {
     632            0 :     if (!NodeMatchesCurrentFilter(nodeData))
     633              :     {
     634            0 :         return;
     635              :     }
     636              : 
     637            0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over DNS-SD");
     638              : 
     639            0 :     auto & commissionableNodeData = nodeData.Get<Dnssd::CommissionNodeData>();
     640              : 
     641            0 :     NotifyCommissionableDeviceDiscovered(commissionableNodeData, std::make_optional(commissionableNodeData.longDiscriminator));
     642              : }
     643              : 
     644            0 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::CommonResolutionData & resolutionData,
     645              :                                                            std::optional<uint16_t> matchedLongDiscriminator)
     646              : {
     647            0 :     if (mDiscoveryType == DiscoveryType::kDiscoveryNetworkOnlyWithoutPASEAutoRetry)
     648              :     {
     649              :         // If the discovery type does not want the PASE auto retry mechanism, we will just store
     650              :         // a single IP. So the discovery process is stopped as it won't be of any help anymore.
     651            0 :         StopDiscoveryOverDNSSD();
     652            0 :         mDiscoveredParameters.emplace_back(resolutionData, matchedLongDiscriminator, 0);
     653              :     }
     654              :     else
     655              :     {
     656            0 :         for (size_t i = 0; i < resolutionData.numIPs; i++)
     657              :         {
     658            0 :             mDiscoveredParameters.emplace_back(resolutionData, matchedLongDiscriminator, i);
     659              :         }
     660              :     }
     661              : 
     662            0 :     ConnectToDiscoveredDevice();
     663            0 : }
     664              : 
     665            0 : bool SetUpCodePairer::StopPairing(NodeId remoteId)
     666              : {
     667            0 :     VerifyOrReturnValue(mRemoteId != kUndefinedNodeId, false);
     668            0 :     VerifyOrReturnValue(remoteId == kUndefinedNodeId || remoteId == mRemoteId, false);
     669              : 
     670            0 :     if (mWaitingForPASE)
     671              :     {
     672            0 :         PASEEstablishmentComplete();
     673              :     }
     674              : 
     675            0 :     ResetDiscoveryState();
     676            0 :     mRemoteId = kUndefinedNodeId;
     677            0 :     return true;
     678              : }
     679              : 
     680            0 : bool SetUpCodePairer::TryNextRendezvousParameters()
     681              : {
     682            0 :     if (ConnectToDiscoveredDevice())
     683              :     {
     684            0 :         ChipLogProgress(Controller, "Trying connection to commissionee over different transport");
     685            0 :         return true;
     686              :     }
     687              : 
     688            0 :     if (DiscoveryInProgress())
     689              :     {
     690            0 :         ChipLogProgress(Controller, "Waiting to discover commissionees that match our filters");
     691            0 :         return true;
     692              :     }
     693              : 
     694            0 :     return false;
     695              : }
     696              : 
     697            0 : bool SetUpCodePairer::DiscoveryInProgress() const
     698              : {
     699            0 :     for (const auto & waiting : mWaitingForDiscovery)
     700              :     {
     701            0 :         if (waiting)
     702              :         {
     703            0 :             return true;
     704              :         }
     705              :     }
     706              : 
     707            0 :     return false;
     708              : }
     709              : 
     710            0 : void SetUpCodePairer::StopAllDiscoveryAttempts()
     711              : {
     712            0 :     LogErrorOnFailure(StopDiscoveryOverBLE());
     713            0 :     LogErrorOnFailure(StopDiscoveryOverDNSSD());
     714            0 :     LogErrorOnFailure(StopDiscoveryOverWiFiPAF());
     715            0 :     LogErrorOnFailure(StopDiscoveryOverNFC());
     716              : 
     717              :     // Just in case any of those failed to reset the waiting state properly.
     718            0 :     for (auto & waiting : mWaitingForDiscovery)
     719              :     {
     720            0 :         waiting = false;
     721              :     }
     722            0 : }
     723              : 
     724            0 : void SetUpCodePairer::ResetDiscoveryState()
     725              : {
     726            0 :     StopAllDiscoveryAttempts();
     727              : 
     728            0 :     mDiscoveredParameters.clear();
     729            0 :     mCurrentPASEParameters.ClearValue();
     730            0 :     mLastPASEError = CHIP_NO_ERROR;
     731              : 
     732            0 :     mSetupPayloads.clear();
     733              : 
     734            0 :     mSystemLayer->CancelTimer(OnDeviceDiscoveredTimeoutCallback, this);
     735            0 : }
     736              : 
     737            0 : void SetUpCodePairer::ExpectPASEEstablishment()
     738              : {
     739            0 :     VerifyOrDie(!mWaitingForPASE);
     740            0 :     mWaitingForPASE = true;
     741            0 :     auto * delegate = mCommissioner->GetPairingDelegate();
     742            0 :     VerifyOrDie(delegate != this);
     743            0 :     mPairingDelegate = delegate;
     744            0 :     mCommissioner->RegisterPairingDelegate(this);
     745            0 : }
     746              : 
     747            0 : void SetUpCodePairer::PASEEstablishmentComplete()
     748              : {
     749            0 :     VerifyOrDie(mWaitingForPASE);
     750            0 :     mWaitingForPASE = false;
     751            0 :     mCommissioner->RegisterPairingDelegate(mPairingDelegate);
     752            0 :     mPairingDelegate = nullptr;
     753            0 : }
     754              : 
     755            0 : void SetUpCodePairer::OnStatusUpdate(DevicePairingDelegate::Status status)
     756              : {
     757            0 :     if (status == DevicePairingDelegate::Status::SecurePairingFailed)
     758              :     {
     759              :         // If we're still waiting on discovery, don't propagate this failure
     760              :         // (which is due to PASE failure with something we discovered, but the
     761              :         // "something" may not have been the right thing) for now.  Wait until
     762              :         // discovery completes.  Then we will either succeed and notify
     763              :         // accordingly or time out and land in OnStatusUpdate again, but at that
     764              :         // point we will not be waiting on discovery anymore.
     765            0 :         if (!mDiscoveredParameters.empty())
     766              :         {
     767            0 :             ChipLogProgress(Controller, "Ignoring SecurePairingFailed status for now; we have more discovered devices to try");
     768            0 :             return;
     769              :         }
     770              : 
     771            0 :         if (DiscoveryInProgress())
     772              :         {
     773            0 :             ChipLogProgress(Controller,
     774              :                             "Ignoring SecurePairingFailed status for now; we are waiting to see if we discover more devices");
     775            0 :             return;
     776              :         }
     777              :     }
     778              : 
     779            0 :     if (mPairingDelegate)
     780              :     {
     781            0 :         mPairingDelegate->OnStatusUpdate(status);
     782              :     }
     783              : }
     784              : 
     785            0 : void SetUpCodePairer::OnPairingComplete(CHIP_ERROR error)
     786              : {
     787              :     // Save the pairing delegate so we can notify it.  We want to notify it
     788              :     // _after_ we restore the state on the commissioner, in case the delegate
     789              :     // ends up immediately calling back into the commissioner again when
     790              :     // notified.
     791            0 :     auto * pairingDelegate = mPairingDelegate;
     792            0 :     PASEEstablishmentComplete();
     793              : 
     794            0 :     if (CHIP_NO_ERROR == error)
     795              :     {
     796            0 :         ChipLogProgress(Controller, "PASE session established with commissionee. Stopping discovery.");
     797            0 :         ResetDiscoveryState();
     798            0 :         mRemoteId = kUndefinedNodeId;
     799              :         MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
     800            0 :         if (pairingDelegate != nullptr)
     801              :         {
     802            0 :             pairingDelegate->OnPairingComplete(error);
     803              :         }
     804            0 :         return;
     805              :     }
     806              : 
     807              :     // It may happen that there is a stale DNS entry. If so, ReconfirmRecord will flush
     808              :     // the record from the daemon cache once it determines that it is invalid.
     809              :     // It may not help for this particular resolve, but may help subsequent resolves.
     810            0 :     if (CHIP_ERROR_TIMEOUT == error && mCurrentPASEParameters.HasValue())
     811              :     {
     812            0 :         const auto & params = mCurrentPASEParameters.Value();
     813            0 :         const auto & peer   = params.GetPeerAddress();
     814            0 :         const auto & ip     = peer.GetIPAddress();
     815            0 :         auto err            = Dnssd::Resolver::Instance().ReconfirmRecord(params.mHostName, ip, params.mInterfaceId);
     816            0 :         if (CHIP_NO_ERROR != err && CHIP_ERROR_NOT_IMPLEMENTED != err)
     817              :         {
     818            0 :             ChipLogError(Controller, "Error when verifying the validity of an address: %" CHIP_ERROR_FORMAT, err.Format());
     819              :         }
     820              :     }
     821            0 :     mCurrentPASEParameters.ClearValue();
     822              : 
     823              :     // We failed to establish PASE.  Try the next thing we have discovered, if
     824              :     // any.
     825            0 :     if (TryNextRendezvousParameters())
     826              :     {
     827              :         // Keep waiting until that finishes.  Don't call OnPairingComplete yet.
     828            0 :         mLastPASEError = error;
     829            0 :         return;
     830              :     }
     831              : 
     832              :     MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
     833            0 :     if (pairingDelegate != nullptr)
     834              :     {
     835            0 :         pairingDelegate->OnPairingComplete(error);
     836              :     }
     837              : }
     838              : 
     839            0 : void SetUpCodePairer::OnPairingDeleted(CHIP_ERROR error)
     840              : {
     841            0 :     if (mPairingDelegate)
     842              :     {
     843            0 :         mPairingDelegate->OnPairingDeleted(error);
     844              :     }
     845            0 : }
     846              : 
     847            0 : void SetUpCodePairer::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error)
     848              : {
     849              :     // Not really expecting this, but handle it anyway.
     850            0 :     if (mPairingDelegate)
     851              :     {
     852            0 :         mPairingDelegate->OnCommissioningComplete(deviceId, error);
     853              :     }
     854            0 : }
     855              : 
     856            0 : void SetUpCodePairer::OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, void * context)
     857              : {
     858            0 :     ChipLogError(Controller, "Discovery timed out");
     859            0 :     auto * pairer = static_cast<SetUpCodePairer *>(context);
     860            0 :     pairer->StopAllDiscoveryAttempts();
     861            0 :     if (!pairer->mWaitingForPASE && pairer->mDiscoveredParameters.empty())
     862              :     {
     863              :         // We're not waiting on any more PASE attempts, and we're not going to
     864              :         // discover anything at this point, so we should just notify our
     865              :         // listener.
     866            0 :         CHIP_ERROR err = pairer->mLastPASEError;
     867            0 :         if (err == CHIP_NO_ERROR)
     868              :         {
     869            0 :             err = CHIP_ERROR_TIMEOUT;
     870              :         }
     871              :         MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, err);
     872            0 :         pairer->mCommissioner->OnSessionEstablishmentError(err);
     873              :     }
     874            0 : }
     875              : 
     876            0 : bool SetUpCodePairer::ShouldDiscoverUsing(RendezvousInformationFlag commissioningChannel) const
     877              : {
     878            0 :     for (auto & payload : mSetupPayloads)
     879              :     {
     880            0 :         auto & rendezvousInformation = payload.rendezvousInformation;
     881            0 :         if (!rendezvousInformation.HasValue())
     882              :         {
     883              :             // No idea which commissioning channels this device supports, so we
     884              :             // should be trying using all of them.
     885            0 :             return true;
     886              :         }
     887              : 
     888            0 :         if (rendezvousInformation.Value().Has(commissioningChannel))
     889              :         {
     890            0 :             return true;
     891              :         }
     892              :     }
     893              : 
     894              :     // None of the payloads claimed support for this commissioning channel.
     895            0 :     return false;
     896              : }
     897              : 
     898            0 : SetUpCodePairerParameters::SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data,
     899            0 :                                                      std::optional<uint16_t> longDiscriminator, size_t index) :
     900            0 :     mLongDiscriminator(longDiscriminator)
     901              : {
     902            0 :     mInterfaceId = data.interfaceId;
     903            0 :     Platform::CopyString(mHostName, data.hostName);
     904              : 
     905            0 :     auto & ip = data.ipAddress[index];
     906            0 :     SetPeerAddress(Transport::PeerAddress::UDP(ip, data.port, ip.IsIPv6LinkLocal() ? data.interfaceId : Inet::InterfaceId::Null()));
     907              : 
     908            0 :     if (data.mrpRetryIntervalIdle.has_value())
     909              :     {
     910            0 :         SetIdleInterval(*data.mrpRetryIntervalIdle);
     911              :     }
     912              : 
     913            0 :     if (data.mrpRetryIntervalActive.has_value())
     914              :     {
     915            0 :         SetActiveInterval(*data.mrpRetryIntervalActive);
     916              :     }
     917            0 : }
     918              : 
     919              : #if CONFIG_NETWORK_LAYER_BLE
     920            0 : SetUpCodePairerParameters::SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> longDiscriminator,
     921            0 :                                                      bool connected) :
     922            0 :     mLongDiscriminator(longDiscriminator)
     923              : {
     924            0 :     Transport::PeerAddress peerAddress = Transport::PeerAddress::BLE();
     925            0 :     SetPeerAddress(peerAddress);
     926            0 :     if (connected)
     927              :     {
     928            0 :         SetConnectionObject(connObj);
     929              :     }
     930              :     else
     931              :     {
     932            0 :         SetDiscoveredObject(connObj);
     933              :     }
     934            0 : }
     935              : #endif // CONFIG_NETWORK_LAYER_BLE
     936              : 
     937              : } // namespace Controller
     938              : } // namespace chip
        

Generated by: LCOV version 2.0-1