/* * * Copyright (c) 2021 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * Declaration of SetUp Code Pairer, a class that parses a given * setup code and uses the extracted informations to discover and * filter commissionables nodes, before initiating the pairing process. * */ #pragma once #include #include #include #include #include #include #include #include #if CONFIG_NETWORK_LAYER_BLE #include #endif // CONFIG_NETWORK_BLE #include #include namespace chip { namespace Controller { class DeviceCommissioner; class SetUpCodePairerParameters : public RendezvousParameters { public: SetUpCodePairerParameters() = default; SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data, size_t index); #if CONFIG_NETWORK_LAYER_BLE SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, bool connected = true); #endif // CONFIG_NETWORK_LAYER_BLE char mHostName[Dnssd::kHostNameMaxLength + 1] = {}; Inet::InterfaceId mInterfaceId; }; enum class SetupCodePairerBehaviour : uint8_t { kCommission, kPaseOnly, }; enum class DiscoveryType : uint8_t { kDiscoveryNetworkOnly, kDiscoveryNetworkOnlyWithoutPASEAutoRetry, kAll, }; class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate { public: SetUpCodePairer(DeviceCommissioner * commissioner) : mCommissioner(commissioner) {} ~SetUpCodePairer(); CHIP_ERROR PairDevice(chip::NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour connectionType = SetupCodePairerBehaviour::kCommission, DiscoveryType discoveryType = DiscoveryType::kAll, Optional resolutionData = NullOptional); // Called by the DeviceCommissioner to notify that we have discovered a new device. void NotifyCommissionableDeviceDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData); void SetSystemLayer(System::Layer * systemLayer) { mSystemLayer = systemLayer; }; #if CONFIG_NETWORK_LAYER_BLE void SetBleLayer(Ble::BleLayer * bleLayer) { mBleLayer = bleLayer; }; #endif // CONFIG_NETWORK_LAYER_BLE // Stop ongoing discovery / pairing of the specified node, or of // whichever node we're pairing if kUndefinedNodeId is passed. bool StopPairing(NodeId remoteId = kUndefinedNodeId); private: // DevicePairingDelegate implementation. void OnStatusUpdate(DevicePairingDelegate::Status status) override; void OnPairingComplete(CHIP_ERROR error) override; void OnPairingDeleted(CHIP_ERROR error) override; void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error) override; CHIP_ERROR Connect(SetupPayload & paload); CHIP_ERROR StartDiscoverOverBle(SetupPayload & payload); CHIP_ERROR StopConnectOverBle(); CHIP_ERROR StartDiscoverOverIP(SetupPayload & payload); CHIP_ERROR StopConnectOverIP(); CHIP_ERROR StartDiscoverOverSoftAP(SetupPayload & payload); CHIP_ERROR StopConnectOverSoftAP(); CHIP_ERROR StartDiscoverOverWiFiPAF(SetupPayload & payload); CHIP_ERROR StopConnectOverWiFiPAF(); // Returns whether we have kicked off a new connection attempt. bool ConnectToDiscoveredDevice(); // Reset our mWaitingForDiscovery/mDiscoveredParameters state to indicate no // pending work. void ResetDiscoveryState(); // Get ready to start PASE establishment via mCommissioner. Sets up // whatever state is needed for that. void ExpectPASEEstablishment(); // PASE establishment by mCommissioner has completed: we either have a PASE // session now or we failed to set one up, but we are done waiting on // mCommissioner. void PASEEstablishmentComplete(); // Called when PASE establishment fails. // // May start a new PASE establishment. // // Will return whether we might in fact have more rendezvous parameters to // try (e.g. because we started a new PASE establishment or are waiting on // more device discovery). // // The commissioner can use the return value to decide whether pairing has // actually failed or not. bool TryNextRendezvousParameters(); // True if we are still waiting on discovery to possibly produce new // RendezvousParameters in the future. bool DiscoveryInProgress() const; // Not an enum class because we use this for indexing into arrays. enum TransportTypes { kBLETransport = 0, kIPTransport, kSoftAPTransport, kWiFiPAFTransport, kTransportTypeCount, }; void NotifyCommissionableDeviceDiscovered(const chip::Dnssd::CommonResolutionData & resolutionData); static void OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, void * context); #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * mBleLayer = nullptr; void OnDiscoveredDeviceOverBle(BLE_CONNECTION_OBJECT connObj); void OnBLEDiscoveryError(CHIP_ERROR err); /////////// BLEConnectionDelegate Callbacks ///////// static void OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj); static void OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err); #endif // CONFIG_NETWORK_LAYER_BLE #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF void OnDiscoveredDeviceOverWifiPAF(); void OnWifiPAFDiscoveryError(CHIP_ERROR err); static void OnWiFiPAFSubscribeComplete(void * appState); static void OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err); #endif bool NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData) const; static bool IdIsPresent(uint16_t vendorOrProductID); Dnssd::DiscoveryFilter mCurrentFilter; // The vendor id and product id from the SetupPayload. They may be 0, which // indicates "not available" (e.g. because the SetupPayload came from a // short manual code). In that case we should not filter on those values. static constexpr uint16_t kNotAvailable = 0; uint16_t mPayloadVendorID = kNotAvailable; uint16_t mPayloadProductID = kNotAvailable; DeviceCommissioner * mCommissioner = nullptr; System::Layer * mSystemLayer = nullptr; chip::NodeId mRemoteId = kUndefinedNodeId; uint32_t mSetUpPINCode = 0; SetupCodePairerBehaviour mConnectionType = SetupCodePairerBehaviour::kCommission; DiscoveryType mDiscoveryType = DiscoveryType::kAll; // While we are trying to pair, we intercept the DevicePairingDelegate // notifications from mCommissioner. We want to make sure we send them on // to the original pairing delegate, if any. DevicePairingDelegate * mPairingDelegate = nullptr; // Boolean will be set to true if we currently have an async discovery // process happening via the relevant transport. bool mWaitingForDiscovery[kTransportTypeCount] = { false }; // Double ended-queue of things we have discovered but not tried connecting to yet. The // general discovery/pairing process will terminate once this queue is empty // and all the booleans in mWaitingForDiscovery are false. std::deque mDiscoveredParameters; // Current thing we are trying to connect to over UDP. If a PASE connection fails with // a CHIP_ERROR_TIMEOUT, the discovered parameters will be used to ask the // mdns daemon to invalidate the Optional mCurrentPASEParameters; // mWaitingForPASE is true if we have called either // EstablishPASEConnection or PairDevice on mCommissioner and are now just // waiting to see whether that works. bool mWaitingForPASE = false; // mLastPASEError is the error from the last OnPairingComplete call we got. CHIP_ERROR mLastPASEError = CHIP_NO_ERROR; }; } // namespace Controller } // namespace chip