Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / OpenThread / GenericThreadStackManagerImpl_OpenThread.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2019 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *          Contains non-inline method definitions for the
23  *          GenericThreadStackManagerImpl_OpenThread<> template.
24  */
25
26 #ifndef GENERIC_THREAD_STACK_MANAGER_IMPL_OPENTHREAD_IPP
27 #define GENERIC_THREAD_STACK_MANAGER_IMPL_OPENTHREAD_IPP
28
29 #include <openthread/cli.h>
30 #include <openthread/dataset.h>
31 #include <openthread/joiner.h>
32 #include <openthread/link.h>
33 #include <openthread/netdata.h>
34 #include <openthread/tasklet.h>
35 #include <openthread/thread.h>
36
37 #if CHIP_DEVICE_CONFIG_THREAD_FTD
38 #include <openthread/dataset_ftd.h>
39 #include <openthread/thread_ftd.h>
40 #endif
41
42 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
43 #include <openthread/srp_client.h>
44 #endif
45
46 #include <core/CHIPEncoding.h>
47 #include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>
48 #include <platform/OpenThread/OpenThreadUtils.h>
49 #include <platform/ThreadStackManager.h>
50 #include <platform/internal/CHIPDeviceLayerInternal.h>
51 #include <platform/internal/DeviceNetworkInfo.h>
52 #include <support/CodeUtils.h>
53 #include <support/logging/CHIPLogging.h>
54
55 extern "C" void otSysProcessDrivers(otInstance * aInstance);
56
57 namespace chip {
58 namespace DeviceLayer {
59 namespace Internal {
60
61 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
62 template class GenericThreadStackManagerImpl_OpenThread<ThreadStackManagerImpl>;
63
64 /**
65  * Called by OpenThread to alert the ThreadStackManager of a change in the state of the Thread stack.
66  *
67  * By default, applications never need to call this method directly.  However, applications that
68  * wish to receive OpenThread state change call-backs directly from OpenThread (e.g. by calling
69  * otSetStateChangedCallback() with their own callback function) can call this method to pass
70  * state change events to the ThreadStackManager.
71  */
72 template <class ImplClass>
73 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::OnOpenThreadStateChange(uint32_t flags, void * context)
74 {
75     ChipDeviceEvent event;
76     event.Type                                = DeviceEventType::kThreadStateChange;
77     event.ThreadStateChange.RoleChanged       = (flags & OT_CHANGED_THREAD_ROLE) != 0;
78     event.ThreadStateChange.AddressChanged    = (flags & (OT_CHANGED_IP6_ADDRESS_ADDED | OT_CHANGED_IP6_ADDRESS_REMOVED)) != 0;
79     event.ThreadStateChange.NetDataChanged    = (flags & OT_CHANGED_THREAD_NETDATA) != 0;
80     event.ThreadStateChange.ChildNodesChanged = (flags & (OT_CHANGED_THREAD_CHILD_ADDED | OT_CHANGED_THREAD_CHILD_REMOVED)) != 0;
81     event.ThreadStateChange.OpenThread.Flags  = flags;
82
83 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
84     if (event.ThreadStateChange.AddressChanged)
85     {
86         const otSrpClientHostInfo * hostInfo =
87             otSrpClientGetHostInfo(static_cast<GenericThreadStackManagerImpl_OpenThread *>(context)->Impl()->OTInstance());
88         if (hostInfo && hostInfo->mName)
89         {
90             static_cast<GenericThreadStackManagerImpl_OpenThread *>(context)->Impl()->_SetupSrpHost(hostInfo->mName);
91         }
92     }
93 #endif
94
95     PlatformMgr().PostEvent(&event);
96 }
97
98 template <class ImplClass>
99 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_ProcessThreadActivity(void)
100 {
101     otTaskletsProcess(mOTInst);
102     otSysProcessDrivers(mOTInst);
103 }
104
105 template <class ImplClass>
106 bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_HaveRouteToAddress(const IPAddress & destAddr)
107 {
108     bool res = false;
109
110     // Lock OpenThread
111     Impl()->LockThreadStack();
112
113     // No routing of IPv4 over Thread.
114     VerifyOrExit(!destAddr.IsIPv4(), res = false);
115
116     // If the device is attached to a Thread network...
117     if (IsThreadAttachedNoLock())
118     {
119         // Link-local addresses are always presumed to be routable, provided the device is attached.
120         if (destAddr.IsIPv6LinkLocal())
121         {
122             ExitNow(res = true);
123         }
124
125         // Iterate over the routes known to the OpenThread stack looking for a route that covers the
126         // destination address.  If found, consider the address routable.
127         // Ignore any routes advertised by this device.
128         // If the destination address is a ULA, ignore default routes. Border routers advertising
129         // default routes are not expected to be capable of routing CHIP fabric ULAs unless they
130         // advertise those routes specifically.
131         {
132             otError otErr;
133             otNetworkDataIterator routeIter = OT_NETWORK_DATA_ITERATOR_INIT;
134             otExternalRouteConfig routeConfig;
135             const bool destIsULA = destAddr.IsIPv6ULA();
136
137             while ((otErr = otNetDataGetNextRoute(Impl()->OTInstance(), &routeIter, &routeConfig)) == OT_ERROR_NONE)
138             {
139                 const IPPrefix prefix = ToIPPrefix(routeConfig.mPrefix);
140                 char addrStr[64];
141                 prefix.IPAddr.ToString(addrStr);
142                 if (!routeConfig.mNextHopIsThisDevice && (!destIsULA || routeConfig.mPrefix.mLength > 0) &&
143                     ToIPPrefix(routeConfig.mPrefix).MatchAddress(destAddr))
144                 {
145                     ExitNow(res = true);
146                 }
147             }
148         }
149     }
150
151 exit:
152
153     // Unlock OpenThread
154     Impl()->UnlockThreadStack();
155
156     return res;
157 }
158
159 template <class ImplClass>
160 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_OnPlatformEvent(const ChipDeviceEvent * event)
161 {
162     if (event->Type == DeviceEventType::kThreadStateChange)
163     {
164         Impl()->LockThreadStack();
165
166 #if CHIP_DETAIL_LOGGING
167
168         LogOpenThreadStateChange(mOTInst, event->ThreadStateChange.OpenThread.Flags);
169
170 #endif // CHIP_DETAIL_LOGGING
171
172         Impl()->UnlockThreadStack();
173     }
174 }
175
176 template <class ImplClass>
177 bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_IsThreadEnabled(void)
178 {
179     otDeviceRole curRole;
180
181     Impl()->LockThreadStack();
182     curRole = otThreadGetDeviceRole(mOTInst);
183     Impl()->UnlockThreadStack();
184
185     return (curRole != OT_DEVICE_ROLE_DISABLED);
186 }
187
188 template <class ImplClass>
189 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetThreadEnabled(bool val)
190 {
191     otError otErr = OT_ERROR_NONE;
192
193     Impl()->LockThreadStack();
194
195     bool isEnabled    = (otThreadGetDeviceRole(mOTInst) != OT_DEVICE_ROLE_DISABLED);
196     bool isIp6Enabled = otIp6IsEnabled(mOTInst);
197
198     if (val && !isIp6Enabled)
199     {
200         otErr = otIp6SetEnabled(mOTInst, val);
201         VerifyOrExit(otErr == OT_ERROR_NONE, );
202     }
203
204     if (val != isEnabled)
205     {
206         otErr = otThreadSetEnabled(mOTInst, val);
207         VerifyOrExit(otErr == OT_ERROR_NONE, );
208     }
209
210     if (!val && isIp6Enabled)
211     {
212         otErr = otIp6SetEnabled(mOTInst, val);
213         VerifyOrExit(otErr == OT_ERROR_NONE, );
214     }
215
216 exit:
217     Impl()->UnlockThreadStack();
218
219     return MapOpenThreadError(otErr);
220 }
221
222 template <class ImplClass>
223 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetThreadProvision(const DeviceNetworkInfo & netInfo)
224 {
225     otError otErr = OT_ERROR_FAILED;
226     otOperationalDataset newDataset;
227
228     // Form a Thread operational dataset from the given network parameters.
229     memset(&newDataset, 0, sizeof(newDataset));
230
231     if (netInfo.ThreadNetworkName[0] != 0)
232     {
233         strncpy((char *) newDataset.mNetworkName.m8, netInfo.ThreadNetworkName, sizeof(newDataset.mNetworkName.m8));
234         newDataset.mComponents.mIsNetworkNamePresent = true;
235     }
236
237     if (netInfo.FieldPresent.ThreadExtendedPANId)
238     {
239         memcpy(newDataset.mExtendedPanId.m8, netInfo.ThreadExtendedPANId, sizeof(newDataset.mExtendedPanId.m8));
240         newDataset.mComponents.mIsExtendedPanIdPresent = true;
241     }
242
243     if (netInfo.FieldPresent.ThreadMeshPrefix)
244     {
245         memcpy(newDataset.mMeshLocalPrefix.m8, netInfo.ThreadMeshPrefix, sizeof(newDataset.mMeshLocalPrefix.m8));
246         newDataset.mComponents.mIsMeshLocalPrefixPresent = true;
247     }
248
249     memcpy(newDataset.mMasterKey.m8, netInfo.ThreadMasterKey, sizeof(newDataset.mMasterKey.m8));
250     newDataset.mComponents.mIsMasterKeyPresent = true;
251
252     if (netInfo.FieldPresent.ThreadPSKc)
253     {
254         memcpy(newDataset.mPskc.m8, netInfo.ThreadPSKc, sizeof(newDataset.mPskc.m8));
255         newDataset.mComponents.mIsPskcPresent = true;
256     }
257
258     if (netInfo.ThreadPANId != kThreadPANId_NotSpecified)
259     {
260         newDataset.mPanId                      = netInfo.ThreadPANId;
261         newDataset.mComponents.mIsPanIdPresent = true;
262     }
263
264     if (netInfo.ThreadChannel != kThreadChannel_NotSpecified)
265     {
266         newDataset.mChannel                      = netInfo.ThreadChannel;
267         newDataset.mComponents.mIsChannelPresent = true;
268     }
269
270     if (netInfo.ThreadDatasetTimestamp != 0)
271     {
272         newDataset.mActiveTimestamp                      = netInfo.ThreadDatasetTimestamp;
273         newDataset.mComponents.mIsActiveTimestampPresent = true;
274     }
275
276     // Set the dataset as the active dataset for the node.
277     Impl()->LockThreadStack();
278     otErr = otDatasetSetActive(mOTInst, &newDataset);
279     Impl()->UnlockThreadStack();
280
281     // post an event alerting other subsystems about change in provisioning state
282     ChipDeviceEvent event;
283     event.Type                                           = DeviceEventType::kServiceProvisioningChange;
284     event.ServiceProvisioningChange.IsServiceProvisioned = true;
285     PlatformMgr().PostEvent(&event);
286
287     return MapOpenThreadError(otErr);
288 }
289
290 template <class ImplClass>
291 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetThreadProvision(const uint8_t * operationalDataset,
292                                                                                     size_t operationalDatasetLen)
293 {
294     otError otErr = OT_ERROR_FAILED;
295     otOperationalDatasetTlvs datasetTlv;
296
297     VerifyOrReturnError(operationalDatasetLen <= sizeof(datasetTlv.mTlvs), CHIP_ERROR_MESSAGE_TOO_LONG);
298     // A compile time check to avoid misbehavior if the openthread implementation changed over time.
299     static_assert(sizeof(datasetTlv.mTlvs) <= UINT8_MAX);
300     memcpy(datasetTlv.mTlvs, operationalDataset, operationalDatasetLen);
301     datasetTlv.mLength = static_cast<uint8_t>(operationalDatasetLen);
302
303     // Set the dataset as the active dataset for the node.
304     Impl()->LockThreadStack();
305     otErr = otDatasetSetActiveTlvs(mOTInst, &datasetTlv);
306     Impl()->UnlockThreadStack();
307
308     // post an event alerting other subsystems about change in provisioning state
309     ChipDeviceEvent event;
310     event.Type                                           = DeviceEventType::kServiceProvisioningChange;
311     event.ServiceProvisioningChange.IsServiceProvisioned = true;
312     PlatformMgr().PostEvent(&event);
313
314     return MapOpenThreadError(otErr);
315 }
316
317 template <class ImplClass>
318 bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_IsThreadProvisioned(void)
319 {
320     bool provisioned;
321
322     Impl()->LockThreadStack();
323     provisioned = otDatasetIsCommissioned(mOTInst);
324     Impl()->UnlockThreadStack();
325
326     return provisioned;
327 }
328
329 template <class ImplClass>
330 bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_IsThreadAttached(void)
331 {
332     otDeviceRole curRole;
333
334     Impl()->LockThreadStack();
335     curRole = otThreadGetDeviceRole(mOTInst);
336     Impl()->UnlockThreadStack();
337
338     return (curRole != OT_DEVICE_ROLE_DISABLED && curRole != OT_DEVICE_ROLE_DETACHED);
339 }
340
341 template <class ImplClass>
342 ConnectivityManager::ThreadDeviceType GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetThreadDeviceType(void)
343 {
344     ConnectivityManager::ThreadDeviceType deviceType;
345
346     Impl()->LockThreadStack();
347
348     const otLinkModeConfig linkMode = otThreadGetLinkMode(mOTInst);
349
350 #if CHIP_DEVICE_CONFIG_THREAD_FTD
351     if (linkMode.mDeviceType && otThreadIsRouterEligible(mOTInst))
352         ExitNow(deviceType = ConnectivityManager::kThreadDeviceType_Router);
353     if (linkMode.mDeviceType)
354         ExitNow(deviceType = ConnectivityManager::kThreadDeviceType_FullEndDevice);
355 #endif
356     if (linkMode.mRxOnWhenIdle)
357         ExitNow(deviceType = ConnectivityManager::kThreadDeviceType_MinimalEndDevice);
358
359     ExitNow(deviceType = ConnectivityManager::kThreadDeviceType_SleepyEndDevice);
360
361 exit:
362     Impl()->UnlockThreadStack();
363
364     return deviceType;
365 }
366
367 template <class ImplClass>
368 CHIP_ERROR
369 GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetThreadDeviceType(ConnectivityManager::ThreadDeviceType deviceType)
370 {
371     CHIP_ERROR err = CHIP_NO_ERROR;
372     otLinkModeConfig linkMode;
373
374     switch (deviceType)
375     {
376 #if CHIP_DEVICE_CONFIG_THREAD_FTD
377     case ConnectivityManager::kThreadDeviceType_Router:
378     case ConnectivityManager::kThreadDeviceType_FullEndDevice:
379 #endif
380     case ConnectivityManager::kThreadDeviceType_MinimalEndDevice:
381     case ConnectivityManager::kThreadDeviceType_SleepyEndDevice:
382         break;
383     default:
384         ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT);
385     }
386
387 #if CHIP_PROGRESS_LOGGING
388
389     {
390         const char * deviceTypeStr;
391         switch (deviceType)
392         {
393         case ConnectivityManager::kThreadDeviceType_Router:
394             deviceTypeStr = "ROUTER";
395             break;
396         case ConnectivityManager::kThreadDeviceType_FullEndDevice:
397             deviceTypeStr = "FULL END DEVICE";
398             break;
399         case ConnectivityManager::kThreadDeviceType_MinimalEndDevice:
400             deviceTypeStr = "MINIMAL END DEVICE";
401             break;
402         case ConnectivityManager::kThreadDeviceType_SleepyEndDevice:
403             deviceTypeStr = "SLEEPY END DEVICE";
404             break;
405         default:
406             deviceTypeStr = "(unknown)";
407             break;
408         }
409         ChipLogProgress(DeviceLayer, "Setting OpenThread device type to %s", deviceTypeStr);
410     }
411
412 #endif // CHIP_PROGRESS_LOGGING
413
414     Impl()->LockThreadStack();
415
416     linkMode = otThreadGetLinkMode(mOTInst);
417
418     switch (deviceType)
419     {
420 #if CHIP_DEVICE_CONFIG_THREAD_FTD
421     case ConnectivityManager::kThreadDeviceType_Router:
422     case ConnectivityManager::kThreadDeviceType_FullEndDevice:
423         linkMode.mDeviceType   = true;
424         linkMode.mRxOnWhenIdle = true;
425         otThreadSetRouterEligible(mOTInst, deviceType == ConnectivityManager::kThreadDeviceType_Router);
426         break;
427 #endif
428     case ConnectivityManager::kThreadDeviceType_MinimalEndDevice:
429         linkMode.mDeviceType   = false;
430         linkMode.mRxOnWhenIdle = true;
431         break;
432     case ConnectivityManager::kThreadDeviceType_SleepyEndDevice:
433         linkMode.mDeviceType   = false;
434         linkMode.mRxOnWhenIdle = false;
435         break;
436     default:
437         break;
438     }
439
440     otThreadSetLinkMode(mOTInst, linkMode);
441
442     Impl()->UnlockThreadStack();
443
444 exit:
445     return err;
446 }
447
448 template <class ImplClass>
449 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetThreadPollingConfig(
450     ConnectivityManager::ThreadPollingConfig & pollingConfig)
451 {
452     pollingConfig = mPollingConfig;
453 }
454
455 template <class ImplClass>
456 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetThreadPollingConfig(
457     const ConnectivityManager::ThreadPollingConfig & pollingConfig)
458 {
459     mPollingConfig = pollingConfig;
460     return Impl()->AdjustPollingInterval();
461 }
462
463 template <class ImplClass>
464 bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_HaveMeshConnectivity(void)
465 {
466     bool res;
467     otDeviceRole curRole;
468
469     Impl()->LockThreadStack();
470
471     // Get the current Thread role.
472     curRole = otThreadGetDeviceRole(mOTInst);
473
474     // If Thread is disabled, or the node is detached, then the node has no mesh connectivity.
475     if (curRole == OT_DEVICE_ROLE_DISABLED || curRole == OT_DEVICE_ROLE_DETACHED)
476     {
477         res = false;
478     }
479
480     // If the node is a child, that implies the existence of a parent node which provides connectivity
481     // to the mesh.
482     else if (curRole == OT_DEVICE_ROLE_CHILD)
483     {
484         res = true;
485     }
486
487     // Otherwise, if the node is acting as a router, scan the Thread neighbor table looking for at least
488     // one other node that is also acting as router.
489     else
490     {
491         otNeighborInfoIterator neighborIter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
492         otNeighborInfo neighborInfo;
493
494         res = false;
495
496         while (otThreadGetNextNeighborInfo(mOTInst, &neighborIter, &neighborInfo) == OT_ERROR_NONE)
497         {
498             if (!neighborInfo.mIsChild)
499             {
500                 res = true;
501                 break;
502             }
503         }
504     }
505
506     Impl()->UnlockThreadStack();
507
508     return res;
509 }
510
511 template <class ImplClass>
512 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_OnMessageLayerActivityChanged(bool messageLayerIsActive)
513 {
514     Impl()->AdjustPollingInterval();
515 }
516
517 template <class ImplClass>
518 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetAndLogThreadStatsCounters(void)
519 {
520     CHIP_ERROR err = CHIP_NO_ERROR;
521     otError otErr;
522     const otMacCounters * macCounters;
523     const otIpCounters * ipCounters;
524     otOperationalDataset activeDataset;
525     otDeviceRole role;
526
527     Impl()->LockThreadStack();
528
529     role = otThreadGetDeviceRole(mOTInst);
530     ChipLogProgress(DeviceLayer, "Thread Role:                  %d\n", role);
531
532     if (otDatasetIsCommissioned(mOTInst))
533     {
534         otErr = otDatasetGetActive(mOTInst, &activeDataset);
535         VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
536
537         if (activeDataset.mComponents.mIsChannelPresent)
538         {
539             ChipLogProgress(DeviceLayer, "Thread Channel:               %d\n", activeDataset.mChannel);
540         }
541     }
542
543     macCounters = otLinkGetCounters(mOTInst);
544
545     ChipLogProgress(DeviceLayer,
546                     "Rx Counters:\n"
547                     "PHY Rx Total:                 %d\n"
548                     "MAC Rx Unicast:               %d\n"
549                     "MAC Rx Broadcast:             %d\n"
550                     "MAC Rx Data:                  %d\n"
551                     "MAC Rx Data Polls:            %d\n"
552                     "MAC Rx Beacons:               %d\n"
553                     "MAC Rx Beacon Reqs:           %d\n"
554                     "MAC Rx Other:                 %d\n"
555                     "MAC Rx Filtered Whitelist:    %d\n"
556                     "MAC Rx Filtered DestAddr:     %d\n",
557                     macCounters->mRxTotal, macCounters->mRxUnicast, macCounters->mRxBroadcast, macCounters->mRxData,
558                     macCounters->mRxDataPoll, macCounters->mRxBeacon, macCounters->mRxBeaconRequest, macCounters->mRxOther,
559                     macCounters->mRxAddressFiltered, macCounters->mRxDestAddrFiltered);
560
561     ChipLogProgress(DeviceLayer,
562                     "Tx Counters:\n"
563                     "PHY Tx Total:                 %d\n"
564                     "MAC Tx Unicast:               %d\n"
565                     "MAC Tx Broadcast:             %d\n"
566                     "MAC Tx Data:                  %d\n"
567                     "MAC Tx Data Polls:            %d\n"
568                     "MAC Tx Beacons:               %d\n"
569                     "MAC Tx Beacon Reqs:           %d\n"
570                     "MAC Tx Other:                 %d\n"
571                     "MAC Tx Retry:                 %d\n"
572                     "MAC Tx CCA Fail:              %d\n",
573                     macCounters->mTxTotal, macCounters->mTxUnicast, macCounters->mTxBroadcast, macCounters->mTxData,
574                     macCounters->mTxDataPoll, macCounters->mTxBeacon, macCounters->mTxBeaconRequest, macCounters->mTxOther,
575                     macCounters->mTxRetry, macCounters->mTxErrCca);
576
577     ChipLogProgress(DeviceLayer,
578                     "Failure Counters:\n"
579                     "MAC Rx Decrypt Fail:          %d\n"
580                     "MAC Rx No Frame Fail:         %d\n"
581                     "MAC Rx Unknown Neighbor Fail: %d\n"
582                     "MAC Rx Invalid Src Addr Fail: %d\n"
583                     "MAC Rx FCS Fail:              %d\n"
584                     "MAC Rx Other Fail:            %d\n",
585                     macCounters->mRxErrSec, macCounters->mRxErrNoFrame, macCounters->mRxErrUnknownNeighbor,
586                     macCounters->mRxErrInvalidSrcAddr, macCounters->mRxErrFcs, macCounters->mRxErrOther);
587
588     ipCounters = otThreadGetIp6Counters(mOTInst);
589
590     ChipLogProgress(DeviceLayer,
591                     "IP Counters:\n"
592                     "IP Tx Success:                %d\n"
593                     "IP Rx Success:                %d\n"
594                     "IP Tx Fail:                   %d\n"
595                     "IP Rx Fail:                   %d\n",
596                     ipCounters->mTxSuccess, ipCounters->mRxSuccess, ipCounters->mTxFailure, ipCounters->mRxFailure);
597
598     Impl()->UnlockThreadStack();
599
600 exit:
601     return err;
602 }
603
604 template <class ImplClass>
605 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetAndLogThreadTopologyMinimal(void)
606 {
607     CHIP_ERROR err = CHIP_NO_ERROR;
608     otError otErr;
609     const otExtAddress * extAddress;
610     uint16_t rloc16;
611     uint16_t routerId;
612     uint16_t leaderRouterId;
613     uint32_t partitionId;
614     int8_t parentAverageRssi;
615     int8_t parentLastRssi;
616     int8_t instantRssi;
617
618     Impl()->LockThreadStack();
619
620     rloc16 = otThreadGetRloc16(mOTInst);
621
622     // Router ID is the top 6 bits of the RLOC
623     routerId = (rloc16 >> 10) & 0x3f;
624
625     leaderRouterId = otThreadGetLeaderRouterId(mOTInst);
626
627     otErr = otThreadGetParentAverageRssi(mOTInst, &parentAverageRssi);
628     VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
629
630     otErr = otThreadGetParentLastRssi(mOTInst, &parentLastRssi);
631     VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
632
633     partitionId = otThreadGetPartitionId(mOTInst);
634
635     extAddress = otLinkGetExtendedAddress(mOTInst);
636
637     instantRssi = otPlatRadioGetRssi(mOTInst);
638
639     ChipLogProgress(DeviceLayer,
640                     "Thread Topology:\n"
641                     "RLOC16:           %04X\n"
642                     "Router ID:        %u\n"
643                     "Leader Router ID: %u\n"
644                     "Parent Avg RSSI:  %d\n"
645                     "Parent Last RSSI: %d\n"
646                     "Partition ID:     %d\n"
647                     "Extended Address: %02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
648                     "Instant RSSI:     %d\n",
649                     rloc16, routerId, leaderRouterId, parentAverageRssi, parentLastRssi, partitionId, extAddress->m8[0],
650                     extAddress->m8[1], extAddress->m8[2], extAddress->m8[3], extAddress->m8[4], extAddress->m8[5],
651                     extAddress->m8[6], extAddress->m8[7], instantRssi);
652
653     Impl()->UnlockThreadStack();
654
655 exit:
656     if (err != CHIP_NO_ERROR)
657     {
658         ChipLogError(DeviceLayer, "GetAndLogThreadTopologyMinimul failed: %d", err);
659     }
660
661     return err;
662 }
663
664 #define TELEM_NEIGHBOR_TABLE_SIZE (64)
665 #define TELEM_PRINT_BUFFER_SIZE (64)
666
667 #if CHIP_DEVICE_CONFIG_THREAD_FTD
668 template <class ImplClass>
669 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetAndLogThreadTopologyFull()
670 {
671     CHIP_ERROR err = CHIP_NO_ERROR;
672     otError otErr;
673     otIp6Address * leaderAddr    = NULL;
674     uint8_t * networkData        = NULL;
675     uint8_t * stableNetworkData  = NULL;
676     uint8_t networkDataLen       = 0;
677     uint8_t stableNetworkDataLen = 0;
678     const otExtAddress * extAddress;
679     otNeighborInfo neighborInfo[TELEM_NEIGHBOR_TABLE_SIZE];
680     otNeighborInfoIterator iter;
681     otNeighborInfoIterator iterCopy;
682     char printBuf[TELEM_PRINT_BUFFER_SIZE];
683     uint16_t rloc16;
684     uint16_t routerId;
685     uint16_t leaderRouterId;
686     uint8_t leaderWeight;
687     uint8_t leaderLocalWeight;
688     uint32_t partitionId;
689     int8_t instantRssi;
690     uint8_t networkDataVersion;
691     uint8_t stableNetworkDataVersion;
692     uint16_t neighborTableSize = 0;
693     uint16_t childTableSize    = 0;
694
695     Impl()->LockThreadStack();
696
697     rloc16 = otThreadGetRloc16(mOTInst);
698
699     // Router ID is the top 6 bits of the RLOC
700     routerId = (rloc16 >> 10) & 0x3f;
701
702     leaderRouterId = otThreadGetLeaderRouterId(mOTInst);
703
704     otErr = otThreadGetLeaderRloc(mOTInst, leaderAddr);
705     VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
706
707     leaderWeight = otThreadGetLeaderWeight(mOTInst);
708
709     leaderLocalWeight = otThreadGetLocalLeaderWeight(mOTInst);
710
711     otErr = otNetDataGet(mOTInst, false, networkData, &networkDataLen);
712     VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
713
714     networkDataVersion = otNetDataGetVersion(mOTInst);
715
716     otErr = otNetDataGet(mOTInst, true, stableNetworkData, &stableNetworkDataLen);
717     VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
718
719     stableNetworkDataVersion = otNetDataGetStableVersion(mOTInst);
720
721     extAddress = otLinkGetExtendedAddress(mOTInst);
722
723     partitionId = otThreadGetPartitionId(mOTInst);
724
725     instantRssi = otPlatRadioGetRssi(mOTInst);
726
727     iter              = OT_NEIGHBOR_INFO_ITERATOR_INIT;
728     iterCopy          = OT_NEIGHBOR_INFO_ITERATOR_INIT;
729     neighborTableSize = 0;
730     childTableSize    = 0;
731
732     while (otThreadGetNextNeighborInfo(mOTInst, &iter, &neighborInfo[iter]) == OT_ERROR_NONE)
733     {
734         neighborTableSize++;
735         if (neighborInfo[iterCopy].mIsChild)
736         {
737             childTableSize++;
738         }
739         iterCopy = iter;
740     }
741
742     ChipLogProgress(DeviceLayer,
743                     "Thread Topology:\n"
744                     "RLOC16:                        %04X\n"
745                     "Router ID:                     %u\n"
746                     "Leader Router ID:              %u\n"
747                     "Leader Address:                %02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
748                     "Leader Weight:                 %d\n"
749                     "Local Leader Weight:           %d\n"
750                     "Network Data Len:              %d\n"
751                     "Network Data Version:          %d\n"
752                     "Stable Network Data Version:   %d\n"
753                     "Extended Address:              %02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
754                     "Partition ID:                  %X\n"
755                     "Instant RSSI:                  %d\n"
756                     "Neighbor Table Length:         %d\n"
757                     "Child Table Length:            %d\n",
758                     rloc16, routerId, leaderRouterId, leaderAddr->mFields.m8[0], leaderAddr->mFields.m8[1],
759                     leaderAddr->mFields.m8[2], leaderAddr->mFields.m8[3], leaderAddr->mFields.m8[4], leaderAddr->mFields.m8[5],
760                     leaderAddr->mFields.m8[6], leaderAddr->mFields.m8[7], leaderAddr->mFields.m8[8], leaderAddr->mFields.m8[9],
761                     leaderAddr->mFields.m8[10], leaderAddr->mFields.m8[11], leaderAddr->mFields.m8[12], leaderAddr->mFields.m8[13],
762                     leaderAddr->mFields.m8[14], leaderAddr->mFields.m8[15], leaderWeight, leaderLocalWeight, networkDataLen,
763                     networkDataVersion, stableNetworkDataVersion, extAddress->m8[0], extAddress->m8[1], extAddress->m8[2],
764                     extAddress->m8[3], extAddress->m8[4], extAddress->m8[5], extAddress->m8[6], extAddress->m8[7], partitionId,
765                     instantRssi, neighborTableSize, childTableSize);
766
767     // Handle each neighbor event seperatly.
768     for (uint32_t i = 0; i < neighborTableSize; i++)
769     {
770         otNeighborInfo * neighbor = &neighborInfo[i];
771
772         if (neighbor->mIsChild)
773         {
774             otChildInfo * child = NULL;
775             otErr               = otThreadGetChildInfoById(mOTInst, neighbor->mRloc16, child);
776             VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
777
778             snprintf(printBuf, TELEM_PRINT_BUFFER_SIZE, ", Timeout: %10" PRIu32 " NetworkDataVersion: %3" PRIu8, child->mTimeout,
779                      child->mNetworkDataVersion);
780         }
781         else
782         {
783             printBuf[0] = 0;
784         }
785
786         ChipLogProgress(DeviceLayer,
787                         "TopoEntry[%u]:     %02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
788                         "RLOC:              %04X\n"
789                         "Age:               %3d\n"
790                         "LQI:               %1d\n"
791                         "AvgRSSI:           %3d\n"
792                         "LastRSSI:          %3d\n"
793                         "LinkFrameCounter:  %10d\n"
794                         "MleFrameCounter:   %10d\n"
795                         "RxOnWhenIdle:      %c\n"
796                         "FullFunction:      %c\n"
797                         "FullNetworkData:   %c\n"
798                         "IsChild:           %c%s\n",
799                         i, neighbor->mExtAddress.m8[0], neighbor->mExtAddress.m8[1], neighbor->mExtAddress.m8[2],
800                         neighbor->mExtAddress.m8[3], neighbor->mExtAddress.m8[4], neighbor->mExtAddress.m8[5],
801                         neighbor->mExtAddress.m8[6], neighbor->mExtAddress.m8[7], neighbor->mRloc16, neighbor->mAge,
802                         neighbor->mLinkQualityIn, neighbor->mAverageRssi, neighbor->mLastRssi, neighbor->mLinkFrameCounter,
803                         neighbor->mMleFrameCounter, neighbor->mRxOnWhenIdle ? 'Y' : 'n', neighbor->mFullThreadDevice ? 'Y' : 'n',
804                         neighbor->mFullNetworkData ? 'Y' : 'n', neighbor->mIsChild ? 'Y' : 'n', printBuf);
805     }
806
807     Impl()->UnlockThreadStack();
808
809 exit:
810     if (err != CHIP_NO_ERROR)
811     {
812         ChipLogError(DeviceLayer, "GetAndLogThreadTopologyFull failed: %s", err);
813     }
814     return err;
815 }
816 #else // CHIP_DEVICE_CONFIG_THREAD_FTD
817 template <class ImplClass>
818 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetAndLogThreadTopologyFull()
819 {
820     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
821 }
822 #endif
823
824 template <class ImplClass>
825 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetPrimary802154MACAddress(uint8_t * buf)
826 {
827     const otExtAddress * extendedAddr = otLinkGetExtendedAddress(mOTInst);
828     memcpy(buf, extendedAddr, sizeof(otExtAddress));
829     return CHIP_NO_ERROR;
830 };
831
832 template <class ImplClass>
833 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetFactoryAssignedEUI64(uint8_t (&buf)[8])
834 {
835     otExtAddress extendedAddr;
836     otLinkGetFactoryAssignedIeeeEui64(mOTInst, &extendedAddr);
837     memcpy(buf, extendedAddr.m8, sizeof(extendedAddr.m8));
838     return CHIP_NO_ERROR;
839 };
840
841 template <class ImplClass>
842 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetExternalIPv6Address(chip::Inet::IPAddress & addr)
843 {
844     const otNetifAddress * otAddresses = otIp6GetUnicastAddresses(mOTInst);
845
846     // Look only for the global unicast addresses, not internally assigned by Thread.
847     for (const otNetifAddress * otAddress = otAddresses; otAddress != nullptr; otAddress = otAddress->mNext)
848     {
849         if (otAddress->mValid)
850         {
851             switch (otAddress->mAddressOrigin)
852             {
853             case OT_ADDRESS_ORIGIN_THREAD:
854                 break;
855             case OT_ADDRESS_ORIGIN_SLAAC:
856             case OT_ADDRESS_ORIGIN_DHCPV6:
857             case OT_ADDRESS_ORIGIN_MANUAL:
858                 addr = ToIPAddress(otAddress->mAddress);
859                 return CHIP_NO_ERROR;
860             default:
861                 break;
862             }
863         }
864     }
865
866     return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
867 }
868
869 template <class ImplClass>
870 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::DoInit(otInstance * otInst)
871 {
872     CHIP_ERROR err = CHIP_NO_ERROR;
873     otError otErr  = OT_ERROR_NONE;
874
875     // Arrange for OpenThread errors to be translated to text.
876     RegisterOpenThreadErrorFormatter();
877
878     mOTInst = NULL;
879     mPollingConfig.Clear();
880
881     // If an OpenThread instance hasn't been supplied, call otInstanceInitSingle() to
882     // create or acquire a singleton instance of OpenThread.
883     if (otInst == NULL)
884     {
885         otInst = otInstanceInitSingle();
886         VerifyOrExit(otInst != NULL, err = MapOpenThreadError(OT_ERROR_FAILED));
887     }
888
889 #if !defined(__ZEPHYR__) && !defined(ENABLE_CHIP_SHELL) && !defined(PW_RPC_ENABLED)
890     otCliUartInit(otInst);
891 #endif
892
893     mOTInst = otInst;
894
895     // Arrange for OpenThread to call the OnOpenThreadStateChange method whenever a
896     // state change occurs.  Note that we reference the OnOpenThreadStateChange method
897     // on the concrete implementation class so that that class can override the default
898     // method implementation if it chooses to.
899     otErr = otSetStateChangedCallback(otInst, ImplClass::OnOpenThreadStateChange, this);
900     VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
901
902     // Enable automatic assignment of Thread advertised addresses.
903 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
904     otIp6SetSlaacEnabled(otInst, true);
905 #endif
906
907 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
908     otSrpClientSetCallback(mOTInst, &OnSrpClientNotification, nullptr);
909     otSrpClientEnableAutoStartMode(mOTInst, &OnSrpClientStateChange, nullptr);
910     memset(&mSrpClient, 0, sizeof(mSrpClient));
911 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
912
913     // If the Thread stack has been provisioned, but is not currently enabled, enable it now.
914     if (otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(otInst))
915     {
916         // Enable the Thread IPv6 interface.
917         otErr = otIp6SetEnabled(otInst, true);
918         VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
919
920         otErr = otThreadSetEnabled(otInst, true);
921         VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
922
923         ChipLogProgress(DeviceLayer, "OpenThread ifconfig up and thread start");
924     }
925
926 exit:
927     ChipLogProgress(DeviceLayer, "OpenThread started: %s", otThreadErrorToString(otErr));
928     return err;
929 }
930
931 template <class ImplClass>
932 bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::IsThreadAttachedNoLock(void)
933 {
934     otDeviceRole curRole = otThreadGetDeviceRole(mOTInst);
935     return (curRole != OT_DEVICE_ROLE_DISABLED && curRole != OT_DEVICE_ROLE_DETACHED);
936 }
937
938 template <class ImplClass>
939 bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::IsThreadInterfaceUpNoLock(void)
940 {
941     return otIp6IsEnabled(mOTInst);
942 }
943
944 template <class ImplClass>
945 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::AdjustPollingInterval(void)
946 {
947     CHIP_ERROR err = CHIP_NO_ERROR;
948
949     uint32_t newPollingIntervalMS = mPollingConfig.InactivePollingIntervalMS;
950
951     if (newPollingIntervalMS != 0)
952     {
953         Impl()->LockThreadStack();
954
955         uint32_t curPollingIntervalMS = otLinkGetPollPeriod(mOTInst);
956
957         if (newPollingIntervalMS != curPollingIntervalMS)
958         {
959             otError otErr = otLinkSetPollPeriod(mOTInst, newPollingIntervalMS);
960             err           = MapOpenThreadError(otErr);
961         }
962
963         Impl()->UnlockThreadStack();
964
965         if (newPollingIntervalMS != curPollingIntervalMS)
966         {
967             ChipLogProgress(DeviceLayer, "OpenThread polling interval set to %" PRId32 "ms", newPollingIntervalMS);
968         }
969     }
970
971     return err;
972 }
973
974 template <class ImplClass>
975 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_ErasePersistentInfo(void)
976 {
977     ChipLogProgress(DeviceLayer, "Erasing Thread persistent info...");
978     Impl()->LockThreadStack();
979     otThreadSetEnabled(mOTInst, false);
980     otInstanceErasePersistentInfo(mOTInst);
981     Impl()->UnlockThreadStack();
982 }
983
984 template <class ImplClass>
985 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::OnJoinerComplete(otError aError, void * aContext)
986 {
987     static_cast<GenericThreadStackManagerImpl_OpenThread *>(aContext)->OnJoinerComplete(aError);
988 }
989
990 template <class ImplClass>
991 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::OnJoinerComplete(otError aError)
992 {
993     ChipLogProgress(DeviceLayer, "Join Thread network: %s", otThreadErrorToString(aError));
994
995     if (aError == OT_ERROR_NONE)
996     {
997         otError error = otThreadSetEnabled(mOTInst, true);
998
999         ChipLogProgress(DeviceLayer, "Start Thread network: %s", otThreadErrorToString(error));
1000     }
1001 }
1002
1003 template <class ImplClass>
1004 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_JoinerStart(void)
1005 {
1006     CHIP_ERROR error = CHIP_NO_ERROR;
1007
1008     Impl()->LockThreadStack();
1009     VerifyOrExit(!otDatasetIsCommissioned(mOTInst) && otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED,
1010                  error = MapOpenThreadError(OT_ERROR_INVALID_STATE));
1011     VerifyOrExit(otJoinerGetState(mOTInst) == OT_JOINER_STATE_IDLE, error = MapOpenThreadError(OT_ERROR_BUSY));
1012
1013     if (!otIp6IsEnabled(mOTInst))
1014     {
1015         SuccessOrExit(error = MapOpenThreadError(otIp6SetEnabled(mOTInst, true)));
1016     }
1017
1018     {
1019         otJoinerDiscerner discerner;
1020         uint16_t discriminator;
1021
1022         SuccessOrExit(error = ConfigurationMgr().GetSetupDiscriminator(discriminator));
1023         discerner.mLength = 12;
1024         discerner.mValue  = discriminator;
1025
1026         ChipLogProgress(DeviceLayer, "Joiner Discerner: %u", discriminator);
1027         otJoinerSetDiscerner(mOTInst, &discerner);
1028     }
1029
1030     {
1031         otJoinerPskd pskd;
1032         uint32_t pincode;
1033
1034         SuccessOrExit(error = ConfigurationMgr().GetSetupPinCode(pincode));
1035         snprintf(pskd.m8, sizeof(pskd.m8) - 1, "%09" PRIu32, pincode);
1036
1037         ChipLogProgress(DeviceLayer, "Joiner PSKd: %s", pskd.m8);
1038         error = MapOpenThreadError(otJoinerStart(mOTInst, pskd.m8, NULL, NULL, NULL, NULL, NULL,
1039                                                  &GenericThreadStackManagerImpl_OpenThread::OnJoinerComplete, this));
1040     }
1041
1042 exit:
1043     Impl()->UnlockThreadStack();
1044
1045     ChipLogProgress(DeviceLayer, "Joiner start: %s", chip::ErrorStr(error));
1046
1047     return error;
1048 }
1049
1050 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
1051
1052 static_assert(OPENTHREAD_API_VERSION >= 80, "SRP Client requires a more recent OpenThread version");
1053
1054 template <class ImplClass>
1055 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::OnSrpClientNotification(otError aError,
1056                                                                                   const otSrpClientHostInfo * aHostInfo,
1057                                                                                   const otSrpClientService * aServices,
1058                                                                                   const otSrpClientService * aRemovedServices,
1059                                                                                   void * aContext)
1060 {
1061     switch (aError)
1062     {
1063     case OT_ERROR_NONE: {
1064         ChipLogProgress(DeviceLayer, "OnSrpClientNotification: Last requested operation completed successfully");
1065
1066         if (aRemovedServices)
1067         {
1068             otSrpClientService * otService = const_cast<otSrpClientService *>(aRemovedServices);
1069             otSrpClientService * next      = nullptr;
1070             using Service                  = typename SrpClient::Service;
1071
1072             // Free memory for all removed services.
1073             do
1074             {
1075                 next         = otService->mNext;
1076                 auto service = reinterpret_cast<Service *>(reinterpret_cast<size_t>(otService) - offsetof(Service, mService));
1077                 memset(service, 0, sizeof(Service));
1078                 otService = next;
1079             } while (otService);
1080         }
1081         break;
1082     }
1083     case OT_ERROR_PARSE:
1084         ChipLogError(DeviceLayer, "OnSrpClientNotification: Parsing operaton failed");
1085         break;
1086     case OT_ERROR_NOT_FOUND:
1087         ChipLogError(DeviceLayer, "OnSrpClientNotification: Domain name or RRset does not exist");
1088         break;
1089     case OT_ERROR_NOT_IMPLEMENTED:
1090         ChipLogError(DeviceLayer, "OnSrpClientNotification: Server does not support query type");
1091         break;
1092     case OT_ERROR_SECURITY:
1093         ChipLogError(DeviceLayer, "OnSrpClientNotification: Operation refused for security reasons");
1094         break;
1095     case OT_ERROR_DUPLICATED:
1096         ChipLogError(DeviceLayer, "OnSrpClientNotification: Domain name or RRset is duplicated");
1097         break;
1098     case OT_ERROR_RESPONSE_TIMEOUT:
1099         ChipLogError(DeviceLayer, "OnSrpClientNotification: Timed out waiting on server response");
1100         break;
1101     case OT_ERROR_INVALID_ARGS:
1102         ChipLogError(DeviceLayer, "OnSrpClientNotification: Invalid service structure detected");
1103         break;
1104     case OT_ERROR_NO_BUFS:
1105         ChipLogError(DeviceLayer, "OnSrpClientNotification: Insufficient buffer to handle message");
1106         break;
1107     case OT_ERROR_FAILED:
1108         ChipLogError(DeviceLayer, "OnSrpClientNotification: Internal server error occurred");
1109         break;
1110     default:
1111         ChipLogError(DeviceLayer, "OnSrpClientNotification: Unknown error occurred");
1112         break;
1113     }
1114 }
1115
1116 template <class ImplClass>
1117 void GenericThreadStackManagerImpl_OpenThread<ImplClass>::OnSrpClientStateChange(const otSockAddr * aServerSockAddr,
1118                                                                                  void * aContext)
1119 {
1120     if (aServerSockAddr)
1121     {
1122         ChipLogProgress(DeviceLayer, "SRP Client was started, as detected server addressed: %x:%x:%x:%x:%x:%x:%x:%x",
1123                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[0]),
1124                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[1]),
1125                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[2]),
1126                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[3]),
1127                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[4]),
1128                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[5]),
1129                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[6]),
1130                         Encoding::BigEndian::HostSwap16(aServerSockAddr->mAddress.mFields.m16[7]));
1131     }
1132     else
1133     {
1134         ChipLogProgress(DeviceLayer, "SRP Client was stopped, because current server is no longer detected.");
1135     }
1136 }
1137
1138 template <class ImplClass>
1139 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_AddSrpService(const char * aInstanceName, const char * aName,
1140                                                                                uint16_t aPort, chip::Mdns::TextEntry * aTxtEntries,
1141                                                                                size_t aTxtEntiresSize, uint32_t aLeaseInterval,
1142                                                                                uint32_t aKeyLeaseInterval)
1143 {
1144     CHIP_ERROR error                         = CHIP_NO_ERROR;
1145     typename SrpClient::Service * srpService = nullptr;
1146
1147     Impl()->LockThreadStack();
1148
1149     VerifyOrExit(aInstanceName, error = CHIP_ERROR_INVALID_ARGUMENT);
1150     VerifyOrExit(strlen(aInstanceName) < SrpClient::kMaxInstanceNameSize, error = CHIP_ERROR_INVALID_STRING_LENGTH);
1151     VerifyOrExit(aName, error = CHIP_ERROR_INVALID_ARGUMENT);
1152     VerifyOrExit(strlen(aName) < SrpClient::kMaxNameSize, error = CHIP_ERROR_INVALID_STRING_LENGTH);
1153
1154     // Check if service with desired instance name already exists and try to find empty slot in array for new service
1155     for (typename SrpClient::Service & service : mSrpClient.mServices)
1156     {
1157         if (strcmp(service.mInstanceName, "") == 0)
1158         {
1159             // Assign first empty slot in array for a new service.
1160             srpService = srpService ? srpService : &service;
1161         }
1162         else
1163         {
1164             VerifyOrExit((strcmp(service.mInstanceName, aInstanceName) != 0) || (strcmp(service.mName, aName) != 0),
1165                          error = MapOpenThreadError(OT_ERROR_DUPLICATED));
1166         }
1167     }
1168
1169     // Verify is there an empty place for new service.
1170     VerifyOrExit(srpService, error = MapOpenThreadError(OT_ERROR_NO_BUFS));
1171
1172     otSrpClientSetLeaseInterval(mOTInst, aLeaseInterval);
1173     otSrpClientSetKeyLeaseInterval(mOTInst, aKeyLeaseInterval);
1174
1175     memcpy(srpService->mInstanceName, aInstanceName, strlen(aInstanceName) + 1);
1176     srpService->mService.mInstanceName = srpService->mInstanceName;
1177
1178     memcpy(srpService->mName, aName, strlen(aName) + 1);
1179     srpService->mService.mName = srpService->mName;
1180
1181     srpService->mService.mPort = aPort;
1182
1183     // Check if there are some optional text entries to add.
1184     if (aTxtEntries && aTxtEntiresSize != 0)
1185     {
1186         VerifyOrExit(aTxtEntiresSize <= SrpClient::kMaxTxtEntriesNumber, error = CHIP_ERROR_INVALID_LIST_LENGTH);
1187
1188         srpService->mService.mNumTxtEntries = static_cast<uint8_t>(aTxtEntiresSize);
1189
1190         for (uint8_t entryId = 0; entryId < aTxtEntiresSize; entryId++)
1191         {
1192             VerifyOrExit(aTxtEntries[entryId].mDataSize <= SrpClient::kMaxTxtValueSize, error = CHIP_ERROR_BUFFER_TOO_SMALL);
1193             VerifyOrExit((strlen(aTxtEntries[entryId].mKey) + 1) <= SrpClient::kMaxTxtKeySize, error = CHIP_ERROR_BUFFER_TOO_SMALL);
1194
1195             srpService->mTxtEntries[entryId].mValueLength = static_cast<uint8_t>(aTxtEntries[entryId].mDataSize);
1196             memcpy(&(srpService->mTxtValueBuffers[entryId][0]), aTxtEntries[entryId].mData, aTxtEntries[entryId].mDataSize);
1197             srpService->mTxtEntries[entryId].mValue = &(srpService->mTxtValueBuffers[entryId][0]);
1198
1199             memcpy(&(srpService->mTxtKeyBuffers[entryId][0]), aTxtEntries[entryId].mKey, strlen(aTxtEntries[entryId].mKey) + 1);
1200             srpService->mTxtEntries[entryId].mKey = &(srpService->mTxtKeyBuffers[entryId][0]);
1201         }
1202
1203         srpService->mService.mTxtEntries = srpService->mTxtEntries;
1204     }
1205
1206     error = MapOpenThreadError(otSrpClientAddService(mOTInst, &(srpService->mService)));
1207
1208 exit:
1209     Impl()->UnlockThreadStack();
1210
1211     return error;
1212 }
1213
1214 template <class ImplClass>
1215 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_RemoveSrpService(const char * aInstanceName, const char * aName)
1216 {
1217     CHIP_ERROR error                         = CHIP_NO_ERROR;
1218     typename SrpClient::Service * srpService = nullptr;
1219
1220     Impl()->LockThreadStack();
1221
1222     VerifyOrExit(aInstanceName, error = CHIP_ERROR_INVALID_ARGUMENT);
1223     VerifyOrExit(strlen(aInstanceName) < SrpClient::kMaxInstanceNameSize, error = CHIP_ERROR_INVALID_STRING_LENGTH);
1224     VerifyOrExit(aName, error = CHIP_ERROR_INVALID_ARGUMENT);
1225     VerifyOrExit(strlen(aName) < SrpClient::kMaxNameSize, error = CHIP_ERROR_INVALID_STRING_LENGTH);
1226
1227     // Check if service to remove exists.
1228     for (typename SrpClient::Service & service : mSrpClient.mServices)
1229     {
1230         if ((strcmp(service.mInstanceName, aInstanceName) == 0) && (strcmp(service.mName, aName) == 0))
1231         {
1232             srpService = &service;
1233             break;
1234         }
1235     }
1236
1237     VerifyOrExit(srpService, error = MapOpenThreadError(OT_ERROR_NOT_FOUND));
1238
1239     error = MapOpenThreadError(otSrpClientRemoveService(mOTInst, &(srpService->mService)));
1240
1241 exit:
1242     Impl()->UnlockThreadStack();
1243
1244     return error;
1245 }
1246
1247 template <class ImplClass>
1248 CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetupSrpHost(const char * aHostName)
1249 {
1250     CHIP_ERROR error = CHIP_NO_ERROR;
1251     Inet::IPAddress hostAddress;
1252
1253     Impl()->LockThreadStack();
1254
1255     VerifyOrExit(aHostName, error = CHIP_ERROR_INVALID_ARGUMENT);
1256     VerifyOrExit(strlen(aHostName) < SrpClient::kMaxHostNameSize, error = CHIP_ERROR_INVALID_STRING_LENGTH);
1257
1258     // Avoid adding the same host name multiple times
1259     if (strcmp(mSrpClient.mHostName, aHostName) != 0)
1260     {
1261         strcpy(mSrpClient.mHostName, aHostName);
1262         error = MapOpenThreadError(otSrpClientSetHostName(mOTInst, aHostName));
1263         SuccessOrExit(error);
1264     }
1265
1266     // Check if device has any external IPv6 assigned. If not, host will be set without IPv6 addresses
1267     // and updated later on.
1268     if (ThreadStackMgr().GetExternalIPv6Address(hostAddress) == CHIP_NO_ERROR)
1269     {
1270         memcpy(&mSrpClient.mHostAddress.mFields.m32, hostAddress.Addr, sizeof(hostAddress.Addr));
1271         error = MapOpenThreadError(otSrpClientSetHostAddresses(mOTInst, &mSrpClient.mHostAddress, 1));
1272     }
1273
1274 exit:
1275     Impl()->UnlockThreadStack();
1276
1277     return error;
1278 }
1279
1280 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
1281
1282 } // namespace Internal
1283 } // namespace DeviceLayer
1284 } // namespace chip
1285
1286 #endif // GENERIC_THREAD_STACK_MANAGER_IMPL_OPENTHREAD_IPP