• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "nstackx_device_local.h"
17 #include <securec.h>
18 #include "nstackx_dfinder_hidump.h"
19 #include "nstackx_error.h"
20 #include "nstackx_dev.h"
21 #include "nstackx_dfinder_log.h"
22 #include "nstackx_statistics.h"
23 #include "nstackx_timer.h"
24 #include "nstackx_util.h"
25 #include "nstackx_device_remote.h"
26 #include "nstackx_list.h"
27 
28 #define TAG "LOCALDEVICE"
29 enum {
30     IFACE_STATE_READY,
31     IFACE_STATE_DESTROYING,
32     IFACE_STATE_CREATING,
33 };
34 
35 struct LocalIface {
36     List node;
37 
38     char ifname[NSTACKX_MAX_INTERFACE_NAME_LEN];
39     char ipStr[NSTACKX_MAX_IP_STRING_LEN];
40     struct in_addr ip;
41 
42     uint8_t type;
43     uint8_t state;
44     uint8_t createCount;
45     struct timespec updateTime;
46 
47     Timer *timer;
48     CoapCtxType *ctx;
49 };
50 
51 typedef struct LocalDevice_ {
52     DeviceInfo deviceInfo;
53 
54     List readyList[IFACE_TYPE_MAX];
55     List creatingList;
56     List destroyList;
57 
58     Timer *timer;
59     bool inited;
60 } LocalDevice;
61 
62 static LocalDevice g_localDevice;
63 
64 #define LOCAL_DEVICE_OFFLINE_DEFERRED_DURATION 5000 /* Defer local device offline event, 5 seconds */
65 
66 #define NSTACKX_DEFAULT_DEVICE_NAME "nStack Device"
67 
68 #define IFACE_COAP_CTX_INIT_MAX_RETRY_TIMES 4
69 static const uint32_t g_ifaceCoapCtxRetryBackoffList[IFACE_COAP_CTX_INIT_MAX_RETRY_TIMES] = { 10, 15, 25, 100 };
70 
71 static pthread_mutex_t g_capabilityLock = PTHREAD_MUTEX_INITIALIZER;
72 static pthread_mutex_t g_serviceDataLock = PTHREAD_MUTEX_INITIALIZER;
73 static pthread_mutex_t g_businessDataLock = PTHREAD_MUTEX_INITIALIZER;
74 static pthread_mutex_t g_extendServiceDataLock = PTHREAD_MUTEX_INITIALIZER;
75 static pthread_mutex_t g_deviceInfoLock = PTHREAD_MUTEX_INITIALIZER;
76 
LocalDeviceTimeout(void * data)77 static void LocalDeviceTimeout(void *data)
78 {
79     (void)data;
80 
81     struct timespec cur;
82     ClockGetTime(CLOCK_MONOTONIC, &cur);
83 
84     uint32_t nextTimeout = 0;
85     List *pos = NULL;
86     List *tmp = NULL;
87     LIST_FOR_EACH_SAFE(pos, tmp, &g_localDevice.destroyList) {
88         struct LocalIface *iface = (struct LocalIface *)pos;
89         uint32_t diff = GetTimeDiffMs(&cur, &iface->updateTime);
90         if (diff < LOCAL_DEVICE_OFFLINE_DEFERRED_DURATION) {
91             nextTimeout = LOCAL_DEVICE_OFFLINE_DEFERRED_DURATION - diff;
92             break;
93         }
94 
95         DestroyLocalIface(iface, NSTACKX_FALSE);
96     }
97 
98     if (nextTimeout != 0) {
99         DFINDER_LOGD(TAG, "start offline timer again, timeout %u", nextTimeout);
100         (void)TimerSetTimeout(g_localDevice.timer, nextTimeout, NSTACKX_FALSE);
101     }
102 }
103 
LocalDeviceDeinit(void)104 void LocalDeviceDeinit(void)
105 {
106     if (!g_localDevice.inited) {
107         DFINDER_LOGW(TAG, "local device not inited");
108         return;
109     }
110 
111     List *pos = NULL;
112     List *tmp = NULL;
113     int i;
114     for (i = 0; i < IFACE_TYPE_MAX; i++) {
115         LIST_FOR_EACH_SAFE(pos, tmp, &g_localDevice.readyList[i]) {
116             DestroyLocalIface((struct LocalIface *)pos, NSTACKX_TRUE);
117         }
118     }
119 
120     LIST_FOR_EACH_SAFE(pos, tmp, &g_localDevice.destroyList) {
121         DestroyLocalIface((struct LocalIface *)pos, NSTACKX_TRUE);
122     }
123 
124     LIST_FOR_EACH_SAFE(pos, tmp, &g_localDevice.creatingList) {
125         DestroyLocalIface((struct LocalIface *)pos, NSTACKX_TRUE);
126     }
127 
128     if (g_localDevice.timer != NULL) {
129         TimerDelete(g_localDevice.timer);
130         g_localDevice.timer = NULL;
131     }
132 
133     g_localDevice.inited = NSTACKX_FALSE;
134 }
135 
LocalDeviceInit(EpollDesc epollfd)136 int LocalDeviceInit(EpollDesc epollfd)
137 {
138     (void)memset_s(&g_localDevice, sizeof(g_localDevice), 0, sizeof(g_localDevice));
139     g_localDevice.timer = TimerStart(epollfd, 0, NSTACKX_FALSE, LocalDeviceTimeout, NULL);
140     if (g_localDevice.timer == NULL) {
141         DFINDER_LOGE(TAG, "timer init failed");
142         return NSTACKX_EFAILED;
143     }
144 
145     int i;
146     for (i = 0; i < IFACE_TYPE_MAX; i++) {
147         ListInitHead(&g_localDevice.readyList[i]);
148     }
149 
150     ListInitHead(&g_localDevice.destroyList);
151     ListInitHead(&g_localDevice.creatingList);
152     g_localDevice.inited = NSTACKX_TRUE;
153 
154     return NSTACKX_EOK;
155 }
156 
ResetLocalDeviceTaskCount(uint8_t isBusy)157 void ResetLocalDeviceTaskCount(uint8_t isBusy)
158 {
159     if (g_localDevice.timer != NULL) {
160         if (isBusy) {
161             DFINDER_LOGI(TAG, "in this busy interval: offline deferred timer task count %llu",
162                          g_localDevice.timer->task.count);
163         }
164         g_localDevice.timer->task.count = 0;
165     }
166 }
167 
LocalIfaceChangeState(struct LocalIface * iface,List * targetList,uint8_t state)168 static inline void LocalIfaceChangeState(struct LocalIface *iface, List *targetList, uint8_t state)
169 {
170     DFINDER_LOGI(TAG, "iface %s state change: %hhu -> %hhu", iface->ifname, iface->state, state);
171     ListRemoveNode(&iface->node);
172     iface->state = state;
173     ListInsertTail(targetList, &iface->node);
174 }
175 
LocalIfaceCreateContextTimeout(void * arg)176 static void LocalIfaceCreateContextTimeout(void *arg)
177 {
178     struct LocalIface *iface = (struct LocalIface *)arg;
179     DFINDER_LOGD(TAG, "iface %s create context for %u times", iface->ifname, iface->createCount);
180     iface->ctx = CoapServerInit(&iface->ip, (void *)iface);
181     if (iface->ctx != NULL) {
182         DFINDER_LOGD(TAG, "iface %s create coap context success", iface->ifname);
183         TimerDelete(iface->timer);
184         iface->timer = NULL;
185         LocalIfaceChangeState(iface, &g_localDevice.readyList[iface->type], IFACE_STATE_READY);
186         return;
187     }
188 
189     if (iface->createCount >= IFACE_COAP_CTX_INIT_MAX_RETRY_TIMES) {
190         DFINDER_LOGE(TAG, "create context retry reach max times %hhu", iface->createCount);
191         DestroyLocalIface(iface, NSTACKX_FALSE);
192         return;
193     }
194 
195     (void)TimerSetTimeout(iface->timer, g_ifaceCoapCtxRetryBackoffList[iface->createCount], NSTACKX_FALSE);
196     iface->createCount++;
197 }
198 
NeedCreateSynchronously(uint8_t ifaceType)199 static inline bool NeedCreateSynchronously(uint8_t ifaceType)
200 {
201     return ifaceType < IFACE_TYPE_P2P;
202 }
203 
LocalIfaceInit(struct LocalIface * iface,const char * ifname,const struct in_addr * ip,const char * ipStr)204 static int LocalIfaceInit(struct LocalIface *iface, const char *ifname, const struct in_addr *ip, const char *ipStr)
205 {
206     DFINDER_LOGI(TAG, "trying to bring up interface %s", ifname);
207 
208     if (strcpy_s(iface->ifname, sizeof(iface->ifname), ifname) != EOK) {
209         DFINDER_LOGE(TAG, "copy ifname %s failed", ifname);
210         return NSTACKX_EFAILED;
211     }
212     if (strcpy_s(iface->ipStr, sizeof(iface->ipStr), ipStr) != EOK) {
213         DFINDER_LOGE(TAG, "copy ip string failed");
214         return NSTACKX_EFAILED;
215     }
216     iface->type = GetIfaceType(ifname);
217     iface->ip.s_addr = ip->s_addr;
218 
219     if (NeedCreateSynchronously(iface->type)) {
220         iface->ctx = CoapServerInit(ip, (void *)iface);
221         if (iface->ctx == NULL) {
222             DFINDER_LOGE(TAG, "create coap context failed");
223             IncStatistics(STATS_CREATE_SERVER_FAILED);
224             return NSTACKX_EFAILED;
225         }
226         iface->state = IFACE_STATE_READY;
227         ListInsertTail(&g_localDevice.readyList[iface->type], &iface->node);
228     } else {
229         iface->timer = TimerStart(GetEpollFD(), g_ifaceCoapCtxRetryBackoffList[0],
230             NSTACKX_FALSE, LocalIfaceCreateContextTimeout, iface);
231         if (iface->timer == NULL) {
232             DFINDER_LOGE(TAG, "iface %s create timer to create context async failed", iface->ifname);
233             return NSTACKX_EFAILED;
234         }
235         iface->createCount = 1;
236         iface->state = IFACE_STATE_CREATING;
237         ListInsertTail(&g_localDevice.creatingList, &iface->node);
238     }
239 
240     return NSTACKX_EOK;
241 }
242 
CreateLocalIface(const char * ifname,const struct in_addr * ip,const char * ipStr)243 static struct LocalIface *CreateLocalIface(const char *ifname, const struct in_addr *ip, const char *ipStr)
244 {
245     struct LocalIface *iface = calloc(1, sizeof(struct LocalIface));
246     if (iface == NULL) {
247         DFINDER_LOGE(TAG, "alloc falied");
248         return NULL;
249     }
250 
251     if (LocalIfaceInit(iface, ifname, ip, ipStr) != NSTACKX_EOK) {
252         DFINDER_LOGE(TAG, "local iface init failed");
253         free(iface);
254         return NULL;
255     }
256 
257     return iface;
258 }
259 
DestroyLocalIface(struct LocalIface * iface,bool moduleDeinit)260 void DestroyLocalIface(struct LocalIface *iface, bool moduleDeinit)
261 {
262     DFINDER_LOGI(TAG, "destroy iface %s, type: %hhu state: %hhu", iface->ifname, iface->type, iface->state);
263 
264 #ifdef DFINDER_SAVE_DEVICE_LIST
265     DestroyRxIfaceByIfname(iface->ifname);
266 #endif
267 
268     if (iface->ctx != NULL) {
269         CoapServerDestroy(iface->ctx, moduleDeinit);
270     }
271     ListRemoveNode(&iface->node);
272     if (iface->timer != NULL) {
273         TimerDelete(iface->timer);
274     }
275     free(iface);
276 }
277 
GetLocalIface(List * head,const char * ifname,const struct in_addr * ip)278 static struct LocalIface *GetLocalIface(List *head, const char *ifname, const struct in_addr *ip)
279 {
280     List *pos = NULL;
281     LIST_FOR_EACH(pos, head) {
282         struct LocalIface *iface = (struct LocalIface *)pos;
283         DFINDER_LOGD(TAG, "local ifname: %s, ifname: %s", iface->ifname, ifname);
284         if (strcmp(iface->ifname, ifname) == 0 && (ip == NULL || ip->s_addr == iface->ip.s_addr)) {
285             return iface;
286         }
287     }
288 
289     return NULL;
290 }
291 
GetActiveLocalIface(const char * ifname)292 static struct LocalIface *GetActiveLocalIface(const char *ifname)
293 {
294     uint8_t type = GetIfaceType(ifname);
295     struct LocalIface *iface = GetLocalIface(&g_localDevice.readyList[type], ifname, NULL);
296     if (iface == NULL) {
297         iface = GetLocalIface(&g_localDevice.creatingList, ifname, NULL);
298     }
299 
300     return iface;
301 }
302 
AddToDestroyList(struct LocalIface * iface)303 static void AddToDestroyList(struct LocalIface *iface)
304 {
305     if (iface->state != IFACE_STATE_DESTROYING) {
306         if (ListIsEmpty(&g_localDevice.destroyList)) {
307             (void)TimerSetTimeout(g_localDevice.timer, LOCAL_DEVICE_OFFLINE_DEFERRED_DURATION, NSTACKX_FALSE);
308             DFINDER_LOGD(TAG, "iface %s start offline timer", iface->ifname);
309         }
310         LocalIfaceChangeState(iface, &g_localDevice.destroyList, IFACE_STATE_DESTROYING);
311         ClockGetTime(CLOCK_MONOTONIC, &iface->updateTime);
312         if (iface->timer != NULL) {
313             (void)TimerSetTimeout(iface->timer, 0, NSTACKX_FALSE);
314             iface->createCount = 0;
315         }
316     }
317 }
318 
AddLocalIface(const char * ifname,const struct in_addr * ip)319 int AddLocalIface(const char *ifname, const struct in_addr *ip)
320 {
321     struct LocalIface *iface = GetActiveLocalIface(ifname);
322     if (iface == NULL) {
323         iface = GetLocalIface(&g_localDevice.destroyList, ifname, ip);
324         if (iface != NULL) {
325             DFINDER_LOGW(TAG, "iface %s is in destroying", ifname);
326             LocalIfaceChangeState(iface, &g_localDevice.readyList[iface->type], IFACE_STATE_READY);
327             return NSTACKX_EOK;
328         }
329     } else {
330         if (iface->ip.s_addr == ip->s_addr) {
331             DFINDER_LOGW(TAG, "iface %s already existed", ifname);
332             return NSTACKX_EOK;
333         }
334 
335         AddToDestroyList(iface);
336     }
337 
338     char ipStr[INET_ADDRSTRLEN] = {0};
339     if (inet_ntop(AF_INET, ip, ipStr, sizeof(ipStr)) == NULL) {
340         DFINDER_LOGE(TAG, "ip to string failed");
341         return NSTACKX_EFAILED;
342     }
343 
344     iface = CreateLocalIface(ifname, ip, ipStr);
345     return (iface == NULL) ? NSTACKX_EFAILED : NSTACKX_EOK;
346 }
347 
RemoveLocalIface(const char * ifname)348 void RemoveLocalIface(const char *ifname)
349 {
350     struct LocalIface *iface = GetActiveLocalIface(ifname);
351     if (iface == NULL) {
352         DFINDER_LOGW(TAG, "iface %s not found when deleting iface", ifname);
353         return;
354     }
355 
356     AddToDestroyList(iface);
357 }
358 
RemoveAllLocalIfaceOfList(List * list)359 static void RemoveAllLocalIfaceOfList(List *list)
360 {
361     List *pos = NULL;
362     List *tmp = NULL;
363     LIST_FOR_EACH_SAFE(pos, tmp, list) {
364         AddToDestroyList((struct LocalIface *)pos);
365     }
366 }
367 
RemoveAllLocalIface(void)368 static void RemoveAllLocalIface(void)
369 {
370     uint8_t i;
371     for (i = IFACE_TYPE_ETH; i < IFACE_TYPE_MAX; i++) {
372         RemoveAllLocalIfaceOfList(&g_localDevice.readyList[i]);
373     }
374 
375     RemoveAllLocalIfaceOfList(&g_localDevice.creatingList);
376 }
377 
RemoveSpecifiedLocalIface(const NSTACKX_InterfaceInfo * ifInfo,uint32_t ifNums)378 static inline void RemoveSpecifiedLocalIface(const NSTACKX_InterfaceInfo *ifInfo, uint32_t ifNums)
379 {
380     uint32_t i;
381     for (i = 0; i < ifNums; ++i) {
382         RemoveLocalIface(ifInfo[i].networkName);
383     }
384 }
385 
AddLocalIfaceIpChanged(const NSTACKX_InterfaceInfo * ifInfo,uint32_t ifNums)386 static int AddLocalIfaceIpChanged(const NSTACKX_InterfaceInfo *ifInfo, uint32_t ifNums)
387 {
388     uint8_t ifaceType = IFACE_TYPE_MAX;
389     uint32_t i;
390     for (i = 0; i < ifNums; ++i) {
391         if (ifInfo->networkName[0] == '\0' || ifInfo->networkIpAddr[0] == '\0') {
392             DFINDER_LOGI(TAG, "skip empty network name or ip addr");
393             continue;
394         }
395 
396         struct in_addr ip;
397         if (inet_pton(AF_INET, ifInfo[i].networkIpAddr, &ip) != 1) {
398             DFINDER_LOGE(TAG, "invalid ip addr of iface %u", ifInfo[i].networkName);
399             return NSTACKX_EFAILED;
400         }
401 
402         if (ip.s_addr == 0) {
403             DFINDER_LOGI(TAG, "skip ip with any");
404             continue;
405         }
406 
407         if (AddLocalIface(ifInfo[i].networkName, &ip) != NSTACKX_EOK) {
408             DFINDER_LOGE(TAG, "create local iface %s failed", ifInfo[i].networkName);
409             return NSTACKX_EFAILED;
410         }
411 
412         uint8_t curIfaceType = GetIfaceType(ifInfo[i].networkName);
413         if (curIfaceType < ifaceType) { /* storge the highest priority interface name */
414             if (strcpy_s(g_localDevice.deviceInfo.networkName, sizeof(g_localDevice.deviceInfo.networkName),
415                 ifInfo[i].networkName) != EOK) {
416                 DFINDER_LOGE(TAG, "copy ifname %s failed", ifInfo[i].networkName);
417                 return NSTACKX_EFAILED;
418             }
419             ifaceType = curIfaceType;
420         }
421     }
422 
423     return NSTACKX_EOK;
424 }
425 
CopyDeviceInfoV2(const NSTACKX_LocalDeviceInfoV2 * devInfo)426 static int CopyDeviceInfoV2(const NSTACKX_LocalDeviceInfoV2 *devInfo)
427 {
428     if (strcpy_s(g_localDevice.deviceInfo.deviceId, sizeof(g_localDevice.deviceInfo.deviceId),
429         devInfo->deviceId) != EOK) {
430         DFINDER_LOGE(TAG, "copy device id failed");
431         return NSTACKX_EFAILED;
432     }
433 
434     if (devInfo->name[0] == '\0') {
435         DFINDER_LOGW(TAG, "Invalid device name. Will use default name");
436         (void)strcpy_s(g_localDevice.deviceInfo.deviceName,
437             sizeof(g_localDevice.deviceInfo.deviceName), NSTACKX_DEFAULT_DEVICE_NAME);
438     } else {
439         if (strcpy_s(g_localDevice.deviceInfo.deviceName,
440             sizeof(g_localDevice.deviceInfo.deviceName), devInfo->name) != EOK) {
441             DFINDER_LOGE(TAG, "copy device name %s failed", devInfo->name);
442             return NSTACKX_EFAILED;
443         }
444     }
445 
446     g_localDevice.deviceInfo.deviceType = devInfo->deviceType;
447     g_localDevice.deviceInfo.businessType = devInfo->businessType;
448     if (devInfo->hasDeviceHash) {
449         SetLocalDeviceHash(devInfo->deviceHash);
450     }
451 
452     return NSTACKX_EOK;
453 }
454 
RegisterLocalDeviceV2(const NSTACKX_LocalDeviceInfoV2 * devInfo,int registerType)455 int RegisterLocalDeviceV2(const NSTACKX_LocalDeviceInfoV2 *devInfo, int registerType)
456 {
457     if (PthreadMutexLock(&g_deviceInfoLock) != 0) {
458         DFINDER_LOGE(TAG, "failed to lock");
459         return NSTACKX_EFAILED;
460     }
461     if (registerType == REGISTER_TYPE_UPDATE_ALL) {
462         RemoveAllLocalIface();
463     } else {
464         RemoveSpecifiedLocalIface(devInfo->localIfInfo, devInfo->ifNums);
465     }
466 
467     if (CopyDeviceInfoV2(devInfo) != NSTACKX_EOK) {
468         if (PthreadMutexUnlock(&g_deviceInfoLock) != 0) {
469             DFINDER_LOGE(TAG, "failed to unlock");
470         }
471         return NSTACKX_EFAILED;
472     }
473 
474     if (AddLocalIfaceIpChanged(devInfo->localIfInfo, devInfo->ifNums) != NSTACKX_EOK) {
475         if (registerType == REGISTER_TYPE_UPDATE_ALL) {
476             RemoveAllLocalIface(); /* maybe some ifaces is added, so remove all ifaces again */
477         }
478         if (PthreadMutexUnlock(&g_deviceInfoLock) != 0) {
479             DFINDER_LOGE(TAG, "failed to unlock");
480         }
481         return NSTACKX_EFAILED;
482     }
483     if (PthreadMutexUnlock(&g_deviceInfoLock) != 0) {
484         DFINDER_LOGE(TAG, "failed to unlock");
485         return NSTACKX_EFAILED;
486     }
487 
488     return NSTACKX_EOK;
489 }
490 
ConfigureLocalDeviceName(const char * localDeviceName)491 void ConfigureLocalDeviceName(const char *localDeviceName)
492 {
493     char backupDevName[NSTACKX_MAX_DEVICE_NAME_LEN] = {0};
494     if (memcpy_s(backupDevName, sizeof(backupDevName), g_localDevice.deviceInfo.deviceName,
495         sizeof(g_localDevice.deviceInfo.deviceName)) != EOK) {
496         DFINDER_LOGE(TAG, "backup local device name failed!");
497         return;
498     }
499     if (strncpy_s(g_localDevice.deviceInfo.deviceName, NSTACKX_MAX_DEVICE_NAME_LEN,
500         localDeviceName, NSTACKX_MAX_DEVICE_NAME_LEN - 1) != EOK) {
501         DFINDER_LOGW(TAG, "copy local device failed, will use current name");
502         if (strcpy_s(g_localDevice.deviceInfo.deviceName, NSTACKX_MAX_DEVICE_NAME_LEN, backupDevName) != EOK) {
503             DFINDER_LOGE(TAG, "config device name failed and cannot restore!");
504         }
505     }
506 }
507 
SetLocalDeviceHash(uint64_t deviceHash)508 void SetLocalDeviceHash(uint64_t deviceHash)
509 {
510     (void)memset_s(g_localDevice.deviceInfo.deviceHash, sizeof(g_localDevice.deviceInfo.deviceHash),
511         0, sizeof(g_localDevice.deviceInfo.deviceHash));
512     if (sprintf_s(g_localDevice.deviceInfo.deviceHash, DEVICE_HASH_LEN,
513         "%ju", deviceHash) == -1) {
514         DFINDER_LOGE(TAG, "set device hash error");
515     }
516 }
517 
SetLocalDeviceCapability(uint32_t capabilityBitmapNum,uint32_t capabilityBitmap[])518 int SetLocalDeviceCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
519 {
520     if (PthreadMutexLock(&g_capabilityLock) != 0) {
521         DFINDER_LOGE(TAG, "failed to lock");
522         return NSTACKX_EFAILED;
523     }
524     (void)memset_s(g_localDevice.deviceInfo.capabilityBitmap, sizeof(g_localDevice.deviceInfo.capabilityBitmap),
525         0, sizeof(g_localDevice.deviceInfo.capabilityBitmap));
526     g_localDevice.deviceInfo.capabilityBitmapNum = 0;
527 
528     if (capabilityBitmapNum > 0) {
529         if (memcpy_s(g_localDevice.deviceInfo.capabilityBitmap, sizeof(g_localDevice.deviceInfo.capabilityBitmap),
530             capabilityBitmap, sizeof(uint32_t) * capabilityBitmapNum) != EOK) {
531             DFINDER_LOGE(TAG, "capabilityBitmap copy error");
532             if (PthreadMutexUnlock(&g_capabilityLock) != 0) {
533                 DFINDER_LOGE(TAG, "failed to unlock");
534             }
535             return NSTACKX_EFAILED;
536         }
537     }
538 
539     g_localDevice.deviceInfo.capabilityBitmapNum = capabilityBitmapNum;
540     if (PthreadMutexUnlock(&g_capabilityLock) != 0) {
541         DFINDER_LOGE(TAG, "failed to unlock");
542         return NSTACKX_EFAILED;
543     }
544     return NSTACKX_EOK;
545 }
546 
SetLocalDeviceServiceData(const char * serviceData)547 int32_t SetLocalDeviceServiceData(const char *serviceData)
548 {
549     if (PthreadMutexLock(&g_serviceDataLock) != 0) {
550         DFINDER_LOGE(TAG, "failed to lock");
551         return NSTACKX_EFAILED;
552     }
553     if (strcpy_s(g_localDevice.deviceInfo.serviceData, NSTACKX_MAX_SERVICE_DATA_LEN, serviceData) != EOK) {
554         DFINDER_LOGE(TAG, "serviceData copy error");
555         if (PthreadMutexUnlock(&g_serviceDataLock) != 0) {
556             DFINDER_LOGE(TAG, "failed to unlock");
557         }
558         return NSTACKX_EFAILED;
559     }
560     if (PthreadMutexUnlock(&g_serviceDataLock) != 0) {
561         DFINDER_LOGE(TAG, "failed to unlock");
562         return NSTACKX_EFAILED;
563     }
564     return NSTACKX_EOK;
565 }
566 
SetLocalDeviceBusinessType(uint8_t businessType)567 void SetLocalDeviceBusinessType(uint8_t businessType)
568 {
569     g_localDevice.deviceInfo.businessType = businessType;
570 }
571 
GetLocalDeviceBusinessType(void)572 uint8_t GetLocalDeviceBusinessType(void)
573 {
574     return g_localDevice.deviceInfo.businessType;
575 }
576 
SetLocalDeviceBusinessData(const char * data,bool unicast)577 int SetLocalDeviceBusinessData(const char *data, bool unicast)
578 {
579     if (PthreadMutexLock(&g_businessDataLock) != 0) {
580         DFINDER_LOGE(TAG, "failed to lock");
581         return NSTACKX_EFAILED;
582     }
583     int ret = EOK;
584     if (unicast) {
585         ret = strcpy_s(g_localDevice.deviceInfo.businessData.businessDataUnicast,
586             NSTACKX_MAX_BUSINESS_DATA_LEN, data);
587     } else {
588         ret = strcpy_s(g_localDevice.deviceInfo.businessData.businessDataBroadcast,
589             NSTACKX_MAX_BUSINESS_DATA_LEN, data);
590     }
591 
592     if (ret != EOK) {
593         DFINDER_LOGE(TAG, "businessData copy error, unicast: %d", unicast);
594         if (PthreadMutexUnlock(&g_businessDataLock) != 0) {
595             DFINDER_LOGE(TAG, "failed to unlock");
596         }
597         return NSTACKX_EFAILED;
598     }
599 
600     if (PthreadMutexUnlock(&g_businessDataLock) != 0) {
601         DFINDER_LOGE(TAG, "failed to unlock");
602         return NSTACKX_EFAILED;
603     }
604 
605     return NSTACKX_EOK;
606 }
607 
LocalizeNotificationMsg(const char * msg)608 int32_t LocalizeNotificationMsg(const char *msg)
609 {
610     if (strcpy_s(g_localDevice.deviceInfo.notification, NSTACKX_MAX_NOTIFICATION_DATA_LEN, msg) != EOK) {
611         DFINDER_LOGE(TAG, "copy notification msg to local dev failed");
612         return NSTACKX_EFAILED;
613     }
614     return NSTACKX_EOK;
615 }
616 
GetLocalDeviceMode(void)617 uint8_t GetLocalDeviceMode(void)
618 {
619     return g_localDevice.deviceInfo.mode;
620 }
621 
SetLocalDeviceMode(uint8_t mode)622 void SetLocalDeviceMode(uint8_t mode)
623 {
624     g_localDevice.deviceInfo.mode = mode;
625 }
626 
627 #ifndef DFINDER_USE_MINI_NSTACKX
SetLocalDeviceExtendServiceData(const char * extendServiceData)628 int32_t SetLocalDeviceExtendServiceData(const char *extendServiceData)
629 {
630     if (PthreadMutexLock(&g_extendServiceDataLock) != 0) {
631         DFINDER_LOGE(TAG, "failed to lock");
632         return NSTACKX_EFAILED;
633     }
634     if (strcpy_s(g_localDevice.deviceInfo.extendServiceData, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN,
635         extendServiceData) != EOK) {
636         DFINDER_LOGE(TAG, "extendServiceData copy error");
637         if (PthreadMutexUnlock(&g_extendServiceDataLock) != 0) {
638             DFINDER_LOGE(TAG, "failed to unlock");
639         }
640         return NSTACKX_EFAILED;
641     }
642     if (PthreadMutexUnlock(&g_extendServiceDataLock) != 0) {
643         DFINDER_LOGE(TAG, "failed to unlock");
644         return NSTACKX_EFAILED;
645     }
646     return NSTACKX_EOK;
647 }
648 
649 #ifndef _WIN32
DetectLocalIface(void * arg)650 void DetectLocalIface(void *arg)
651 {
652     struct ifconf ifc;
653     struct ifreq req[INTERFACE_MAX];
654     int fd = GetInterfaceList(&ifc, req, sizeof(req));
655     if (fd < 0) {
656         DFINDER_LOGE(TAG, "get iface list failed");
657         return;
658     }
659 
660     int interfaceNum = ifc.ifc_len / (int)sizeof(struct ifreq);
661     for (int i = 0; i < interfaceNum && i < INTERFACE_MAX; i++) {
662         /* get IP of this interface */
663         int state = GetInterfaceIP(fd, &req[i]);
664         if (state == NSTACKX_EFAILED) {
665             (void)close(fd);
666             return;
667         } else if (state == NSTACKX_EINVAL) {
668             continue;
669         }
670 
671         uint8_t ifaceType = GetIfaceType(req[i].ifr_name);
672         if (ifaceType > IFACE_TYPE_WLAN) {
673             DFINDER_LOGI(TAG, "skip iface %s", req[i].ifr_name);
674             continue;
675         }
676 
677         struct in_addr *ip = &((struct sockaddr_in *)&req[i].ifr_addr)->sin_addr;
678         if (req[i].ifr_addr.sa_family != AF_INET || ip->s_addr == 0) {
679             DFINDER_LOGD(TAG, "iface %s is not ipv4 or ip is any", req[i].ifr_name);
680             continue;
681         }
682 
683         DFINDER_LOGI(TAG, "try to add new iface %s", req[i].ifr_name);
684         (void)AddLocalIface(req[i].ifr_name, ip);
685     }
686     (void)close(fd);
687 
688     (void)arg;
689 }
690 #endif /* _WIN32 */
691 
692 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
693 
GetBroadcastIp(const struct LocalIface * iface,char * ipStr,size_t ipStrLen)694 int GetBroadcastIp(const struct LocalIface *iface, char *ipStr, size_t ipStrLen)
695 {
696 #ifdef _WIN32
697     return GetIfBroadcastAddr(&iface->ip, ipStr, ipStrLen);
698 #else
699     return GetIfBroadcastIp(iface->ifname, ipStr, ipStrLen);
700 #endif
701 }
702 
GetLocalDeviceId(void)703 const char *GetLocalDeviceId(void)
704 {
705     return g_localDevice.deviceInfo.deviceId;
706 }
707 
GetLocalDeviceInfo(void)708 DeviceInfo *GetLocalDeviceInfo(void)
709 {
710     return &g_localDevice.deviceInfo;
711 }
712 
GetLocalDeviceNetworkName(void)713 const char *GetLocalDeviceNetworkName(void)
714 {
715     return g_localDevice.deviceInfo.networkName;
716 }
717 
GetLocalIfaceIp(const struct LocalIface * iface)718 const struct in_addr *GetLocalIfaceIp(const struct LocalIface *iface)
719 {
720     return &iface->ip;
721 }
722 
GetLocalIfaceIpStr(const struct LocalIface * iface)723 const char *GetLocalIfaceIpStr(const struct LocalIface *iface)
724 {
725     return iface->ipStr;
726 }
727 
GetLocalIfaceName(const struct LocalIface * iface)728 const char *GetLocalIfaceName(const struct LocalIface *iface)
729 {
730     return iface->ifname;
731 }
732 
LocalIfaceGetCoapCtx(const char * ifname)733 CoapCtxType *LocalIfaceGetCoapCtx(const char *ifname)
734 {
735     int i;
736     for (i = 0; i < IFACE_TYPE_MAX; i++) {
737         List *pos = NULL;
738         LIST_FOR_EACH(pos, &g_localDevice.readyList[i]) {
739             struct LocalIface *iface = (struct LocalIface *)pos;
740             if (strcmp(iface->ifname, ifname) != 0) {
741                 continue;
742             }
743 
744             return iface->ctx;
745         }
746     }
747 
748     return NULL;
749 }
750 
751 #ifdef _WIN32
GetLocalIfaceByLocalIp(const struct in_addr * ip)752 static struct LocalIface *GetLocalIfaceByLocalIp(const struct in_addr *ip)
753 {
754     int i;
755     for (i = 0; i < IFACE_TYPE_MAX; i++) {
756         List *pos = NULL;
757         LIST_FOR_EACH(pos, &g_localDevice.readyList[i]) {
758             struct LocalIface *iface = (struct LocalIface *)pos;
759             if (iface->ip.s_addr != ip->s_addr) {
760                 continue;
761             }
762 
763             return iface;
764         }
765     }
766 
767     return NULL;
768 }
769 #endif
770 
771 #ifndef DFINDER_USE_MINI_NSTACKX
IfaceTypeIsMatch(uint8_t ifaceType,uint8_t serverType)772 static inline bool IfaceTypeIsMatch(uint8_t ifaceType, uint8_t serverType)
773 {
774     return serverType == INVALID_TYPE ||
775         (serverType == SERVER_TYPE_WLANORETH && (ifaceType == IFACE_TYPE_ETH || ifaceType == IFACE_TYPE_WLAN)) ||
776         (serverType == SERVER_TYPE_P2P && ifaceType == IFACE_TYPE_P2P) ||
777         (serverType == SERVER_TYPE_USB && ifaceType == IFACE_TYPE_USB);
778 }
779 
LocalIfaceGetCoapCtxByRemoteIp(const struct in_addr * remoteIp,uint8_t serverType)780 CoapCtxType *LocalIfaceGetCoapCtxByRemoteIp(const struct in_addr *remoteIp, uint8_t serverType)
781 {
782     struct LocalIface *iface = NULL;
783     struct sockaddr_in addr;
784     addr.sin_addr.s_addr = remoteIp->s_addr;
785 #ifdef _WIN32
786     InterfaceInfo localDev;
787     (void)memset_s(&localDev, sizeof(InterfaceInfo), 0, sizeof(InterfaceInfo));
788     if (GetTargetAdapter(&addr, &localDev) != NSTACKX_EOK) {
789         DFINDER_LOGE(TAG, "get target adapter failed");
790         return NULL;
791     }
792     struct in_addr localIp = { .s_addr = localDev.ipAddr };
793     iface = GetLocalIfaceByLocalIp(&localIp);
794 #else
795     struct ifreq req;
796     (void)memset_s(&req, sizeof(struct ifreq), 0, sizeof(struct ifreq));
797     if (GetTargetInterface(&addr, &req) != NSTACKX_EOK) {
798         DFINDER_LOGE(TAG, "get target interface failed");
799         return NULL;
800     }
801 
802     uint8_t ifaceType = GetIfaceType(req.ifr_ifrn.ifrn_name);
803     DFINDER_LOGD(TAG, "ifaceType: %hhu", ifaceType);
804     iface = GetLocalIface(&g_localDevice.readyList[ifaceType], req.ifr_ifrn.ifrn_name, NULL);
805 #endif
806     if (iface == NULL) {
807         DFINDER_LOGE(TAG, "can not find iface");
808         return NULL;
809     }
810 
811     if (!IfaceTypeIsMatch(iface->type, serverType)) {
812         DFINDER_LOGE(TAG, "type not match, iface type: %hhu, server type: %hhu", iface->type, serverType);
813         return NULL;
814     }
815 
816     return iface->ctx;
817 }
818 #endif
819 
820 #ifdef NSTACKX_DFINDER_HIDUMP
LocalIfaceDump(char * buf,size_t size)821 int LocalIfaceDump(char *buf, size_t size)
822 {
823     List *pos = NULL;
824     struct LocalIface *iface = NULL;
825     int ret;
826     size_t index = 0;
827     int i;
828     for (i = 0; i < IFACE_TYPE_MAX; i++) {
829         LIST_FOR_EACH(pos, &g_localDevice.readyList[i]) {
830             iface = (struct LocalIface *)pos;
831             ret = DFinderDumpIface(buf + index, size - index, iface->ifname, &iface->ip, iface->state);
832             if (ret < 0 || (uint32_t)ret > size - index) {
833                 return NSTACKX_EFAILED;
834             }
835 
836             index += (uint32_t)ret;
837         }
838     }
839 
840     LIST_FOR_EACH(pos, &g_localDevice.creatingList) {
841         iface = (struct LocalIface *)pos;
842         ret = DFinderDumpIface(buf + index, size - index, iface->ifname, &iface->ip, iface->state);
843         if (ret < 0 || (uint32_t)ret > size - index) {
844             return NSTACKX_EFAILED;
845         }
846 
847         index += (uint32_t)ret;
848     }
849 
850     LIST_FOR_EACH(pos, &g_localDevice.destroyList) {
851         iface = (struct LocalIface *)pos;
852         ret = DFinderDumpIface(buf + index, size - index, iface->ifname, &iface->ip, iface->state);
853         if (ret < 0 || (uint32_t)ret > size - index) {
854             return NSTACKX_EFAILED;
855         }
856 
857         index += (uint32_t)ret;
858     }
859 
860     return index;
861 }
862 #endif
863