1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for the Commissioner role.
*/
#ifndef COMMISSIONER_HPP_
#define COMMISSIONER_HPP_
#include "openthread-core-config.h"
#include <openthread/commissioner.h>
#include "coap/coap.hpp"
#include "coap/coap_secure.hpp"
#include "common/locator.hpp"
#include "common/timer.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/announce_begin_client.hpp"
#include "meshcop/dtls.hpp"
#include "meshcop/energy_scan_client.hpp"
#include "meshcop/panid_query_client.hpp"
#include "net/udp6.hpp"
#include "thread/key_manager.hpp"
#include "thread/mle.hpp"
namespace ot {
namespace MeshCoP {
class Commissioner : public InstanceLocator
{
public:
/**
* Joiner operation flags.
*
*/
enum JoinerOpFlag
{
kJoinerOpFlagDefault = 0, ///< The default flags
kJoinerOpFlagNotNotifyLeader = 1 << 0, ///< Do not notify Leader
};
/**
* This constructor initializes the Commissioner object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Commissioner(Instance &aInstance);
/**
* This method starts the Commissioner service.
*
* @param[in] aStateCallback A pointer to a function that is called when the commissioner state changes.
* @param[in] aJoinerCallback A pointer to a function that is called when a joiner event occurs.
* @param[in] aCallbackContext A pointer to application-specific context.
*
* @retval OT_ERROR_NONE Successfully started the Commissioner service.
* @retval OT_ERROR_ALREADY Commissioner is already started.
* @retval OT_ERROR_INVALID_STATE Device is not currently attached to a network.
*
*/
otError Start(otCommissionerStateCallback aStateCallback,
otCommissionerJoinerCallback aJoinerCallback,
void * aCallbackContext);
/**
* This method stops the Commissioner service.
*
* @param[in] aResign Whether send LEAD_KA.req to resign as Commissioner
*
* @retval OT_ERROR_NONE Successfully stopped the Commissioner service.
* @retval OT_ERROR_ALREADY Commissioner is already stopped.
*
*/
otError Stop(bool aResign);
/**
* This method clears all Joiner entries.
*
*/
void ClearJoiners(void);
/**
* This method adds a Joiner entry.
*
* @param[in] aEui64 A pointer to the Joiner's IEEE EUI-64 or NULL for any Joiner.
* @param[in] aPskd A pointer to the PSKd.
* @param[in] aTimeout A time after which a Joiner is automatically removed, in seconds.
*
* @retval OT_ERROR_NONE Successfully added the Joiner.
* @retval OT_ERROR_NO_BUFS No buffers available to add the Joiner.
* @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
*
*/
otError AddJoiner(const Mac::ExtAddress *aEui64, const char *aPskd, uint32_t aTimeout);
/**
* This method get joiner info at aIterator position.
*
* @param[inout] aIterator A iterator to the index of the joiner.
* @param[out] aJoiner A reference to Joiner info.
*
* @retval OT_ERROR_NONE Successfully get the Joiner info.
* @retval OT_ERROR_NOT_FOUND Not found next Joiner.
*
*/
otError GetNextJoinerInfo(uint16_t &aIterator, otJoinerInfo &aJoiner) const;
/**
* This method removes a Joiner entry.
*
* @param[in] aEui64 A pointer to the Joiner's IEEE EUI-64 or NULL for any Joiner.
* @param[in] aDelay The delay to remove Joiner (in seconds).
* @param[in] aFlags The flags for removing the Joiner.
*
* @retval OT_ERROR_NONE Successfully added the Joiner.
* @retval OT_ERROR_NOT_FOUND The Joiner specified by @p aEui64 was not found.
* @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
*
* @sa JoinerOpFlag
*/
otError RemoveJoiner(const Mac::ExtAddress *aEui64, uint32_t aDelay, JoinerOpFlag aFlags = kJoinerOpFlagDefault);
/**
* This method gets the Provisioning URL.
*
* @returns A pointer to char buffer containing the URL string.
*
*/
const char *GetProvisioningUrl(void) const { return mProvisioningUrl; }
/**
* This method sets the Provisioning URL.
*
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be NULL to set URL to empty string).
*
* @retval OT_ERROR_NONE Successfully set the Provisioning URL.
* @retval OT_ERROR_INVALID_ARGS @p aProvisioningUrl is invalid (too long).
*
*/
otError SetProvisioningUrl(const char *aProvisioningUrl);
/**
* This method returns the Commissioner Session ID.
*
* @returns The Commissioner Session ID.
*
*/
uint16_t GetSessionId(void) const { return mSessionId; }
/**
* This method indicates whether or not the Commissioner role is active.
*
* @returns TRUE if the Commissioner role is active, FALSE otherwise.
*
*/
bool IsActive(void) const { return mState == OT_COMMISSIONER_STATE_ACTIVE; }
/**
* This method indicates whether or not the Commissioner role is disabled.
*
* @returns TRUE if the Commissioner role is disabled, FALSE otherwise.
*
*/
bool IsDisabled(void) const { return mState == OT_COMMISSIONER_STATE_DISABLED; }
/**
* This function returns the Commissioner State.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval OT_COMMISSIONER_STATE_DISABLED Commissioner disabled.
* @retval OT_COMMISSIONER_STATE_PETITION Becoming the commissioner.
* @retval OT_COMMISSIONER_STATE_ACTIVE Commissioner enabled.
*
*/
otCommissionerState GetState(void) const { return mState; }
/**
* This method sends MGMT_COMMISSIONER_GET.
*
* @param[in] aTlvs A pointer to Commissioning Data TLVs.
* @param[in] aLength The length of requested TLVs in bytes.
*
* @retval OT_ERROR_NONE Send MGMT_COMMISSIONER_GET successfully.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
* @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
*
*/
otError SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength);
/**
* This method sends MGMT_COMMISSIONER_SET.
*
* @param[in] aDataset A reference to Commissioning Data.
* @param[in] aTlvs A pointer to user specific Commissioning Data TLVs.
* @param[in] aLength The length of user specific TLVs in bytes.
*
* @retval OT_ERROR_NONE Send MGMT_COMMISSIONER_SET successfully.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
* @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
*
*/
otError SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
const uint8_t * aTlvs,
uint8_t aLength);
/**
* This method returns a reference to the AnnounceBeginClient instance.
*
* @returns A reference to the AnnounceBeginClient instance.
*
*/
AnnounceBeginClient &GetAnnounceBeginClient(void) { return mAnnounceBegin; }
/**
* This method returns a reference to the EnergyScanClient instance.
*
* @returns A reference to the EnergyScanClient instance.
*
*/
EnergyScanClient &GetEnergyScanClient(void) { return mEnergyScan; }
/**
* This method returns a reference to the PanIdQueryClient instance.
*
* @returns A reference to the PanIdQueryClient instance.
*
*/
PanIdQueryClient &GetPanIdQueryClient(void) { return mPanIdQuery; }
/**
* This method applies the Mesh Local Prefix.
*
*/
void ApplyMeshLocalPrefix(void);
private:
enum
{
kPetitionAttemptDelay = 5, ///< COMM_PET_ATTEMPT_DELAY (seconds)
kPetitionRetryCount = 2, ///< COMM_PET_RETRY_COUNT
kPetitionRetryDelay = 1, ///< COMM_PET_RETRY_DELAY (seconds)
kKeepAliveTimeout = 50, ///< TIMEOUT_COMM_PET (seconds)
kRemoveJoinerDelay = 20, ///< Delay to remove successfully joined joiner
};
void AddCoapResources(void);
void RemoveCoapResources(void);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
static void HandleJoinerExpirationTimer(Timer &aTimer);
void HandleJoinerExpirationTimer(void);
void UpdateJoinerExpirationTimer(void);
static void HandleMgmtCommissionerSetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
otError aResult);
void HandleMgmtCommissionerSetResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
otError aResult);
static void HandleMgmtCommissionerGetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
otError aResult);
void HandleMgmtCommissionerGetResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
otError aResult);
static void HandleLeaderPetitionResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
otError aResult);
void HandleLeaderPetitionResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
static void HandleLeaderKeepAliveResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
otError aResult);
void HandleLeaderKeepAliveResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
static void HandleCoapsConnected(bool aConnected, void *aContext);
void HandleCoapsConnected(bool aConnected);
static void HandleRelayReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleRelayReceive(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleDatasetChanged(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleDatasetChanged(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleJoinerFinalize(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleJoinerFinalize(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SendJoinFinalizeResponse(const Coap::Message &aRequest, StateTlv::State aState);
static otError SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError SendCommissionerSet(void);
otError SendPetition(void);
void SendKeepAlive(void);
void SendKeepAlive(uint16_t aSessionId);
void SetState(otCommissionerState aState);
void SignalJoinerEvent(otCommissionerJoinerEvent aEvent, const Mac::ExtAddress &aJoinerId);
static const char *StateToString(otCommissionerState aState);
struct Joiner
{
Mac::ExtAddress mEui64;
TimeMilli mExpirationTime;
char mPsk[Dtls::kPskMaxLength + 1];
bool mValid : 1;
bool mAny : 1;
};
Joiner mJoiners[OPENTHREAD_CONFIG_COMMISSIONER_MAX_JOINER_ENTRIES];
uint8_t mJoinerIid[Ip6::Address::kInterfaceIdentifierSize];
uint16_t mJoinerPort;
uint16_t mJoinerRloc;
uint16_t mSessionId;
uint8_t mJoinerIndex;
uint8_t mTransmitAttempts;
TimerMilli mJoinerExpirationTimer;
TimerMilli mTimer;
Coap::Resource mRelayReceive;
Coap::Resource mDatasetChanged;
Coap::Resource mJoinerFinalize;
AnnounceBeginClient mAnnounceBegin;
EnergyScanClient mEnergyScan;
PanIdQueryClient mPanIdQuery;
Ip6::NetifUnicastAddress mCommissionerAloc;
char mProvisioningUrl[OT_PROVISIONING_URL_MAX_SIZE + 1]; // + 1 is for null char at end of string.
otCommissionerStateCallback mStateCallback;
otCommissionerJoinerCallback mJoinerCallback;
void * mCallbackContext;
otCommissionerState mState;
};
} // namespace MeshCoP
} // namespace ot
#endif // COMMISSIONER_HPP_