LCOV - code coverage report
Current view: top level - controller - SetUpCodePairer.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 0 286 0.0 %
Date: 2024-02-15 08:20:41 Functions: 0 31 0.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 <system/SystemClock.h>
      33             : 
      34             : constexpr uint32_t kDeviceDiscoveredTimeout = CHIP_CONFIG_SETUP_CODE_PAIRER_DISCOVERY_TIMEOUT_SECS * chip::kMillisecondsPerSecond;
      35             : 
      36             : namespace chip {
      37             : namespace Controller {
      38             : 
      39             : namespace {
      40             : 
      41           0 : CHIP_ERROR GetPayload(const char * setUpCode, SetupPayload & payload)
      42             : {
      43           0 :     bool isQRCode = strncmp(setUpCode, kQRCodePrefix, strlen(kQRCodePrefix)) == 0;
      44           0 :     if (isQRCode)
      45             :     {
      46           0 :         ReturnErrorOnFailure(QRCodeSetupPayloadParser(setUpCode).populatePayload(payload));
      47           0 :         VerifyOrReturnError(payload.isValidQRCodePayload(), CHIP_ERROR_INVALID_ARGUMENT);
      48             :     }
      49             :     else
      50             :     {
      51           0 :         ReturnErrorOnFailure(ManualSetupPayloadParser(setUpCode).populatePayload(payload));
      52           0 :         VerifyOrReturnError(payload.isValidManualCode(), CHIP_ERROR_INVALID_ARGUMENT);
      53             :     }
      54             : 
      55           0 :     return CHIP_NO_ERROR;
      56             : }
      57             : } // namespace
      58             : 
      59           0 : CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour commission,
      60             :                                        DiscoveryType discoveryType, Optional<Dnssd::CommonResolutionData> resolutionData)
      61             : {
      62           0 :     VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE);
      63           0 :     VerifyOrReturnError(remoteId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
      64             : 
      65           0 :     SetupPayload payload;
      66           0 :     ReturnErrorOnFailure(GetPayload(setUpCode, payload));
      67             : 
      68           0 :     if (resolutionData.HasValue())
      69             :     {
      70           0 :         VerifyOrReturnError(discoveryType != DiscoveryType::kAll, CHIP_ERROR_INVALID_ARGUMENT);
      71           0 :         if (mRemoteId == remoteId && mSetUpPINCode == payload.setUpPINCode && mConnectionType == commission &&
      72           0 :             mDiscoveryType == discoveryType)
      73             :         {
      74           0 :             NotifyCommissionableDeviceDiscovered(resolutionData.Value());
      75           0 :             return CHIP_NO_ERROR;
      76             :         }
      77             :     }
      78             : 
      79           0 :     mConnectionType = commission;
      80           0 :     mDiscoveryType  = discoveryType;
      81           0 :     mRemoteId       = remoteId;
      82           0 :     mSetUpPINCode   = payload.setUpPINCode;
      83             : 
      84           0 :     ResetDiscoveryState();
      85             : 
      86           0 :     if (resolutionData.HasValue())
      87             :     {
      88           0 :         NotifyCommissionableDeviceDiscovered(resolutionData.Value());
      89           0 :         return CHIP_NO_ERROR;
      90             :     }
      91             : 
      92           0 :     ReturnErrorOnFailure(Connect(payload));
      93           0 :     return mSystemLayer->StartTimer(System::Clock::Milliseconds32(kDeviceDiscoveredTimeout), OnDeviceDiscoveredTimeoutCallback,
      94           0 :                                     this);
      95           0 : }
      96           0 : CHIP_ERROR SetUpCodePairer::Connect(SetupPayload & payload)
      97             : {
      98           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
      99           0 :     bool isRunning = false;
     100             : 
     101           0 :     bool searchOverAll = !payload.rendezvousInformation.HasValue();
     102             : 
     103           0 :     if (mDiscoveryType == DiscoveryType::kAll)
     104             :     {
     105           0 :         if (searchOverAll || payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kBLE))
     106             :         {
     107           0 :             if (CHIP_NO_ERROR == (err = StartDiscoverOverBle(payload)))
     108             :             {
     109           0 :                 isRunning = true;
     110             :             }
     111           0 :             VerifyOrReturnError(searchOverAll || CHIP_NO_ERROR == err || CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err, err);
     112             :         }
     113             : 
     114           0 :         if (searchOverAll || payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kSoftAP))
     115             :         {
     116           0 :             if (CHIP_NO_ERROR == (err = StartDiscoverOverSoftAP(payload)))
     117             :             {
     118           0 :                 isRunning = true;
     119             :             }
     120           0 :             VerifyOrReturnError(searchOverAll || CHIP_NO_ERROR == err || CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err, err);
     121             :         }
     122             :     }
     123             : 
     124             :     // We always want to search on network because any node that has already been commissioned will use on-network regardless of the
     125             :     // QR code flag.
     126           0 :     if (CHIP_NO_ERROR == (err = StartDiscoverOverIP(payload)))
     127             :     {
     128           0 :         isRunning = true;
     129             :     }
     130           0 :     VerifyOrReturnError(searchOverAll || CHIP_NO_ERROR == err, err);
     131             : 
     132           0 :     return isRunning ? CHIP_NO_ERROR : CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     133             : }
     134             : 
     135           0 : CHIP_ERROR SetUpCodePairer::StartDiscoverOverBle(SetupPayload & payload)
     136             : {
     137             : #if CONFIG_NETWORK_LAYER_BLE
     138             : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     139             :     VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
     140             :     mCommissioner->ConnectBleTransportToSelf();
     141             : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     142           0 :     VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
     143             : 
     144           0 :     ChipLogProgress(Controller, "Starting commissioning discovery over BLE");
     145             : 
     146             :     // Handle possibly-sync callbacks.
     147           0 :     mWaitingForDiscovery[kBLETransport] = true;
     148           0 :     CHIP_ERROR err = mBleLayer->NewBleConnectionByDiscriminator(payload.discriminator, this, OnDiscoveredDeviceOverBleSuccess,
     149             :                                                                 OnDiscoveredDeviceOverBleError);
     150           0 :     if (err != CHIP_NO_ERROR)
     151             :     {
     152           0 :         mWaitingForDiscovery[kBLETransport] = false;
     153             :     }
     154           0 :     return err;
     155             : #else
     156             :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     157             : #endif // CONFIG_NETWORK_LAYER_BLE
     158             : }
     159             : 
     160           0 : CHIP_ERROR SetUpCodePairer::StopConnectOverBle()
     161             : {
     162             :     // Make sure to not call CancelBleIncompleteConnection unless we are in fact
     163             :     // waiting on BLE discovery.  It will cancel connections that are in fact
     164             :     // completed. In particular, if we just established PASE over BLE calling
     165             :     // CancelBleIncompleteConnection here unconditionally would cancel the BLE
     166             :     // connection underlying the PASE session.  So make sure to only call
     167             :     // CancelBleIncompleteConnection if we're still waiting to hear back on the
     168             :     // BLE discovery bits.
     169           0 :     if (!mWaitingForDiscovery[kBLETransport])
     170             :     {
     171           0 :         return CHIP_NO_ERROR;
     172             :     }
     173             : 
     174           0 :     mWaitingForDiscovery[kBLETransport] = false;
     175             : #if CONFIG_NETWORK_LAYER_BLE
     176           0 :     VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
     177           0 :     ChipLogDetail(Controller, "Stopping commissioning discovery over BLE");
     178           0 :     return mBleLayer->CancelBleIncompleteConnection();
     179             : #else
     180             :     return CHIP_NO_ERROR;
     181             : #endif // CONFIG_NETWORK_LAYER_BLE
     182             : }
     183             : 
     184           0 : CHIP_ERROR SetUpCodePairer::StartDiscoverOverIP(SetupPayload & payload)
     185             : {
     186           0 :     ChipLogProgress(Controller, "Starting commissioning discovery over DNS-SD");
     187             : 
     188           0 :     auto & discriminator = payload.discriminator;
     189           0 :     if (discriminator.IsShortDiscriminator())
     190             :     {
     191           0 :         mCurrentFilter.type = Dnssd::DiscoveryFilterType::kShortDiscriminator;
     192           0 :         mCurrentFilter.code = discriminator.GetShortValue();
     193             :     }
     194             :     else
     195             :     {
     196           0 :         mCurrentFilter.type = Dnssd::DiscoveryFilterType::kLongDiscriminator;
     197           0 :         mCurrentFilter.code = discriminator.GetLongValue();
     198             :     }
     199           0 :     mPayloadVendorID  = payload.vendorID;
     200           0 :     mPayloadProductID = payload.productID;
     201             : 
     202             :     // Handle possibly-sync callbacks.
     203           0 :     mWaitingForDiscovery[kIPTransport] = true;
     204           0 :     CHIP_ERROR err                     = mCommissioner->DiscoverCommissionableNodes(mCurrentFilter);
     205           0 :     if (err != CHIP_NO_ERROR)
     206             :     {
     207           0 :         mWaitingForDiscovery[kIPTransport] = false;
     208             :     }
     209           0 :     return err;
     210             : }
     211             : 
     212           0 : CHIP_ERROR SetUpCodePairer::StopConnectOverIP()
     213             : {
     214           0 :     ChipLogDetail(Controller, "Stopping commissioning discovery over DNS-SD");
     215             : 
     216           0 :     mWaitingForDiscovery[kIPTransport] = false;
     217           0 :     mCurrentFilter.type                = Dnssd::DiscoveryFilterType::kNone;
     218           0 :     mPayloadVendorID                   = kNotAvailable;
     219           0 :     mPayloadProductID                  = kNotAvailable;
     220             : 
     221           0 :     mCommissioner->StopCommissionableDiscovery();
     222           0 :     return CHIP_NO_ERROR;
     223             : }
     224             : 
     225           0 : CHIP_ERROR SetUpCodePairer::StartDiscoverOverSoftAP(SetupPayload & payload)
     226             : {
     227           0 :     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     228             : }
     229             : 
     230           0 : CHIP_ERROR SetUpCodePairer::StopConnectOverSoftAP()
     231             : {
     232           0 :     mWaitingForDiscovery[kSoftAPTransport] = false;
     233           0 :     return CHIP_NO_ERROR;
     234             : }
     235             : 
     236           0 : bool SetUpCodePairer::ConnectToDiscoveredDevice()
     237             : {
     238           0 :     if (mWaitingForPASE)
     239             :     {
     240             :         // Nothing to do.  Just wait until we either succeed or fail at that
     241             :         // PASE session establishment.
     242           0 :         return false;
     243             :     }
     244             : 
     245           0 :     while (!mDiscoveredParameters.empty())
     246             :     {
     247             :         // Grab the first element from the queue and try connecting to it.
     248             :         // Remove it from the queue before we try to connect, in case the
     249             :         // connection attempt fails and calls right back into us to try the next
     250             :         // thing.
     251           0 :         SetUpCodePairerParameters params(mDiscoveredParameters.front());
     252           0 :         mDiscoveredParameters.pop_front();
     253             : 
     254           0 :         params.SetSetupPINCode(mSetUpPINCode);
     255             : 
     256             : #if CHIP_PROGRESS_LOGGING
     257             :         char buf[Transport::PeerAddress::kMaxToStringSize];
     258           0 :         params.GetPeerAddress().ToString(buf);
     259           0 :         ChipLogProgress(Controller, "Attempting PASE connection to %s", buf);
     260             : #endif // CHIP_PROGRESS_LOGGING
     261             : 
     262             :         // Handle possibly-sync call backs from attempts to establish PASE.
     263           0 :         ExpectPASEEstablishment();
     264             : 
     265           0 :         if (params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
     266             :         {
     267           0 :             mCurrentPASEParameters.SetValue(params);
     268             :         }
     269             : 
     270             :         CHIP_ERROR err;
     271           0 :         if (mConnectionType == SetupCodePairerBehaviour::kCommission)
     272             :         {
     273           0 :             err = mCommissioner->PairDevice(mRemoteId, params);
     274             :         }
     275             :         else
     276             :         {
     277           0 :             err = mCommissioner->EstablishPASEConnection(mRemoteId, params);
     278             :         }
     279             : 
     280           0 :         LogErrorOnFailure(err);
     281           0 :         if (err == CHIP_NO_ERROR)
     282             :         {
     283           0 :             return true;
     284             :         }
     285             : 
     286             :         // Failed to start establishing PASE.  Move on to the next item.
     287           0 :         PASEEstablishmentComplete();
     288           0 :     }
     289             : 
     290           0 :     return false;
     291             : }
     292             : 
     293             : #if CONFIG_NETWORK_LAYER_BLE
     294           0 : void SetUpCodePairer::OnDiscoveredDeviceOverBle(BLE_CONNECTION_OBJECT connObj)
     295             : {
     296           0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over BLE");
     297             : 
     298           0 :     mWaitingForDiscovery[kBLETransport] = false;
     299             : 
     300             :     // In order to not wait for all the possible addresses discovered over mdns to
     301             :     // be tried before trying to connect over BLE, the discovered connection object is
     302             :     // inserted at the beginning of the list.
     303             :     //
     304             :     // It makes it the 'next' thing to try to connect to if there are already some
     305             :     // discovered parameters in the list.
     306           0 :     mDiscoveredParameters.emplace_front(connObj);
     307           0 :     ConnectToDiscoveredDevice();
     308           0 : }
     309             : 
     310           0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
     311             : {
     312           0 :     (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj);
     313           0 : }
     314             : 
     315           0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
     316             : {
     317           0 :     static_cast<SetUpCodePairer *>(appState)->OnBLEDiscoveryError(err);
     318           0 : }
     319             : 
     320           0 : void SetUpCodePairer::OnBLEDiscoveryError(CHIP_ERROR err)
     321             : {
     322           0 :     ChipLogError(Controller, "Commissioning discovery over BLE failed: %" CHIP_ERROR_FORMAT, err.Format());
     323           0 :     mWaitingForDiscovery[kBLETransport] = false;
     324           0 :     LogErrorOnFailure(err);
     325           0 : }
     326             : #endif // CONFIG_NETWORK_LAYER_BLE
     327             : 
     328           0 : bool SetUpCodePairer::IdIsPresent(uint16_t vendorOrProductID)
     329             : {
     330           0 :     return vendorOrProductID != kNotAvailable;
     331             : }
     332             : 
     333           0 : bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData) const
     334             : {
     335           0 :     if (nodeData.commissionData.commissioningMode == 0)
     336             :     {
     337           0 :         ChipLogProgress(Controller, "Discovered device does not have an open commissioning window.");
     338           0 :         return false;
     339             :     }
     340             : 
     341             :     // The advertisement may not include a vendor id.
     342           0 :     if (IdIsPresent(mPayloadVendorID) && IdIsPresent(nodeData.commissionData.vendorId) &&
     343           0 :         mPayloadVendorID != nodeData.commissionData.vendorId)
     344             :     {
     345           0 :         ChipLogProgress(Controller, "Discovered device does not match our vendor id.");
     346           0 :         return false;
     347             :     }
     348             : 
     349             :     // The advertisement may not include a product id.
     350           0 :     if (IdIsPresent(mPayloadProductID) && IdIsPresent(nodeData.commissionData.productId) &&
     351           0 :         mPayloadProductID != nodeData.commissionData.productId)
     352             :     {
     353           0 :         ChipLogProgress(Controller, "Discovered device does not match our product id.");
     354           0 :         return false;
     355             :     }
     356             : 
     357           0 :     bool discriminatorMatches = false;
     358           0 :     switch (mCurrentFilter.type)
     359             :     {
     360           0 :     case Dnssd::DiscoveryFilterType::kShortDiscriminator:
     361           0 :         discriminatorMatches = (((nodeData.commissionData.longDiscriminator >> 8) & 0x0F) == mCurrentFilter.code);
     362           0 :         break;
     363           0 :     case Dnssd::DiscoveryFilterType::kLongDiscriminator:
     364           0 :         discriminatorMatches = (nodeData.commissionData.longDiscriminator == mCurrentFilter.code);
     365           0 :         break;
     366           0 :     default:
     367           0 :         ChipLogError(Controller, "Unknown filter type; all matches will fail");
     368           0 :         return false;
     369             :     }
     370           0 :     if (!discriminatorMatches)
     371             :     {
     372           0 :         ChipLogProgress(Controller, "Discovered device does not match our discriminator.");
     373             :     }
     374           0 :     return discriminatorMatches;
     375             : }
     376             : 
     377           0 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::DiscoveredNodeData & nodeData)
     378             : {
     379           0 :     if (!NodeMatchesCurrentFilter(nodeData))
     380             :     {
     381           0 :         return;
     382             :     }
     383             : 
     384           0 :     ChipLogProgress(Controller, "Discovered device to be commissioned over DNS-SD");
     385             : 
     386           0 :     NotifyCommissionableDeviceDiscovered(nodeData.resolutionData);
     387             : }
     388             : 
     389           0 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::CommonResolutionData & resolutionData)
     390             : {
     391           0 :     if (mDiscoveryType == DiscoveryType::kDiscoveryNetworkOnlyWithoutPASEAutoRetry)
     392             :     {
     393             :         // If the discovery type does not want the PASE auto retry mechanism, we will just store
     394             :         // a single IP. So the discovery process is stopped as it won't be of any help anymore.
     395           0 :         StopConnectOverIP();
     396           0 :         mDiscoveredParameters.emplace_back(resolutionData, 0);
     397             :     }
     398             :     else
     399             :     {
     400           0 :         for (size_t i = 0; i < resolutionData.numIPs; i++)
     401             :         {
     402           0 :             mDiscoveredParameters.emplace_back(resolutionData, i);
     403             :         }
     404             :     }
     405             : 
     406           0 :     ConnectToDiscoveredDevice();
     407           0 : }
     408             : 
     409           0 : bool SetUpCodePairer::StopPairing(NodeId remoteId)
     410             : {
     411           0 :     VerifyOrReturnValue(mRemoteId != kUndefinedNodeId, false);
     412           0 :     VerifyOrReturnValue(remoteId == kUndefinedNodeId || remoteId == mRemoteId, false);
     413             : 
     414           0 :     if (mWaitingForPASE)
     415             :     {
     416           0 :         PASEEstablishmentComplete();
     417             :     }
     418             : 
     419           0 :     ResetDiscoveryState();
     420           0 :     mRemoteId = kUndefinedNodeId;
     421           0 :     return true;
     422             : }
     423             : 
     424           0 : bool SetUpCodePairer::TryNextRendezvousParameters()
     425             : {
     426           0 :     if (ConnectToDiscoveredDevice())
     427             :     {
     428           0 :         ChipLogProgress(Controller, "Trying connection to commissionee over different transport");
     429           0 :         return true;
     430             :     }
     431             : 
     432           0 :     if (DiscoveryInProgress())
     433             :     {
     434           0 :         ChipLogProgress(Controller, "Waiting to discover commissionees that match our filters");
     435           0 :         return true;
     436             :     }
     437             : 
     438           0 :     return false;
     439             : }
     440             : 
     441           0 : bool SetUpCodePairer::DiscoveryInProgress() const
     442             : {
     443           0 :     for (const auto & waiting : mWaitingForDiscovery)
     444             :     {
     445           0 :         if (waiting)
     446             :         {
     447           0 :             return true;
     448             :         }
     449             :     }
     450             : 
     451           0 :     return false;
     452             : }
     453             : 
     454           0 : void SetUpCodePairer::ResetDiscoveryState()
     455             : {
     456           0 :     StopConnectOverBle();
     457           0 :     StopConnectOverIP();
     458           0 :     StopConnectOverSoftAP();
     459             : 
     460             :     // Just in case any of those failed to reset the waiting state properly.
     461           0 :     for (auto & waiting : mWaitingForDiscovery)
     462             :     {
     463           0 :         waiting = false;
     464             :     }
     465             : 
     466           0 :     mDiscoveredParameters.clear();
     467           0 :     mCurrentPASEParameters.ClearValue();
     468           0 :     mLastPASEError = CHIP_NO_ERROR;
     469             : 
     470           0 :     mSystemLayer->CancelTimer(OnDeviceDiscoveredTimeoutCallback, this);
     471           0 : }
     472             : 
     473           0 : void SetUpCodePairer::ExpectPASEEstablishment()
     474             : {
     475           0 :     VerifyOrDie(!mWaitingForPASE);
     476           0 :     mWaitingForPASE = true;
     477           0 :     auto * delegate = mCommissioner->GetPairingDelegate();
     478           0 :     VerifyOrDie(delegate != this);
     479           0 :     mPairingDelegate = delegate;
     480           0 :     mCommissioner->RegisterPairingDelegate(this);
     481           0 : }
     482             : 
     483           0 : void SetUpCodePairer::PASEEstablishmentComplete()
     484             : {
     485           0 :     VerifyOrDie(mWaitingForPASE);
     486           0 :     mWaitingForPASE = false;
     487           0 :     mCommissioner->RegisterPairingDelegate(mPairingDelegate);
     488           0 :     mPairingDelegate = nullptr;
     489           0 : }
     490             : 
     491           0 : void SetUpCodePairer::OnStatusUpdate(DevicePairingDelegate::Status status)
     492             : {
     493           0 :     if (status == DevicePairingDelegate::Status::SecurePairingFailed)
     494             :     {
     495             :         // If we're still waiting on discovery, don't propagate this failure
     496             :         // (which is due to PASE failure with something we discovered, but the
     497             :         // "something" may not have been the right thing) for now.  Wait until
     498             :         // discovery completes.  Then we will either succeed and notify
     499             :         // accordingly or time out and land in OnStatusUpdate again, but at that
     500             :         // point we will not be waiting on discovery anymore.
     501           0 :         if (!mDiscoveredParameters.empty())
     502             :         {
     503           0 :             ChipLogProgress(Controller, "Ignoring SecurePairingFailed status for now; we have more discovered devices to try");
     504           0 :             return;
     505             :         }
     506             : 
     507           0 :         if (DiscoveryInProgress())
     508             :         {
     509           0 :             ChipLogProgress(Controller,
     510             :                             "Ignoring SecurePairingFailed status for now; we are waiting to see if we discover more devices");
     511           0 :             return;
     512             :         }
     513             :     }
     514             : 
     515           0 :     if (mPairingDelegate)
     516             :     {
     517           0 :         mPairingDelegate->OnStatusUpdate(status);
     518             :     }
     519             : }
     520             : 
     521           0 : void SetUpCodePairer::OnPairingComplete(CHIP_ERROR error)
     522             : {
     523             :     // Save the pairing delegate so we can notify it.  We want to notify it
     524             :     // _after_ we restore the state on the commissioner, in case the delegate
     525             :     // ends up immediately calling back into the commissioner again when
     526             :     // notified.
     527           0 :     auto * pairingDelegate = mPairingDelegate;
     528           0 :     PASEEstablishmentComplete();
     529             : 
     530           0 :     if (CHIP_NO_ERROR == error)
     531             :     {
     532           0 :         ChipLogProgress(Controller, "Pairing with commissionee successful, stopping discovery");
     533           0 :         ResetDiscoveryState();
     534           0 :         mRemoteId = kUndefinedNodeId;
     535           0 :         if (pairingDelegate != nullptr)
     536             :         {
     537           0 :             pairingDelegate->OnPairingComplete(error);
     538             :         }
     539           0 :         return;
     540             :     }
     541             : 
     542             :     // It may happen that there is a stale DNS entry. If so, ReconfirmRecord will flush
     543             :     // the record from the daemon cache once it determines that it is invalid.
     544             :     // It may not help for this particular resolve, but may help subsequent resolves.
     545           0 :     if (CHIP_ERROR_TIMEOUT == error && mCurrentPASEParameters.HasValue())
     546             :     {
     547           0 :         const auto & params = mCurrentPASEParameters.Value();
     548           0 :         const auto & peer   = params.GetPeerAddress();
     549           0 :         const auto & ip     = peer.GetIPAddress();
     550           0 :         auto err            = Dnssd::Resolver::Instance().ReconfirmRecord(params.mHostName, ip, params.mInterfaceId);
     551           0 :         if (CHIP_NO_ERROR != err && CHIP_ERROR_NOT_IMPLEMENTED != err)
     552             :         {
     553           0 :             ChipLogError(Controller, "Error when verifying the validity of an address: %" CHIP_ERROR_FORMAT, err.Format());
     554             :         }
     555             :     }
     556           0 :     mCurrentPASEParameters.ClearValue();
     557             : 
     558             :     // We failed to establish PASE.  Try the next thing we have discovered, if
     559             :     // any.
     560           0 :     if (TryNextRendezvousParameters())
     561             :     {
     562             :         // Keep waiting until that finishes.  Don't call OnPairingComplete yet.
     563           0 :         mLastPASEError = error;
     564           0 :         return;
     565             :     }
     566             : 
     567           0 :     if (pairingDelegate != nullptr)
     568             :     {
     569           0 :         pairingDelegate->OnPairingComplete(error);
     570             :     }
     571             : }
     572             : 
     573           0 : void SetUpCodePairer::OnPairingDeleted(CHIP_ERROR error)
     574             : {
     575           0 :     if (mPairingDelegate)
     576             :     {
     577           0 :         mPairingDelegate->OnPairingDeleted(error);
     578             :     }
     579           0 : }
     580             : 
     581           0 : void SetUpCodePairer::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error)
     582             : {
     583             :     // Not really expecting this, but handle it anyway.
     584           0 :     if (mPairingDelegate)
     585             :     {
     586           0 :         mPairingDelegate->OnCommissioningComplete(deviceId, error);
     587             :     }
     588           0 : }
     589             : 
     590           0 : void SetUpCodePairer::OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, void * context)
     591             : {
     592           0 :     ChipLogError(Controller, "Discovery timed out");
     593           0 :     auto * pairer = static_cast<SetUpCodePairer *>(context);
     594           0 :     LogErrorOnFailure(pairer->StopConnectOverBle());
     595           0 :     LogErrorOnFailure(pairer->StopConnectOverIP());
     596           0 :     LogErrorOnFailure(pairer->StopConnectOverSoftAP());
     597           0 :     if (!pairer->mWaitingForPASE && pairer->mDiscoveredParameters.empty())
     598             :     {
     599             :         // We're not waiting on any more PASE attempts, and we're not going to
     600             :         // discover anything at this point, so we should just notify our
     601             :         // listener.
     602           0 :         CHIP_ERROR err = pairer->mLastPASEError;
     603           0 :         if (err == CHIP_NO_ERROR)
     604             :         {
     605           0 :             err = CHIP_ERROR_TIMEOUT;
     606             :         }
     607           0 :         pairer->mCommissioner->OnSessionEstablishmentError(err);
     608             :     }
     609           0 : }
     610             : 
     611           0 : SetUpCodePairerParameters::SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data, size_t index)
     612             : {
     613           0 :     mInterfaceId = data.interfaceId;
     614           0 :     Platform::CopyString(mHostName, data.hostName);
     615             : 
     616           0 :     auto & ip = data.ipAddress[index];
     617           0 :     SetPeerAddress(Transport::PeerAddress::UDP(ip, data.port, ip.IsIPv6LinkLocal() ? data.interfaceId : Inet::InterfaceId::Null()));
     618             : 
     619           0 :     if (data.mrpRetryIntervalIdle.HasValue())
     620             :     {
     621           0 :         SetIdleInterval(data.mrpRetryIntervalIdle.Value());
     622             :     }
     623             : 
     624           0 :     if (data.mrpRetryIntervalActive.HasValue())
     625             :     {
     626           0 :         SetActiveInterval(data.mrpRetryIntervalActive.Value());
     627             :     }
     628           0 : }
     629             : 
     630             : #if CONFIG_NETWORK_LAYER_BLE
     631           0 : SetUpCodePairerParameters::SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, bool connected)
     632             : {
     633           0 :     Transport::PeerAddress peerAddress = Transport::PeerAddress::BLE();
     634           0 :     SetPeerAddress(peerAddress);
     635           0 :     if (connected)
     636             :     {
     637           0 :         SetConnectionObject(connObj);
     638             :     }
     639             :     else
     640             :     {
     641           0 :         SetDiscoveredObject(connObj);
     642             :     }
     643           0 : }
     644             : #endif // CONFIG_NETWORK_LAYER_BLE
     645             : 
     646             : } // namespace Controller
     647             : } // namespace chip

Generated by: LCOV version 1.14