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 0 : ChipLogDetail(AppServer, "---- Identification Declaration Start ----");
197 :
198 0 : ChipLogDetail(AppServer, "\tinstance: %s", mInstanceName);
199 0 : if (strlen(mDeviceName) != 0)
200 : {
201 0 : ChipLogDetail(AppServer, "\tdevice Name: %s", mDeviceName);
202 : }
203 0 : if (mVendorId != 0)
204 : {
205 0 : ChipLogDetail(AppServer, "\tvendor id: %d", mVendorId);
206 : }
207 0 : if (mProductId != 0)
208 : {
209 0 : ChipLogDetail(AppServer, "\tproduct id: %d", mProductId);
210 : }
211 0 : if (mCdPort != 0)
212 : {
213 0 : ChipLogDetail(AppServer, "\tcd port: %d", mCdPort);
214 : }
215 0 : if (mRotatingIdLen > 0)
216 : {
217 0 : char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
218 0 : Encoding::BytesToUppercaseHexString(mRotatingId, mRotatingIdLen, rotatingIdString, sizeof(rotatingIdString));
219 0 : ChipLogDetail(AppServer, "\trotating id: %s", rotatingIdString);
220 : }
221 0 : for (uint8_t i = 0; i < mNumTargetAppInfos; i++)
222 : {
223 0 : ChipLogDetail(AppServer, "\tapp vendor id / product id [%d]: %u/%u", i, mTargetAppInfos[i].vendorId,
224 : mTargetAppInfos[i].productId);
225 : }
226 0 : if (strlen(mPairingInst) != 0)
227 : {
228 0 : ChipLogDetail(AppServer, "\tpairing instruction: %s", mPairingInst);
229 : }
230 0 : if (mPairingHint != 0)
231 : {
232 0 : ChipLogDetail(AppServer, "\tpairing hint: %d", mPairingHint);
233 : }
234 0 : if (mNoPasscode)
235 : {
236 0 : ChipLogDetail(AppServer, "\tno passcode: true");
237 : }
238 0 : if (mCdUponPasscodeDialog)
239 : {
240 0 : ChipLogDetail(AppServer, "\tcd upon passcode dialog: true");
241 : }
242 0 : if (mCommissionerPasscode)
243 : {
244 0 : ChipLogDetail(AppServer, "\tcommissioner passcode: true");
245 : }
246 0 : if (mCommissionerPasscodeReady)
247 : {
248 0 : ChipLogDetail(AppServer, "\tcommissioner passcode ready: true");
249 : }
250 0 : if (mCancelPasscode)
251 : {
252 0 : ChipLogDetail(AppServer, "\tcancel passcode: true");
253 : }
254 0 : if (mPasscodeLength != 0)
255 : {
256 0 : ChipLogDetail(AppServer, "\tpasscode length: %d", static_cast<uint16_t>(mPasscodeLength));
257 : }
258 0 : ChipLogDetail(AppServer, "---- Identification Declaration End ----");
259 0 : }
260 :
261 : private:
262 : // TODO: update spec per the latest tags
263 : enum IdentificationDeclarationTLVTag
264 : {
265 : kVendorIdTag = 1,
266 : kProductIdTag,
267 : kDeviceNameTag,
268 : kDeviceTypeTag,
269 : kPairingInstTag,
270 : kPairingHintTag,
271 : kRotatingIdTag,
272 : kCdPortTag,
273 : kTargetAppListTag,
274 : kTargetAppTag,
275 : kAppVendorIdTag,
276 : kAppProductIdTag,
277 : kNoPasscodeTag,
278 : kCdUponPasscodeDialogTag,
279 : kCommissionerPasscodeTag,
280 : kCommissionerPasscodeReadyTag,
281 : kCancelPasscodeTag,
282 : kPasscodeLengthTag,
283 :
284 : kMaxNum = UINT8_MAX
285 : };
286 :
287 : char mInstanceName[Dnssd::Commission::kInstanceNameMaxLength + 1] = {};
288 : char mDeviceName[Dnssd::kMaxDeviceNameLen + 1] = {};
289 : uint16_t mCdPort = 0;
290 :
291 : uint16_t mVendorId = 0;
292 : uint16_t mProductId = 0;
293 : uint8_t mRotatingId[chip::Dnssd::kMaxRotatingIdLen];
294 : size_t mRotatingIdLen = 0;
295 :
296 : constexpr static size_t kMaxTargetAppInfos = 10;
297 : uint8_t mNumTargetAppInfos = 0; // number of vendor Ids
298 : TargetAppInfo mTargetAppInfos[kMaxTargetAppInfos];
299 :
300 : char mPairingInst[chip::Dnssd::kMaxPairingInstructionLen + 1] = {};
301 : uint16_t mPairingHint = 0;
302 :
303 : bool mNoPasscode = false;
304 : bool mCdUponPasscodeDialog = false;
305 : bool mCommissionerPasscode = false;
306 : bool mCommissionerPasscodeReady = false;
307 : bool mCancelPasscode = false;
308 : uint8_t mPasscodeLength = 0;
309 : };
310 :
311 : /**
312 : * Represents the Commissioner Delaration message
313 : * sent by a UDC server to a UDC client.
314 : */
315 : class DLL_EXPORT CommissionerDeclaration
316 : {
317 : public:
318 : enum class CdError : uint16_t
319 : {
320 : kNoError = 0,
321 : kCommissionableDiscoveryFailed = 1,
322 : kPaseConnectionFailed = 2,
323 : kPaseAuthFailed = 3,
324 : kDacValidationFailed = 4,
325 : kAlreadyOnFabric = 5,
326 : kOperationalDiscoveryFailed = 6,
327 : kCaseConnectionFailed = 7,
328 : kCaseAuthFailed = 8,
329 : kConfigurationFailed = 9,
330 : kBindingConfigurationFailed = 10,
331 : kCommissionerPasscodeNotSupported = 11,
332 : kInvalidIdentificationDeclarationParams = 12,
333 : kAppInstallConsentPending = 13,
334 : kAppInstalling = 14,
335 : kAppInstallFailed = 15,
336 : kAppInstalledRetryNeeded = 16,
337 : kCommissionerPasscodeDisabled = 17,
338 : kUnexpectedCommissionerPasscodeReady = 18
339 : };
340 :
341 : constexpr static size_t kUdcTLVDataMaxBytes = 500;
342 :
343 1 : void SetErrorCode(CdError newValue) { mErrorCode = newValue; };
344 3 : CdError GetErrorCode() const { return mErrorCode; };
345 :
346 1 : void SetNeedsPasscode(bool newValue) { mNeedsPasscode = newValue; };
347 3 : bool GetNeedsPasscode() const { return mNeedsPasscode; };
348 :
349 1 : void SetNoAppsFound(bool newValue) { mNoAppsFound = newValue; };
350 3 : bool GetNoAppsFound() const { return mNoAppsFound; };
351 :
352 1 : void SetPasscodeDialogDisplayed(bool newValue) { mPasscodeDialogDisplayed = newValue; };
353 3 : bool GetPasscodeDialogDisplayed() const { return mPasscodeDialogDisplayed; };
354 :
355 1 : void SetCommissionerPasscode(bool newValue) { mCommissionerPasscode = newValue; };
356 3 : bool GetCommissionerPasscode() const { return mCommissionerPasscode; };
357 :
358 1 : void SetQRCodeDisplayed(bool newValue) { mQRCodeDisplayed = newValue; };
359 3 : bool GetQRCodeDisplayed() const { return mQRCodeDisplayed; };
360 :
361 : void SetCancelPasscode(bool newValue) { mCancelPasscode = newValue; };
362 : bool GetCancelPasscode() const { return mCancelPasscode; };
363 :
364 1 : void SetPasscodeLength(uint8_t newValue) { mPasscodeLength = newValue; };
365 4 : uint8_t GetPasscodeLength() const { return mPasscodeLength; };
366 :
367 : /**
368 : * Writes the CommissionerDeclaration message to the given buffer.
369 : *
370 : * @return Total number of bytes written or 0 if an error occurred.
371 : */
372 : uint32_t WritePayload(uint8_t * payloadBuffer, size_t payloadBufferSize);
373 :
374 : /**
375 : * Reads the CommissionerDeclaration message from the given buffer.
376 : */
377 : CHIP_ERROR ReadPayload(uint8_t * payloadBuffer, size_t payloadBufferSize);
378 :
379 0 : void DebugLog()
380 : {
381 0 : ChipLogDetail(AppServer, "---- Commissioner Declaration Start ----");
382 :
383 0 : if (mErrorCode != CdError::kNoError)
384 : {
385 0 : ChipLogDetail(AppServer, "\terror code: %d", static_cast<uint16_t>(mErrorCode));
386 : }
387 :
388 0 : if (mNeedsPasscode)
389 : {
390 0 : ChipLogDetail(AppServer, "\tneeds passcode: true");
391 : }
392 0 : if (mNoAppsFound)
393 : {
394 0 : ChipLogDetail(AppServer, "\tno apps found: true");
395 : }
396 0 : if (mPasscodeDialogDisplayed)
397 : {
398 0 : ChipLogDetail(AppServer, "\tpasscode dialog displayed: true");
399 : }
400 0 : if (mCommissionerPasscode)
401 : {
402 0 : ChipLogDetail(AppServer, "\tcommissioner passcode: true");
403 : }
404 0 : if (mQRCodeDisplayed)
405 : {
406 0 : ChipLogDetail(AppServer, "\tQR code displayed: true");
407 : }
408 0 : if (mCancelPasscode)
409 : {
410 0 : ChipLogDetail(AppServer, "\tPasscode cancelled: true");
411 : }
412 0 : if (mPasscodeLength != 0)
413 : {
414 0 : ChipLogDetail(AppServer, "\tpasscode length: %d", static_cast<uint16_t>(mPasscodeLength));
415 : }
416 0 : ChipLogDetail(AppServer, "---- Commissioner Declaration End ----");
417 0 : }
418 :
419 : private:
420 : // TODO: update spec per the latest tags
421 : enum CommissionerDeclarationTLVTag
422 : {
423 : kErrorCodeTag = 1,
424 : kNeedsPasscodeTag,
425 : kNoAppsFoundTag,
426 : kPasscodeDialogDisplayedTag,
427 : kCommissionerPasscodeTag,
428 : kQRCodeDisplayedTag,
429 : kCancelPasscodeTag,
430 : kPasscodeLengthTag,
431 :
432 : kMaxNum = UINT8_MAX
433 : };
434 :
435 : CdError mErrorCode = CdError::kNoError;
436 : bool mNeedsPasscode = false;
437 : bool mNoAppsFound = false;
438 : bool mPasscodeDialogDisplayed = false;
439 : bool mCommissionerPasscode = false;
440 : bool mQRCodeDisplayed = false;
441 : bool mCancelPasscode = false;
442 : uint8_t mPasscodeLength = 0;
443 : };
444 :
445 : class DLL_EXPORT InstanceNameResolver
446 : {
447 : public:
448 : /**
449 : * @brief
450 : * Called when a UDC message is received specifying the given instanceName
451 : * This method indicates that UDC Server needs the Commissionable Node corresponding to
452 : * the given instance name to be found. UDC Server will wait for OnCommissionableNodeFound.
453 : *
454 : * @param instanceName DNS-SD instance name for the client requesting commissioning
455 : *
456 : */
457 : virtual void FindCommissionableNode(char * instanceName) = 0;
458 :
459 1 : virtual ~InstanceNameResolver() = default;
460 : };
461 :
462 : class DLL_EXPORT UserConfirmationProvider
463 : {
464 : public:
465 : /**
466 : * @brief
467 : * Called when an Identification Declaration UDC message has been received
468 : * and corresponding nodeData has been found.
469 : * It is expected that the implementer will prompt the user to confirm their intention to
470 : * commission the given node, and obtain the setup code to allow commissioning to proceed,
471 : * and then invoke commissioning on the given Node (using CHIP Device Controller, for example)
472 : *
473 : * @param[in] state The state for the UDC Client.
474 : *
475 : */
476 : virtual void OnUserDirectedCommissioningRequest(UDCClientState state) = 0;
477 :
478 : /**
479 : * @brief
480 : * Called when an Identification Declaration UDC message has been received
481 : * with the cancel flag set.
482 : * It is expected that the implementer will tear down any dialog prompts for the
483 : * commissionee instance (identified in the UDC client state argument).
484 : *
485 : * @param[in] state The state for the UDC Client.
486 : *
487 : */
488 : virtual void OnCancel(UDCClientState state) = 0;
489 :
490 : /**
491 : * @brief
492 : * Called when an Identification Declaration UDC message has been received
493 : * with the commissioner passcode ready flag set.
494 : * It is expected that the implementer will invoke commissioning on the
495 : * commissionee instance (identified in the UDC client state argument).
496 : *
497 : * @param[in] state The state for the UDC Client.
498 : *
499 : */
500 : virtual void OnCommissionerPasscodeReady(UDCClientState state) = 0;
501 :
502 1 : virtual ~UserConfirmationProvider() = default;
503 : };
504 :
505 : class DLL_EXPORT CommissionerDeclarationHandler
506 : {
507 : public:
508 : /**
509 : * @brief
510 : * Called when a Commissioner Declaration UDC message has been received.
511 : * It is expected that the implementer will de-dup messages received from the
512 : * same source within a short (1 second) time window.
513 : *
514 : * @param[in] source The source of the Commissioner Declaration Message.
515 : * @param[in] cd The Commissioner Declaration Message.
516 : *
517 : */
518 : virtual void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, CommissionerDeclaration cd) = 0;
519 :
520 : virtual ~CommissionerDeclarationHandler() = default;
521 : };
522 :
523 : /**
524 : * TODO:
525 : * - add processing of Commissioner Declaration flags
526 : */
527 : class DLL_EXPORT UserDirectedCommissioningClient : public TransportMgrDelegate
528 : {
529 : public:
530 : /**
531 : * Send a User Directed Commissioning message to a CHIP node.
532 : *
533 : * @param transportMgr A transport to use for sending the message.
534 : * @param idMessage The Identification Declaration message.
535 : * @param peerAddress Address of destination.
536 : *
537 : * @return CHIP_ERROR_NO_MEMORY if allocation fails.
538 : * Other CHIP_ERROR codes as returned by the lower layers.
539 : *
540 : */
541 :
542 : CHIP_ERROR SendUDCMessage(TransportMgrBase * transportMgr, IdentificationDeclaration idMessage,
543 : chip::Transport::PeerAddress peerAddress);
544 :
545 : /**
546 : * Encode a User Directed Commissioning message.
547 : *
548 : * @param payload A PacketBufferHandle with the payload.
549 : *
550 : * @return CHIP_ERROR_NO_MEMORY if allocation fails.
551 : * Other CHIP_ERROR codes as returned by the lower layers.
552 : *
553 : */
554 :
555 : CHIP_ERROR EncodeUDCMessage(const System::PacketBufferHandle & payload);
556 :
557 : /**
558 : * Set the listener to be called when a Commissioner Declaration UDC request is received.
559 : *
560 : * @param[in] commissionerDeclarationHandler The callback function to handle the message.
561 : *
562 : */
563 : void SetCommissionerDeclarationHandler(CommissionerDeclarationHandler * commissionerDeclarationHandler)
564 : {
565 : ChipLogProgress(AppServer, "UserDirectedCommissioningClient::SetCommissionerDeclarationHandler()");
566 : mCommissionerDeclarationHandler = commissionerDeclarationHandler;
567 : }
568 :
569 : private:
570 : void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf,
571 : Transport::MessageTransportContext * ctxt = nullptr) override;
572 :
573 : CommissionerDeclarationHandler * mCommissionerDeclarationHandler = nullptr;
574 : };
575 :
576 : /**
577 : * TODO:
578 : * - add processing of Identification Declaration flags
579 : */
580 : class DLL_EXPORT UserDirectedCommissioningServer : public TransportMgrDelegate
581 : {
582 : public:
583 : /**
584 : * Set the listener to be called when a UDC request is received
585 : * and the Instance Name provided needs to be resolved.
586 : *
587 : * The resolver should call OnCommissionableNodeFound when the instance is found
588 : *
589 : * @param[in] instanceNameResolver The callback function to receive UDC request instance name.
590 : *
591 : */
592 : void SetInstanceNameResolver(InstanceNameResolver * instanceNameResolver) { mInstanceNameResolver = instanceNameResolver; }
593 :
594 : /**
595 : * Set the listener to be called when a UDC request is received
596 : * and the Instance Name has been resolved.
597 : *
598 : * The provider should prompt the user to allow commissioning of the node and provide the setup code.
599 : *
600 : * @param[in] userConfirmationProvider The callback function to obtain user confirmation.
601 : *
602 : */
603 1 : void SetUserConfirmationProvider(UserConfirmationProvider * userConfirmationProvider)
604 : {
605 1 : mUserConfirmationProvider = userConfirmationProvider;
606 1 : }
607 :
608 : /**
609 : * Update the processing state for a UDC Client based upon instance name.
610 : *
611 : * This can be used by the UX to set the state to one of the following values:
612 : * - kUserDeclined
613 : * - kObtainingOnboardingPayload
614 : * - kCommissioningNode
615 : * - kCommissioningFailed
616 : *
617 : * @param[in] instanceName The instance name for the UDC Client.
618 : * @param[in] state The state for the UDC Client.
619 : *
620 : */
621 : void SetUDCClientProcessingState(char * instanceName, UDCClientProcessingState state);
622 :
623 : /**
624 : * Reset the processing states for all UDC Clients
625 : *
626 : */
627 : void ResetUDCClientProcessingStates() { mUdcClients.ResetUDCClientStates(); }
628 :
629 : /**
630 : * Called when a CHIP Node in commissioning mode is found.
631 : *
632 : * Lookup instanceName from nodeData in the active UDC Client states
633 : * and if current state is kDiscoveringNode then change to kPromptingUser and
634 : * call UX Prompt callback
635 : *
636 : * @param[in] nodeData DNS-SD response data.
637 : *
638 : */
639 : void OnCommissionableNodeFound(const Dnssd::DiscoveredNodeData & nodeData);
640 :
641 : /**
642 : * Get the cache of UDC Clients
643 : *
644 : */
645 6 : UDCClients<kMaxUDCClients> & GetUDCClients() { return mUdcClients; }
646 :
647 : /**
648 : * Print the cache of UDC Clients
649 : *
650 : */
651 : void PrintUDCClients();
652 :
653 : /**
654 : * Send a Commissioner Declaration message to the given peer address
655 : *
656 : * Only one message will be sent.
657 : * Clients should follow spec and send up to 5 times with 100ms sleep between each call.
658 : */
659 : CHIP_ERROR SendCDCMessage(CommissionerDeclaration cdMessage, chip::Transport::PeerAddress peerAddress);
660 :
661 : /**
662 : * Encode a User Directed Commissioning message.
663 : *
664 : * @param payload A PacketBufferHandle with the payload.
665 : *
666 : * @return CHIP_ERROR_NO_MEMORY if allocation fails.
667 : * Other CHIP_ERROR codes as returned by the lower layers.
668 : *
669 : */
670 : CHIP_ERROR EncodeUDCMessage(const System::PacketBufferHandle & payload);
671 :
672 : /**
673 : * Assign the transport manager to use for Commissioner Declaration messages
674 : */
675 : void SetTransportManager(TransportMgrBase * transportMgr) { mTransportMgr = transportMgr; }
676 :
677 : private:
678 : InstanceNameResolver * mInstanceNameResolver = nullptr;
679 : UserConfirmationProvider * mUserConfirmationProvider = nullptr;
680 :
681 : void HandleNewUDC(const Transport::PeerAddress & source, IdentificationDeclaration & id);
682 : void HandleUDCCancel(IdentificationDeclaration & id);
683 : void HandleUDCCommissionerPasscodeReady(IdentificationDeclaration & id);
684 : void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf,
685 : Transport::MessageTransportContext * ctxt = nullptr) override;
686 :
687 : UDCClients<kMaxUDCClients> mUdcClients; // < Active UDC clients
688 :
689 : TransportMgrBase * mTransportMgr = nullptr;
690 : };
691 :
692 : } // namespace UserDirectedCommissioning
693 :
694 : template <>
695 : struct MessageTypeTraits<UserDirectedCommissioning::MsgType>
696 : {
697 1 : static constexpr const Protocols::Id & ProtocolId() { return UserDirectedCommissioning::Id; }
698 :
699 0 : static auto GetTypeToNameTable()
700 : {
701 : static const std::array<MessageTypeNameLookup, 1> typeToNameTable = {
702 : {
703 : { UserDirectedCommissioning::MsgType::IdentificationDeclaration, "IdentificationDeclaration" },
704 : },
705 : };
706 :
707 0 : return &typeToNameTable;
708 : }
709 : };
710 :
711 : } // namespace Protocols
712 : } // namespace chip
|