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 <platform/internal/NFCCommissioningManager.h>
34 : #include <system/SystemClock.h>
35 : #include <tracing/metric_event.h>
36 : #include <utility>
37 : #include <vector>
38 :
39 : constexpr uint32_t kDeviceDiscoveredTimeout = CHIP_CONFIG_SETUP_CODE_PAIRER_DISCOVERY_TIMEOUT_SECS * chip::kMillisecondsPerSecond;
40 :
41 : using namespace chip::Tracing;
42 :
43 : namespace chip {
44 : namespace Controller {
45 :
46 0 : CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour commission,
47 : DiscoveryType discoveryType, Optional<Dnssd::CommonResolutionData> resolutionData)
48 : {
49 0 : VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE);
50 0 : VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, remoteId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
51 :
52 0 : std::vector<SetupPayload> payloads;
53 0 : ReturnErrorOnFailure(SetupPayload::FromStringRepresentation(setUpCode, payloads));
54 :
55 : // If the caller has provided a specific single resolution data, and we were
56 : // only looking for one commissionee, and the caller says that the provided
57 : // data matches that one commissionee, just go ahead and use the provided data.
58 : //
59 : // If we were looking for more than one device (i.e. if either of the
60 : // payload arrays involved does not have length 1), we can't make use of the
61 : // incoming resolution data, since it does not contain the long
62 : // discriminator of the thing that was discovered, and therefore we can't
63 : // tell which setup passcode to use for it.
64 0 : if (resolutionData.HasValue() && payloads.size() == 1 && mSetupPayloads.size() == 1)
65 : {
66 0 : VerifyOrReturnErrorWithMetric(kMetricSetupCodePairerPairDevice, discoveryType != DiscoveryType::kAll,
67 : CHIP_ERROR_INVALID_ARGUMENT);
68 0 : if (mRemoteId == remoteId && mSetupPayloads[0].setUpPINCode == payloads[0].setUpPINCode && mConnectionType == commission &&
69 0 : mDiscoveryType == discoveryType)
70 : {
71 : // Not passing a discriminator is ok, since we have only one payload.
72 0 : NotifyCommissionableDeviceDiscovered(resolutionData.Value(), /* matchedLongDiscriminator = */ std::nullopt);
73 0 : return CHIP_NO_ERROR;
74 : }
75 : }
76 :
77 0 : ResetDiscoveryState();
78 :
79 0 : mConnectionType = commission;
80 0 : mDiscoveryType = discoveryType;
81 0 : mRemoteId = remoteId;
82 0 : mSetupPayloads = std::move(payloads);
83 :
84 0 : if (resolutionData.HasValue() && mSetupPayloads.size() == 1)
85 : {
86 : // No need to pass in a discriminator if we have only one payload, which
87 : // is good because we don't have a full discriminator here anyway.
88 0 : NotifyCommissionableDeviceDiscovered(resolutionData.Value(), /* matchedLongDiscriminator = */ std::nullopt);
89 0 : return CHIP_NO_ERROR;
90 : }
91 :
92 0 : ReturnErrorOnFailureWithMetric(kMetricSetupCodePairerPairDevice, Connect());
93 : auto errorCode =
94 0 : mSystemLayer->StartTimer(System::Clock::Milliseconds32(kDeviceDiscoveredTimeout), OnDeviceDiscoveredTimeoutCallback, this);
95 0 : if (CHIP_NO_ERROR == errorCode)
96 : {
97 : MATTER_LOG_METRIC_BEGIN(kMetricSetupCodePairerPairDevice);
98 : }
99 0 : return errorCode;
100 0 : }
101 :
102 0 : CHIP_ERROR SetUpCodePairer::Connect()
103 : {
104 0 : if (mDiscoveryType == DiscoveryType::kAll)
105 : {
106 0 : if (ShouldDiscoverUsing(RendezvousInformationFlag::kBLE))
107 : {
108 0 : CHIP_ERROR err = StartDiscoveryOverBLE();
109 0 : if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
110 : {
111 0 : ChipLogProgress(Controller,
112 : "Skipping commissionable node discovery over BLE since not supported by the controller!");
113 : }
114 0 : else if (err != CHIP_NO_ERROR)
115 : {
116 0 : ChipLogError(Controller, "Failed to start commissionable node discovery over BLE: %" CHIP_ERROR_FORMAT,
117 : err.Format());
118 : }
119 : }
120 0 : if (ShouldDiscoverUsing(RendezvousInformationFlag::kWiFiPAF))
121 : {
122 0 : CHIP_ERROR err = StartDiscoveryOverWiFiPAF();
123 0 : if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
124 : {
125 0 : ChipLogProgress(Controller,
126 : "Skipping commissionable node discovery over Wi-Fi PAF since not supported by the controller!");
127 : }
128 0 : else if (err != CHIP_NO_ERROR)
129 : {
130 0 : ChipLogError(Controller, "Failed to start commissionable node discovery over Wi-Fi PAF: %" CHIP_ERROR_FORMAT,
131 : err.Format());
132 : }
133 : }
134 0 : if (ShouldDiscoverUsing(RendezvousInformationFlag::kNFC))
135 : {
136 0 : CHIP_ERROR err = StartDiscoveryOverNFC();
137 0 : if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
138 : {
139 0 : ChipLogProgress(Controller,
140 : "Skipping commissionable node discovery over NFC since not supported by the controller!");
141 : }
142 0 : else if (err == CHIP_ERROR_NOT_FOUND)
143 : {
144 0 : ChipLogProgress(Controller,
145 : "Skipping commissionable node discovery over NFC since no NFC Reader Transport is present");
146 : }
147 0 : else if (err != CHIP_NO_ERROR)
148 : {
149 0 : ChipLogError(Controller, "Failed to start commissionable node discovery over NFC: %" CHIP_ERROR_FORMAT,
150 : err.Format());
151 : }
152 : }
153 0 : if (ShouldDiscoverUsing(RendezvousInformationFlag::kThread))
154 : {
155 0 : CHIP_ERROR err = StartDiscoveryOverThreadMeshcop();
156 0 : if ((CHIP_ERROR_NOT_IMPLEMENTED == err) || (CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err))
157 : {
158 0 : ChipLogProgress(Controller,
159 : "Skipping commissionable node discovery over ThreadMeshcop since not supported by the controller!");
160 : }
161 0 : else if (err != CHIP_NO_ERROR)
162 : {
163 0 : ChipLogError(Controller, "Failed to start commissionable node discovery over ThreadMeshcop: %" CHIP_ERROR_FORMAT,
164 : err.Format());
165 : }
166 : }
167 : }
168 :
169 : // We always want to search on network because any node that has already been commissioned will use on-network regardless of the
170 : // QR code flag.
171 0 : CHIP_ERROR err = StartDiscoveryOverDNSSD();
172 0 : if (err != CHIP_NO_ERROR)
173 : {
174 0 : ChipLogError(Controller, "Failed to start commissionable node discovery over DNS-SD: %" CHIP_ERROR_FORMAT, err.Format());
175 : }
176 0 : return err;
177 : }
178 :
179 0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverBLE()
180 : {
181 : #if CONFIG_NETWORK_LAYER_BLE
182 : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
183 : VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
184 : mCommissioner->ConnectBleTransportToSelf();
185 : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
186 0 : VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
187 :
188 0 : ChipLogProgress(Controller, "Starting commissionable node discovery over BLE");
189 :
190 : // Handle possibly-sync callbacks.
191 0 : mWaitingForDiscovery[kBLETransport] = true;
192 : CHIP_ERROR err;
193 : // Not all BLE backends support the new NewBleConnectionByDiscriminators
194 : // API, so use the old one when we can (i.e. when we only have one setup
195 : // payload), to avoid breaking existing API consumers.
196 0 : if (mSetupPayloads.size() == 1)
197 : {
198 0 : err = mBleLayer->NewBleConnectionByDiscriminator(mSetupPayloads[0].discriminator, this, OnDiscoveredDeviceOverBleSuccess,
199 : OnDiscoveredDeviceOverBleError);
200 : }
201 : else
202 : {
203 0 : std::vector<SetupDiscriminator> discriminators;
204 0 : discriminators.reserve(mSetupPayloads.size());
205 0 : for (auto & payload : mSetupPayloads)
206 : {
207 0 : discriminators.emplace_back(payload.discriminator);
208 : }
209 0 : err = mBleLayer->NewBleConnectionByDiscriminators(Span(discriminators.data(), discriminators.size()), this,
210 : OnDiscoveredDeviceWithDiscriminatorOverBleSuccess,
211 : OnDiscoveredDeviceOverBleError);
212 0 : }
213 0 : if (err != CHIP_NO_ERROR)
214 : {
215 0 : mWaitingForDiscovery[kBLETransport] = false;
216 : }
217 0 : return err;
218 : #else
219 : return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
220 : #endif // CONFIG_NETWORK_LAYER_BLE
221 : }
222 :
223 1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverBLE()
224 : {
225 : // Make sure to not call CancelBleIncompleteConnection unless we are in fact
226 : // waiting on BLE discovery. It will cancel connections that are in fact
227 : // completed. In particular, if we just established PASE over BLE calling
228 : // CancelBleIncompleteConnection here unconditionally would cancel the BLE
229 : // connection underlying the PASE session. So make sure to only call
230 : // CancelBleIncompleteConnection if we're still waiting to hear back on the
231 : // BLE discovery bits.
232 1 : if (!mWaitingForDiscovery[kBLETransport])
233 : {
234 0 : return CHIP_NO_ERROR;
235 : }
236 :
237 1 : mWaitingForDiscovery[kBLETransport] = false;
238 : #if CONFIG_NETWORK_LAYER_BLE
239 1 : VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
240 0 : ChipLogProgress(Controller, "Stopping commissionable node discovery over BLE");
241 0 : return mBleLayer->CancelBleIncompleteConnection();
242 : #else
243 : return CHIP_NO_ERROR;
244 : #endif // CONFIG_NETWORK_LAYER_BLE
245 : }
246 :
247 0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverDNSSD()
248 : {
249 0 : ChipLogProgress(Controller, "Starting commissionable node discovery over DNS-SD");
250 :
251 0 : Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kNone);
252 0 : if (mSetupPayloads.size() == 1)
253 : {
254 0 : auto & discriminator = mSetupPayloads[0].discriminator;
255 0 : if (discriminator.IsShortDiscriminator())
256 : {
257 0 : filter.type = Dnssd::DiscoveryFilterType::kShortDiscriminator;
258 0 : filter.code = discriminator.GetShortValue();
259 : }
260 : else
261 : {
262 0 : filter.type = Dnssd::DiscoveryFilterType::kLongDiscriminator;
263 0 : filter.code = discriminator.GetLongValue();
264 : }
265 : }
266 :
267 : // In theory we could try to filter on the vendor ID if it's the same across all the setup
268 : // payloads, but DNS-SD advertisements are not required to include the Vendor ID subtype, so in
269 : // practice that's not doable.
270 :
271 : // Handle possibly-sync callbacks.
272 0 : mWaitingForDiscovery[kIPTransport] = true;
273 0 : CHIP_ERROR err = mCommissioner->DiscoverCommissionableNodes(filter);
274 0 : if (err != CHIP_NO_ERROR)
275 : {
276 0 : mWaitingForDiscovery[kIPTransport] = false;
277 : }
278 0 : return err;
279 : }
280 :
281 2 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverDNSSD()
282 : {
283 2 : ChipLogProgress(Controller, "Stopping commissionable node discovery over DNS-SD");
284 :
285 2 : mWaitingForDiscovery[kIPTransport] = false;
286 :
287 2 : return mCommissioner->StopCommissionableDiscovery();
288 : }
289 :
290 0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverWiFiPAF()
291 : {
292 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
293 0 : if (mSetupPayloads.size() != 1)
294 : {
295 0 : ChipLogError(Controller, "Wi-Fi PAF commissioning does not support concatenated QR codes yet.");
296 0 : return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
297 : }
298 :
299 0 : auto & payload = mSetupPayloads[0];
300 :
301 0 : ChipLogProgress(Controller, "Starting commissionable node discovery over Wi-Fi PAF");
302 0 : VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
303 :
304 0 : const SetupDiscriminator connDiscriminator(payload.discriminator);
305 0 : VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
306 : ChipLogError(Controller, "Error, Long discriminator is required"));
307 0 : uint16_t discriminator = connDiscriminator.GetLongValue();
308 0 : WiFiPAF::WiFiPAFSession sessionInfo = { .role = WiFiPAF::WiFiPafRole::kWiFiPafRole_Subscriber,
309 0 : .nodeId = mRemoteId,
310 0 : .discriminator = discriminator };
311 0 : ReturnErrorOnFailure(
312 : DeviceLayer::ConnectivityMgr().GetWiFiPAF()->AddPafSession(WiFiPAF::PafInfoAccess::kAccNodeInfo, sessionInfo));
313 :
314 0 : mWaitingForDiscovery[kWiFiPAFTransport] = true;
315 0 : CHIP_ERROR err = DeviceLayer::ConnectivityMgr().WiFiPAFSubscribe(discriminator, (void *) this, OnWiFiPAFSubscribeComplete,
316 : OnWiFiPAFSubscribeError);
317 0 : if (err != CHIP_NO_ERROR)
318 : {
319 0 : ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed, err = %" CHIP_ERROR_FORMAT, err.Format());
320 0 : mWaitingForDiscovery[kWiFiPAFTransport] = false;
321 : }
322 0 : return err;
323 : #else
324 : return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
325 : #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
326 : }
327 :
328 1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverWiFiPAF()
329 : {
330 1 : mWaitingForDiscovery[kWiFiPAFTransport] = false;
331 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
332 1 : return DeviceLayer::ConnectivityMgr().WiFiPAFCancelIncompleteSubscribe();
333 : #else
334 : return CHIP_NO_ERROR;
335 : #endif
336 : }
337 :
338 0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverNFC()
339 : {
340 : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
341 : if (mSetupPayloads.size() != 1)
342 : {
343 : ChipLogError(Controller, "NFC commissioning does not support concatenated QR codes yet.");
344 : return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
345 : }
346 :
347 : auto & payload = mSetupPayloads[0];
348 :
349 : ChipLogProgress(Controller, "Starting commissionable node discovery over NFC");
350 : VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
351 :
352 : const SetupDiscriminator connDiscriminator(payload.discriminator);
353 : VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
354 : ChipLogError(Controller, "Error, Long discriminator is required"));
355 : chip::Nfc::NFCTag::Identifier identifier = { .discriminator = payload.discriminator.GetLongValue() };
356 : Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
357 : if (!readerTransport)
358 : {
359 : // No valid NFC reader transport
360 : return CHIP_ERROR_NOT_FOUND;
361 : }
362 :
363 : readerTransport->SetDelegate(this);
364 : CHIP_ERROR err = readerTransport->StartDiscoveringTagMatchingAddress(identifier);
365 : if (err != CHIP_NO_ERROR)
366 : {
367 : ChipLogError(Controller, "Commissionable node discovery over NFC failed, err = %" CHIP_ERROR_FORMAT, err.Format());
368 : }
369 : else
370 : {
371 : mWaitingForDiscovery[kNFCTransport] = true;
372 : }
373 : return err;
374 : #else
375 0 : return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
376 : #endif // CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
377 : }
378 :
379 1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverNFC()
380 : {
381 : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
382 : mWaitingForDiscovery[kNFCTransport] = false;
383 :
384 : Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
385 : if (!readerTransport)
386 : {
387 : // No valid NFC reader transport.
388 : return CHIP_ERROR_NOT_FOUND;
389 : }
390 :
391 : ChipLogProgress(Controller, "Stopping commissionable node discovery over NFC by removing delegate");
392 : readerTransport->SetDelegate(nullptr);
393 : #endif
394 1 : return CHIP_NO_ERROR;
395 : }
396 :
397 0 : CHIP_ERROR SetUpCodePairer::StartDiscoveryOverThreadMeshcop()
398 : {
399 : #if CHIP_SUPPORT_THREAD_MESHCOP
400 0 : if (mSetupPayloads.size() != 1)
401 : {
402 0 : ChipLogError(Controller, "Thread Meshcop commissioning does not support concatenated QR codes yet.");
403 0 : return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
404 : }
405 :
406 0 : if (!mThreadMeshcopCommissionProxy)
407 : {
408 0 : ChipLogError(Controller, "The meshcopCommissioningProxy is not set");
409 0 : return CHIP_ERROR_INVALID_ARGUMENT;
410 : }
411 :
412 0 : if (!mThreadMeshcopCommissionParams.HasValue() ||
413 0 : mThreadMeshcopCommissionParams.Value().mBorderAgentAddress.GetTransportType() != Transport::Type::kThreadMeshcop)
414 : {
415 0 : ChipLogError(Controller, "The meshcopCommissioningParams is not set");
416 0 : return CHIP_ERROR_INVALID_ARGUMENT;
417 : }
418 :
419 0 : auto & payload = mSetupPayloads[0];
420 :
421 0 : ChipLogProgress(Controller, "Starting commissionable node discovery over Thread Meshcop");
422 0 : VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
423 :
424 0 : const SetupDiscriminator connDiscriminator(payload.discriminator);
425 0 : Thread::DiscoveryCode code;
426 0 : if (connDiscriminator.IsShortDiscriminator())
427 : {
428 0 : code = Thread::DiscoveryCode(connDiscriminator.GetShortValue());
429 0 : ChipLogProgress(Controller, "Discovery code from short discriminator: 0x%" PRIx64, code.AsUInt64());
430 : }
431 : else
432 : {
433 0 : code = Thread::DiscoveryCode(connDiscriminator.GetLongValue());
434 0 : ChipLogProgress(Controller, "Discovery code from long discriminator: 0x%" PRIx64, code.AsUInt64());
435 : }
436 :
437 0 : ByteSpan pskc(mThreadMeshcopCommissionParams.Value().mPSKcBuffer);
438 : {
439 0 : mWaitingForDiscovery[kThreadMeshcopTransport] = true;
440 0 : Dnssd::DiscoveredNodeData discoveredNodeData;
441 :
442 0 : CHIP_ERROR err = mThreadMeshcopCommissionProxy->Discover(pskc, mThreadMeshcopCommissionParams.Value().mBorderAgentAddress,
443 : code, connDiscriminator, discoveredNodeData, 30);
444 :
445 0 : mWaitingForDiscovery[kThreadMeshcopTransport] = false;
446 0 : ReturnErrorOnFailure(err);
447 0 : mCommissioner->OnNodeDiscovered(discoveredNodeData);
448 0 : ChipLogProgress(Controller, "Joiner discovered");
449 0 : }
450 0 : return CHIP_NO_ERROR;
451 : #else
452 : return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
453 : #endif // CHIP_SUPPORT_THREAD_MESHCOP
454 : }
455 :
456 1 : CHIP_ERROR SetUpCodePairer::StopDiscoveryOverThreadMeshcop()
457 : {
458 : // Currently we don't have any methods to stop discovery Over Thread Meshcop.
459 : // Still return no error here to prevent error logs.
460 1 : return CHIP_NO_ERROR;
461 : }
462 :
463 6 : bool SetUpCodePairer::ConnectToDiscoveredDevice()
464 : {
465 6 : if (mWaitingForPASE)
466 : {
467 : // Nothing to do. Just wait until we either succeed or fail at that
468 : // PASE session establishment.
469 4 : return false;
470 : }
471 :
472 2 : while (!mDiscoveredParameters.empty())
473 : {
474 0 : mCurrentPASEPayload.reset();
475 :
476 : // Grab the first element from the queue and try connecting to it.
477 : // Remove it from the queue before we try to connect, in case the
478 : // connection attempt fails and calls right back into us to try the next
479 : // thing.
480 0 : SetUpCodePairerParameters params(mDiscoveredParameters.front());
481 0 : mDiscoveredParameters.pop_front();
482 :
483 0 : if (params.mLongDiscriminator)
484 : {
485 0 : auto longDiscriminator = *params.mLongDiscriminator;
486 : // Look for a matching setup passcode.
487 0 : for (auto & payload : mSetupPayloads)
488 : {
489 0 : if (payload.discriminator.MatchesLongDiscriminator(longDiscriminator))
490 : {
491 0 : params.SetSetupPINCode(payload.setUpPINCode);
492 0 : params.SetSetupDiscriminator(payload.discriminator);
493 0 : mCurrentPASEPayload = payload;
494 0 : break;
495 : }
496 : }
497 0 : if (!mCurrentPASEPayload)
498 : {
499 0 : ChipLogError(Controller, "SetUpCodePairer: Discovered discriminator %u does not match any of our setup payloads",
500 : longDiscriminator);
501 : // Move on to the the next discovered params; nothing we can do here.
502 0 : continue;
503 : }
504 : }
505 : else
506 : {
507 : // No discriminator known for this discovered device. This can work if we have only one
508 : // setup payload, but otherwise we have no idea what setup passcode to use for it.
509 0 : if (mSetupPayloads.size() == 1)
510 : {
511 0 : params.SetSetupPINCode(mSetupPayloads[0].setUpPINCode);
512 0 : params.SetSetupDiscriminator(mSetupPayloads[0].discriminator);
513 0 : mCurrentPASEPayload = mSetupPayloads[0];
514 : }
515 : else
516 : {
517 0 : ChipLogError(Controller,
518 : "SetUpCodePairer: Unable to handle discovered parameters with no discriminator, because it has %u "
519 : "possible payloads",
520 : static_cast<unsigned>(mSetupPayloads.size()));
521 0 : continue;
522 : }
523 : }
524 :
525 : #if CHIP_PROGRESS_LOGGING
526 : char buf[Transport::PeerAddress::kMaxToStringSize];
527 0 : params.GetPeerAddress().ToString(buf);
528 0 : ChipLogProgress(Controller, "Attempting PASE connection to %s", buf);
529 : #endif // CHIP_PROGRESS_LOGGING
530 :
531 : // Handle possibly-sync call backs from attempts to establish PASE.
532 0 : ExpectPASEEstablishment();
533 :
534 0 : if (params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
535 : {
536 0 : mCurrentPASEParameters.SetValue(params);
537 : }
538 :
539 : CHIP_ERROR err;
540 0 : if (mConnectionType == SetupCodePairerBehaviour::kCommission)
541 : {
542 0 : err = mCommissioner->PairDevice(mRemoteId, params);
543 : }
544 : else
545 : {
546 0 : err = mCommissioner->EstablishPASEConnection(mRemoteId, params);
547 : }
548 :
549 0 : LogErrorOnFailure(err);
550 0 : if (err == CHIP_NO_ERROR)
551 : {
552 0 : return true;
553 : }
554 :
555 : // Failed to start establishing PASE. Move on to the next item.
556 0 : mCurrentPASEParameters.ClearValue();
557 0 : mCurrentPASEPayload.reset();
558 0 : PASEEstablishmentComplete();
559 : }
560 :
561 2 : return false;
562 : }
563 :
564 : #if CONFIG_NETWORK_LAYER_BLE
565 0 : void SetUpCodePairer::OnDiscoveredDeviceOverBle(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> matchedLongDiscriminator)
566 : {
567 0 : ChipLogProgress(Controller, "Discovered device to be commissioned over BLE");
568 :
569 0 : mWaitingForDiscovery[kBLETransport] = false;
570 :
571 : // In order to not wait for all the possible addresses discovered over mdns to
572 : // be tried before trying to connect over BLE, the discovered connection object is
573 : // inserted at the beginning of the list.
574 : //
575 : // It makes it the 'next' thing to try to connect to if there are already some
576 : // discovered parameters in the list.
577 : //
578 : // TODO: Consider implementing the SHOULD the spec has about commissioning things
579 : // in QR code order by waiting for a second or something before actually starting
580 : // the first PASE session when we have multiple setup payloads, and sorting the
581 : // results in setup payload order. If we do this, we might want to restrict it to
582 : // cases when the different payloads have different vendor/product IDs, since if
583 : // they are all the same product presumably ordering really does not matter.
584 0 : mDiscoveredParameters.emplace_front(connObj, matchedLongDiscriminator);
585 0 : ConnectToDiscoveredDevice();
586 0 : }
587 :
588 0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
589 : {
590 0 : (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::nullopt);
591 0 : }
592 :
593 0 : void SetUpCodePairer::OnDiscoveredDeviceWithDiscriminatorOverBleSuccess(void * appState, uint16_t matchedLongDiscriminator,
594 : BLE_CONNECTION_OBJECT connObj)
595 : {
596 0 : (static_cast<SetUpCodePairer *>(appState))->OnDiscoveredDeviceOverBle(connObj, std::make_optional(matchedLongDiscriminator));
597 0 : }
598 :
599 0 : void SetUpCodePairer::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
600 : {
601 0 : static_cast<SetUpCodePairer *>(appState)->OnBLEDiscoveryError(err);
602 0 : }
603 :
604 0 : void SetUpCodePairer::OnBLEDiscoveryError(CHIP_ERROR err)
605 : {
606 0 : ChipLogError(Controller, "Commissionable node discovery over BLE failed: %" CHIP_ERROR_FORMAT, err.Format());
607 0 : mWaitingForDiscovery[kBLETransport] = false;
608 0 : LogErrorOnFailure(err);
609 0 : StopPairingIfTransportsExhausted(err);
610 0 : }
611 : #endif // CONFIG_NETWORK_LAYER_BLE
612 :
613 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
614 0 : void SetUpCodePairer::OnDiscoveredDeviceOverWifiPAF()
615 : {
616 0 : ChipLogProgress(Controller, "Discovered device to be commissioned over Wi-Fi PAF, RemoteId: %" PRIu64, mRemoteId);
617 :
618 0 : mWaitingForDiscovery[kWiFiPAFTransport] = false;
619 0 : auto param = SetUpCodePairerParameters();
620 0 : param.SetPeerAddress(Transport::PeerAddress(Transport::Type::kWiFiPAF, mRemoteId));
621 : // TODO: This needs to support concatenated QR codes and set the relevant
622 : // long discriminator on param.
623 : //
624 : // See https://github.com/project-chip/connectedhomeip/issues/39134
625 0 : mDiscoveredParameters.emplace_back(param);
626 0 : ConnectToDiscoveredDevice();
627 0 : }
628 :
629 0 : void SetUpCodePairer::OnWifiPAFDiscoveryError(CHIP_ERROR err)
630 : {
631 0 : ChipLogError(Controller, "Commissionable node discovery over Wi-Fi PAF failed: %" CHIP_ERROR_FORMAT, err.Format());
632 0 : mWaitingForDiscovery[kWiFiPAFTransport] = false;
633 0 : StopPairingIfTransportsExhausted(err);
634 0 : }
635 :
636 0 : void SetUpCodePairer::OnWiFiPAFSubscribeComplete(void * appState)
637 : {
638 0 : auto self = reinterpret_cast<SetUpCodePairer *>(appState);
639 0 : self->OnDiscoveredDeviceOverWifiPAF();
640 0 : }
641 :
642 0 : void SetUpCodePairer::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err)
643 : {
644 0 : auto self = reinterpret_cast<SetUpCodePairer *>(appState);
645 0 : self->OnWifiPAFDiscoveryError(err);
646 0 : }
647 : #endif
648 :
649 : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
650 : void SetUpCodePairer::OnTagDiscovered(const chip::Nfc::NFCTag::Identifier & identifier)
651 : {
652 : ChipLogProgress(Controller, "Discovered device to be commissioned over NFC, Identifier: %u", identifier.discriminator);
653 :
654 : mWaitingForDiscovery[kNFCTransport] = false;
655 : auto param = SetUpCodePairerParameters();
656 : param.SetPeerAddress(Transport::PeerAddress(Transport::PeerAddress::NFC(identifier.discriminator)));
657 : // TODO: This needs to support concatenated QR codes and set the relevant
658 : // long discriminator on param.
659 : //
660 : // See https://github.com/project-chip/connectedhomeip/issues/39134
661 : mDiscoveredParameters.emplace_back(param);
662 : ConnectToDiscoveredDevice();
663 : }
664 :
665 : void SetUpCodePairer::OnTagDiscoveryFailed(CHIP_ERROR error)
666 : {
667 : ChipLogError(Controller, "Commissionable node discovery over NFC failed: %" CHIP_ERROR_FORMAT, error.Format());
668 : mWaitingForDiscovery[kNFCTransport] = false;
669 : StopPairingIfTransportsExhausted(error);
670 : }
671 : #endif
672 :
673 0 : bool SetUpCodePairer::IdIsPresent(uint16_t vendorOrProductID)
674 : {
675 0 : return vendorOrProductID != kNotAvailable;
676 : }
677 :
678 0 : bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & discNodeData) const
679 : {
680 0 : if (!discNodeData.Is<Dnssd::CommissionNodeData>())
681 : {
682 0 : return false;
683 : }
684 :
685 0 : const Dnssd::CommissionNodeData & nodeData = discNodeData.Get<Dnssd::CommissionNodeData>();
686 :
687 0 : VerifyOrReturnError(mCommissioner != nullptr, false);
688 0 : VerifyOrReturnError(mCommissioner->HasValidCommissioningMode(nodeData), false);
689 :
690 : // Check whether this matches one of our setup payloads.
691 0 : for (auto & payload : mSetupPayloads)
692 : {
693 : // The advertisement may not include a vendor id, and the payload may not have one either.
694 0 : if (IdIsPresent(payload.vendorID) && IdIsPresent(nodeData.vendorId) && payload.vendorID != nodeData.vendorId)
695 : {
696 0 : ChipLogProgress(Controller, "Discovered device vendor ID (%u) does not match our vendor ID (%u).", nodeData.vendorId,
697 : payload.vendorID);
698 0 : continue;
699 : }
700 :
701 : // The advertisement may not include a product id, and the payload may not have one either.
702 0 : if (IdIsPresent(payload.productID) && IdIsPresent(nodeData.productId) && payload.productID != nodeData.productId)
703 : {
704 0 : ChipLogProgress(Controller, "Discovered device product ID (%u) does not match our product ID (%u).", nodeData.productId,
705 : payload.productID);
706 0 : continue;
707 : }
708 :
709 0 : if (!payload.discriminator.MatchesLongDiscriminator(nodeData.longDiscriminator))
710 : {
711 0 : ChipLogProgress(Controller, "Discovered device discriminator (%u) does not match our discriminator.",
712 : nodeData.longDiscriminator);
713 0 : continue;
714 : }
715 :
716 0 : ChipLogProgress(Controller, "Discovered device with discriminator %u matches one of our setup payloads",
717 : nodeData.longDiscriminator);
718 0 : return true;
719 : }
720 :
721 0 : return false;
722 : }
723 :
724 0 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::DiscoveredNodeData & nodeData)
725 : {
726 0 : if (!NodeMatchesCurrentFilter(nodeData))
727 : {
728 0 : return;
729 : }
730 :
731 0 : ChipLogProgress(Controller, "Discovered device to be commissioned over DNS-SD");
732 :
733 0 : auto & commissionableNodeData = nodeData.Get<Dnssd::CommissionNodeData>();
734 :
735 0 : NotifyCommissionableDeviceDiscovered(commissionableNodeData, std::make_optional(commissionableNodeData.longDiscriminator));
736 : }
737 :
738 4 : void SetUpCodePairer::NotifyCommissionableDeviceDiscovered(const Dnssd::CommonResolutionData & resolutionData,
739 : std::optional<uint16_t> matchedLongDiscriminator)
740 : {
741 4 : if (mDiscoveryType == DiscoveryType::kDiscoveryNetworkOnlyWithoutPASEAutoRetry)
742 : {
743 : // If the discovery type does not want the PASE auto retry mechanism, we will just store
744 : // a single IP. So the discovery process is stopped as it won't be of any help anymore.
745 0 : TEMPORARY_RETURN_IGNORED StopDiscoveryOverDNSSD();
746 0 : EnqueueDiscoveredParametersIfNotDuplicate(SetUpCodePairerParameters(resolutionData, matchedLongDiscriminator, 0));
747 : }
748 : else
749 : {
750 9 : for (size_t i = 0; i < resolutionData.numIPs; i++)
751 : {
752 5 : EnqueueDiscoveredParametersIfNotDuplicate(SetUpCodePairerParameters(resolutionData, matchedLongDiscriminator, i));
753 : }
754 : }
755 :
756 4 : ConnectToDiscoveredDevice();
757 4 : }
758 :
759 5 : void SetUpCodePairer::EnqueueDiscoveredParametersIfNotDuplicate(SetUpCodePairerParameters && params)
760 : {
761 : // The same device can be advertised more than once -- most notably the same non-link-local
762 : // address arriving on multiple interfaces -- producing candidates that would drive an identical
763 : // PASE attempt. Retrying the same attempt just wastes it and adds latency, so drop duplicates.
764 6 : for (const SetUpCodePairerParameters & existing : mDiscoveredParameters)
765 : {
766 3 : if (existing.CanCoalesceWith(params))
767 : {
768 2 : ChipLogDetail(Controller, "SetUpCodePairer: dropping duplicate discovered rendezvous parameters");
769 2 : return;
770 : }
771 : }
772 :
773 3 : mDiscoveredParameters.emplace_back(std::move(params));
774 : }
775 :
776 0 : bool SetUpCodePairer::StopPairing(NodeId remoteId)
777 : {
778 0 : VerifyOrReturnValue(mRemoteId != kUndefinedNodeId, false);
779 0 : VerifyOrReturnValue(remoteId == kUndefinedNodeId || remoteId == mRemoteId, false);
780 :
781 0 : if (mWaitingForPASE)
782 : {
783 0 : PASEEstablishmentComplete();
784 : }
785 :
786 0 : ResetDiscoveryState();
787 0 : mRemoteId = kUndefinedNodeId;
788 0 : return true;
789 : }
790 :
791 2 : bool SetUpCodePairer::TryNextRendezvousParameters()
792 : {
793 2 : if (ConnectToDiscoveredDevice())
794 : {
795 0 : ChipLogProgress(Controller, "Trying connection to commissionee over different transport");
796 0 : return true;
797 : }
798 :
799 2 : if (DiscoveryInProgress())
800 : {
801 2 : ChipLogProgress(Controller, "Waiting to discover commissionees that match our filters");
802 2 : return true;
803 : }
804 :
805 0 : return false;
806 : }
807 :
808 3 : bool SetUpCodePairer::DiscoveryInProgress() const
809 : {
810 8 : for (const auto & waiting : mWaitingForDiscovery)
811 : {
812 7 : if (waiting)
813 : {
814 2 : return true;
815 : }
816 : }
817 :
818 1 : return false;
819 : }
820 :
821 1 : void SetUpCodePairer::StopPairingIfTransportsExhausted(CHIP_ERROR err)
822 : {
823 1 : if (mWaitingForPASE || !mDiscoveredParameters.empty() || DiscoveryInProgress() || mRemoteId == kUndefinedNodeId)
824 : {
825 0 : return;
826 : }
827 : // Clear mRemoteId first to guard against re-entrant calls (e.g. from an async
828 : // cancel callback fired after StopAllDiscoveryAttempts already cleared the flags).
829 1 : mRemoteId = kUndefinedNodeId;
830 2 : CHIP_ERROR failErr = mLastPASEError != CHIP_NO_ERROR ? mLastPASEError : err;
831 : MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, failErr);
832 1 : mCommissioner->OnSessionEstablishmentError(failErr);
833 : }
834 :
835 1 : void SetUpCodePairer::StopAllDiscoveryAttempts()
836 : {
837 1 : LogErrorOnFailure(StopDiscoveryOverBLE());
838 1 : LogErrorOnFailure(StopDiscoveryOverDNSSD());
839 1 : LogErrorOnFailure(StopDiscoveryOverWiFiPAF());
840 2 : LogErrorOnFailure(StopDiscoveryOverNFC().NoErrorIf(CHIP_ERROR_NOT_FOUND));
841 1 : LogErrorOnFailure(StopDiscoveryOverThreadMeshcop());
842 :
843 : // Just in case any of those failed to reset the waiting state properly.
844 5 : for (auto & waiting : mWaitingForDiscovery)
845 : {
846 4 : waiting = false;
847 : }
848 1 : }
849 :
850 0 : void SetUpCodePairer::ResetDiscoveryState()
851 : {
852 0 : StopAllDiscoveryAttempts();
853 :
854 0 : mDiscoveredParameters.clear();
855 0 : mCurrentPASEParameters.ClearValue();
856 0 : mLastPASEError = CHIP_NO_ERROR;
857 :
858 0 : mSetupPayloads.clear();
859 :
860 0 : mSystemLayer->CancelTimer(OnDeviceDiscoveredTimeoutCallback, this);
861 0 : }
862 :
863 2 : void SetUpCodePairer::ExpectPASEEstablishment()
864 : {
865 2 : VerifyOrDie(!mWaitingForPASE);
866 2 : mWaitingForPASE = true;
867 2 : auto * delegate = mCommissioner->GetPairingDelegate();
868 2 : VerifyOrDie(delegate != this);
869 2 : mPairingDelegate = delegate;
870 2 : mCommissioner->RegisterPairingDelegate(this);
871 2 : }
872 :
873 2 : void SetUpCodePairer::PASEEstablishmentComplete()
874 : {
875 2 : VerifyOrDie(mWaitingForPASE);
876 2 : mWaitingForPASE = false;
877 2 : mCommissioner->RegisterPairingDelegate(mPairingDelegate);
878 2 : mPairingDelegate = nullptr;
879 2 : }
880 :
881 0 : void SetUpCodePairer::OnStatusUpdate(DevicePairingDelegate::Status status)
882 : {
883 0 : if (status == DevicePairingDelegate::Status::SecurePairingFailed)
884 : {
885 : // If we're still waiting on discovery, don't propagate this failure
886 : // (which is due to PASE failure with something we discovered, but the
887 : // "something" may not have been the right thing) for now. Wait until
888 : // discovery completes. Then we will either succeed and notify
889 : // accordingly or time out and land in OnStatusUpdate again, but at that
890 : // point we will not be waiting on discovery anymore.
891 0 : if (!mDiscoveredParameters.empty())
892 : {
893 0 : ChipLogProgress(Controller, "Ignoring SecurePairingFailed status for now; we have more discovered devices to try");
894 0 : return;
895 : }
896 :
897 0 : if (DiscoveryInProgress())
898 : {
899 0 : ChipLogProgress(Controller,
900 : "Ignoring SecurePairingFailed status for now; we are waiting to see if we discover more devices");
901 0 : return;
902 : }
903 : }
904 :
905 0 : if (mPairingDelegate)
906 : {
907 0 : mPairingDelegate->OnStatusUpdate(status);
908 : }
909 : }
910 :
911 2 : void SetUpCodePairer::OnPairingComplete(CHIP_ERROR error, const std::optional<RendezvousParameters> & rendezvousParameters,
912 : const std::optional<SetupPayload> & setupPayload)
913 : {
914 : // Save the pairing delegate so we can notify it. We want to notify it
915 : // _after_ we restore the state on the commissioner, in case the delegate
916 : // ends up immediately calling back into the commissioner again when
917 : // notified.
918 2 : auto * pairingDelegate = mPairingDelegate;
919 2 : PASEEstablishmentComplete();
920 :
921 : // Make sure to clear out mCurrentPASEPayload whether we succeeded or failed.
922 2 : std::optional<SetupPayload> pasePayload;
923 2 : pasePayload.swap(mCurrentPASEPayload);
924 :
925 4 : if (CHIP_NO_ERROR == error)
926 : {
927 0 : ChipLogProgress(Controller, "PASE session established with commissionee. Stopping discovery.");
928 0 : ResetDiscoveryState();
929 0 : mRemoteId = kUndefinedNodeId;
930 : MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
931 0 : if (pairingDelegate != nullptr)
932 : {
933 : // We don't expect to have a setupPayload passed in here.
934 0 : if (setupPayload)
935 : {
936 0 : ChipLogError(Controller,
937 : "Unexpected setupPayload passed to SetUpCodePairer::OnPairingComplete. Where did it come from?");
938 : }
939 0 : pairingDelegate->OnPairingComplete(error, rendezvousParameters, pasePayload);
940 : }
941 0 : return;
942 : }
943 :
944 : // It may happen that there is a stale DNS entry. If so, ReconfirmRecord will flush
945 : // the record from the daemon cache once it determines that it is invalid.
946 : // It may not help for this particular resolve, but may help subsequent resolves.
947 4 : if (CHIP_ERROR_TIMEOUT == error && mCurrentPASEParameters.HasValue())
948 : {
949 1 : const auto & params = mCurrentPASEParameters.Value();
950 1 : const auto & peer = params.GetPeerAddress();
951 1 : const auto & ip = peer.GetIPAddress();
952 1 : auto err = Dnssd::Resolver::Instance().ReconfirmRecord(params.mHostName, ip, params.mInterfaceId);
953 3 : if (CHIP_NO_ERROR != err && CHIP_ERROR_NOT_IMPLEMENTED != err)
954 : {
955 0 : ChipLogError(Controller, "Error when verifying the validity of an address: %" CHIP_ERROR_FORMAT, err.Format());
956 : }
957 : }
958 2 : mCurrentPASEParameters.ClearValue();
959 :
960 : // We failed to establish PASE. Try the next thing we have discovered, if
961 : // any.
962 2 : if (TryNextRendezvousParameters())
963 : {
964 : // Keep waiting until that finishes. Don't call OnPairingComplete yet.
965 2 : mLastPASEError = error;
966 2 : return;
967 : }
968 :
969 : MATTER_LOG_METRIC_END(kMetricSetupCodePairerPairDevice, error);
970 0 : if (pairingDelegate != nullptr)
971 : {
972 0 : pairingDelegate->OnPairingComplete(error, rendezvousParameters, pasePayload);
973 : }
974 2 : }
975 :
976 0 : void SetUpCodePairer::OnPairingDeleted(CHIP_ERROR error)
977 : {
978 0 : if (mPairingDelegate)
979 : {
980 0 : mPairingDelegate->OnPairingDeleted(error);
981 : }
982 0 : }
983 :
984 0 : void SetUpCodePairer::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error)
985 : {
986 : // Not really expecting this, but handle it anyway.
987 0 : if (mPairingDelegate)
988 : {
989 0 : mPairingDelegate->OnCommissioningComplete(deviceId, error);
990 : }
991 0 : }
992 :
993 2 : void SetUpCodePairer::OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, void * context)
994 : {
995 2 : ChipLogError(Controller, "Discovery timed out");
996 2 : auto * pairer = static_cast<SetUpCodePairer *>(context);
997 :
998 : // If a PASE attempt is in progress, do not stop physical-proximity
999 : // transports (BLE, Wi-Fi PAF, NFC) — they have their own completion/timeout
1000 : // mechanisms. DNS-SD, however, runs indefinitely, so stop it now to
1001 : // prevent DiscoveryInProgress() from being true forever.
1002 2 : if (pairer->mWaitingForPASE)
1003 : {
1004 1 : LogErrorOnFailure(pairer->StopDiscoveryOverDNSSD());
1005 1 : return;
1006 : }
1007 :
1008 : // No PASE in progress — stop all remaining discovery and fail if nothing is left to try.
1009 1 : pairer->StopAllDiscoveryAttempts();
1010 1 : pairer->StopPairingIfTransportsExhausted(CHIP_ERROR_TIMEOUT);
1011 : }
1012 :
1013 0 : bool SetUpCodePairer::ShouldDiscoverUsing(RendezvousInformationFlag commissioningChannel) const
1014 : {
1015 0 : for (auto & payload : mSetupPayloads)
1016 : {
1017 0 : auto & rendezvousInformation = payload.rendezvousInformation;
1018 0 : if (!rendezvousInformation.HasValue())
1019 : {
1020 : // No idea which commissioning channels this device supports, so we
1021 : // should be trying using all of them.
1022 0 : return true;
1023 : }
1024 :
1025 0 : if (rendezvousInformation.Value().Has(commissioningChannel))
1026 : {
1027 0 : return true;
1028 : }
1029 : }
1030 :
1031 : // None of the payloads claimed support for this commissioning channel.
1032 0 : return false;
1033 : }
1034 :
1035 15 : SetUpCodePairerParameters::SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data,
1036 15 : std::optional<uint16_t> longDiscriminator, size_t index) :
1037 15 : mLongDiscriminator(longDiscriminator)
1038 : {
1039 15 : mInterfaceId = data.interfaceId;
1040 15 : Platform::CopyString(mHostName, data.hostName);
1041 :
1042 15 : auto & ip = data.ipAddress[index];
1043 15 : SetPeerAddress(Transport::PeerAddress::UDP(ip, data.port, ip.IsIPv6LinkLocal() ? data.interfaceId : Inet::InterfaceId::Null()));
1044 :
1045 15 : if (data.mrpRetryIntervalIdle.has_value())
1046 : {
1047 2 : SetIdleInterval(*data.mrpRetryIntervalIdle);
1048 : }
1049 :
1050 15 : if (data.mrpRetryIntervalActive.has_value())
1051 : {
1052 0 : SetActiveInterval(*data.mrpRetryIntervalActive);
1053 : }
1054 15 : }
1055 :
1056 : #if CONFIG_NETWORK_LAYER_BLE
1057 0 : SetUpCodePairerParameters::SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, std::optional<uint16_t> longDiscriminator,
1058 0 : bool connected) :
1059 0 : mLongDiscriminator(longDiscriminator)
1060 : {
1061 0 : Transport::PeerAddress peerAddress = Transport::PeerAddress::BLE();
1062 0 : SetPeerAddress(peerAddress);
1063 0 : if (connected)
1064 : {
1065 0 : SetConnectionObject(connObj);
1066 : }
1067 : else
1068 : {
1069 0 : SetDiscoveredObject(connObj);
1070 : }
1071 0 : }
1072 : #endif // CONFIG_NETWORK_LAYER_BLE
1073 :
1074 : } // namespace Controller
1075 : } // namespace chip
|