• 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 Joiner role.
32  */
33 
34 #ifndef JOINER_HPP_
35 #define JOINER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_JOINER_ENABLE
40 
41 #include <openthread/joiner.h>
42 
43 #include "coap/coap.hpp"
44 #include "coap/coap_message.hpp"
45 #include "coap/coap_secure.hpp"
46 #include "common/as_core_type.hpp"
47 #include "common/locator.hpp"
48 #include "common/log.hpp"
49 #include "common/message.hpp"
50 #include "common/non_copyable.hpp"
51 #include "mac/mac_types.hpp"
52 #include "meshcop/dtls.hpp"
53 #include "meshcop/meshcop.hpp"
54 #include "meshcop/meshcop_tlvs.hpp"
55 #include "thread/discover_scanner.hpp"
56 
57 namespace ot {
58 
59 namespace MeshCoP {
60 
61 class Joiner : public InstanceLocator, private NonCopyable
62 {
63 public:
64     /**
65      * This enumeration type defines the Joiner State.
66      *
67      */
68     enum State : uint8_t
69     {
70         kStateIdle      = OT_JOINER_STATE_IDLE,
71         kStateDiscover  = OT_JOINER_STATE_DISCOVER,
72         kStateConnect   = OT_JOINER_STATE_CONNECT,
73         kStateConnected = OT_JOINER_STATE_CONNECTED,
74         kStateEntrust   = OT_JOINER_STATE_ENTRUST,
75         kStateJoined    = OT_JOINER_STATE_JOINED,
76     };
77 
78     /**
79      * This constructor initializes the Joiner object.
80      *
81      * @param[in]  aInstance     A reference to the OpenThread instance.
82      *
83      */
84     explicit Joiner(Instance &aInstance);
85 
86     /**
87      * This method starts the Joiner service.
88      *
89      * @param[in]  aPskd             A pointer to the PSKd.
90      * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be `nullptr`).
91      * @param[in]  aVendorName       A pointer to the Vendor Name (may be `nullptr`).
92      * @param[in]  aVendorModel      A pointer to the Vendor Model (may be `nullptr`).
93      * @param[in]  aVendorSwVersion  A pointer to the Vendor SW Version (may be `nullptr`).
94      * @param[in]  aVendorData       A pointer to the Vendor Data (may be `nullptr`).
95      * @param[in]  aCallback         A pointer to a function that is called when the join operation completes.
96      * @param[in]  aContext          A pointer to application-specific context.
97      *
98      * @retval kErrorNone          Successfully started the Joiner service.
99      * @retval kErrorBusy          The previous attempt is still on-going.
100      * @retval kErrorInvalidState  The IPv6 stack is not enabled or Thread stack is fully enabled.
101      *
102      */
103     Error Start(const char *     aPskd,
104                 const char *     aProvisioningUrl,
105                 const char *     aVendorName,
106                 const char *     aVendorModel,
107                 const char *     aVendorSwVersion,
108                 const char *     aVendorData,
109                 otJoinerCallback aCallback,
110                 void *           aContext);
111 
112     /**
113      * This method stops the Joiner service.
114      *
115      */
116     void Stop(void);
117 
118     /**
119      * This method gets the Joiner State.
120      *
121      * @returns The Joiner state (see `State`).
122      *
123      */
GetState(void) const124     State GetState(void) const { return mState; }
125 
126     /**
127      * This method retrieves the Joiner ID.
128      *
129      * @returns The Joiner ID.
130      *
131      */
GetId(void) const132     const Mac::ExtAddress &GetId(void) const { return mId; }
133 
134     /**
135      * This method gets the Jointer Discerner.
136      *
137      * @returns A pointer to the current Joiner Discerner or `nullptr` if none is set.
138      *
139      */
140     const JoinerDiscerner *GetDiscerner(void) const;
141 
142     /**
143      * This method sets the Joiner Discerner.
144      *
145      * The Joiner Discerner is used to calculate the Joiner ID used during commissioning/joining process.
146      *
147      * By default (when a discerner is not provided or cleared), Joiner ID is derived as first 64 bits of the
148      * result of computing SHA-256 over factory-assigned IEEE EUI-64. Note that this is the main behavior expected by
149      * Thread specification.
150      *
151      * @param[in]   aDiscerner  A Joiner Discerner
152      *
153      * @retval kErrorNone          The Joiner Discerner updated successfully.
154      * @retval kErrorInvalidArgs   @p aDiscerner is not valid (specified length is not within valid range).
155      * @retval kErrorInvalidState  There is an ongoing Joining process so Joiner Discerner could not be changed.
156      *
157      */
158     Error SetDiscerner(const JoinerDiscerner &aDiscerner);
159 
160     /**
161      * This method clears any previously set Joiner Discerner.
162      *
163      * When cleared, Joiner ID is derived as first 64 bits of SHA-256 of factory-assigned IEEE EUI-64.
164      *
165      * @retval kErrorNone          The Joiner Discerner cleared and Joiner ID updated.
166      * @retval kErrorInvalidState  There is an ongoing Joining process so Joiner Discerner could not be changed.
167      *
168      */
169     Error ClearDiscerner(void);
170 
171     /**
172      * This method converts a given Joiner state to its human-readable string representation.
173      *
174      * @param[in] aState  The Joiner state to convert.
175      *
176      * @returns A human-readable string representation of @p aState.
177      *
178      */
179     static const char *StateToString(State aState);
180 
181 private:
182     static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
183 
184     static constexpr uint32_t kConfigExtAddressDelay = 100;  // in msec.
185     static constexpr uint32_t kReponseTimeout        = 4000; ///< Max wait time to receive response (in msec).
186 
187     struct JoinerRouter
188     {
189         Mac::ExtAddress mExtAddr;
190         Mac::PanId      mPanId;
191         uint16_t        mJoinerUdpPort;
192         uint8_t         mChannel;
193         uint8_t         mPriority;
194     };
195 
196     static void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult, void *aContext);
197     void        HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult);
198 
199     static void HandleSecureCoapClientConnect(bool aConnected, void *aContext);
200     void        HandleSecureCoapClientConnect(bool aConnected);
201 
202     static void HandleJoinerFinalizeResponse(void *               aContext,
203                                              otMessage *          aMessage,
204                                              const otMessageInfo *aMessageInfo,
205                                              Error                aResult);
206     void HandleJoinerFinalizeResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
207 
208     static void HandleJoinerEntrust(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
209     void        HandleJoinerEntrust(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
210 
211     static void HandleTimer(Timer &aTimer);
212     void        HandleTimer(void);
213 
214     void    SetState(State aState);
215     void    SetIdFromIeeeEui64(void);
216     void    SaveDiscoveredJoinerRouter(const Mle::DiscoverScanner::ScanResult &aResult);
217     void    TryNextJoinerRouter(Error aPrevError);
218     Error   Connect(JoinerRouter &aRouter);
219     void    Finish(Error aError);
220     uint8_t CalculatePriority(int8_t aRssi, bool aSteeringDataAllowsAny);
221 
222     Error PrepareJoinerFinalizeMessage(const char *aProvisioningUrl,
223                                        const char *aVendorName,
224                                        const char *aVendorModel,
225                                        const char *aVendorSwVersion,
226                                        const char *aVendorData);
227     void  FreeJoinerFinalizeMessage(void);
228     void  SendJoinerFinalize(void);
229     void  SendJoinerEntrustResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aRequestInfo);
230 
231 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
232     void LogCertMessage(const char *aText, const Coap::Message &aMessage) const;
233 #endif
234 
235     Mac::ExtAddress mId;
236     JoinerDiscerner mDiscerner;
237 
238     State mState;
239 
240     otJoinerCallback mCallback;
241     void *           mContext;
242 
243     JoinerRouter mJoinerRouters[OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES];
244     uint16_t     mJoinerRouterIndex;
245 
246     Coap::Message *mFinalizeMessage;
247 
248     TimerMilli     mTimer;
249     Coap::Resource mJoinerEntrust;
250 };
251 
252 } // namespace MeshCoP
253 
254 DefineMapEnum(otJoinerState, MeshCoP::Joiner::State);
255 
256 } // namespace ot
257 
258 #endif // OPENTHREAD_CONFIG_JOINER_ENABLE
259 
260 #endif // JOINER_HPP_
261