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 : * This file defines objects for a User-Directed Commissioning unsolicited
22 : * initiator (client) and recipient (server).
23 : *
24 : */
25 :
26 : #pragma once
27 :
28 : #include "UDCClients.h"
29 : #include <lib/core/CHIPCore.h>
30 : #include <lib/dnssd/Resolver.h>
31 : #include <lib/support/CodeUtils.h>
32 : #include <lib/support/DLLUtil.h>
33 : #include <lib/support/logging/CHIPLogging.h>
34 : #include <messaging/ExchangeContext.h>
35 : #include <messaging/ExchangeMgr.h>
36 : #include <messaging/Flags.h>
37 : #include <protocols/Protocols.h>
38 : #include <transport/TransportMgr.h>
39 :
40 : namespace chip {
41 : namespace Protocols {
42 : namespace UserDirectedCommissioning {
43 :
44 : inline constexpr char kProtocolName[] = "UserDirectedCommissioning";
45 :
46 : // Cache contains 16 clients. This may need to be tweaked.
47 : inline constexpr uint8_t kMaxUDCClients = 16;
48 :
49 : /**
50 : * User Directed Commissioning Protocol Message Types
51 : */
52 : enum class MsgType : uint8_t
53 : {
54 : IdentificationDeclaration = 0x00,
55 : };
56 :
57 : /**
58 : * Represents the Identification Delaration message
59 : * sent by a UDC client to a UDC server.
60 : *
61 : * ### IdentificationDeclaration format
62 : *
63 : * <pre>
64 : * ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
65 : * ┃ instance name '\n' ┃ ignore ┃ additional data TLV ┃
66 : * ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━┛
67 : * │← · · kInstanceNameMaxLength + 1 · · →│← TLV DataLength() →│
68 : *
69 : * Commissioning kInstanceNameMaxLength is 16
70 : * </pre>
71 : *
72 : */
73 : class DLL_EXPORT IdentificationDeclaration
74 : {
75 : public:
76 : constexpr static size_t kUdcTLVDataMaxBytes = 500;
77 :
78 2 : const char * GetInstanceName() const { return mInstanceName; }
79 1 : void SetInstanceName(const char * instanceName) { Platform::CopyString(mInstanceName, instanceName); }
80 :
81 2 : bool HasDiscoveryInfo() { return mVendorId != 0 && mProductId != 0 && mCdPort != 0 && strlen(mDeviceName) > 0; }
82 :
83 2 : const char * GetDeviceName() const { return mDeviceName; }
84 1 : void SetDeviceName(const char * deviceName) { Platform::CopyString(mDeviceName, deviceName); }
85 :
86 3 : uint16_t GetCdPort() const { return mCdPort; }
87 1 : void SetCdPort(uint16_t port) { mCdPort = port; }
88 :
89 3 : uint16_t GetVendorId() const { return mVendorId; }
90 1 : void SetVendorId(uint16_t vendorId) { mVendorId = vendorId; }
91 :
92 3 : uint16_t GetProductId() const { return mProductId; }
93 1 : void SetProductId(uint16_t productId) { mProductId = productId; }
94 :
95 2 : const uint8_t * GetRotatingId() const { return mRotatingId; }
96 2 : size_t GetRotatingIdLength() const { return mRotatingIdLen; }
97 1 : void SetRotatingId(const uint8_t * rotatingId, size_t rotatingIdLen)
98 : {
99 1 : size_t maxSize = MATTER_ARRAY_SIZE(mRotatingId);
100 1 : mRotatingIdLen = (maxSize < rotatingIdLen) ? maxSize : rotatingIdLen;
101 1 : memcpy(mRotatingId, rotatingId, mRotatingIdLen);
102 1 : }
103 :
104 6 : bool GetTargetAppInfo(uint8_t index, TargetAppInfo & info) const
105 : {
106 6 : if (index < mNumTargetAppInfos)
107 : {
108 6 : info.vendorId = mTargetAppInfos[index].vendorId;
109 6 : info.productId = mTargetAppInfos[index].productId;
110 6 : return true;
111 : }
112 0 : return false;
113 : }
114 3 : uint8_t GetNumTargetAppInfos() const { return mNumTargetAppInfos; }
115 :
116 3 : bool AddTargetAppInfo(TargetAppInfo vid)
117 : {
118 3 : if (mNumTargetAppInfos >= sizeof(mTargetAppInfos))
119 : {
120 : // already at max
121 0 : return false;
122 : }
123 3 : mTargetAppInfos[mNumTargetAppInfos].vendorId = vid.vendorId;
124 3 : mTargetAppInfos[mNumTargetAppInfos].productId = vid.productId;
125 3 : mNumTargetAppInfos++;
126 3 : return true;
127 : }
128 :
129 2 : const char * GetPairingInst() const { return mPairingInst; }
130 1 : void SetPairingInst(const char * pairingInst) { Platform::CopyString(mPairingInst, pairingInst); }
131 :
132 2 : uint16_t GetPairingHint() const { return mPairingHint; }
133 1 : void SetPairingHint(uint16_t pairingHint) { mPairingHint = pairingHint; }
134 :
135 1 : void SetNoPasscode(bool newValue) { mNoPasscode = newValue; };
136 3 : bool GetNoPasscode() const { return mNoPasscode; };
137 :
138 1 : void SetCdUponPasscodeDialog(bool newValue) { mCdUponPasscodeDialog = newValue; };
139 3 : bool GetCdUponPasscodeDialog() const { return mCdUponPasscodeDialog; };
140 :
141 1 : void SetCommissionerPasscode(bool newValue) { mCommissionerPasscode = newValue; };
142 3 : bool GetCommissionerPasscode() const { return mCommissionerPasscode; };
143 :
144 1 : void SetCommissionerPasscodeReady(bool newValue) { mCommissionerPasscodeReady = newValue; };
145 3 : bool GetCommissionerPasscodeReady() const { return mCommissionerPasscodeReady; };
146 :
147 : void SetCancelPasscode(bool newValue) { mCancelPasscode = newValue; };
148 0 : bool GetCancelPasscode() const { return mCancelPasscode; };
149 :
150 1 : void SetPasscodeLength(uint8_t newValue) { mPasscodeLength = newValue; };
151 4 : uint8_t GetPasscodeLength() const { return mPasscodeLength; };
152 :
153 : /**
154 : * Writes the IdentificationDeclaration message to the given buffer.
155 : *
156 : * @return Total number of bytes written or 0 if an error occurred.
157 : */
158 : uint32_t WritePayload(uint8_t * payloadBuffer, size_t payloadBufferSize);
159 :
160 : /**
161 : * Reads the IdentificationDeclaration message from the given buffer.
162 : */
163 : CHIP_ERROR ReadPayload(uint8_t * payloadBuffer, size_t payloadBufferSize);
164 :
165 : /**
166 : * Assigns fields from this Identification Declaration to the given UDC client state.
167 : */
168 0 : void UpdateClientState(UDCClientState * client)
169 : {
170 0 : client->SetDeviceName(GetDeviceName());
171 0 : client->SetVendorId(GetVendorId());
172 0 : client->SetProductId(GetProductId());
173 0 : client->SetRotatingId(GetRotatingId(), GetRotatingIdLength());
174 0 : client->SetPairingInst(GetPairingInst());
175 0 : client->SetPairingHint(GetPairingHint());
176 0 : for (uint8_t i = 0; i < GetNumTargetAppInfos(); i++)
177 : {
178 0 : TargetAppInfo info;
179 0 : if (GetTargetAppInfo(i, info))
180 : {
181 0 : client->AddTargetAppInfo(info);
182 : }
183 : }
184 :
185 0 : client->SetCdPort(GetCdPort());
186 0 : client->SetNoPasscode(GetNoPasscode());
187 0 : client->SetCdUponPasscodeDialog(GetCdUponPasscodeDialog());
188 0 : client->SetCommissionerPasscode(GetCommissionerPasscode());
189 0 : client->SetCommissionerPasscodeReady(GetCommissionerPasscodeReady());
190 0 : client->SetCancelPasscode(GetCancelPasscode());
191 0 : client->SetPasscodeLength(GetPasscodeLength());
192 0 : }
193 :
194 0 : void DebugLog()
195 : {
196 : #if CHIP_DETAIL_LOGGING
197 0 : ChipLogDetail(AppServer, "---- Identification Declaration Start ----");
198 :
199 0 : ChipLogDetail(AppServer, "\tinstance: %s", mInstanceName);
200 0 : if (strlen(mDeviceName) != 0)
201 : {
202 0 : ChipLogDetail(AppServer, "\tdevice Name: %s", mDeviceName);
203 : }
204 0 : if (mVendorId != 0)
205 : {
206 0 : ChipLogDetail(AppServer, "\tvendor id: %d", mVendorId);
207 : }
208 0 : if (mProductId != 0)
209 : {
210 0 : ChipLogDetail(AppServer, "\tproduct id: %d", mProductId);
211 : }
212 0 : if (mCdPort != 0)
213 : {
214 0 : ChipLogDetail(AppServer, "\tcd port: %d", mCdPort);
215 : }
216 0 : if (mRotatingIdLen > 0)
217 : {
218 0 : char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
219 0 : const char * rotatingIdStringPtr = rotatingIdString;
220 0 : if (Encoding::BytesToUppercaseHexString(mRotatingId, mRotatingIdLen, rotatingIdString, sizeof(rotatingIdString)) !=
221 0 : CHIP_NO_ERROR)
222 : {
223 0 : rotatingIdStringPtr = "<invalid id>";
224 : }
225 0 : ChipLogDetail(AppServer, "\trotating id: %s", rotatingIdStringPtr);
226 : }
227 0 : for (uint8_t i = 0; i < mNumTargetAppInfos; i++)
228 : {
229 0 : ChipLogDetail(AppServer, "\tapp vendor id / product id [%d]: %u/%u", i, mTargetAppInfos[i].vendorId,
230 : mTargetAppInfos[i].productId);
231 : }
232 0 : if (strlen(mPairingInst) != 0)
233 : {
234 0 : ChipLogDetail(AppServer, "\tpairing instruction: %s", mPairingInst);
235 : }
236 0 : if (mPairingHint != 0)
237 : {
238 0 : ChipLogDetail(AppServer, "\tpairing hint: %d", mPairingHint);
239 : }
240 0 : if (mNoPasscode)
241 : {
242 0 : ChipLogDetail(AppServer, "\tno passcode: true");
243 : }
244 0 : if (mCdUponPasscodeDialog)
245 : {
246 0 : ChipLogDetail(AppServer, "\tcd upon passcode dialog: true");
247 : }
248 0 : if (mCommissionerPasscode)
249 : {
250 0 : ChipLogDetail(AppServer, "\tcommissioner passcode: true");
251 : }
252 0 : if (mCommissionerPasscodeReady)
253 : {
254 0 : ChipLogDetail(AppServer, "\tcommissioner passcode ready: true");
255 : }
256 0 : if (mCancelPasscode)
257 : {
258 0 : ChipLogDetail(AppServer, "\tcancel passcode: true");
259 : }
260 0 : if (mPasscodeLength != 0)
261 : {
262 0 : ChipLogDetail(AppServer, "\tpasscode length: %d", static_cast<uint16_t>(mPasscodeLength));
263 : }
264 0 : ChipLogDetail(AppServer, "---- Identification Declaration End ----");
265 : #endif
266 0 : }
267 :
268 : private:
269 : // TODO: update spec per the latest tags
270 : enum IdentificationDeclarationTLVTag
271 : {
272 : kVendorIdTag = 1,
273 : kProductIdTag,
274 : kDeviceNameTag,
275 : kDeviceTypeTag,
276 : kPairingInstTag,
277 : kPairingHintTag,
278 : kRotatingIdTag,
279 : kCdPortTag,
280 : kTargetAppListTag,
281 : kTargetAppTag,
282 : kAppVendorIdTag,
283 : kAppProductIdTag,
284 : kNoPasscodeTag,
285 : kCdUponPasscodeDialogTag,
286 : kCommissionerPasscodeTag,
287 : kCommissionerPasscodeReadyTag,
288 : kCancelPasscodeTag,
289 : kPasscodeLengthTag,
290 :
291 : kMaxNum = UINT8_MAX
292 : };
293 :
294 : char mInstanceName[Dnssd::Commission::kInstanceNameMaxLength + 1] = {};
295 : char mDeviceName[Dnssd::kMaxDeviceNameLen + 1] = {};
296 : uint16_t mCdPort = 0;
297 :
298 : uint16_t mVendorId = 0;
299 : uint16_t mProductId = 0;
300 : uint8_t mRotatingId[chip::Dnssd::kMaxRotatingIdLen];
301 : size_t mRotatingIdLen = 0;
302 :
303 : constexpr static size_t kMaxTargetAppInfos = 10;
304 : uint8_t mNumTargetAppInfos = 0; // number of vendor Ids
305 : TargetAppInfo mTargetAppInfos[kMaxTargetAppInfos];
306 :
307 : char mPairingInst[chip::Dnssd::kMaxPairingInstructionLen + 1] = {};
308 : uint16_t mPairingHint = 0;
309 :
310 : bool mNoPasscode = false;
311 : bool mCdUponPasscodeDialog = false;
312 : bool mCommissionerPasscode = false;
313 : bool mCommissionerPasscodeReady = false;
314 : bool mCancelPasscode = false;
315 : uint8_t mPasscodeLength = 0;
316 : };
317 :
318 : /**
319 : * Represents the Commissioner Delaration message
320 : * sent by a UDC server to a UDC client.
321 : */
322 : class DLL_EXPORT CommissionerDeclaration
323 : {
324 : public:
325 : enum class CdError : uint16_t
326 : {
327 : kNoError = 0,
328 : kCommissionableDiscoveryFailed = 1,
329 : kPaseConnectionFailed = 2,
330 : kPaseAuthFailed = 3,
331 : kDacValidationFailed = 4,
332 : kAlreadyOnFabric = 5,
333 : kOperationalDiscoveryFailed = 6,
334 : kCaseConnectionFailed = 7,
335 : kCaseAuthFailed = 8,
336 : kConfigurationFailed = 9,
337 : kBindingConfigurationFailed = 10,
338 : kCommissionerPasscodeNotSupported = 11,
339 : kInvalidIdentificationDeclarationParams = 12,
340 : kAppInstallConsentPending = 13,
341 : kAppInstalling = 14,
342 : kAppInstallFailed = 15,
343 : kAppInstalledRetryNeeded = 16,
344 : kCommissionerPasscodeDisabled = 17,
345 : kUnexpectedCommissionerPasscodeReady = 18
346 : };
347 :
348 : constexpr static size_t kUdcTLVDataMaxBytes = 500;
349 :
350 1 : void SetErrorCode(CdError newValue) { mErrorCode = newValue; };
351 3 : CdError GetErrorCode() const { return mErrorCode; };
352 :
353 1 : void SetNeedsPasscode(bool newValue) { mNeedsPasscode = newValue; };
354 3 : bool GetNeedsPasscode() const { return mNeedsPasscode; };
355 :
356 1 : void SetNoAppsFound(bool newValue) { mNoAppsFound = newValue; };
357 3 : bool GetNoAppsFound() const { return mNoAppsFound; };
358 :
359 1 : void SetPasscodeDialogDisplayed(bool newValue) { mPasscodeDialogDisplayed = newValue; };
360 3 : bool GetPasscodeDialogDisplayed() const { return mPasscodeDialogDisplayed; };
361 :
362 1 : void SetCommissionerPasscode(bool newValue) { mCommissionerPasscode = newValue; };
363 3 : bool GetCommissionerPasscode() const { return mCommissionerPasscode; };
364 :
365 1 : void SetQRCodeDisplayed(bool newValue) { mQRCodeDisplayed = newValue; };
366 3 : bool GetQRCodeDisplayed() const { return mQRCodeDisplayed; };
367 :
368 : void SetCancelPasscode(bool newValue) { mCancelPasscode = newValue; };
369 : bool GetCancelPasscode() const { return mCancelPasscode; };
370 :
371 1 : void SetPasscodeLength(uint8_t newValue) { mPasscodeLength = newValue; };
372 4 : uint8_t GetPasscodeLength() const { return mPasscodeLength; };
373 :
374 : /**
375 : * Writes the CommissionerDeclaration message to the given buffer.
376 : *
377 : * @return Total number of bytes written or 0 if an error occurred.
378 : */
379 : uint32_t WritePayload(uint8_t * payloadBuffer, size_t payloadBufferSize);
380 :
381 : /**
382 : * Reads the CommissionerDeclaration message from the given buffer.
383 : */
384 : CHIP_ERROR ReadPayload(uint8_t * payloadBuffer, size_t payloadBufferSize);
385 :
386 0 : void DebugLog()
387 : {
388 0 : ChipLogDetail(AppServer, "---- Commissioner Declaration Start ----");
389 :
390 0 : if (mErrorCode != CdError::kNoError)
391 : {
392 0 : ChipLogDetail(AppServer, "\terror code: %d", static_cast<uint16_t>(mErrorCode));
393 : }
394 :
395 0 : if (mNeedsPasscode)
396 : {
397 0 : ChipLogDetail(AppServer, "\tneeds passcode: true");
398 : }
399 0 : if (mNoAppsFound)
400 : {
401 0 : ChipLogDetail(AppServer, "\tno apps found: true");
402 : }
403 0 : if (mPasscodeDialogDisplayed)
404 : {
405 0 : ChipLogDetail(AppServer, "\tpasscode dialog displayed: true");
406 : }
407 0 : if (mCommissionerPasscode)
408 : {
409 0 : ChipLogDetail(AppServer, "\tcommissioner passcode: true");
410 : }
411 0 : if (mQRCodeDisplayed)
412 : {
413 0 : ChipLogDetail(AppServer, "\tQR code displayed: true");
414 : }
415 0 : if (mCancelPasscode)
416 : {
417 0 : ChipLogDetail(AppServer, "\tPasscode cancelled: true");
418 : }
419 0 : if (mPasscodeLength != 0)
420 : {
421 0 : ChipLogDetail(AppServer, "\tpasscode length: %d", static_cast<uint16_t>(mPasscodeLength));
422 : }
423 0 : ChipLogDetail(AppServer, "---- Commissioner Declaration End ----");
424 0 : }
425 :
426 : private:
427 : // TODO: update spec per the latest tags
428 : enum CommissionerDeclarationTLVTag
429 : {
430 : kErrorCodeTag = 1,
431 : kNeedsPasscodeTag,
432 : kNoAppsFoundTag,
433 : kPasscodeDialogDisplayedTag,
434 : kCommissionerPasscodeTag,
435 : kQRCodeDisplayedTag,
436 : kCancelPasscodeTag,
437 : kPasscodeLengthTag,
438 :
439 : kMaxNum = UINT8_MAX
440 : };
441 :
442 : CdError mErrorCode = CdError::kNoError;
443 : bool mNeedsPasscode = false;
444 : bool mNoAppsFound = false;
445 : bool mPasscodeDialogDisplayed = false;
446 : bool mCommissionerPasscode = false;
447 : bool mQRCodeDisplayed = false;
448 : bool mCancelPasscode = false;
449 : uint8_t mPasscodeLength = 0;
450 : };
451 :
452 : class DLL_EXPORT InstanceNameResolver
453 : {
454 : public:
455 : /**
456 : * @brief
457 : * Called when a UDC message is received specifying the given instanceName
458 : * This method indicates that UDC Server needs the Commissionable Node corresponding to
459 : * the given instance name to be found. UDC Server will wait for OnCommissionableNodeFound.
460 : *
461 : * @param instanceName DNS-SD instance name for the client requesting commissioning
462 : *
463 : */
464 : virtual void FindCommissionableNode(char * instanceName) = 0;
465 :
466 1 : virtual ~InstanceNameResolver() = default;
467 : };
468 :
469 : class DLL_EXPORT UserConfirmationProvider
470 : {
471 : public:
472 : /**
473 : * @brief
474 : * Called when an Identification Declaration UDC message has been received
475 : * and corresponding nodeData has been found.
476 : * It is expected that the implementer will prompt the user to confirm their intention to
477 : * commission the given node, and obtain the setup code to allow commissioning to proceed,
478 : * and then invoke commissioning on the given Node (using CHIP Device Controller, for example)
479 : *
480 : * @param[in] state The state for the UDC Client.
481 : *
482 : */
483 : virtual void OnUserDirectedCommissioningRequest(UDCClientState state) = 0;
484 :
485 : /**
486 : * @brief
487 : * Called when an Identification Declaration UDC message has been received
488 : * with the cancel flag set.
489 : * It is expected that the implementer will tear down any dialog prompts for the
490 : * commissionee instance (identified in the UDC client state argument).
491 : *
492 : * @param[in] state The state for the UDC Client.
493 : *
494 : */
495 : virtual void OnCancel(UDCClientState state) = 0;
496 :
497 : /**
498 : * @brief
499 : * Called when an Identification Declaration UDC message has been received
500 : * with the commissioner passcode ready flag set.
501 : * It is expected that the implementer will invoke commissioning on the
502 : * commissionee instance (identified in the UDC client state argument).
503 : *
504 : * @param[in] state The state for the UDC Client.
505 : *
506 : */
507 : virtual void OnCommissionerPasscodeReady(UDCClientState state) = 0;
508 :
509 1 : virtual ~UserConfirmationProvider() = default;
510 : };
511 :
512 : class DLL_EXPORT CommissionerDeclarationHandler
513 : {
514 : public:
515 : /**
516 : * @brief
517 : * Called when a Commissioner Declaration UDC message has been received.
518 : * It is expected that the implementer will de-dup messages received from the
519 : * same source within a short (1 second) time window.
520 : *
521 : * @param[in] source The source of the Commissioner Declaration Message.
522 : * @param[in] cd The Commissioner Declaration Message.
523 : *
524 : */
525 : virtual void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, CommissionerDeclaration cd) = 0;
526 :
527 : virtual ~CommissionerDeclarationHandler() = default;
528 : };
529 :
530 : /**
531 : * TODO:
532 : * - add processing of Commissioner Declaration flags
533 : */
534 : class DLL_EXPORT UserDirectedCommissioningClient : public TransportMgrDelegate
535 : {
536 : public:
537 : /**
538 : * Send a User Directed Commissioning message to a CHIP node.
539 : *
540 : * @param transportMgr A transport to use for sending the message.
541 : * @param idMessage The Identification Declaration message.
542 : * @param peerAddress Address of destination.
543 : *
544 : * @return CHIP_ERROR_NO_MEMORY if allocation fails.
545 : * Other CHIP_ERROR codes as returned by the lower layers.
546 : *
547 : */
548 :
549 : CHIP_ERROR SendUDCMessage(TransportMgrBase * transportMgr, IdentificationDeclaration idMessage,
550 : chip::Transport::PeerAddress peerAddress);
551 :
552 : /**
553 : * Encode a User Directed Commissioning message.
554 : *
555 : * @param payload A PacketBufferHandle with the payload.
556 : *
557 : * @return CHIP_ERROR_NO_MEMORY if allocation fails.
558 : * Other CHIP_ERROR codes as returned by the lower layers.
559 : *
560 : */
561 :
562 : CHIP_ERROR EncodeUDCMessage(const System::PacketBufferHandle & payload);
563 :
564 : /**
565 : * Set the listener to be called when a Commissioner Declaration UDC request is received.
566 : *
567 : * @param[in] commissionerDeclarationHandler The callback function to handle the message.
568 : *
569 : */
570 : void SetCommissionerDeclarationHandler(CommissionerDeclarationHandler * commissionerDeclarationHandler)
571 : {
572 : ChipLogProgress(AppServer, "UserDirectedCommissioningClient::SetCommissionerDeclarationHandler()");
573 : mCommissionerDeclarationHandler = commissionerDeclarationHandler;
574 : }
575 :
576 : private:
577 : void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf,
578 : Transport::MessageTransportContext * ctxt = nullptr) override;
579 :
580 : CommissionerDeclarationHandler * mCommissionerDeclarationHandler = nullptr;
581 : };
582 :
583 : /**
584 : * TODO:
585 : * - add processing of Identification Declaration flags
586 : */
587 : class DLL_EXPORT UserDirectedCommissioningServer : public TransportMgrDelegate
588 : {
589 : public:
590 : /**
591 : * Set the listener to be called when a UDC request is received
592 : * and the Instance Name provided needs to be resolved.
593 : *
594 : * The resolver should call OnCommissionableNodeFound when the instance is found
595 : *
596 : * @param[in] instanceNameResolver The callback function to receive UDC request instance name.
597 : *
598 : */
599 : void SetInstanceNameResolver(InstanceNameResolver * instanceNameResolver) { mInstanceNameResolver = instanceNameResolver; }
600 :
601 : /**
602 : * Set the listener to be called when a UDC request is received
603 : * and the Instance Name has been resolved.
604 : *
605 : * The provider should prompt the user to allow commissioning of the node and provide the setup code.
606 : *
607 : * @param[in] userConfirmationProvider The callback function to obtain user confirmation.
608 : *
609 : */
610 1 : void SetUserConfirmationProvider(UserConfirmationProvider * userConfirmationProvider)
611 : {
612 1 : mUserConfirmationProvider = userConfirmationProvider;
613 1 : }
614 :
615 : /**
616 : * Update the processing state for a UDC Client based upon instance name.
617 : *
618 : * This can be used by the UX to set the state to one of the following values:
619 : * - kUserDeclined
620 : * - kObtainingOnboardingPayload
621 : * - kCommissioningNode
622 : * - kCommissioningFailed
623 : *
624 : * @param[in] instanceName The instance name for the UDC Client.
625 : * @param[in] state The state for the UDC Client.
626 : *
627 : */
628 : void SetUDCClientProcessingState(char * instanceName, UDCClientProcessingState state);
629 :
630 : /**
631 : * Reset the processing states for all UDC Clients
632 : *
633 : */
634 : void ResetUDCClientProcessingStates() { mUdcClients.ResetUDCClientStates(); }
635 :
636 : /**
637 : * Called when a CHIP Node in commissioning mode is found.
638 : *
639 : * Lookup instanceName from nodeData in the active UDC Client states
640 : * and if current state is kDiscoveringNode then change to kPromptingUser and
641 : * call UX Prompt callback
642 : *
643 : * @param[in] nodeData DNS-SD response data.
644 : *
645 : */
646 : void OnCommissionableNodeFound(const Dnssd::DiscoveredNodeData & nodeData);
647 :
648 : /**
649 : * Get the cache of UDC Clients
650 : *
651 : */
652 6 : UDCClients<kMaxUDCClients> & GetUDCClients() { return mUdcClients; }
653 :
654 : /**
655 : * Print the cache of UDC Clients
656 : *
657 : */
658 : void PrintUDCClients();
659 :
660 : /**
661 : * Send a Commissioner Declaration message to the given peer address
662 : *
663 : * Only one message will be sent.
664 : * Clients should follow spec and send up to 5 times with 100ms sleep between each call.
665 : */
666 : CHIP_ERROR SendCDCMessage(CommissionerDeclaration cdMessage, chip::Transport::PeerAddress peerAddress);
667 :
668 : /**
669 : * Encode a User Directed Commissioning message.
670 : *
671 : * @param payload A PacketBufferHandle with the payload.
672 : *
673 : * @return CHIP_ERROR_NO_MEMORY if allocation fails.
674 : * Other CHIP_ERROR codes as returned by the lower layers.
675 : *
676 : */
677 : CHIP_ERROR EncodeUDCMessage(const System::PacketBufferHandle & payload);
678 :
679 : /**
680 : * Assign the transport manager to use for Commissioner Declaration messages
681 : */
682 : void SetTransportManager(TransportMgrBase * transportMgr) { mTransportMgr = transportMgr; }
683 :
684 : private:
685 : InstanceNameResolver * mInstanceNameResolver = nullptr;
686 : UserConfirmationProvider * mUserConfirmationProvider = nullptr;
687 :
688 : void HandleNewUDC(const Transport::PeerAddress & source, IdentificationDeclaration & id);
689 : void HandleUDCCancel(IdentificationDeclaration & id);
690 : void HandleUDCCommissionerPasscodeReady(IdentificationDeclaration & id);
691 : void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf,
692 : Transport::MessageTransportContext * ctxt = nullptr) override;
693 :
694 : UDCClients<kMaxUDCClients> mUdcClients; // < Active UDC clients
695 :
696 : TransportMgrBase * mTransportMgr = nullptr;
697 : };
698 :
699 : } // namespace UserDirectedCommissioning
700 :
701 : template <>
702 : struct MessageTypeTraits<UserDirectedCommissioning::MsgType>
703 : {
704 1 : static constexpr const Protocols::Id & ProtocolId() { return UserDirectedCommissioning::Id; }
705 :
706 0 : static auto GetTypeToNameTable()
707 : {
708 : static const std::array<MessageTypeNameLookup, 1> typeToNameTable = {
709 : {
710 : { UserDirectedCommissioning::MsgType::IdentificationDeclaration, "IdentificationDeclaration" },
711 : },
712 : };
713 :
714 0 : return &typeToNameTable;
715 : }
716 : };
717 :
718 : } // namespace Protocols
719 : } // namespace chip
|