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

Generated by: LCOV version 2.0-1