1 /* 2 * Copyright (c) 2020, 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 Thread helper. 32 */ 33 34 #ifndef OTBR_THREAD_HELPER_HPP_ 35 #define OTBR_THREAD_HELPER_HPP_ 36 37 #include "openthread-br/config.h" 38 39 #include <chrono> 40 #include <functional> 41 #include <map> 42 #include <random> 43 #include <string> 44 #include <vector> 45 46 #include <openthread/instance.h> 47 #include <openthread/ip6.h> 48 #include <openthread/jam_detection.h> 49 #include <openthread/joiner.h> 50 #include <openthread/netdata.h> 51 #include <openthread/thread.h> 52 #include "mdns/mdns.hpp" 53 #if OTBR_ENABLE_TELEMETRY_DATA_API 54 #include "proto/thread_telemetry.pb.h" 55 #endif 56 57 namespace otbr { 58 namespace Ncp { 59 class ControllerOpenThread; 60 } 61 } // namespace otbr 62 63 namespace otbr { 64 namespace agent { 65 66 /** 67 * This class implements Thread helper. 68 */ 69 class ThreadHelper 70 { 71 public: 72 using DeviceRoleHandler = std::function<void(otDeviceRole)>; 73 using ScanHandler = std::function<void(otError, const std::vector<otActiveScanResult> &)>; 74 using EnergyScanHandler = std::function<void(otError, const std::vector<otEnergyScanResult> &)>; 75 using ResultHandler = std::function<void(otError)>; 76 using AttachHandler = std::function<void(otError, int64_t)>; 77 using UpdateMeshCopTxtHandler = std::function<void(std::map<std::string, std::vector<uint8_t>>)>; 78 using DatasetChangeHandler = std::function<void(const otOperationalDatasetTlvs &)>; 79 80 /** 81 * The constructor of a Thread helper. 82 * 83 * @param[in] aInstance The Thread instance. 84 * @param[in] aNcp The ncp controller. 85 * 86 */ 87 ThreadHelper(otInstance *aInstance, otbr::Ncp::ControllerOpenThread *aNcp); 88 89 /** 90 * This method adds a callback for device role change. 91 * 92 * @param[in] aHandler The device role handler. 93 * 94 */ 95 void AddDeviceRoleHandler(DeviceRoleHandler aHandler); 96 97 /** 98 * This method adds a callback for active dataset change. 99 * 100 * @param[in] aHandler The active dataset change handler. 101 */ 102 void AddActiveDatasetChangeHandler(DatasetChangeHandler aHandler); 103 104 /** 105 * This method permits unsecure join on port. 106 * 107 * @param[in] aPort The port number. 108 * @param[in] aSeconds The timeout to close the port, 0 for never close. 109 * 110 * @returns The error value of underlying OpenThread api calls. 111 * 112 */ 113 otError PermitUnsecureJoin(uint16_t aPort, uint32_t aSeconds); 114 115 /** 116 * This method performs a Thread network scan. 117 * 118 * @param[in] aHandler The scan result handler. 119 * 120 */ 121 void Scan(ScanHandler aHandler); 122 123 /** 124 * This method performs an IEEE 802.15.4 Energy Scan. 125 * 126 * @param[in] aScanDuration The duration for the scan, in milliseconds. 127 * @param[in] aHandler The scan result handler. 128 * 129 */ 130 void EnergyScan(uint32_t aScanDuration, EnergyScanHandler aHandler); 131 132 /** 133 * This method attaches the device to the Thread network. 134 * 135 * @note The joiner start and the attach proccesses are exclusive 136 * 137 * @param[in] aNetworkName The network name. 138 * @param[in] aPanId The pan id, UINT16_MAX for random. 139 * @param[in] aExtPanId The extended pan id, UINT64_MAX for random. 140 * @param[in] aNetworkKey The network key, empty for random. 141 * @param[in] aPSKc The pre-shared commissioner key, empty for random. 142 * @param[in] aChannelMask A bitmask for valid channels, will random select one. 143 * @param[in] aHandler The attach result handler. 144 * 145 */ 146 void Attach(const std::string &aNetworkName, 147 uint16_t aPanId, 148 uint64_t aExtPanId, 149 const std::vector<uint8_t> &aNetworkKey, 150 const std::vector<uint8_t> &aPSKc, 151 uint32_t aChannelMask, 152 AttachHandler aHandler); 153 154 /** 155 * This method detaches the device from the Thread network. 156 * 157 * @returns The error value of underlying OpenThread API calls. 158 * 159 */ 160 otError Detach(void); 161 162 /** 163 * This method attaches the device to the Thread network. 164 * 165 * @note The joiner start and the attach proccesses are exclusive, and the 166 * network parameter will be set through the active dataset. 167 * 168 * @param[in] aHandler The attach result handler. 169 * 170 */ 171 void Attach(AttachHandler aHandler); 172 173 /** 174 * This method makes all nodes in the current network attach to the network specified by the dataset TLVs. 175 * 176 * @param[in] aDatasetTlvs The dataset TLVs. 177 * @param[in] aHandler The result handler. 178 * 179 */ 180 void AttachAllNodesTo(const std::vector<uint8_t> &aDatasetTlvs, AttachHandler aHandler); 181 182 /** 183 * This method resets the OpenThread stack. 184 * 185 * @returns The error value of underlying OpenThread api calls. 186 * 187 */ 188 otError Reset(void); 189 190 /** 191 * This method triggers a thread join process. 192 * 193 * @note The joiner start and the attach proccesses are exclusive 194 * 195 * @param[in] aPskd The pre-shared key for device. 196 * @param[in] aProvisioningUrl The provision url. 197 * @param[in] aVendorName The vendor name. 198 * @param[in] aVendorModel The vendor model. 199 * @param[in] aVendorSwVersion The vendor software version. 200 * @param[in] aVendorData The vendor custom data. 201 * @param[in] aHandler The join result handler. 202 * 203 */ 204 void JoinerStart(const std::string &aPskd, 205 const std::string &aProvisioningUrl, 206 const std::string &aVendorName, 207 const std::string &aVendorModel, 208 const std::string &aVendorSwVersion, 209 const std::string &aVendorData, 210 ResultHandler aHandler); 211 212 /** 213 * This method tries to restore the network after reboot 214 * 215 * @returns The error value of underlying OpenThread api calls. 216 * 217 */ 218 otError TryResumeNetwork(void); 219 220 /** 221 * This method returns the underlying OpenThread instance. 222 * 223 * @returns The underlying instance. 224 * 225 */ GetInstance(void)226 otInstance *GetInstance(void) { return mInstance; } 227 228 /** 229 * This method handles OpenThread state changed notification. 230 * 231 * @param[in] aFlags A bit-field indicating specific state that has changed. See `OT_CHANGED_*` definitions. 232 * 233 */ 234 void StateChangedCallback(otChangedFlags aFlags); 235 236 #if OTBR_ENABLE_DBUS_SERVER 237 /** 238 * This method sets a callback for calls of UpdateVendorMeshCopTxtEntries D-Bus API. 239 * 240 * @param[in] aHandler The handler on MeshCoP TXT changes. 241 * 242 */ SetUpdateMeshCopTxtHandler(UpdateMeshCopTxtHandler aHandler)243 void SetUpdateMeshCopTxtHandler(UpdateMeshCopTxtHandler aHandler) 244 { 245 mUpdateMeshCopTxtHandler = std::move(aHandler); 246 } 247 248 /** 249 * This method handles MeshCoP TXT updates done by UpdateVendorMeshCopTxtEntries D-Bus API. 250 * 251 * @param[in] aUpdate The key-value pairs to be updated in the TXT record. 252 * 253 */ 254 void OnUpdateMeshCopTxt(std::map<std::string, std::vector<uint8_t>> aUpdate); 255 #endif 256 257 void DetachGracefully(ResultHandler aHandler); 258 259 #if OTBR_ENABLE_TELEMETRY_DATA_API 260 /** 261 * This method populates the telemetry data with best effort. The best effort means, for a given 262 * telemetry, if its retrieval has error, it is left unpopulated and the process continues to 263 * retrieve the remaining telemetries instead of the immediately return. The error code 264 * OT_ERRROR_FAILED will be returned if there is one or more error(s) happened in the process. 265 * 266 * @param[in] aPublisher The Mdns::Publisher to provide MDNS telemetry if it is not `nullptr`. 267 * @param[in] telemetryData The telemetry data to be populated. 268 * 269 * @retval OTBR_ERROR_NONE There is no error happened in the process. 270 * @retval OT_ERRROR_FAILED There is one or more error(s) happened in the process. 271 */ 272 otError RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadnetwork::TelemetryData &telemetryData); 273 #endif // OTBR_ENABLE_TELEMETRY_DATA_API 274 275 /** 276 * This method logs OpenThread action result. 277 * 278 * @param[in] aAction The action OpenThread performs. 279 * @param[in] aError The action result. 280 * 281 */ 282 static void LogOpenThreadResult(const char *aAction, otError aError); 283 284 private: 285 static void ActiveScanHandler(otActiveScanResult *aResult, void *aThreadHelper); 286 void ActiveScanHandler(otActiveScanResult *aResult); 287 288 static void EnergyScanCallback(otEnergyScanResult *aResult, void *aThreadHelper); 289 void EnergyScanCallback(otEnergyScanResult *aResult); 290 291 static void JoinerCallback(otError aError, void *aThreadHelper); 292 void JoinerCallback(otError aResult); 293 294 static void MgmtSetResponseHandler(otError aResult, void *aContext); 295 void MgmtSetResponseHandler(otError aResult); 296 297 static void DetachGracefullyCallback(void *aContext); 298 void DetachGracefullyCallback(void); 299 300 void RandomFill(void *aBuf, size_t size); 301 uint8_t RandomChannelFromChannelMask(uint32_t aChannelMask); 302 303 void ActiveDatasetChangedCallback(void); 304 305 otInstance *mInstance; 306 307 otbr::Ncp::ControllerOpenThread *mNcp; 308 309 ScanHandler mScanHandler; 310 std::vector<otActiveScanResult> mScanResults; 311 EnergyScanHandler mEnergyScanHandler; 312 std::vector<otEnergyScanResult> mEnergyScanResults; 313 314 std::vector<DeviceRoleHandler> mDeviceRoleHandlers; 315 std::vector<DatasetChangeHandler> mActiveDatasetChangeHandlers; 316 317 std::map<uint16_t, size_t> mUnsecurePortRefCounter; 318 319 bool mWaitingMgmtSetResponse = 320 false; // During waiting for mgmt set response, calls to AttachHandler by StateChangedCallback will be ignored 321 int64_t mAttachDelayMs = 0; 322 AttachHandler mAttachHandler; 323 ResultHandler mJoinerHandler; 324 325 ResultHandler mDetachGracefullyHandler = nullptr; 326 327 otOperationalDatasetTlvs mAttachPendingDatasetTlvs = {}; 328 329 std::random_device mRandomDevice; 330 331 #if OTBR_ENABLE_DBUS_SERVER 332 UpdateMeshCopTxtHandler mUpdateMeshCopTxtHandler; 333 #endif 334 335 #if OTBR_ENABLE_TELEMETRY_DATA_API && (OTBR_ENABLE_NAT64 || OTBR_ENABLE_DHCP6_PD) 336 static constexpr uint8_t kNat64PdCommonHashSaltLength = 16; 337 uint8_t mNat64PdCommonSalt[kNat64PdCommonHashSaltLength]; 338 #endif 339 }; 340 341 } // namespace agent 342 } // namespace otbr 343 344 #endif // OTBR_THREAD_HELPER_HPP_ 345