Matter SDK Coverage Report
Current view: top level - controller - SetUpCodePairer.h (source / functions) Coverage Total Hit
Test: SHA:6c8f029dd2432dc900f1c9245c324e69bd79e40a Lines: 45.5 % 11 5
Test Date: 2026-08-08 07:40:09 Functions: 62.5 % 8 5

            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              :  *      Declaration 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              : #pragma once
      28              : 
      29              : #include <controller/DevicePairingDelegate.h>
      30              : #include <lib/core/CHIPError.h>
      31              : #include <lib/core/NodeId.h>
      32              : #include <lib/support/DLLUtil.h>
      33              : #include <lib/support/ThreadOperationalDataset.h>
      34              : #include <platform/CHIPDeviceConfig.h>
      35              : #include <protocols/secure_channel/RendezvousParameters.h>
      36              : #include <setup_payload/ManualSetupPayloadParser.h>
      37              : #include <setup_payload/QRCodeSetupPayloadParser.h>
      38              : 
      39              : #if CONFIG_NETWORK_LAYER_BLE
      40              : #include <ble/Ble.h>
      41              : #endif // CONFIG_NETWORK_BLE
      42              : 
      43              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
      44              : #include <nfc/NFC.h>
      45              : #endif // CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
      46              : 
      47              : #if CHIP_SUPPORT_THREAD_MESHCOP
      48              : #include <controller/ThreadMeshcopCommissionProxy.h>
      49              : #endif // CHIP_SUPPORT_THREAD_MESHCOP
      50              : 
      51              : #include <controller/DeviceDiscoveryDelegate.h>
      52              : 
      53              : #include <deque>
      54              : #include <optional>
      55              : #include <vector>
      56              : 
      57              : namespace chip {
      58              : 
      59              : namespace Testing {
      60              : 
      61              : class SetUpCodePairerTestAccess;
      62              : 
      63              : } // namespace Testing
      64              : 
      65              : namespace Controller {
      66              : 
      67              : class DeviceCommissioner;
      68              : 
      69              : /**
      70              :  * A class that represents a discovered device.  This includes both the inputs to discovery (via the
      71              :  * RendezvousParameters super-class), and the outputs from discovery (the PeerAddress in
      72              :  * RendezvousParameters but also some of our members like mHostName, mInterfaceId,
      73              :  * mLongDiscriminator).
      74              :  */
      75              : class SetUpCodePairerParameters : public RendezvousParameters
      76              : {
      77              : public:
      78            2 :     SetUpCodePairerParameters() = default;
      79              :     SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data, std::optional<uint16_t> longDiscriminator, size_t index);
      80              : #if CONFIG_NETWORK_LAYER_BLE
      81              :     SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> longDiscriminator, bool connected = true);
      82              : #endif // CONFIG_NETWORK_LAYER_BLE
      83              :     char mHostName[Dnssd::kHostNameMaxLength + 1] = {};
      84              :     Inet::InterfaceId mInterfaceId;
      85              : 
      86              :     // The long discriminator of the device that was actually discovered, if this is known.  This
      87              :     // differs from the mSetupDiscriminator member of RendezvousParameters in that the latter may be
      88              :     // a short discriminator from a numeric setup code (which may match multiple devices), while
      89              :     // this member, if set, is always a long discriminator that was actually advertised by the
      90              :     // device represented by our PeerAddress.
      91              :     std::optional<uint16_t> mLongDiscriminator = std::nullopt;
      92              : 
      93              :     // Whether this discovered candidate would drive the same PASE attempt as `other`, so one of the
      94              :     // two can be dropped.  The comparison is the full RendezvousParameters base (all PASE connection
      95              :     // inputs) plus mLongDiscriminator, which selects which setup payload's passcode we use.  mHostName
      96              :     // and mInterfaceId are discovery bookkeeping, not connection inputs, and are intentionally
      97              :     // excluded: the same non-link-local address advertised on multiple interfaces yields the same
      98              :     // interface-less PeerAddress and identical mLongDiscriminator, and should coalesce to a single
      99              :     // attempt.  Deliberately not operator==, since it does not compare all members.
     100            8 :     bool CanCoalesceWith(const SetUpCodePairerParameters & other) const
     101              :     {
     102            8 :         return RendezvousParameters::operator==(other) && mLongDiscriminator == other.mLongDiscriminator;
     103              :     }
     104              : };
     105              : 
     106              : enum class SetupCodePairerBehaviour : uint8_t
     107              : {
     108              :     kCommission,
     109              :     kPaseOnly,
     110              : };
     111              : 
     112              : enum class DiscoveryType : uint8_t
     113              : {
     114              :     kDiscoveryNetworkOnly,
     115              :     kDiscoveryNetworkOnlyWithoutPASEAutoRetry,
     116              :     kAll,
     117              : };
     118              : 
     119              : class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate
     120              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     121              :     ,
     122              :                                    public Nfc::NFCReaderTransportDelegate
     123              : #endif
     124              : {
     125              :     friend class chip::Testing::SetUpCodePairerTestAccess;
     126              : 
     127              : public:
     128              :     struct ThreadMeshcopCommissionParameters
     129              :     {
     130              :         Transport::PeerAddress mBorderAgentAddress;
     131              :         uint8_t mPSKcBuffer[Thread::kSizePSKc];
     132              :     };
     133           39 :     SetUpCodePairer(DeviceCommissioner * commissioner) : mCommissioner(commissioner) {}
     134           50 :     virtual ~SetUpCodePairer() {}
     135              : 
     136              :     CHIP_ERROR PairDevice(chip::NodeId remoteId, const char * setUpCode,
     137              :                           SetupCodePairerBehaviour connectionType              = SetupCodePairerBehaviour::kCommission,
     138              :                           DiscoveryType discoveryType                          = DiscoveryType::kAll,
     139              :                           Optional<Dnssd::CommonResolutionData> resolutionData = NullOptional);
     140              : 
     141              :     // Called by the DeviceCommissioner to notify that we have discovered a new device.
     142              :     void NotifyCommissionableDeviceDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData);
     143              : 
     144            0 :     void SetSystemLayer(System::Layer * systemLayer) { mSystemLayer = systemLayer; };
     145              : 
     146              : #if CONFIG_NETWORK_LAYER_BLE
     147            0 :     void SetBleLayer(Ble::BleLayer * bleLayer) { mBleLayer = bleLayer; };
     148              : #endif // CONFIG_NETWORK_LAYER_BLE
     149              : 
     150              : #if CHIP_SUPPORT_THREAD_MESHCOP
     151            0 :     void SetThreadMeshcopCommissionParamsAndProxy(ThreadMeshcopCommissionParameters & meshcopCommissionParams,
     152              :                                                   ThreadMeshcopCommissionProxy * proxy)
     153              :     {
     154            0 :         mThreadMeshcopCommissionProxy = proxy;
     155            0 :         mThreadMeshcopCommissionParams.SetValue(meshcopCommissionParams);
     156            0 :     }
     157              : #endif
     158              : 
     159              :     // Stop ongoing discovery / pairing of the specified node, or of
     160              :     // whichever node we're pairing if kUndefinedNodeId is passed.
     161              :     bool StopPairing(NodeId remoteId = kUndefinedNodeId);
     162              : 
     163              : private:
     164              :     // DevicePairingDelegate implementation.
     165              :     void OnStatusUpdate(DevicePairingDelegate::Status status) override;
     166              :     void OnPairingComplete(CHIP_ERROR error, const std::optional<RendezvousParameters> & rendezvousParameters,
     167              :                            const std::optional<SetupPayload> & setupPayload) override;
     168              :     void OnPairingDeleted(CHIP_ERROR error) override;
     169              :     void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error) override;
     170              : 
     171              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     172              :     // Nfc::NFCReaderTransportDelegate implementation
     173              :     void OnTagDiscovered(const chip::Nfc::NFCTag::Identifier & identifer) override;
     174              :     void OnTagDiscoveryFailed(CHIP_ERROR error) override;
     175              : #endif
     176              : 
     177              :     CHIP_ERROR Connect();
     178              :     CHIP_ERROR StartDiscoveryOverBLE();
     179              :     CHIP_ERROR StopDiscoveryOverBLE();
     180              :     CHIP_ERROR StartDiscoveryOverDNSSD();
     181              :     CHIP_ERROR StopDiscoveryOverDNSSD();
     182              :     CHIP_ERROR StartDiscoveryOverWiFiPAF();
     183              :     CHIP_ERROR StopDiscoveryOverWiFiPAF();
     184              :     CHIP_ERROR StartDiscoveryOverNFC();
     185              :     CHIP_ERROR StopDiscoveryOverNFC();
     186              :     CHIP_ERROR StartDiscoveryOverThreadMeshcop();
     187              :     CHIP_ERROR StopDiscoveryOverThreadMeshcop();
     188              : 
     189              :     // Returns whether we have kicked off a new connection attempt.
     190              :     bool ConnectToDiscoveredDevice();
     191              : 
     192              :     // Stop attempts to discover more things to connect to, but keep trying to
     193              :     // connect to the ones we have already discovered.
     194              :     void StopAllDiscoveryAttempts();
     195              : 
     196              :     // Reset our mWaitingForDiscovery/mDiscoveredParameters state to indicate no
     197              :     // pending work.
     198              :     void ResetDiscoveryState();
     199              : 
     200              :     // Get ready to start PASE establishment via mCommissioner.  Sets up
     201              :     // whatever state is needed for that.
     202              :     void ExpectPASEEstablishment();
     203              : 
     204              :     // PASE establishment by mCommissioner has completed: we either have a PASE
     205              :     // session now or we failed to set one up, but we are done waiting on
     206              :     // mCommissioner.
     207              :     void PASEEstablishmentComplete();
     208              : 
     209              :     // Called when PASE establishment fails.
     210              :     //
     211              :     // May start a new PASE establishment.
     212              :     //
     213              :     // Will return whether we might in fact have more rendezvous parameters to
     214              :     // try (e.g. because we started a new PASE establishment or are waiting on
     215              :     // more device discovery).
     216              :     //
     217              :     // The commissioner can use the return value to decide whether pairing has
     218              :     // actually failed or not.
     219              :     bool TryNextRendezvousParameters();
     220              : 
     221              :     // True if we are still waiting on discovery to possibly produce new
     222              :     // RendezvousParameters in the future.
     223              :     bool DiscoveryInProgress() const;
     224              : 
     225              :     // If there is nothing left to try (no PASE in progress, no queued discovered
     226              :     // parameters, no discovery in progress), notify the commissioner that pairing
     227              :     // has failed.  err is used as the failure error only if no PASE attempt has
     228              :     // produced an error yet.
     229              :     void StopPairingIfTransportsExhausted(CHIP_ERROR err);
     230              : 
     231              :     // Not an enum class because we use this for indexing into arrays.
     232              :     enum TransportTypes
     233              :     {
     234              :         kBLETransport = 0,
     235              :         kIPTransport,
     236              :         kWiFiPAFTransport,
     237              : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
     238              :         kNFCTransport,
     239              : #endif
     240              : #if CHIP_SUPPORT_THREAD_MESHCOP
     241              :         kThreadMeshcopTransport,
     242              : #endif
     243              :         kTransportTypeCount,
     244              :     };
     245              : 
     246              :     void NotifyCommissionableDeviceDiscovered(const chip::Dnssd::CommonResolutionData & resolutionData,
     247              :                                               std::optional<uint16_t> matchedLongDiscriminator);
     248              : 
     249              :     // Append newly discovered parameters to mDiscoveredParameters, unless they would drive the same
     250              :     // PASE attempt as something already queued (see SetUpCodePairerParameters::CanCoalesceWith), in
     251              :     // which case they are dropped.
     252              :     void EnqueueDiscoveredParametersIfNotDuplicate(SetUpCodePairerParameters && params);
     253              : 
     254              :     static void OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, void * context);
     255              : 
     256              : #if CONFIG_NETWORK_LAYER_BLE
     257              :     Ble::BleLayer * mBleLayer = nullptr;
     258              :     void OnDiscoveredDeviceOverBle(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> matchedLongDiscriminator);
     259              :     void OnBLEDiscoveryError(CHIP_ERROR err);
     260              :     /////////// BLEConnectionDelegate Callbacks /////////
     261              :     static void OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj);
     262              :     static void OnDiscoveredDeviceWithDiscriminatorOverBleSuccess(void * appState, uint16_t matchedLongDiscriminator,
     263              :                                                                   BLE_CONNECTION_OBJECT connObj);
     264              :     static void OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err);
     265              : #endif // CONFIG_NETWORK_LAYER_BLE
     266              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
     267              :     void OnDiscoveredDeviceOverWifiPAF();
     268              :     void OnWifiPAFDiscoveryError(CHIP_ERROR err);
     269              :     static void OnWiFiPAFSubscribeComplete(void * appState);
     270              :     static void OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err);
     271              : #endif
     272              : 
     273              :     bool NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData) const;
     274              :     static bool IdIsPresent(uint16_t vendorOrProductID);
     275              : 
     276              :     bool ShouldDiscoverUsing(RendezvousInformationFlag commissioningChannel) const;
     277              : 
     278              :     // kNotAvailable represents unavailable vendor/product ID values in setup payloads.
     279              :     static constexpr uint16_t kNotAvailable = 0;
     280              : 
     281              :     DeviceCommissioner * mCommissioner       = nullptr;
     282              :     System::Layer * mSystemLayer             = nullptr;
     283              :     chip::NodeId mRemoteId                   = kUndefinedNodeId;
     284              :     SetupCodePairerBehaviour mConnectionType = SetupCodePairerBehaviour::kCommission;
     285              :     DiscoveryType mDiscoveryType             = DiscoveryType::kAll;
     286              :     std::vector<SetupPayload> mSetupPayloads;
     287              : 
     288              :     // The payload we are using for our current PASE connection attempt.  Only
     289              :     // set while we are attempting PASE.
     290              :     std::optional<SetupPayload> mCurrentPASEPayload;
     291              : 
     292              :     // While we are trying to pair, we intercept the DevicePairingDelegate
     293              :     // notifications from mCommissioner.  We want to make sure we send them on
     294              :     // to the original pairing delegate, if any.
     295              :     DevicePairingDelegate * mPairingDelegate = nullptr;
     296              : 
     297              :     // Boolean will be set to true if we currently have an async discovery
     298              :     // process happening via the relevant transport.
     299              :     bool mWaitingForDiscovery[kTransportTypeCount] = { false };
     300              : 
     301              :     // Double ended-queue of things we have discovered but not tried connecting to yet.  The
     302              :     // general discovery/pairing process will terminate once this queue is empty
     303              :     // and all the booleans in mWaitingForDiscovery are false.
     304              :     std::deque<SetUpCodePairerParameters> mDiscoveredParameters;
     305              : 
     306              :     // Current thing we are trying to connect to over UDP. If a PASE connection fails with
     307              :     // a CHIP_ERROR_TIMEOUT, the discovered parameters will be used to ask the
     308              :     // mdns daemon to invalidate its caches.
     309              :     Optional<SetUpCodePairerParameters> mCurrentPASEParameters;
     310              : 
     311              :     // mWaitingForPASE is true if we have called either
     312              :     // EstablishPASEConnection or PairDevice on mCommissioner and are now just
     313              :     // waiting to see whether that works.
     314              :     bool mWaitingForPASE = false;
     315              : 
     316              :     // mLastPASEError is the error from the last OnPairingComplete call we got.
     317              :     CHIP_ERROR mLastPASEError = CHIP_NO_ERROR;
     318              : 
     319              : #if CHIP_SUPPORT_THREAD_MESHCOP
     320              :     Optional<ThreadMeshcopCommissionParameters> mThreadMeshcopCommissionParams;
     321              :     ThreadMeshcopCommissionProxy * mThreadMeshcopCommissionProxy = nullptr;
     322              : #endif
     323              : };
     324              : 
     325              : } // namespace Controller
     326              : } // namespace chip
        

Generated by: LCOV version 2.0-1