1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for the Commissioner role.
32  */
33 
34 #ifndef COMMISSIONER_HPP_
35 #define COMMISSIONER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
40 
41 #include <openthread/commissioner.h>
42 
43 #include "coap/coap_secure.hpp"
44 #include "common/as_core_type.hpp"
45 #include "common/callback.hpp"
46 #include "common/clearable.hpp"
47 #include "common/locator.hpp"
48 #include "common/log.hpp"
49 #include "common/non_copyable.hpp"
50 #include "common/timer.hpp"
51 #include "mac/mac_types.hpp"
52 #include "meshcop/announce_begin_client.hpp"
53 #include "meshcop/dtls.hpp"
54 #include "meshcop/energy_scan_client.hpp"
55 #include "meshcop/panid_query_client.hpp"
56 #include "net/ip6_address.hpp"
57 #include "net/udp6.hpp"
58 #include "thread/key_manager.hpp"
59 #include "thread/mle.hpp"
60 #include "thread/tmf.hpp"
61 
62 namespace ot {
63 
64 namespace MeshCoP {
65 
66 class Commissioner : public InstanceLocator, private NonCopyable
67 {
68     friend class Tmf::Agent;
69     friend class Tmf::SecureAgent;
70 
71 public:
72     /**
73      * Type represents the Commissioner State.
74      *
75      */
76     enum State : uint8_t
77     {
78         kStateDisabled = OT_COMMISSIONER_STATE_DISABLED, ///< Disabled.
79         kStatePetition = OT_COMMISSIONER_STATE_PETITION, ///< Petitioning to become a Commissioner.
80         kStateActive   = OT_COMMISSIONER_STATE_ACTIVE,   ///< Active Commissioner.
81     };
82 
83     /**
84      * Type represents Joiner Event.
85      *
86      */
87     enum JoinerEvent : uint8_t
88     {
89         kJoinerEventStart     = OT_COMMISSIONER_JOINER_START,
90         kJoinerEventConnected = OT_COMMISSIONER_JOINER_CONNECTED,
91         kJoinerEventFinalize  = OT_COMMISSIONER_JOINER_FINALIZE,
92         kJoinerEventEnd       = OT_COMMISSIONER_JOINER_END,
93         kJoinerEventRemoved   = OT_COMMISSIONER_JOINER_REMOVED,
94     };
95 
96     typedef otCommissionerStateCallback  StateCallback;  ///< State change callback function pointer type.
97     typedef otCommissionerJoinerCallback JoinerCallback; ///< Joiner state change callback function pointer type.
98 
99     /**
100      * Represents a Commissioning Dataset.
101      *
102      */
103     class Dataset : public otCommissioningDataset, public Clearable<Dataset>
104     {
105     public:
106         /**
107          * Indicates whether or not the Border Router RLOC16 Locator is set in the Dataset.
108          *
109          * @returns TRUE if Border Router RLOC16 Locator is set, FALSE otherwise.
110          *
111          */
IsLocatorSet(void) const112         bool IsLocatorSet(void) const { return mIsLocatorSet; }
113 
114         /**
115          * Gets the Border Router RLOC16 Locator in the Dataset.
116          *
117          * MUST be used when Locator is set in the Dataset, otherwise its behavior is undefined.
118          *
119          * @returns The Border Router RLOC16 Locator in the Dataset.
120          *
121          */
GetLocator(void) const122         uint16_t GetLocator(void) const { return mLocator; }
123 
124         /**
125          * Sets the Border Router RLOCG16 Locator in the Dataset.
126          *
127          * @param[in] aLocator  A Locator.
128          *
129          */
SetLocator(uint16_t aLocator)130         void SetLocator(uint16_t aLocator)
131         {
132             mIsLocatorSet = true;
133             mLocator      = aLocator;
134         }
135 
136         /**
137          * Indicates whether or not the Session ID is set in the Dataset.
138          *
139          * @returns TRUE if Session ID is set, FALSE otherwise.
140          *
141          */
IsSessionIdSet(void) const142         bool IsSessionIdSet(void) const { return mIsSessionIdSet; }
143 
144         /**
145          * Gets the Session ID in the Dataset.
146          *
147          * MUST be used when Session ID is set in the Dataset, otherwise its behavior is undefined.
148          *
149          * @returns The Session ID in the Dataset.
150          *
151          */
GetSessionId(void) const152         uint16_t GetSessionId(void) const { return mSessionId; }
153 
154         /**
155          * Sets the Session ID in the Dataset.
156          *
157          * @param[in] aSessionId  The Session ID.
158          *
159          */
SetSessionId(uint16_t aSessionId)160         void SetSessionId(uint16_t aSessionId)
161         {
162             mIsSessionIdSet = true;
163             mSessionId      = aSessionId;
164         }
165 
166         /**
167          * Indicates whether or not the Steering Data is set in the Dataset.
168          *
169          * @returns TRUE if Steering Data is set, FALSE otherwise.
170          *
171          */
IsSteeringDataSet(void) const172         bool IsSteeringDataSet(void) const { return mIsSteeringDataSet; }
173 
174         /**
175          * Gets the Steering Data in the Dataset.
176          *
177          * MUST be used when Steering Data is set in the Dataset, otherwise its behavior is undefined.
178          *
179          * @returns The Steering Data in the Dataset.
180          *
181          */
GetSteeringData(void) const182         const SteeringData &GetSteeringData(void) const { return AsCoreType(&mSteeringData); }
183 
184         /**
185          * Returns a reference to the Steering Data in the Dataset to be updated by caller.
186          *
187          * @returns A reference to the Steering Data in the Dataset.
188          *
189          */
UpdateSteeringData(void)190         SteeringData &UpdateSteeringData(void)
191         {
192             mIsSteeringDataSet = true;
193             return AsCoreType(&mSteeringData);
194         }
195 
196         /**
197          * Indicates whether or not the Joiner UDP port is set in the Dataset.
198          *
199          * @returns TRUE if Joiner UDP port is set, FALSE otherwise.
200          *
201          */
IsJoinerUdpPortSet(void) const202         bool IsJoinerUdpPortSet(void) const { return mIsJoinerUdpPortSet; }
203 
204         /**
205          * Gets the Joiner UDP port in the Dataset.
206          *
207          * MUST be used when Joiner UDP port is set in the Dataset, otherwise its behavior is undefined.
208          *
209          * @returns The Joiner UDP port in the Dataset.
210          *
211          */
GetJoinerUdpPort(void) const212         uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
213 
214         /**
215          * Sets the Joiner UDP Port in the Dataset.
216          *
217          * @param[in] aJoinerUdpPort  The Joiner UDP Port.
218          *
219          */
SetJoinerUdpPort(uint16_t aJoinerUdpPort)220         void SetJoinerUdpPort(uint16_t aJoinerUdpPort)
221         {
222             mIsJoinerUdpPortSet = true;
223             mJoinerUdpPort      = aJoinerUdpPort;
224         }
225     };
226 
227     /**
228      * Initializes the Commissioner object.
229      *
230      * @param[in]  aInstance     A reference to the OpenThread instance.
231      *
232      */
233     explicit Commissioner(Instance &aInstance);
234 
235     /**
236      * Starts the Commissioner service.
237      *
238      * @param[in]  aStateCallback    A pointer to a function that is called when the commissioner state changes.
239      * @param[in]  aJoinerCallback   A pointer to a function that is called when a joiner event occurs.
240      * @param[in]  aCallbackContext  A pointer to application-specific context.
241      *
242      * @retval kErrorNone           Successfully started the Commissioner service.
243      * @retval kErrorAlready        Commissioner is already started.
244      * @retval kErrorInvalidState   Device is not currently attached to a network.
245      *
246      */
247     Error Start(StateCallback aStateCallback, JoinerCallback aJoinerCallback, void *aCallbackContext);
248 
249     /**
250      * Stops the Commissioner service.
251      *
252      * @retval kErrorNone     Successfully stopped the Commissioner service.
253      * @retval kErrorAlready  Commissioner is already stopped.
254      *
255      */
Stop(void)256     Error Stop(void) { return Stop(kSendKeepAliveToResign); }
257 
258     /**
259      * Returns the Commissioner Id.
260      *
261      * @returns The Commissioner Id.
262      *
263      */
GetId(void) const264     const char *GetId(void) const { return mCommissionerId; }
265 
266     /**
267      * Sets the Commissioner Id.
268      *
269      * @param[in]  aId   A pointer to a string character array. Must be null terminated.
270      *
271      * @retval kErrorNone           Successfully set the Commissioner Id.
272      * @retval kErrorInvalidArgs    Given name is too long.
273      * @retval kErrorInvalidState   The commissioner is active and id cannot be changed.
274      *
275      */
276     Error SetId(const char *aId);
277 
278     /**
279      * Clears all Joiner entries.
280      *
281      */
282     void ClearJoiners(void);
283 
284     /**
285      * Adds a Joiner entry accepting any Joiner.
286      *
287      * @param[in]  aPskd         A pointer to the PSKd.
288      * @param[in]  aTimeout      A time after which a Joiner is automatically removed, in seconds.
289      *
290      * @retval kErrorNone          Successfully added the Joiner.
291      * @retval kErrorNoBufs        No buffers available to add the Joiner.
292      * @retval kErrorInvalidState  Commissioner service is not started.
293      *
294      */
AddJoinerAny(const char * aPskd,uint32_t aTimeout)295     Error AddJoinerAny(const char *aPskd, uint32_t aTimeout) { return AddJoiner(nullptr, nullptr, aPskd, aTimeout); }
296 
297     /**
298      * Adds a Joiner entry.
299      *
300      * @param[in]  aEui64        The Joiner's IEEE EUI-64.
301      * @param[in]  aPskd         A pointer to the PSKd.
302      * @param[in]  aTimeout      A time after which a Joiner is automatically removed, in seconds.
303      *
304      * @retval kErrorNone          Successfully added the Joiner.
305      * @retval kErrorNoBufs        No buffers available to add the Joiner.
306      * @retval kErrorInvalidState  Commissioner service is not started.
307      *
308      */
AddJoiner(const Mac::ExtAddress & aEui64,const char * aPskd,uint32_t aTimeout)309     Error AddJoiner(const Mac::ExtAddress &aEui64, const char *aPskd, uint32_t aTimeout)
310     {
311         return AddJoiner(&aEui64, nullptr, aPskd, aTimeout);
312     }
313 
314     /**
315      * Adds a Joiner entry with a Joiner Discerner.
316      *
317      * @param[in]  aDiscerner  A Joiner Discerner.
318      * @param[in]  aPskd       A pointer to the PSKd.
319      * @param[in]  aTimeout    A time after which a Joiner is automatically removed, in seconds.
320      *
321      * @retval kErrorNone          Successfully added the Joiner.
322      * @retval kErrorNoBufs        No buffers available to add the Joiner.
323      * @retval kErrorInvalidState  Commissioner service is not started.
324      *
325      */
AddJoiner(const JoinerDiscerner & aDiscerner,const char * aPskd,uint32_t aTimeout)326     Error AddJoiner(const JoinerDiscerner &aDiscerner, const char *aPskd, uint32_t aTimeout)
327     {
328         return AddJoiner(nullptr, &aDiscerner, aPskd, aTimeout);
329     }
330 
331     /**
332      * Get joiner info at aIterator position.
333      *
334      * @param[in,out]   aIterator   A iterator to the index of the joiner.
335      * @param[out]      aJoiner     A reference to Joiner info.
336      *
337      * @retval kErrorNone       Successfully get the Joiner info.
338      * @retval kErrorNotFound   Not found next Joiner.
339      *
340      */
341     Error GetNextJoinerInfo(uint16_t &aIterator, otJoinerInfo &aJoiner) const;
342 
343     /**
344      * Removes a Joiner entry accepting any Joiner.
345      *
346      * @param[in]  aDelay         The delay to remove Joiner (in seconds).
347      *
348      * @retval kErrorNone          Successfully added the Joiner.
349      * @retval kErrorNotFound      The Joiner entry accepting any Joiner was not found.
350      * @retval kErrorInvalidState  Commissioner service is not started.
351      *
352      */
RemoveJoinerAny(uint32_t aDelay)353     Error RemoveJoinerAny(uint32_t aDelay) { return RemoveJoiner(nullptr, nullptr, aDelay); }
354 
355     /**
356      * Removes a Joiner entry.
357      *
358      * @param[in]  aEui64         The Joiner's IEEE EUI-64.
359      * @param[in]  aDelay         The delay to remove Joiner (in seconds).
360      *
361      * @retval kErrorNone          Successfully added the Joiner.
362      * @retval kErrorNotFound      The Joiner specified by @p aEui64 was not found.
363      * @retval kErrorInvalidState  Commissioner service is not started.
364      *
365      */
RemoveJoiner(const Mac::ExtAddress & aEui64,uint32_t aDelay)366     Error RemoveJoiner(const Mac::ExtAddress &aEui64, uint32_t aDelay)
367     {
368         return RemoveJoiner(&aEui64, nullptr, aDelay);
369     }
370 
371     /**
372      * Removes a Joiner entry.
373      *
374      * @param[in]  aDiscerner     A Joiner Discerner.
375      * @param[in]  aDelay         The delay to remove Joiner (in seconds).
376      *
377      * @retval kErrorNone          Successfully added the Joiner.
378      * @retval kErrorNotFound      The Joiner specified by @p aEui64 was not found.
379      * @retval kErrorInvalidState  Commissioner service is not started.
380      *
381      */
RemoveJoiner(const JoinerDiscerner & aDiscerner,uint32_t aDelay)382     Error RemoveJoiner(const JoinerDiscerner &aDiscerner, uint32_t aDelay)
383     {
384         return RemoveJoiner(nullptr, &aDiscerner, aDelay);
385     }
386 
387     /**
388      * Gets the Provisioning URL.
389      *
390      * @returns A pointer to char buffer containing the URL string.
391      *
392      */
GetProvisioningUrl(void) const393     const char *GetProvisioningUrl(void) const { return mProvisioningUrl; }
394 
395     /**
396      * Sets the Provisioning URL.
397      *
398      * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be `nullptr` to set URL to empty string).
399      *
400      * @retval kErrorNone         Successfully set the Provisioning URL.
401      * @retval kErrorInvalidArgs  @p aProvisioningUrl is invalid (too long).
402      *
403      */
404     Error SetProvisioningUrl(const char *aProvisioningUrl);
405 
406     /**
407      * Returns the Commissioner Session ID.
408      *
409      * @returns The Commissioner Session ID.
410      *
411      */
GetSessionId(void) const412     uint16_t GetSessionId(void) const { return mSessionId; }
413 
414     /**
415      * Indicates whether or not the Commissioner role is active.
416      *
417      * @returns TRUE if the Commissioner role is active, FALSE otherwise.
418      *
419      */
IsActive(void) const420     bool IsActive(void) const { return mState == kStateActive; }
421 
422     /**
423      * Indicates whether or not the Commissioner role is disabled.
424      *
425      * @returns TRUE if the Commissioner role is disabled, FALSE otherwise.
426      *
427      */
IsDisabled(void) const428     bool IsDisabled(void) const { return mState == kStateDisabled; }
429 
430     /**
431      * Gets the Commissioner State.
432      *
433      * @returns The Commissioner State.
434      *
435      */
GetState(void) const436     State GetState(void) const { return mState; }
437 
438     /**
439      * Sends MGMT_COMMISSIONER_GET.
440      *
441      * @param[in]  aTlvs        A pointer to Commissioning Data TLVs.
442      * @param[in]  aLength      The length of requested TLVs in bytes.
443      *
444      * @retval kErrorNone          Send MGMT_COMMISSIONER_GET successfully.
445      * @retval kErrorNoBufs        Insufficient buffer space to send.
446      * @retval kErrorInvalidState  Commissioner service is not started.
447      *
448      */
449     Error SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength);
450 
451     /**
452      * Sends MGMT_COMMISSIONER_SET.
453      *
454      * @param[in]  aDataset     A reference to Commissioning Data.
455      * @param[in]  aTlvs        A pointer to user specific Commissioning Data TLVs.
456      * @param[in]  aLength      The length of user specific TLVs in bytes.
457      *
458      * @retval kErrorNone          Send MGMT_COMMISSIONER_SET successfully.
459      * @retval kErrorNoBufs        Insufficient buffer space to send.
460      * @retval kErrorInvalidState  Commissioner service is not started.
461      *
462      */
463     Error SendMgmtCommissionerSetRequest(const Dataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
464 
465     /**
466      * Returns a reference to the AnnounceBeginClient instance.
467      *
468      * @returns A reference to the AnnounceBeginClient instance.
469      *
470      */
GetAnnounceBeginClient(void)471     AnnounceBeginClient &GetAnnounceBeginClient(void) { return mAnnounceBegin; }
472 
473     /**
474      * Returns a reference to the EnergyScanClient instance.
475      *
476      * @returns A reference to the EnergyScanClient instance.
477      *
478      */
GetEnergyScanClient(void)479     EnergyScanClient &GetEnergyScanClient(void) { return mEnergyScan; }
480 
481     /**
482      * Returns a reference to the PanIdQueryClient instance.
483      *
484      * @returns A reference to the PanIdQueryClient instance.
485      *
486      */
GetPanIdQueryClient(void)487     PanIdQueryClient &GetPanIdQueryClient(void) { return mPanIdQuery; }
488 
489     /**
490      * Applies the Mesh Local Prefix.
491      *
492      */
493     void ApplyMeshLocalPrefix(void);
494 
495 private:
496     static constexpr uint32_t kPetitionAttemptDelay = 5;  // COMM_PET_ATTEMPT_DELAY (seconds)
497     static constexpr uint8_t  kPetitionRetryCount   = 2;  // COMM_PET_RETRY_COUNT
498     static constexpr uint32_t kPetitionRetryDelay   = 1;  // COMM_PET_RETRY_DELAY (seconds)
499     static constexpr uint32_t kKeepAliveTimeout     = 50; // TIMEOUT_COMM_PET (seconds)
500     static constexpr uint32_t kRemoveJoinerDelay    = 20; // Delay to remove successfully joined joiner
501 
502     static constexpr uint32_t kJoinerSessionTimeoutMillis =
503         1000 * OPENTHREAD_CONFIG_COMMISSIONER_JOINER_SESSION_TIMEOUT; // Expiration time for active Joiner session
504 
505     enum ResignMode : uint8_t
506     {
507         kSendKeepAliveToResign,
508         kDoNotSendKeepAlive,
509     };
510 
511     struct Joiner
512     {
513         enum Type : uint8_t
514         {
515             kTypeUnused = 0, // Need to be 0 to ensure `memset()` clears all `Joiners`
516             kTypeAny,
517             kTypeEui64,
518             kTypeDiscerner,
519         };
520 
521         TimeMilli mExpirationTime;
522 
523         union
524         {
525             Mac::ExtAddress mEui64;
526             JoinerDiscerner mDiscerner;
527         } mSharedId;
528 
529         JoinerPskd mPskd;
530         Type       mType;
531 
532         void CopyToJoinerInfo(otJoinerInfo &aJoiner) const;
533     };
534 
535     Error   Stop(ResignMode aResignMode);
536     Joiner *GetUnusedJoinerEntry(void);
537     Joiner *FindJoinerEntry(const Mac::ExtAddress *aEui64);
538     Joiner *FindJoinerEntry(const JoinerDiscerner &aDiscerner);
539     Joiner *FindBestMatchingJoinerEntry(const Mac::ExtAddress &aReceivedJoinerId);
540     void    RemoveJoinerEntry(Joiner &aJoiner);
541 
542     Error AddJoiner(const Mac::ExtAddress *aEui64,
543                     const JoinerDiscerner *aDiscerner,
544                     const char            *aPskd,
545                     uint32_t               aTimeout);
546     Error RemoveJoiner(const Mac::ExtAddress *aEui64, const JoinerDiscerner *aDiscerner, uint32_t aDelay);
547     void  RemoveJoiner(Joiner &aJoiner, uint32_t aDelay);
548 
549     void HandleTimer(void);
550     void HandleJoinerExpirationTimer(void);
551 
552     static void HandleMgmtCommissionerSetResponse(void                *aContext,
553                                                   otMessage           *aMessage,
554                                                   const otMessageInfo *aMessageInfo,
555                                                   Error                aResult);
556     void        HandleMgmtCommissionerSetResponse(Coap::Message          *aMessage,
557                                                   const Ip6::MessageInfo *aMessageInfo,
558                                                   Error                   aResult);
559     static void HandleMgmtCommissionerGetResponse(void                *aContext,
560                                                   otMessage           *aMessage,
561                                                   const otMessageInfo *aMessageInfo,
562                                                   Error                aResult);
563     void        HandleMgmtCommissionerGetResponse(Coap::Message          *aMessage,
564                                                   const Ip6::MessageInfo *aMessageInfo,
565                                                   Error                   aResult);
566     static void HandleLeaderPetitionResponse(void                *aContext,
567                                              otMessage           *aMessage,
568                                              const otMessageInfo *aMessageInfo,
569                                              Error                aResult);
570     void HandleLeaderPetitionResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
571     static void HandleLeaderKeepAliveResponse(void                *aContext,
572                                               otMessage           *aMessage,
573                                               const otMessageInfo *aMessageInfo,
574                                               Error                aResult);
575     void HandleLeaderKeepAliveResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
576 
577     static void HandleSecureAgentConnected(bool aConnected, void *aContext);
578     void        HandleSecureAgentConnected(bool aConnected);
579 
580     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
581 
582     void HandleRelayReceive(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
583 
584     void HandleJoinerSessionTimer(void);
585 
586     void SendJoinFinalizeResponse(const Coap::Message &aRequest, StateTlv::State aState);
587 
588     static Error SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
589     Error        SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
590 
591     void  ComputeBloomFilter(SteeringData &aSteeringData) const;
592     void  SendCommissionerSet(void);
593     Error SendPetition(void);
594     void  SendKeepAlive(void);
595     void  SendKeepAlive(uint16_t aSessionId);
596 
597     void SetState(State aState);
598     void SignalJoinerEvent(JoinerEvent aEvent, const Joiner *aJoiner) const;
599     void LogJoinerEntry(const char *aAction, const Joiner &aJoiner) const;
600 
601     static const char *StateToString(State aState);
602 
603     using JoinerExpirationTimer = TimerMilliIn<Commissioner, &Commissioner::HandleJoinerExpirationTimer>;
604     using CommissionerTimer     = TimerMilliIn<Commissioner, &Commissioner::HandleTimer>;
605     using JoinerSessionTimer    = TimerMilliIn<Commissioner, &Commissioner::HandleJoinerSessionTimer>;
606 
607     Joiner mJoiners[OPENTHREAD_CONFIG_COMMISSIONER_MAX_JOINER_ENTRIES];
608 
609     Joiner                  *mActiveJoiner;
610     Ip6::InterfaceIdentifier mJoinerIid;
611     uint16_t                 mJoinerPort;
612     uint16_t                 mJoinerRloc;
613     uint16_t                 mSessionId;
614     uint8_t                  mTransmitAttempts;
615     JoinerExpirationTimer    mJoinerExpirationTimer;
616     CommissionerTimer        mTimer;
617     JoinerSessionTimer       mJoinerSessionTimer;
618 
619     AnnounceBeginClient mAnnounceBegin;
620     EnergyScanClient    mEnergyScan;
621     PanIdQueryClient    mPanIdQuery;
622 
623     Ip6::Netif::UnicastAddress mCommissionerAloc;
624 
625     char mProvisioningUrl[OT_PROVISIONING_URL_MAX_SIZE + 1]; // + 1 is for null char at end of string.
626     char mCommissionerId[CommissionerIdTlv::kMaxLength + 1];
627 
628     State mState;
629 
630     Callback<StateCallback>  mStateCallback;
631     Callback<JoinerCallback> mJoinerCallback;
632 };
633 
634 DeclareTmfHandler(Commissioner, kUriDatasetChanged);
635 DeclareTmfHandler(Commissioner, kUriRelayRx);
636 DeclareTmfHandler(Commissioner, kUriJoinerFinalize);
637 
638 } // namespace MeshCoP
639 
640 DefineMapEnum(otCommissionerState, MeshCoP::Commissioner::State);
641 DefineMapEnum(otCommissionerJoinerEvent, MeshCoP::Commissioner::JoinerEvent);
642 DefineCoreType(otCommissioningDataset, MeshCoP::Commissioner::Dataset);
643 
644 } // namespace ot
645 
646 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
647 
648 #endif // COMMISSIONER_HPP_
649