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