• 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_message.hpp"
44 #include "coap/coap_secure.hpp"
45 #include "common/as_core_type.hpp"
46 #include "common/callback.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/meshcop.hpp"
53 #include "meshcop/meshcop_tlvs.hpp"
54 #include "meshcop/secure_transport.hpp"
55 #include "thread/discover_scanner.hpp"
56 #include "thread/tmf.hpp"
57 
58 namespace ot {
59 
60 namespace MeshCoP {
61 
62 #if !OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
63 #error "Joiner feature requires `OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE`"
64 #endif
65 
66 class Joiner : public InstanceLocator, private NonCopyable
67 {
68     friend class Tmf::Agent;
69 
70 public:
71     /**
72      * Type defines the Joiner State.
73      */
74     enum State : uint8_t
75     {
76         kStateIdle      = OT_JOINER_STATE_IDLE,
77         kStateDiscover  = OT_JOINER_STATE_DISCOVER,
78         kStateConnect   = OT_JOINER_STATE_CONNECT,
79         kStateConnected = OT_JOINER_STATE_CONNECTED,
80         kStateEntrust   = OT_JOINER_STATE_ENTRUST,
81         kStateJoined    = OT_JOINER_STATE_JOINED,
82     };
83 
84     /**
85      * Initializes the Joiner object.
86      *
87      * @param[in]  aInstance     A reference to the OpenThread instance.
88      */
89     explicit Joiner(Instance &aInstance);
90 
91     /**
92      * Starts the Joiner service.
93      *
94      * @param[in]  aPskd             A pointer to the PSKd.
95      * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be `nullptr`).
96      * @param[in]  aVendorName       A pointer to the Vendor Name (may be `nullptr`).
97      * @param[in]  aVendorModel      A pointer to the Vendor Model (may be `nullptr`).
98      * @param[in]  aVendorSwVersion  A pointer to the Vendor SW Version (may be `nullptr`).
99      * @param[in]  aVendorData       A pointer to the Vendor Data (may be `nullptr`).
100      * @param[in]  aCallback         A pointer to a function that is called when the join operation completes.
101      * @param[in]  aContext          A pointer to application-specific context.
102      *
103      * @retval kErrorNone          Successfully started the Joiner service.
104      * @retval kErrorBusy          The previous attempt is still on-going.
105      * @retval kErrorInvalidState  The IPv6 stack is not enabled or Thread stack is fully enabled.
106      */
107     Error Start(const char      *aPskd,
108                 const char      *aProvisioningUrl,
109                 const char      *aVendorName,
110                 const char      *aVendorModel,
111                 const char      *aVendorSwVersion,
112                 const char      *aVendorData,
113                 otJoinerCallback aCallback,
114                 void            *aContext);
115 
116     /**
117      * Stops the Joiner service.
118      */
119     void Stop(void);
120 
121     /**
122      * Gets the Joiner State.
123      *
124      * @returns The Joiner state (see `State`).
125      */
GetState(void) const126     State GetState(void) const { return mState; }
127 
128     /**
129      * Retrieves the Joiner ID.
130      *
131      * @returns The Joiner ID.
132      */
GetId(void) const133     const Mac::ExtAddress &GetId(void) const { return mId; }
134 
135     /**
136      * Gets the Jointer Discerner.
137      *
138      * @returns A pointer to the current Joiner Discerner or `nullptr` if none is set.
139      */
140     const JoinerDiscerner *GetDiscerner(void) const;
141 
142     /**
143      * 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     Error SetDiscerner(const JoinerDiscerner &aDiscerner);
158 
159     /**
160      * Clears any previously set Joiner Discerner.
161      *
162      * When cleared, Joiner ID is derived as first 64 bits of SHA-256 of factory-assigned IEEE EUI-64.
163      *
164      * @retval kErrorNone          The Joiner Discerner cleared and Joiner ID updated.
165      * @retval kErrorInvalidState  There is an ongoing Joining process so Joiner Discerner could not be changed.
166      */
167     Error ClearDiscerner(void);
168 
169     /**
170      * Converts a given Joiner state to its human-readable string representation.
171      *
172      * @param[in] aState  The Joiner state to convert.
173      *
174      * @returns A human-readable string representation of @p aState.
175      */
176     static const char *StateToString(State aState);
177 
178 private:
179     static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
180 
181     static constexpr uint32_t kConfigExtAddressDelay = 100;  // in msec.
182     static constexpr uint32_t kResponseTimeout       = 4000; ///< Max wait time to receive response (in msec).
183 
184     struct JoinerRouter
185     {
186         Mac::ExtAddress mExtAddr;
187         Mac::PanId      mPanId;
188         uint16_t        mJoinerUdpPort;
189         uint8_t         mChannel;
190         uint8_t         mPriority;
191     };
192 
193     static void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult, void *aContext);
194     void        HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult);
195 
196     static void HandleSecureCoapClientConnect(Dtls::Session::ConnectEvent aEvent, void *aContext);
197     void        HandleSecureCoapClientConnect(Dtls::Session::ConnectEvent aEvent);
198 
199     static void HandleJoinerFinalizeResponse(void                *aContext,
200                                              otMessage           *aMessage,
201                                              const otMessageInfo *aMessageInfo,
202                                              otError              aResult);
203     void HandleJoinerFinalizeResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
204 
205     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
206 
207     void HandleTimer(void);
208 
209     void    SetState(State aState);
210     void    SetIdFromIeeeEui64(void);
211     void    SaveDiscoveredJoinerRouter(const Mle::DiscoverScanner::ScanResult &aResult);
212     void    TryNextJoinerRouter(Error aPrevError);
213     Error   Connect(JoinerRouter &aRouter);
214     void    Finish(Error aError);
215     uint8_t CalculatePriority(int8_t aRssi, bool aSteeringDataAllowsAny);
216 
217     Error PrepareJoinerFinalizeMessage(const char *aProvisioningUrl,
218                                        const char *aVendorName,
219                                        const char *aVendorModel,
220                                        const char *aVendorSwVersion,
221                                        const char *aVendorData);
222     void  FreeJoinerFinalizeMessage(void);
223     void  SendJoinerFinalize(void);
224     void  SendJoinerEntrustResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aRequestInfo);
225 
226     using JoinerTimer = TimerMilliIn<Joiner, &Joiner::HandleTimer>;
227 
228     Mac::ExtAddress mId;
229     JoinerDiscerner mDiscerner;
230 
231     State mState;
232 
233     Callback<otJoinerCallback> mCallback;
234 
235     JoinerRouter mJoinerRouters[OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES];
236     uint16_t     mJoinerRouterIndex;
237 
238     Coap::Message *mFinalizeMessage;
239 
240     JoinerTimer mTimer;
241 };
242 
243 DeclareTmfHandler(Joiner, kUriJoinerEntrust);
244 
245 } // namespace MeshCoP
246 
247 DefineMapEnum(otJoinerState, MeshCoP::Joiner::State);
248 
249 } // namespace ot
250 
251 #endif // OPENTHREAD_CONFIG_JOINER_ENABLE
252 
253 #endif // JOINER_HPP_
254