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