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