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