• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.hpp"
44 #include "coap/coap_secure.hpp"
45 #include "common/as_core_type.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 
61 namespace ot {
62 
63 namespace MeshCoP {
64 
65 class Commissioner : public InstanceLocator, private NonCopyable
66 {
67 public:
68     /**
69      * This enumeration type represents the Commissioner State.
70      *
71      */
72     enum State : uint8_t
73     {
74         kStateDisabled = OT_COMMISSIONER_STATE_DISABLED, ///< Disabled.
75         kStatePetition = OT_COMMISSIONER_STATE_PETITION, ///< Petitioning to become a Commissioner.
76         kStateActive   = OT_COMMISSIONER_STATE_ACTIVE,   ///< Active Commissioner.
77     };
78 
79     /**
80      * This enumeration type represents Joiner Event.
81      *
82      */
83     enum JoinerEvent : uint8_t
84     {
85         kJoinerEventStart     = OT_COMMISSIONER_JOINER_START,
86         kJoinerEventConnected = OT_COMMISSIONER_JOINER_CONNECTED,
87         kJoinerEventFinalize  = OT_COMMISSIONER_JOINER_FINALIZE,
88         kJoinerEventEnd       = OT_COMMISSIONER_JOINER_END,
89         kJoinerEventRemoved   = OT_COMMISSIONER_JOINER_REMOVED,
90     };
91 
92     typedef otCommissionerStateCallback  StateCallback;  ///< State change callback function pointer type.
93     typedef otCommissionerJoinerCallback JoinerCallback; ///< Joiner state change callback function pointer type.
94 
95     /**
96      * This type represents a Commissioning Dataset.
97      *
98      */
99     class Dataset : public otCommissioningDataset, public Clearable<Dataset>
100     {
101     public:
102         /**
103          * This method indicates whether or not the Border Router RLOC16 Locator is set in the Dataset.
104          *
105          * @returns TRUE if Border Router RLOC16 Locator is set, FALSE otherwise.
106          *
107          */
IsLocatorSet(void) const108         bool IsLocatorSet(void) const { return mIsLocatorSet; }
109 
110         /**
111          * This method gets the Border Router RLOC16 Locator in the Dataset.
112          *
113          * This method MUST be used when Locator is set in the Dataset, otherwise its behavior is undefined.
114          *
115          * @returns The Border Router RLOC16 Locator in the Dataset.
116          *
117          */
GetLocator(void) const118         uint16_t GetLocator(void) const { return mLocator; }
119 
120         /**
121          * This method sets the Border Router RLOCG16 Locator in the Dataset.
122          *
123          * @param[in] aLocator  A Locator.
124          *
125          */
SetLocator(uint16_t aLocator)126         void SetLocator(uint16_t aLocator)
127         {
128             mIsLocatorSet = true;
129             mLocator      = aLocator;
130         }
131 
132         /**
133          * This method indicates whether or not the Session ID is set in the Dataset.
134          *
135          * @returns TRUE if Session ID is set, FALSE otherwise.
136          *
137          */
IsSessionIdSet(void) const138         bool IsSessionIdSet(void) const { return mIsSessionIdSet; }
139 
140         /**
141          * This method gets the Session ID in the Dataset.
142          *
143          * This method MUST be used when Session ID is set in the Dataset, otherwise its behavior is undefined.
144          *
145          * @returns The Session ID in the Dataset.
146          *
147          */
GetSessionId(void) const148         uint16_t GetSessionId(void) const { return mSessionId; }
149 
150         /**
151          * This method sets the Session ID in the Dataset.
152          *
153          * @param[in] aSessionId  The Session ID.
154          *
155          */
SetSessionId(uint16_t aSessionId)156         void SetSessionId(uint16_t aSessionId)
157         {
158             mIsSessionIdSet = true;
159             mSessionId      = aSessionId;
160         }
161 
162         /**
163          * This method indicates whether or not the Steering Data is set in the Dataset.
164          *
165          * @returns TRUE if Steering Data is set, FALSE otherwise.
166          *
167          */
IsSteeringDataSet(void) const168         bool IsSteeringDataSet(void) const { return mIsSteeringDataSet; }
169 
170         /**
171          * This method gets the Steering Data in the Dataset.
172          *
173          * This method MUST be used when Steering Data is set in the Dataset, otherwise its behavior is undefined.
174          *
175          * @returns The Steering Data in the Dataset.
176          *
177          */
GetSteeringData(void) const178         const SteeringData &GetSteeringData(void) const { return AsCoreType(&mSteeringData); }
179 
180         /**
181          * This method returns a reference to the Steering Data in the Dataset to be updated by caller.
182          *
183          * @returns A reference to the Steering Data in the Dataset.
184          *
185          */
UpdateSteeringData(void)186         SteeringData &UpdateSteeringData(void)
187         {
188             mIsSteeringDataSet = true;
189             return AsCoreType(&mSteeringData);
190         }
191 
192         /**
193          * This method indicates whether or not the Joiner UDP port is set in the Dataset.
194          *
195          * @returns TRUE if Joiner UDP port is set, FALSE otherwise.
196          *
197          */
IsJoinerUdpPortSet(void) const198         bool IsJoinerUdpPortSet(void) const { return mIsJoinerUdpPortSet; }
199 
200         /**
201          * This method gets the Joiner UDP port in the Dataset.
202          *
203          * This method MUST be used when Joiner UDP port is set in the Dataset, otherwise its behavior is undefined.
204          *
205          * @returns The Joiner UDP port in the Dataset.
206          *
207          */
GetJoinerUdpPort(void) const208         uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
209 
210         /**
211          * This method sets the Joiner UDP Port in the Dataset.
212          *
213          * @param[in] aJoinerUdpPort  The Joiner UDP Port.
214          *
215          */
SetJoinerUdpPort(uint16_t aJoinerUdpPort)216         void SetJoinerUdpPort(uint16_t aJoinerUdpPort)
217         {
218             mIsJoinerUdpPortSet = true;
219             mJoinerUdpPort      = aJoinerUdpPort;
220         }
221     };
222 
223     /**
224      * This constructor initializes the Commissioner object.
225      *
226      * @param[in]  aInstance     A reference to the OpenThread instance.
227      *
228      */
229     explicit Commissioner(Instance &aInstance);
230 
231     /**
232      * This method starts the Commissioner service.
233      *
234      * @param[in]  aStateCallback    A pointer to a function that is called when the commissioner state changes.
235      * @param[in]  aJoinerCallback   A pointer to a function that is called when a joiner event occurs.
236      * @param[in]  aCallbackContext  A pointer to application-specific context.
237      *
238      * @retval kErrorNone           Successfully started the Commissioner service.
239      * @retval kErrorAlready        Commissioner is already started.
240      * @retval kErrorInvalidState   Device is not currently attached to a network.
241      *
242      */
243     Error Start(StateCallback aStateCallback, JoinerCallback aJoinerCallback, void *aCallbackContext);
244 
245     /**
246      * This method stops the Commissioner service.
247      *
248      * @retval kErrorNone     Successfully stopped the Commissioner service.
249      * @retval kErrorAlready  Commissioner is already stopped.
250      *
251      */
Stop(void)252     Error Stop(void) { return Stop(kSendKeepAliveToResign); }
253 
254     /**
255      * This method returns the Commissioner Id.
256      *
257      * @returns The Commissioner Id.
258      *
259      */
GetId(void) const260     const char *GetId(void) const { return mCommissionerId; }
261 
262     /**
263      * This method sets the Commissioner Id.
264      *
265      * @param[in]  aId   A pointer to a string character array. Must be null terminated.
266      *
267      * @retval kErrorNone           Successfully set the Commissioner Id.
268      * @retval kErrorInvalidArgs    Given name is too long.
269      * @retval kErrorInvalidState   The commissioner is active and id cannot be changed.
270      *
271      */
272     Error SetId(const char *aId);
273 
274     /**
275      * This method clears all Joiner entries.
276      *
277      */
278     void ClearJoiners(void);
279 
280     /**
281      * This method adds a Joiner entry accepting any Joiner.
282      *
283      * @param[in]  aPskd         A pointer to the PSKd.
284      * @param[in]  aTimeout      A time after which a Joiner is automatically removed, in seconds.
285      *
286      * @retval kErrorNone          Successfully added the Joiner.
287      * @retval kErrorNoBufs        No buffers available to add the Joiner.
288      * @retval kErrorInvalidState  Commissioner service is not started.
289      *
290      */
AddJoinerAny(const char * aPskd,uint32_t aTimeout)291     Error AddJoinerAny(const char *aPskd, uint32_t aTimeout) { return AddJoiner(nullptr, nullptr, aPskd, aTimeout); }
292 
293     /**
294      * This method adds a Joiner entry.
295      *
296      * @param[in]  aEui64        The Joiner's IEEE EUI-64.
297      * @param[in]  aPskd         A pointer to the PSKd.
298      * @param[in]  aTimeout      A time after which a Joiner is automatically removed, in seconds.
299      *
300      * @retval kErrorNone          Successfully added the Joiner.
301      * @retval kErrorNoBufs        No buffers available to add the Joiner.
302      * @retval kErrorInvalidState  Commissioner service is not started.
303      *
304      */
AddJoiner(const Mac::ExtAddress & aEui64,const char * aPskd,uint32_t aTimeout)305     Error AddJoiner(const Mac::ExtAddress &aEui64, const char *aPskd, uint32_t aTimeout)
306     {
307         return AddJoiner(&aEui64, nullptr, aPskd, aTimeout);
308     }
309 
310     /**
311      * This method adds a Joiner entry with a Joiner Discerner.
312      *
313      * @param[in]  aDiscerner  A Joiner Discerner.
314      * @param[in]  aPskd       A pointer to the PSKd.
315      * @param[in]  aTimeout    A time after which a Joiner is automatically removed, in seconds.
316      *
317      * @retval kErrorNone          Successfully added the Joiner.
318      * @retval kErrorNoBufs        No buffers available to add the Joiner.
319      * @retval kErrorInvalidState  Commissioner service is not started.
320      *
321      */
AddJoiner(const JoinerDiscerner & aDiscerner,const char * aPskd,uint32_t aTimeout)322     Error AddJoiner(const JoinerDiscerner &aDiscerner, const char *aPskd, uint32_t aTimeout)
323     {
324         return AddJoiner(nullptr, &aDiscerner, aPskd, aTimeout);
325     }
326 
327     /**
328      * This method get joiner info at aIterator position.
329      *
330      * @param[in,out]   aIterator   A iterator to the index of the joiner.
331      * @param[out]      aJoiner     A reference to Joiner info.
332      *
333      * @retval kErrorNone       Successfully get the Joiner info.
334      * @retval kErrorNotFound   Not found next Joiner.
335      *
336      */
337     Error GetNextJoinerInfo(uint16_t &aIterator, otJoinerInfo &aJoiner) const;
338 
339     /**
340      * This method removes a Joiner entry accepting any Joiner.
341      *
342      * @param[in]  aDelay         The delay to remove Joiner (in seconds).
343      *
344      * @retval kErrorNone          Successfully added the Joiner.
345      * @retval kErrorNotFound      The Joiner entry accepting any Joiner was not found.
346      * @retval kErrorInvalidState  Commissioner service is not started.
347      *
348      */
RemoveJoinerAny(uint32_t aDelay)349     Error RemoveJoinerAny(uint32_t aDelay) { return RemoveJoiner(nullptr, nullptr, aDelay); }
350 
351     /**
352      * This method removes a Joiner entry.
353      *
354      * @param[in]  aEui64         The Joiner's IEEE EUI-64.
355      * @param[in]  aDelay         The delay to remove Joiner (in seconds).
356      *
357      * @retval kErrorNone          Successfully added the Joiner.
358      * @retval kErrorNotFound      The Joiner specified by @p aEui64 was not found.
359      * @retval kErrorInvalidState  Commissioner service is not started.
360      *
361      */
RemoveJoiner(const Mac::ExtAddress & aEui64,uint32_t aDelay)362     Error RemoveJoiner(const Mac::ExtAddress &aEui64, uint32_t aDelay)
363     {
364         return RemoveJoiner(&aEui64, nullptr, aDelay);
365     }
366 
367     /**
368      * This method removes a Joiner entry.
369      *
370      * @param[in]  aDiscerner     A Joiner Discerner.
371      * @param[in]  aDelay         The delay to remove Joiner (in seconds).
372      *
373      * @retval kErrorNone          Successfully added the Joiner.
374      * @retval kErrorNotFound      The Joiner specified by @p aEui64 was not found.
375      * @retval kErrorInvalidState  Commissioner service is not started.
376      *
377      */
RemoveJoiner(const JoinerDiscerner & aDiscerner,uint32_t aDelay)378     Error RemoveJoiner(const JoinerDiscerner &aDiscerner, uint32_t aDelay)
379     {
380         return RemoveJoiner(nullptr, &aDiscerner, aDelay);
381     }
382 
383     /**
384      * This method gets the Provisioning URL.
385      *
386      * @returns A pointer to char buffer containing the URL string.
387      *
388      */
GetProvisioningUrl(void) const389     const char *GetProvisioningUrl(void) const { return mProvisioningUrl; }
390 
391     /**
392      * This method sets the Provisioning URL.
393      *
394      * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be `nullptr` to set URL to empty string).
395      *
396      * @retval kErrorNone         Successfully set the Provisioning URL.
397      * @retval kErrorInvalidArgs  @p aProvisioningUrl is invalid (too long).
398      *
399      */
400     Error SetProvisioningUrl(const char *aProvisioningUrl);
401 
402     /**
403      * This method returns the Commissioner Session ID.
404      *
405      * @returns The Commissioner Session ID.
406      *
407      */
GetSessionId(void) const408     uint16_t GetSessionId(void) const { return mSessionId; }
409 
410     /**
411      * This method indicates whether or not the Commissioner role is active.
412      *
413      * @returns TRUE if the Commissioner role is active, FALSE otherwise.
414      *
415      */
IsActive(void) const416     bool IsActive(void) const { return mState == kStateActive; }
417 
418     /**
419      * This method indicates whether or not the Commissioner role is disabled.
420      *
421      * @returns TRUE if the Commissioner role is disabled, FALSE otherwise.
422      *
423      */
IsDisabled(void) const424     bool IsDisabled(void) const { return mState == kStateDisabled; }
425 
426     /**
427      * This method gets the Commissioner State.
428      *
429      * @returns The Commissioner State.
430      *
431      */
GetState(void) const432     State GetState(void) const { return mState; }
433 
434     /**
435      * This method sends MGMT_COMMISSIONER_GET.
436      *
437      * @param[in]  aTlvs        A pointer to Commissioning Data TLVs.
438      * @param[in]  aLength      The length of requested TLVs in bytes.
439      *
440      * @retval kErrorNone          Send MGMT_COMMISSIONER_GET successfully.
441      * @retval kErrorNoBufs        Insufficient buffer space to send.
442      * @retval kErrorInvalidState  Commissioner service is not started.
443      *
444      */
445     Error SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength);
446 
447     /**
448      * This method sends MGMT_COMMISSIONER_SET.
449      *
450      * @param[in]  aDataset     A reference to Commissioning Data.
451      * @param[in]  aTlvs        A pointer to user specific Commissioning Data TLVs.
452      * @param[in]  aLength      The length of user specific TLVs in bytes.
453      *
454      * @retval kErrorNone          Send MGMT_COMMISSIONER_SET successfully.
455      * @retval kErrorNoBufs        Insufficient buffer space to send.
456      * @retval kErrorInvalidState  Commissioner service is not started.
457      *
458      */
459     Error SendMgmtCommissionerSetRequest(const Dataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
460 
461     /**
462      * This method returns a reference to the AnnounceBeginClient instance.
463      *
464      * @returns A reference to the AnnounceBeginClient instance.
465      *
466      */
GetAnnounceBeginClient(void)467     AnnounceBeginClient &GetAnnounceBeginClient(void) { return mAnnounceBegin; }
468 
469     /**
470      * This method returns a reference to the EnergyScanClient instance.
471      *
472      * @returns A reference to the EnergyScanClient instance.
473      *
474      */
GetEnergyScanClient(void)475     EnergyScanClient &GetEnergyScanClient(void) { return mEnergyScan; }
476 
477     /**
478      * This method returns a reference to the PanIdQueryClient instance.
479      *
480      * @returns A reference to the PanIdQueryClient instance.
481      *
482      */
GetPanIdQueryClient(void)483     PanIdQueryClient &GetPanIdQueryClient(void) { return mPanIdQuery; }
484 
485     /**
486      * This method applies the Mesh Local Prefix.
487      *
488      */
489     void ApplyMeshLocalPrefix(void);
490 
491 private:
492     static constexpr uint32_t kPetitionAttemptDelay = 5;  // COMM_PET_ATTEMPT_DELAY (seconds)
493     static constexpr uint8_t  kPetitionRetryCount   = 2;  // COMM_PET_RETRY_COUNT
494     static constexpr uint32_t kPetitionRetryDelay   = 1;  // COMM_PET_RETRY_DELAY (seconds)
495     static constexpr uint32_t kKeepAliveTimeout     = 50; // TIMEOUT_COMM_PET (seconds)
496     static constexpr uint32_t kRemoveJoinerDelay    = 20; // Delay to remove successfully joined joiner
497 
498     enum ResignMode : uint8_t
499     {
500         kSendKeepAliveToResign,
501         kDoNotSendKeepAlive,
502     };
503 
504     struct Joiner
505     {
506         enum Type : uint8_t
507         {
508             kTypeUnused = 0, // Need to be 0 to ensure `memset()` clears all `Joiners`
509             kTypeAny,
510             kTypeEui64,
511             kTypeDiscerner,
512         };
513 
514         TimeMilli mExpirationTime;
515 
516         union
517         {
518             Mac::ExtAddress mEui64;
519             JoinerDiscerner mDiscerner;
520         } mSharedId;
521 
522         JoinerPskd mPskd;
523         Type       mType;
524 
525         void CopyToJoinerInfo(otJoinerInfo &aJoiner) const;
526     };
527 
528     Error   Stop(ResignMode aResignMode);
529     Joiner *GetUnusedJoinerEntry(void);
530     Joiner *FindJoinerEntry(const Mac::ExtAddress *aEui64);
531     Joiner *FindJoinerEntry(const JoinerDiscerner &aDiscerner);
532     Joiner *FindBestMatchingJoinerEntry(const Mac::ExtAddress &aReceivedJoinerId);
533     void    RemoveJoinerEntry(Joiner &aJoiner);
534 
535     Error AddJoiner(const Mac::ExtAddress *aEui64,
536                     const JoinerDiscerner *aDiscerner,
537                     const char *           aPskd,
538                     uint32_t               aTimeout);
539     Error RemoveJoiner(const Mac::ExtAddress *aEui64, const JoinerDiscerner *aDiscerner, uint32_t aDelay);
540     void  RemoveJoiner(Joiner &aJoiner, uint32_t aDelay);
541 
542     void AddCoapResources(void);
543     void RemoveCoapResources(void);
544 
545     static void HandleTimer(Timer &aTimer);
546     void        HandleTimer(void);
547 
548     static void HandleJoinerExpirationTimer(Timer &aTimer);
549     void        HandleJoinerExpirationTimer(void);
550 
551     void UpdateJoinerExpirationTimer(void);
552 
553     static void HandleMgmtCommissionerSetResponse(void *               aContext,
554                                                   otMessage *          aMessage,
555                                                   const otMessageInfo *aMessageInfo,
556                                                   Error                aResult);
557     void        HandleMgmtCommissionerSetResponse(Coap::Message *         aMessage,
558                                                   const Ip6::MessageInfo *aMessageInfo,
559                                                   Error                   aResult);
560     static void HandleMgmtCommissionerGetResponse(void *               aContext,
561                                                   otMessage *          aMessage,
562                                                   const otMessageInfo *aMessageInfo,
563                                                   Error                aResult);
564     void        HandleMgmtCommissionerGetResponse(Coap::Message *         aMessage,
565                                                   const Ip6::MessageInfo *aMessageInfo,
566                                                   Error                   aResult);
567     static void HandleLeaderPetitionResponse(void *               aContext,
568                                              otMessage *          aMessage,
569                                              const otMessageInfo *aMessageInfo,
570                                              Error                aResult);
571     void HandleLeaderPetitionResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
572     static void HandleLeaderKeepAliveResponse(void *               aContext,
573                                               otMessage *          aMessage,
574                                               const otMessageInfo *aMessageInfo,
575                                               Error                aResult);
576     void HandleLeaderKeepAliveResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
577 
578     static void HandleCoapsConnected(bool aConnected, void *aContext);
579     void        HandleCoapsConnected(bool aConnected);
580 
581     static void HandleRelayReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
582     void        HandleRelayReceive(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
583 
584     static void HandleDatasetChanged(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
585     void        HandleDatasetChanged(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
586 
587     static void HandleJoinerFinalize(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
588     void        HandleJoinerFinalize(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
589 
590     void SendJoinFinalizeResponse(const Coap::Message &aRequest, StateTlv::State aState);
591 
592     static Error SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
593     Error        SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
594 
595     void  ComputeBloomFilter(SteeringData &aSteeringData) const;
596     void  SendCommissionerSet(void);
597     Error SendPetition(void);
598     void  SendKeepAlive(void);
599     void  SendKeepAlive(uint16_t aSessionId);
600 
601     void SetState(State aState);
602     void SignalJoinerEvent(JoinerEvent aEvent, const Joiner *aJoiner) const;
603     void LogJoinerEntry(const char *aAction, const Joiner &aJoiner) const;
604 
605     static const char *StateToString(State aState);
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     TimerMilli               mJoinerExpirationTimer;
616     TimerMilli               mTimer;
617 
618     Coap::Resource mRelayReceive;
619     Coap::Resource mDatasetChanged;
620     Coap::Resource mJoinerFinalize;
621 
622     AnnounceBeginClient mAnnounceBegin;
623     EnergyScanClient    mEnergyScan;
624     PanIdQueryClient    mPanIdQuery;
625 
626     Ip6::Netif::UnicastAddress mCommissionerAloc;
627 
628     char mProvisioningUrl[OT_PROVISIONING_URL_MAX_SIZE + 1]; // + 1 is for null char at end of string.
629     char mCommissionerId[CommissionerIdTlv::kMaxLength + 1];
630 
631     State mState;
632 
633     StateCallback  mStateCallback;
634     JoinerCallback mJoinerCallback;
635     void *         mCallbackContext;
636 };
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