Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / src / agent / ncp_openthread.cpp
1 /*
2  *    Copyright (c) 2019, 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 #include "agent/ncp_openthread.hpp"
30
31 #include <assert.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 #include <openthread/backbone_router_ftd.h>
36 #include <openthread/cli.h>
37 #include <openthread/dataset.h>
38 #include <openthread/logging.h>
39 #include <openthread/srp_server.h>
40 #include <openthread/tasklet.h>
41 #include <openthread/thread.h>
42 #include <openthread/thread_ftd.h>
43 #include <openthread/platform/logging.h>
44 #include <openthread/platform/misc.h>
45 #include <openthread/platform/radio.h>
46 #include <openthread/platform/settings.h>
47
48 #include "common/code_utils.hpp"
49 #include "common/logging.hpp"
50 #include "common/types.hpp"
51
52 #if OTBR_ENABLE_LEGACY
53 #include <ot-legacy-pairing-ext.h>
54 #endif
55
56 using std::chrono::duration_cast;
57 using std::chrono::microseconds;
58 using std::chrono::seconds;
59 using std::chrono::steady_clock;
60
61 namespace otbr {
62 namespace Ncp {
63
64 ControllerOpenThread::ControllerOpenThread(const char *aInterfaceName,
65                                            const char *aRadioUrl,
66                                            const char *aBackboneInterfaceName)
67     : mInstance(nullptr)
68 {
69     memset(&mConfig, 0, sizeof(mConfig));
70
71     mConfig.mInterfaceName         = aInterfaceName;
72     mConfig.mBackboneInterfaceName = aBackboneInterfaceName;
73     mConfig.mRadioUrl              = aRadioUrl;
74     mConfig.mSpeedUpFactor         = 1;
75 }
76
77 ControllerOpenThread::~ControllerOpenThread(void)
78 {
79     otInstanceFinalize(mInstance);
80     otSysDeinit();
81 }
82
83 otbrError ControllerOpenThread::Init(void)
84 {
85     otbrError  error = OTBR_ERROR_NONE;
86     otLogLevel level = OT_LOG_LEVEL_NONE;
87
88     switch (otbrLogGetLevel())
89     {
90     case OTBR_LOG_EMERG:
91     case OTBR_LOG_ALERT:
92     case OTBR_LOG_CRIT:
93         level = OT_LOG_LEVEL_CRIT;
94         break;
95     case OTBR_LOG_ERR:
96     case OTBR_LOG_WARNING:
97         level = OT_LOG_LEVEL_WARN;
98         break;
99     case OTBR_LOG_NOTICE:
100         level = OT_LOG_LEVEL_NOTE;
101         break;
102     case OTBR_LOG_INFO:
103         level = OT_LOG_LEVEL_INFO;
104         break;
105     case OTBR_LOG_DEBUG:
106         level = OT_LOG_LEVEL_DEBG;
107         break;
108     default:
109         ExitNow(error = OTBR_ERROR_OPENTHREAD);
110         break;
111     }
112     VerifyOrExit(otLoggingSetLevel(level) == OT_ERROR_NONE, error = OTBR_ERROR_OPENTHREAD);
113
114     mInstance = otSysInit(&mConfig);
115     otCliUartInit(mInstance);
116 #if OTBR_ENABLE_LEGACY
117     otLegacyInit();
118 #endif
119
120     {
121         otError result = otSetStateChangedCallback(mInstance, &ControllerOpenThread::HandleStateChanged, this);
122
123         agent::ThreadHelper::LogOpenThreadResult("Set state callback", result);
124         VerifyOrExit(result == OT_ERROR_NONE, error = OTBR_ERROR_OPENTHREAD);
125     }
126
127 #if OTBR_ENABLE_BACKBONE_ROUTER
128     otBackboneRouterSetDomainPrefixCallback(mInstance, &ControllerOpenThread::HandleBackboneRouterDomainPrefixEvent,
129                                             this);
130     otBackboneRouterSetNdProxyCallback(mInstance, &ControllerOpenThread::HandleBackboneRouterNdProxyEvent, this);
131 #endif
132
133 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
134     otSrpServerSetEnabled(mInstance, /* aEnabled */ true);
135 #endif
136
137     mThreadHelper = std::unique_ptr<otbr::agent::ThreadHelper>(new otbr::agent::ThreadHelper(mInstance, this));
138
139 exit:
140     return error;
141 }
142
143 void ControllerOpenThread::HandleStateChanged(otChangedFlags aFlags)
144 {
145     if (aFlags & OT_CHANGED_THREAD_NETWORK_NAME)
146     {
147         EventEmitter::Emit(kEventNetworkName, otThreadGetNetworkName(mInstance));
148     }
149
150     if (aFlags & OT_CHANGED_THREAD_EXT_PANID)
151     {
152         EventEmitter::Emit(kEventExtPanId, otThreadGetExtendedPanId(mInstance));
153     }
154
155     if (aFlags & OT_CHANGED_THREAD_ROLE)
156     {
157         bool attached = false;
158
159         switch (otThreadGetDeviceRole(mInstance))
160         {
161         case OT_DEVICE_ROLE_DISABLED:
162 #if OTBR_ENABLE_LEGACY
163             otLegacyStop();
164 #endif
165             break;
166         case OT_DEVICE_ROLE_CHILD:
167         case OT_DEVICE_ROLE_ROUTER:
168         case OT_DEVICE_ROLE_LEADER:
169 #if OTBR_ENABLE_LEGACY
170             otLegacyStart();
171 #endif
172             attached = true;
173             break;
174         default:
175             break;
176         }
177
178         EventEmitter::Emit(kEventThreadState, attached);
179     }
180
181 #if OTBR_ENABLE_BACKBONE_ROUTER
182     if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
183     {
184         EventEmitter::Emit(kEventBackboneRouterState);
185     }
186 #endif
187
188     mThreadHelper->StateChangedCallback(aFlags);
189 }
190
191 static struct timeval ToTimeVal(const microseconds &aTime)
192 {
193     constexpr int  kUsPerSecond = 1000000;
194     struct timeval val;
195
196     val.tv_sec  = aTime.count() / kUsPerSecond;
197     val.tv_usec = aTime.count() % kUsPerSecond;
198
199     return val;
200 };
201
202 void ControllerOpenThread::UpdateFdSet(otSysMainloopContext &aMainloop)
203 {
204     microseconds timeout = microseconds(aMainloop.mTimeout.tv_usec) + seconds(aMainloop.mTimeout.tv_sec);
205     auto         now     = steady_clock::now();
206
207     if (otTaskletsArePending(mInstance))
208     {
209         timeout = microseconds::zero();
210     }
211     else if (!mTimers.empty())
212     {
213         if (mTimers.begin()->first < now)
214         {
215             timeout = microseconds::zero();
216         }
217         else
218         {
219             timeout = std::min(timeout, duration_cast<microseconds>(mTimers.begin()->first - now));
220         }
221     }
222
223     aMainloop.mTimeout = ToTimeVal(timeout);
224
225     otSysMainloopUpdate(mInstance, &aMainloop);
226 }
227
228 void ControllerOpenThread::Process(const otSysMainloopContext &aMainloop)
229 {
230     auto now = steady_clock::now();
231
232     otTaskletsProcess(mInstance);
233
234     otSysMainloopProcess(mInstance, &aMainloop);
235
236     while (!mTimers.empty() && mTimers.begin()->first <= now)
237     {
238         mTimers.begin()->second();
239         mTimers.erase(mTimers.begin());
240     }
241
242     if (getenv("OTBR_NO_AUTO_ATTACH") == nullptr && mThreadHelper->TryResumeNetwork() == OT_ERROR_NONE)
243     {
244         setenv("OTBR_NO_AUTO_ATTACH", "1", 0);
245     }
246 }
247
248 otbrError ControllerOpenThread::RequestEvent(int aEvent)
249 {
250     otbrError ret = OTBR_ERROR_NONE;
251
252     switch (aEvent)
253     {
254     case kEventExtPanId:
255     {
256         EventEmitter::Emit(kEventExtPanId, otThreadGetExtendedPanId(mInstance));
257         break;
258     }
259     case kEventThreadState:
260     {
261         bool attached = false;
262
263         switch (otThreadGetDeviceRole(mInstance))
264         {
265         case OT_DEVICE_ROLE_CHILD:
266         case OT_DEVICE_ROLE_ROUTER:
267         case OT_DEVICE_ROLE_LEADER:
268             attached = true;
269             break;
270         default:
271             break;
272         }
273
274         EventEmitter::Emit(kEventThreadState, attached);
275         break;
276     }
277     case kEventNetworkName:
278     {
279         EventEmitter::Emit(kEventNetworkName, otThreadGetNetworkName(mInstance));
280         break;
281     }
282     case kEventPSKc:
283     {
284         EventEmitter::Emit(kEventPSKc, otThreadGetPskc(mInstance));
285         break;
286     }
287     case kEventThreadVersion:
288     {
289         EventEmitter::Emit(kEventThreadVersion, otThreadGetVersion());
290         break;
291     }
292     case kEventExtAddr:
293     {
294         const otExtAddress *extAddr;
295
296         extAddr = otLinkGetExtendedAddress(mInstance);
297         EventEmitter::Emit(kEventExtAddr, extAddr);
298         break;
299     }
300     default:
301         assert(false);
302         break;
303     }
304
305     return ret;
306 }
307
308 void ControllerOpenThread::PostTimerTask(std::chrono::steady_clock::time_point aTimePoint,
309                                          const std::function<void(void)> &     aTask)
310 {
311     mTimers.insert({aTimePoint, aTask});
312 }
313
314 void ControllerOpenThread::RegisterResetHandler(std::function<void(void)> aHandler)
315 {
316     mResetHandlers.emplace_back(std::move(aHandler));
317 }
318
319 #if OTBR_ENABLE_BACKBONE_ROUTER
320 void ControllerOpenThread::HandleBackboneRouterDomainPrefixEvent(void *                            aContext,
321                                                                  otBackboneRouterDomainPrefixEvent aEvent,
322                                                                  const otIp6Prefix *               aDomainPrefix)
323 {
324     static_cast<ControllerOpenThread *>(aContext)->HandleBackboneRouterDomainPrefixEvent(aEvent, aDomainPrefix);
325 }
326
327 void ControllerOpenThread::HandleBackboneRouterDomainPrefixEvent(otBackboneRouterDomainPrefixEvent aEvent,
328                                                                  const otIp6Prefix *               aDomainPrefix)
329 {
330     EventEmitter::Emit(kEventBackboneRouterDomainPrefixEvent, aEvent, aDomainPrefix);
331 }
332
333 void ControllerOpenThread::HandleBackboneRouterNdProxyEvent(void *                       aContext,
334                                                             otBackboneRouterNdProxyEvent aEvent,
335                                                             const otIp6Address *         aAddress)
336 {
337     static_cast<ControllerOpenThread *>(aContext)->HandleBackboneRouterNdProxyEvent(aEvent, aAddress);
338 }
339
340 void ControllerOpenThread::HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent,
341                                                             const otIp6Address *         aAddress)
342 {
343     EventEmitter::Emit(kEventBackboneRouterNdProxyEvent, aEvent, aAddress);
344 }
345 #endif
346
347 Controller *Controller::Create(const char *aInterfaceName, const char *aRadioUrl, const char *aBackboneInterfaceName)
348 {
349     return new ControllerOpenThread(aInterfaceName, aRadioUrl, aBackboneInterfaceName);
350 }
351
352 /*
353  * Provide, if required an "otPlatLog()" function
354  */
355 extern "C" void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
356 {
357     OT_UNUSED_VARIABLE(aLogRegion);
358
359     int otbrLogLevel;
360
361     switch (aLogLevel)
362     {
363     case OT_LOG_LEVEL_NONE:
364         otbrLogLevel = OTBR_LOG_EMERG;
365         break;
366     case OT_LOG_LEVEL_CRIT:
367         otbrLogLevel = OTBR_LOG_CRIT;
368         break;
369     case OT_LOG_LEVEL_WARN:
370         otbrLogLevel = OTBR_LOG_WARNING;
371         break;
372     case OT_LOG_LEVEL_NOTE:
373         otbrLogLevel = OTBR_LOG_NOTICE;
374         break;
375     case OT_LOG_LEVEL_INFO:
376         otbrLogLevel = OTBR_LOG_INFO;
377         break;
378     case OT_LOG_LEVEL_DEBG:
379         otbrLogLevel = OTBR_LOG_DEBUG;
380         break;
381     default:
382         otbrLogLevel = OTBR_LOG_DEBUG;
383         break;
384     }
385
386     va_list ap;
387     va_start(ap, aFormat);
388     otbrLogv(otbrLogLevel, aFormat, ap);
389     va_end(ap);
390 }
391
392 } // namespace Ncp
393 } // namespace otbr