• 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_common.h"
17 
18 #include <securec.h>
19 #ifndef _WIN32
20 #include <pthread.h>
21 #include <semaphore.h>
22 #include <stdatomic.h>
23 #include <unistd.h>
24 #endif
25 #include "cJSON.h"
26 
27 #ifndef DFINDER_USE_MINI_NSTACKX
28 #include <coap3/coap.h>
29 #endif
30 
31 #include "coap_app.h"
32 #include "coap_discover.h"
33 #include "nstackx.h"
34 #include "nstackx_device.h"
35 #include "nstackx_epoll.h"
36 #include "nstackx_error.h"
37 #include "nstackx_event.h"
38 #include "nstackx_dfinder_log.h"
39 #include "nstackx_smartgenius.h"
40 #include "nstackx_timer.h"
41 #include "nstackx_util.h"
42 #include "nstackx_inet.h"
43 #include "json_payload.h"
44 #include "nstackx_statistics.h"
45 #include "nstackx_dfinder_hidump.h"
46 #include "nstackx_dfinder_hievent.h"
47 #include "nstackx_device_local.h"
48 #include "nstackx_device_remote.h"
49 
50 #ifdef DFINDER_USE_MINI_NSTACKX
51 #include "cmsis_os2.h"
52 #include "ohos_init.h"
53 #define DFINDER_THREAD_STACK_SIZE (1024 * 32)
54 #endif
55 
56 #define MAX_COAP_SERVICE_DATA_CNT 3
57 #define SINGLE_NIC_CNT 1
58 #define TAG "nStackXDFinder"
59 #define DFINDER_THREAD_NAME TAG
60 #define DFINDER_POST_EVENT_MAX_BLOCK_SECONDS 3
61 #define NSEC_TICKS_PER_SEC (1000000000)
62 
63 enum {
64     NSTACKX_INIT_STATE_START = 0,
65     NSTACKX_INIT_STATE_ONGOING,
66     NSTACKX_INIT_STATE_DONE,
67 };
68 
69 #ifdef DFINDER_USE_MINI_NSTACKX
70 static osThreadId_t g_threadId;
71 #else
72 static pthread_t g_tid;
73 #endif
74 
75 static EpollDesc g_epollfd = INVALID_EPOLL_DESC;
76 static List g_eventNodeChain = {&(g_eventNodeChain), &(g_eventNodeChain)};
77 
78 static uint8_t g_validTidFlag = NSTACKX_FALSE;
79 static uint8_t g_terminateFlag = NSTACKX_FALSE;
80 
81 static pthread_mutex_t g_threadInitLock = PTHREAD_MUTEX_INITIALIZER;
82 static NSTACKX_Parameter g_parameter;
83 static atomic_uint_fast8_t g_nstackInitState = NSTACKX_INIT_STATE_START;
84 static atomic_uint_fast8_t g_nstackThreadInitState = NSTACKX_INIT_STATE_START;
85 static bool g_isNotifyPerDevice;
86 
87 #define EVENT_COUNT_RATE_INTERVAL 2000 /* 2 SECONDS */
88 #define MAX_EVENT_PROCESS_NUM_PER_INTERVAL 700
89 #define MAX_CONTINUOUS_BUSY_INTERVAL_NUM 20
90 
91 typedef struct {
92     uint32_t epollWaitTimeoutCount;
93     uint32_t epollWaitEventCount;
94     struct timespec measureBefore;
95 } EventProcessRatePara;
96 static EventProcessRatePara g_processRatePara;
97 static uint32_t g_continuousBusyIntervals;
98 
99 static int32_t CheckDiscoverySettings(const NSTACKX_DiscoverySettings *discoverySettings);
100 static int32_t RegisterDeviceWithType(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo, int registerType);
101 
GetIsNotifyPerDevice(void)102 bool GetIsNotifyPerDevice(void)
103 {
104     return g_isNotifyPerDevice;
105 }
106 
107 #ifdef DFINDER_SUPPORT_COVERITY_TAINTED_SET
Coverity_Tainted_Set(void * buf)108 void Coverity_Tainted_Set(void *buf)
109 {
110     (void)buf;
111 }
112 #endif
113 
GetEventNodeChain(void)114 List *GetEventNodeChain(void)
115 {
116     return &g_eventNodeChain;
117 }
118 
GetEpollFD(void)119 EpollDesc GetEpollFD(void)
120 {
121     return g_epollfd;
122 }
123 
NotifyDFinderMsgRecver(DFinderMsgType msgType)124 void NotifyDFinderMsgRecver(DFinderMsgType msgType)
125 {
126     if (g_parameter.onDFinderMsgReceived != NULL) {
127         g_parameter.onDFinderMsgReceived(msgType);
128     }
129 }
130 
ShouldAutoReplyUnicast(uint8_t businessType)131 int32_t ShouldAutoReplyUnicast(uint8_t businessType)
132 {
133     switch (businessType) {
134         case NSTACKX_BUSINESS_TYPE_SOFTBUS:
135         case NSTACKX_BUSINESS_TYPE_AUTONET:
136         case NSTACKX_BUSINESS_TYPE_STRATEGY:
137             return NSTACKX_FALSE;
138         case NSTACKX_BUSINESS_TYPE_NULL:
139         case NSTACKX_BUSINESS_TYPE_HICOM:
140         case NSTACKX_BUSINESS_TYPE_NEARBY:
141         default:
142             return NSTACKX_TRUE;
143     }
144 }
145 
GetDefaultDiscoverInterval(uint32_t discoverCount)146 uint32_t GetDefaultDiscoverInterval(uint32_t discoverCount)
147 {
148     if (discoverCount < COAP_FIRST_DISCOVER_COUNT_RANGE) {
149         return COAP_FIRST_DISCOVER_INTERVAL;
150     } else if (discoverCount < COAP_SECOND_DISCOVER_COUNT_RANGE) {
151         return COAP_SECOND_DISCOVER_INTERVAL;
152     } else {
153         return COAP_LAST_DISCOVER_INTERVAL;
154     }
155 }
156 
GetServiceDiscoverInfo(const uint8_t * buf,size_t size,struct DeviceInfo * deviceInfo,char ** remoteUrlPtr)157 int32_t GetServiceDiscoverInfo(const uint8_t *buf, size_t size, struct DeviceInfo *deviceInfo, char **remoteUrlPtr)
158 {
159     uint8_t *newBuf = NULL;
160     if (size <= 0) {
161         DFINDER_LOGE(TAG, "buf size <= 0");
162         return NSTACKX_EFAILED;
163     }
164     if (buf[size - 1] != '\0') {
165         newBuf = (uint8_t *)calloc(size + 1, 1U);
166         if (newBuf == NULL) {
167             DFINDER_LOGE(TAG, "data is not end with 0 and new buf calloc error");
168             return NSTACKX_ENOMEM;
169         }
170         if (memcpy_s(newBuf, size + 1, buf, size) != EOK) {
171             DFINDER_LOGE(TAG, "data is not end with 0 and memcpy data error");
172             goto L_COAP_ERR;
173         }
174         DFINDER_LOGI(TAG, "data is not end with 0");
175         buf = newBuf;
176     }
177     if (ParseServiceDiscover(buf, deviceInfo, remoteUrlPtr) != NSTACKX_EOK) {
178         DFINDER_LOGE(TAG, "parse service discover error");
179         goto L_COAP_ERR;
180     }
181 
182     if (newBuf != NULL) {
183         free(newBuf);
184     }
185 
186     return NSTACKX_EOK;
187 L_COAP_ERR:
188     if (newBuf != NULL) {
189         free(newBuf);
190     }
191     return NSTACKX_EFAILED;
192 }
193 
GetServiceNotificationInfo(const uint8_t * buf,size_t size,NSTACKX_NotificationConfig * notification)194 int32_t GetServiceNotificationInfo(const uint8_t *buf, size_t size, NSTACKX_NotificationConfig *notification)
195 {
196     uint8_t *newBuf = NULL;
197     if (buf[size - 1] != '\0') {
198         newBuf = (uint8_t *)calloc(size + 1, 1U);
199         if (newBuf == NULL) {
200             DFINDER_LOGE(TAG, "data is not end with 0 and new buf calloc error");
201             return NSTACKX_ENOMEM;
202         }
203         if (memcpy_s(newBuf, size + 1, buf, size) != EOK) {
204             DFINDER_LOGE(TAG, "data is not end with 0 and memcpy data error");
205             goto L_COAP_ERR;
206         }
207         DFINDER_LOGI(TAG, "data is not end with 0");
208         buf = newBuf;
209     }
210     if (ParseServiceNotification(buf, notification) != NSTACKX_EOK) {
211         DFINDER_LOGE(TAG, "parse service notification error");
212         goto L_COAP_ERR;
213     }
214 
215     if (newBuf != NULL) {
216         free(newBuf);
217     }
218 
219     return NSTACKX_EOK;
220 L_COAP_ERR:
221     if (newBuf != NULL) {
222         free(newBuf);
223     }
224     return NSTACKX_EFAILED;
225 }
226 
ResetMainEpollTaskCount(uint8_t isBusy)227 static void ResetMainEpollTaskCount(uint8_t isBusy)
228 {
229     EpollTask *task = GetEpollTask(&g_eventNodeChain, g_epollfd);
230     if (task == NULL) {
231         return;
232     }
233     if (isBusy) {
234         DFINDER_LOGI(TAG, "in this busy interval: main epoll task count %llu", task->count);
235     }
236     task->count = 0;
237 }
238 
IsBusyInterval(uint32_t eventCount,uint32_t timeMs)239 static uint8_t IsBusyInterval(uint32_t eventCount, uint32_t timeMs)
240 {
241     uint8_t retFlag = NSTACKX_TRUE;
242     if ((uint64_t)eventCount * EVENT_COUNT_RATE_INTERVAL <
243         MAX_EVENT_PROCESS_NUM_PER_INTERVAL * (uint64_t)timeMs) {
244         retFlag = NSTACKX_FALSE;
245     }
246 
247     ResetMainEpollTaskCount(retFlag);
248     ResetCoapSocketTaskCount(retFlag);
249     ResetCoapDiscoverTaskCount(retFlag);
250     ResetDeviceTaskCount(retFlag);
251 #ifndef DFINDER_USE_MINI_NSTACKX
252     ResetSmartGeniusTaskCount(retFlag);
253 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
254 
255     return retFlag;
256 }
257 
CalculateEventProcessRate(void)258 static void CalculateEventProcessRate(void)
259 {
260     struct timespec now;
261     ClockGetTime(CLOCK_MONOTONIC, &now);
262     uint32_t measureElapse = GetTimeDiffMs(&now, &g_processRatePara.measureBefore);
263     if (measureElapse <= EVENT_COUNT_RATE_INTERVAL) {
264         return;
265     }
266     uint32_t totalCount = g_processRatePara.epollWaitEventCount + g_processRatePara.epollWaitTimeoutCount;
267     if (!IsBusyInterval(totalCount, measureElapse)) {
268         g_continuousBusyIntervals = 0;
269     } else {
270         DFINDER_LOGI(TAG, "main loop seems to be busy in the past interval. Timeout count %u, event count %u",
271                         g_processRatePara.epollWaitTimeoutCount, g_processRatePara.epollWaitEventCount);
272         g_continuousBusyIntervals++;
273         if (g_continuousBusyIntervals >= MAX_CONTINUOUS_BUSY_INTERVAL_NUM) {
274             DFINDER_LOGE(TAG, "main loop seems to be busy in the past %u intervals. notify user to restart",
275                             g_continuousBusyIntervals);
276             NotifyDFinderMsgRecver(DFINDER_ON_TOO_BUSY);
277             g_continuousBusyIntervals = 0;
278         }
279     }
280     g_processRatePara.epollWaitTimeoutCount = 0;
281     g_processRatePara.epollWaitEventCount = 0;
282     ClockGetTime(CLOCK_MONOTONIC, &g_processRatePara.measureBefore);
283 }
284 
NstackMainLoop(void * arg)285 static void *NstackMainLoop(void *arg)
286 {
287     int32_t ret;
288     (void)arg;
289     (void)memset_s(&g_processRatePara, sizeof(g_processRatePara), 0, sizeof(g_processRatePara));
290     g_continuousBusyIntervals = 0;
291     ClockGetTime(CLOCK_MONOTONIC, &g_processRatePara.measureBefore);
292 #ifndef DFINDER_USE_MINI_NSTACKX
293     SetThreadName(DFINDER_THREAD_NAME);
294 #endif
295     while (g_terminateFlag == NSTACKX_FALSE) {
296 #ifndef DFINDER_USE_MINI_NSTACKX
297         uint32_t timeout = RegisterCoAPEpollTask(g_epollfd);
298         ret = EpollLoop(g_epollfd, timeout);
299 #else
300         ret = EpollLoop(g_epollfd, -1);
301 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
302         if (ret == NSTACKX_EFAILED) {
303             IncStatistics(STATS_EPOLL_ERROR);
304             DFINDER_LOGE(TAG, "epoll loop failed");
305 #ifndef DFINDER_USE_MINI_NSTACKX
306             DeRegisterCoAPEpollTask();
307 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
308             break;
309         } else if (ret == NSTACKX_ETIMEOUT) {
310             g_processRatePara.epollWaitTimeoutCount++;
311         } else if (ret > 0) {
312             g_processRatePara.epollWaitEventCount++;
313         } else {
314             /* do nothing */
315         }
316         CalculateEventProcessRate();
317 #ifndef DFINDER_USE_MINI_NSTACKX
318         DeRegisterCoAPEpollTask();
319 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
320     }
321     return NULL;
322 }
323 
GetMainLoopEpollFd(void)324 EpollDesc GetMainLoopEpollFd(void)
325 {
326     return g_epollfd;
327 }
328 
GetMainLoopEvendChain(void)329 List *GetMainLoopEvendChain(void)
330 {
331     return &g_eventNodeChain;
332 }
333 
InternalInit(EpollDesc epollfd,uint32_t maxDeviceNum)334 static int32_t InternalInit(EpollDesc epollfd, uint32_t maxDeviceNum)
335 {
336     int32_t ret = EventModuleInit(&g_eventNodeChain, g_epollfd);
337     if (ret != NSTACKX_EOK) {
338         return ret;
339     }
340 
341     ret = DeviceModuleInit(epollfd, maxDeviceNum);
342     if (ret != NSTACKX_EOK) {
343         return ret;
344     }
345 
346 #ifdef _WIN32
347     ret = CoapThreadInit();
348     if (ret != NSTACKX_EOK) {
349         return ret;
350     }
351 #endif
352 
353     ret = CoapDiscoverInit(epollfd);
354     if (ret != NSTACKX_EOK) {
355         return ret;
356     }
357 
358 #ifndef DFINDER_USE_MINI_NSTACKX
359     ret = SmartGeniusInit(epollfd);
360 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
361     return ret;
362 }
363 
364 #ifdef DFINDER_USE_MINI_NSTACKX
ReportMainLoopStopInner(void * argument)365 static void ReportMainLoopStopInner(void *argument)
366 {
367     (void)argument;
368     DFINDER_LOGI(TAG, "receive message to stop main loop");
369 }
370 
ReportMainLoopStop(void)371 static void ReportMainLoopStop(void)
372 {
373     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
374         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
375         return;
376     }
377     if (PostEvent(&g_eventNodeChain, g_epollfd, ReportMainLoopStopInner, NULL) != NSTACKX_EOK) {
378         DFINDER_LOGE(TAG, "Failed to report mainloop stop!");
379     }
380 }
381 #endif
382 
NSTACKX_ThreadInit(void)383 int32_t NSTACKX_ThreadInit(void)
384 {
385     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
386         DFINDER_LOGE(TAG, "nstack is not initiated foundation yet");
387         return NSTACKX_EFAILED;
388     }
389     if (PthreadMutexLock(&g_threadInitLock) != 0) {
390         DFINDER_LOGE(TAG, "Failed to lock");
391         return NSTACKX_EFAILED;
392     }
393     DFINDER_LOGI(TAG, "nstack begin init thread");
394     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_START) {
395         (void)PthreadMutexUnlock(&g_threadInitLock);
396         DFINDER_LOGI(TAG, "nstack init thread done");
397         return NSTACKX_EOK;
398     }
399     g_nstackThreadInitState = NSTACKX_INIT_STATE_ONGOING;
400     g_terminateFlag = NSTACKX_FALSE;
401     g_validTidFlag = NSTACKX_FALSE;
402 #ifndef DFINDER_USE_MINI_NSTACKX
403     int32_t ret = PthreadCreate(&g_tid, NULL, NstackMainLoop, NULL);
404     if (ret != 0) {
405         DFINDER_LOGE(TAG, "thread create failed");
406         g_terminateFlag = NSTACKX_TRUE;
407         (void)PthreadMutexUnlock(&g_threadInitLock);
408         return ret;
409     }
410 #else
411     osThreadAttr_t attr = {0};
412     attr.name = DFINDER_THREAD_NAME;
413     attr.stack_size = DFINDER_THREAD_STACK_SIZE;
414     // osPriorityNormal equals 24
415     attr.priority = osPriorityNormal;
416     g_threadId = osThreadNew((osThreadFunc_t)NstackMainLoop, NULL, &attr);
417     if (g_threadId == NULL) {
418         DFINDER_LOGE(TAG, "thread create failed with attribute settings");
419         g_terminateFlag = NSTACKX_TRUE;
420         (void)PthreadMutexUnlock(&g_threadInitLock);
421         return NSTACKX_EFAILED;
422     }
423 #endif
424     g_validTidFlag = NSTACKX_TRUE;
425     g_nstackThreadInitState = NSTACKX_INIT_STATE_DONE;
426     (void)PthreadMutexUnlock(&g_threadInitLock);
427     DFINDER_LOGI(TAG, "nstack init thread success");
428     return NSTACKX_EOK;
429 }
430 
NSTACKX_ThreadDeinit(void)431 void NSTACKX_ThreadDeinit(void)
432 {
433     if (g_nstackThreadInitState == NSTACKX_INIT_STATE_START) {
434         return;
435     }
436     DFINDER_LOGI(TAG, "nstack begin deinit thread");
437     if (PthreadMutexLock(&g_threadInitLock) != 0) {
438         DFINDER_LOGE(TAG, "Failed to lock");
439         return;
440     }
441     if (g_validTidFlag) {
442         g_terminateFlag = NSTACKX_TRUE;
443 #ifndef DFINDER_USE_MINI_NSTACKX
444         PthreadJoin(g_tid, NULL);
445 #else
446         ReportMainLoopStop();
447         if (osThreadTerminate(g_threadId) != osOK) {
448             DFINDER_LOGE(TAG, "os thread terminate failed");
449         }
450 #endif
451         g_validTidFlag = NSTACKX_FALSE;
452     }
453     g_nstackThreadInitState = NSTACKX_INIT_STATE_START;
454     (void)PthreadMutexUnlock(&g_threadInitLock);
455 }
456 
457 #if !defined(DFINDER_USE_MINI_NSTACKX) && !defined(DFINDER_ENABLE_COAP_LOG)
CoapLogHandler(coap_log_t level,const char * message)458 static void CoapLogHandler(coap_log_t level, const char *message)
459 {
460     (void)level;
461     (void)message;
462 }
463 #endif
464 
InitLogLevel(void)465 static void InitLogLevel(void)
466 {
467     // default log
468     SetLogLevel(NSTACKX_LOG_LEVEL_DEBUG);
469 
470     // user defined log
471 #ifdef ENABLE_USER_LOG
472     SetDFinderLogLevel(DFINDER_LOG_LEVEL_DEBUG);
473 #endif
474 
475 #ifndef DFINDER_USE_MINI_NSTACKX
476     // opensource libcoap log
477 #ifdef DFINDER_ENABLE_COAP_LOG
478     coap_set_log_level(COAP_LOG_DEBUG);
479 #else
480     coap_set_log_handler(CoapLogHandler);
481 #endif
482 #endif
483 }
484 
NstackxInitEx(const NSTACKX_Parameter * parameter,bool isNotifyPerDevice)485 static int32_t NstackxInitEx(const NSTACKX_Parameter *parameter, bool isNotifyPerDevice)
486 {
487     Coverity_Tainted_Set((void *)parameter);
488 
489     int32_t ret;
490 
491     if (g_nstackInitState != NSTACKX_INIT_STATE_START) {
492         return NSTACKX_EOK;
493     }
494 
495     g_nstackInitState = NSTACKX_INIT_STATE_ONGOING;
496     cJSON_InitHooks(NULL);
497 
498     InitLogLevel();
499 
500 #ifdef NSTACKX_WITH_LITEOS
501     EpollEventPtrInit(); /* init g_epollEventPtrMutex g_epollEventPtrArray */
502 #endif
503 
504     g_epollfd = CreateEpollDesc();
505     if (!IsEpollDescValid(g_epollfd)) {
506         DFINDER_LOGE(TAG, "epoll creat fail! errno: %d", errno);
507         g_nstackInitState = NSTACKX_INIT_STATE_START;
508         return NSTACKX_EFAILED;
509     }
510 
511     DFINDER_LOGD(TAG, "nstack ctrl creat epollfd %d", REPRESENT_EPOLL_DESC(g_epollfd));
512 #ifdef DFINDER_SAVE_DEVICE_LIST
513     ret = InternalInit(g_epollfd, parameter != NULL ? parameter->maxDeviceNum : NSTACKX_DEFAULT_DEVICE_NUM);
514 #else
515     ret = InternalInit(g_epollfd, parameter != NULL ? parameter->maxDeviceNum : NSTACKX_MAX_DEVICE_NUM);
516 #endif
517     if (ret != NSTACKX_EOK) {
518         DFINDER_LOGE(TAG, "internal init failed, ret=%d", ret);
519         goto L_ERR_INIT;
520     }
521     (void)memset_s(&g_parameter, sizeof(g_parameter), 0, sizeof(g_parameter));
522     if (parameter != NULL) {
523         (void)memcpy_s(&g_parameter, sizeof(g_parameter), parameter, sizeof(NSTACKX_Parameter));
524     }
525 
526 #ifndef DFINDER_USE_MINI_NSTACKX
527     CoapInitSubscribeModuleInner(); /* initialize subscribe module number */
528 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
529     g_isNotifyPerDevice = isNotifyPerDevice;
530     g_nstackInitState = NSTACKX_INIT_STATE_DONE;
531     DFINDER_LOGI(TAG, "DFinder init successfully");
532     return NSTACKX_EOK;
533 
534 L_ERR_INIT:
535     NSTACKX_Deinit();
536     return ret;
537 }
538 
NSTACKX_Init(const NSTACKX_Parameter * parameter)539 int32_t NSTACKX_Init(const NSTACKX_Parameter *parameter)
540 {
541     return NstackxInitEx(parameter, false);
542 }
543 
NSTACKX_InitV2(const NSTACKX_Parameter * parameter,bool isNotifyPerDevice)544 int32_t NSTACKX_InitV2(const NSTACKX_Parameter *parameter, bool isNotifyPerDevice)
545 {
546     return NstackxInitEx(parameter, isNotifyPerDevice);
547 }
548 
NSTACKX_Deinit(void)549 void NSTACKX_Deinit(void)
550 {
551     if (g_nstackInitState == NSTACKX_INIT_STATE_START) {
552         return;
553     }
554     NSTACKX_ThreadDeinit();
555 #ifndef DFINDER_USE_MINI_NSTACKX
556     SmartGeniusClean();
557 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
558     CoapDiscoverDeinit();
559 
560 #ifdef _WIN32
561     CoapThreadDestroy();
562 #endif
563     DeviceModuleClean();
564     EventNodeChainClean(&g_eventNodeChain);
565     if (IsEpollDescValid(g_epollfd)) {
566         CloseEpollDesc(g_epollfd);
567         g_epollfd = INVALID_EPOLL_DESC;
568     }
569     ResetStatistics();
570     ResetEventFunc();
571     ResetSequenceNumber();
572     g_nstackInitState = NSTACKX_INIT_STATE_START;
573     DFINDER_LOGI(TAG, "deinit successfully");
574 }
575 
DeviceDiscoverInner(void * argument)576 static void DeviceDiscoverInner(void *argument)
577 {
578     if (!IsCoapContextReady()) {
579         DFINDER_LOGE(TAG, "no iface is ready, notify user with empty list");
580         NotifyDeviceFound(NULL, 0);
581         return;
582     }
583 
584     (void)argument;
585     SetCoapDiscoverType(COAP_BROADCAST_TYPE_DEFAULT);
586     SetLocalDeviceBusinessType(NSTACKX_BUSINESS_TYPE_NULL);
587     CoapServiceDiscoverInner(INNER_DISCOVERY);
588 }
589 
DeviceDiscoverInnerAn(void * argument)590 static void DeviceDiscoverInnerAn(void *argument)
591 {
592     (void)argument;
593     SetCoapDiscoverType(COAP_BROADCAST_TYPE_DEFAULT);
594     SetLocalDeviceBusinessType(NSTACKX_BUSINESS_TYPE_NULL);
595     CoapServiceDiscoverInnerAn(INNER_DISCOVERY);
596 }
597 
DeviceDiscoverInnerConfigurable(void * argument)598 static void DeviceDiscoverInnerConfigurable(void *argument)
599 {
600     NSTACKX_DiscoverySettings *discoverySettings = argument;
601     int32_t configResult = ConfigureDiscoverySettings(discoverySettings);
602     free(discoverySettings->businessData);
603     free(discoverySettings);
604     if (configResult != NSTACKX_EOK) {
605         DFINDER_LOGE(TAG, "config discovery settings failed");
606         return;
607     }
608     CoapServiceDiscoverInnerConfigurable(INNER_DISCOVERY);
609 }
610 
DiscConfig(void * argument)611 static void DiscConfig(void *argument)
612 {
613     DFinderDiscConfig *discConfig = argument;
614     uint8_t businessTypeLocal = GetLocalDeviceBusinessType();
615     if (discConfig->businessType != businessTypeLocal) {
616         DFINDER_LOGE(TAG, "business type is different, config: %hhu, local: %hhu",
617             discConfig->businessType, businessTypeLocal);
618         free(discConfig->businessData);
619         free(discConfig->bcastInterval);
620         free(discConfig);
621         return;
622     }
623     int32_t configResult = DiscConfigInner(discConfig);
624     free(discConfig->businessData);
625     free(discConfig->bcastInterval);
626     free(discConfig);
627     if (configResult != NSTACKX_EOK) {
628         DFINDER_LOGE(TAG, "config for discover failed");
629         return;
630     }
631     CoapServiceDiscoverInnerConfigurable(INNER_DISCOVERY);
632 }
633 
DeviceDiscoverStopInner(void * argument)634 static void DeviceDiscoverStopInner(void *argument)
635 {
636     (void)argument;
637     CoapServiceDiscoverStopInner();
638     NotifyStatisticsEvent();
639 }
640 
NSTACKX_StartDeviceFind(void)641 int32_t NSTACKX_StartDeviceFind(void)
642 {
643     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
644         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
645         return NSTACKX_EFAILED;
646     }
647     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInner, NULL) != NSTACKX_EOK) {
648         DFINDER_LOGE(TAG, "Failed to start device discover!");
649         return NSTACKX_EFAILED;
650     }
651     return NSTACKX_EOK;
652 }
653 
NSTACKX_StartDeviceFindAn(uint8_t mode)654 int32_t NSTACKX_StartDeviceFindAn(uint8_t mode)
655 {
656     Coverity_Tainted_Set((void *)&mode);
657     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
658         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
659         return NSTACKX_EFAILED;
660     }
661     SetModeInfo(mode);
662     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerAn, NULL) != NSTACKX_EOK) {
663         DFINDER_LOGE(TAG, "Failed to start device discover!");
664         return NSTACKX_EFAILED;
665     }
666     return NSTACKX_EOK;
667 }
668 
NSTACKX_StopDeviceFind(void)669 int32_t NSTACKX_StopDeviceFind(void)
670 {
671     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
672         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
673         return NSTACKX_EFAILED;
674     }
675     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverStopInner, NULL) != NSTACKX_EOK) {
676         DFINDER_LOGE(TAG, "Failed to stop device discover!");
677         return NSTACKX_EFAILED;
678     }
679     return NSTACKX_EOK;
680 }
681 
CopyDiscoverySettings(NSTACKX_DiscoverySettings * dupDiscoverySettings,const NSTACKX_DiscoverySettings * discoverySettings)682 static int32_t CopyDiscoverySettings(NSTACKX_DiscoverySettings *dupDiscoverySettings,
683                                      const NSTACKX_DiscoverySettings *discoverySettings)
684 {
685     dupDiscoverySettings->businessType = discoverySettings->businessType;
686     dupDiscoverySettings->discoveryMode = discoverySettings->discoveryMode;
687     dupDiscoverySettings->length = discoverySettings->length;
688     if (discoverySettings->businessData != NULL) {
689         if (strncpy_s(dupDiscoverySettings->businessData, (dupDiscoverySettings->length + 1),
690             discoverySettings->businessData, discoverySettings->length) != EOK) {
691             DFINDER_LOGE(TAG, "businessData strncpy failed");
692             return NSTACKX_EINVAL;
693         }
694     }
695     dupDiscoverySettings->advertiseCount = discoverySettings->advertiseCount;
696     dupDiscoverySettings->advertiseDuration = discoverySettings->advertiseDuration;
697     return NSTACKX_EOK;
698 }
699 
CheckDiscoverySettings(const NSTACKX_DiscoverySettings * discoverySettings)700 static int32_t CheckDiscoverySettings(const NSTACKX_DiscoverySettings *discoverySettings)
701 {
702     if (discoverySettings == NULL) {
703         DFINDER_LOGE(TAG, "Invalid discoverySettings info");
704         return NSTACKX_EINVAL;
705     }
706     if ((discoverySettings->businessData == NULL) && (discoverySettings->length != 0)) {
707         DFINDER_LOGE(TAG, "Invalid discoverySettings bData info");
708         return NSTACKX_EINVAL;
709     }
710     if (discoverySettings->length >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
711         DFINDER_LOGE(TAG, "businessData length is too long");
712         return NSTACKX_EINVAL;
713     }
714     uint32_t advertiseCount = discoverySettings->advertiseCount;
715     uint32_t advertiseDuration = discoverySettings->advertiseDuration;
716     if ((advertiseCount == 0) && (advertiseDuration == 0)) {
717         return NSTACKX_EOK;
718     }
719     if ((advertiseCount < NSTACKX_MIN_ADVERTISE_COUNT) || (advertiseCount > NSTACKX_MAX_ADVERTISE_COUNT) ||
720         (advertiseDuration < NSTACKX_MIN_ADVERTISE_DURATION) || (advertiseDuration > NSTACKX_MAX_ADVERTISE_DURATION)) {
721         DFINDER_LOGE(TAG, "Invalid discoverySettings advertise info");
722         return NSTACKX_EINVAL;
723     }
724     return NSTACKX_EOK;
725 }
726 
NSTACKX_StartDeviceDiscovery(const NSTACKX_DiscoverySettings * discoverySettings)727 int32_t NSTACKX_StartDeviceDiscovery(const NSTACKX_DiscoverySettings *discoverySettings)
728 {
729     DFINDER_LOGI(TAG, "begin to NSTACKX_StartDeviceDiscovery!");
730     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
731         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
732         return NSTACKX_EFAILED;
733     }
734     if (CheckDiscoverySettings(discoverySettings) != NSTACKX_EOK) {
735         return NSTACKX_EINVAL;
736     }
737 
738     NSTACKX_DiscoverySettings *dupDiscoverySettings = malloc(sizeof(NSTACKX_DiscoverySettings));
739     if (dupDiscoverySettings == NULL) {
740         DFINDER_LOGE(TAG, "malloc failed");
741         return NSTACKX_ENOMEM;
742     }
743     dupDiscoverySettings->businessData = (char *)calloc((discoverySettings->length + 1), sizeof(char));
744     if (dupDiscoverySettings->businessData == NULL) {
745         DFINDER_LOGE(TAG, "businessData calloc fail");
746         free(dupDiscoverySettings);
747         return NSTACKX_ENOMEM;
748     }
749     if (CopyDiscoverySettings(dupDiscoverySettings, discoverySettings) != NSTACKX_EOK) {
750         free(dupDiscoverySettings->businessData);
751         free(dupDiscoverySettings);
752         return NSTACKX_EINVAL;
753     }
754 
755     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerConfigurable, dupDiscoverySettings) != NSTACKX_EOK) {
756         DFINDER_LOGE(TAG, "Failed to start device discover!");
757         free(dupDiscoverySettings->businessData);
758         free(dupDiscoverySettings);
759         return NSTACKX_EFAILED;
760     }
761     return NSTACKX_EOK;
762 }
763 
CopyDiscConfig(const DFinderDiscConfig * src,DFinderDiscConfig * dst)764 static int32_t CopyDiscConfig(const DFinderDiscConfig *src, DFinderDiscConfig *dst)
765 {
766     dst->businessType = src->businessType;
767     dst->discoveryMode = src->discoveryMode;
768     dst->intervalArrLen = src->intervalArrLen;
769     for (size_t idx = 0; idx < dst->intervalArrLen; ++idx) {
770         (dst->bcastInterval)[idx] = (src->bcastInterval)[idx];
771     }
772     if (src->businessData != NULL) {
773         if (strncpy_s(dst->businessData, dst->businessDataLen, src->businessData, src->businessDataLen) != EOK) {
774             DFINDER_LOGE(TAG, "copy business data failed");
775             return NSTACKX_EFAILED;
776         }
777     }
778     return NSTACKX_EOK;
779 }
780 
CheckDiscInterval(uint32_t * intervalArr,uint32_t arrLen)781 static int32_t CheckDiscInterval(uint32_t *intervalArr, uint32_t arrLen)
782 {
783     if (intervalArr == NULL || arrLen == 0) {
784         DFINDER_LOGE(TAG, "illegal param, arrlen: %ld", arrLen);
785         return NSTACKX_EINVAL;
786     }
787     // check interval values one by one
788     for (size_t i = 0; i < arrLen; ++i) {
789         if (intervalArr[i] < NSTACKX_MIN_ADVERTISE_INTERVAL || intervalArr[i] > NSTACKX_MAX_ADVERTISE_INTERVAL) {
790             DFINDER_LOGE(TAG, "invalid interval");
791             return NSTACKX_EINVAL;
792         }
793     }
794     return NSTACKX_EOK;
795 }
796 
CheckDiscConfig(const DFinderDiscConfig * discConfig)797 static int32_t CheckDiscConfig(const DFinderDiscConfig *discConfig)
798 {
799     if (discConfig == NULL) {
800         DFINDER_LOGE(TAG, "disc config passed in is null");
801         return NSTACKX_EINVAL;
802     }
803     // minus one for the first broadcast without interval
804     if (discConfig->bcastInterval == NULL || discConfig->intervalArrLen > (NSTACKX_MAX_ADVERTISE_COUNT - 1) ||
805         discConfig->intervalArrLen == 0) {
806         DFINDER_LOGE(TAG, "invalid broadcast interval params");
807         return NSTACKX_EINVAL;
808     }
809     if (CheckDiscInterval(discConfig->bcastInterval, discConfig->intervalArrLen) != NSTACKX_EOK) {
810         return NSTACKX_EINVAL;
811     }
812     if ((discConfig->businessData == NULL) && (discConfig->businessDataLen != 0)) {
813         DFINDER_LOGE(TAG, "invalid business data params");
814         return NSTACKX_EINVAL;
815     }
816     if (discConfig->businessDataLen >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
817         DFINDER_LOGE(TAG, "business data is too long");
818         return NSTACKX_EINVAL;
819     }
820     return NSTACKX_EOK;
821 }
822 
NSTACKX_StartDeviceDiscoveryWithConfig(const DFinderDiscConfig * discConfig)823 int32_t NSTACKX_StartDeviceDiscoveryWithConfig(const DFinderDiscConfig *discConfig)
824 {
825     DFINDER_LOGI(TAG, "dfinder start disc with config");
826     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
827         DFINDER_LOGE(TAG, "nstackx ctrl is not initialed yet");
828         return NSTACKX_EFAILED;
829     }
830     if (CheckDiscConfig(discConfig) != NSTACKX_EOK) {
831         return NSTACKX_EINVAL;
832     }
833     DFinderDiscConfig *dupDiscConfig = (DFinderDiscConfig *)malloc(sizeof(DFinderDiscConfig));
834     if (dupDiscConfig == NULL) {
835         DFINDER_LOGE(TAG, "malloc for duplicate disc config failed");
836         return NSTACKX_ENOMEM;
837     }
838     dupDiscConfig->bcastInterval = (uint32_t *)malloc(sizeof(uint32_t) * (discConfig->intervalArrLen));
839     if (dupDiscConfig->bcastInterval == NULL) {
840         DFINDER_LOGE(TAG, "malloc for duplicate broadcast interval failed");
841         free(dupDiscConfig);
842         return NSTACKX_ENOMEM;
843     }
844     dupDiscConfig->businessData = (char *)calloc((discConfig->businessDataLen + 1), sizeof(char));
845     if (dupDiscConfig->businessData == NULL) {
846         DFINDER_LOGE(TAG, "malloc for duplicate business data failed");
847         free(dupDiscConfig->bcastInterval);
848         free(dupDiscConfig);
849         return NSTACKX_ENOMEM;
850     }
851     // 1 to store the terminator
852     dupDiscConfig->businessDataLen = discConfig->businessDataLen + 1;
853     if (CopyDiscConfig(discConfig, dupDiscConfig) != NSTACKX_EOK) {
854         free(dupDiscConfig->businessData);
855         free(dupDiscConfig->bcastInterval);
856         free(dupDiscConfig);
857         return NSTACKX_EFAILED;
858     }
859     if (PostEvent(&g_eventNodeChain, g_epollfd, DiscConfig, dupDiscConfig) != NSTACKX_EOK) {
860         free(dupDiscConfig->businessData);
861         free(dupDiscConfig->bcastInterval);
862         free(dupDiscConfig);
863         return NSTACKX_EFAILED;
864     }
865     return NSTACKX_EOK;
866 }
867 
868 #ifndef DFINDER_USE_MINI_NSTACKX
NSTACKX_SubscribeModule(void)869 int32_t NSTACKX_SubscribeModule(void)
870 {
871     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
872         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
873         return NSTACKX_EFAILED;
874     }
875     CoapSubscribeModuleInner(INNER_DISCOVERY);
876     return NSTACKX_EOK;
877 }
878 
NSTACKX_UnsubscribeModule(void)879 int32_t NSTACKX_UnsubscribeModule(void)
880 {
881     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
882         return NSTACKX_EFAILED;
883     }
884     CoapUnsubscribeModuleInner(INNER_DISCOVERY);
885     return NSTACKX_EOK;
886 }
887 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
888 
IsNetworkNameValid(const char * networkName,size_t len)889 static bool IsNetworkNameValid(const char *networkName, size_t len)
890 {
891     if (!StringHasEOF(networkName, len)) {
892         DFINDER_LOGE(TAG, "network name is not ended");
893         return NSTACKX_FALSE;
894     }
895 
896     return NSTACKX_TRUE;
897 }
898 
IsIpAddressValid(const char * ipStr,size_t len)899 static bool IsIpAddressValid(const char *ipStr, size_t len)
900 {
901     if (!StringHasEOF(ipStr, len)) {
902         DFINDER_LOGE(TAG, "ip addr is not ended");
903         return NSTACKX_FALSE;
904     }
905 
906     union InetAddr addr;
907     if (len != 0 && ipStr[0] != '\0' && InetGetAfType(ipStr, &addr) == AF_ERROR) {
908         DFINDER_LOGE(TAG, "invalid ip address");
909         return NSTACKX_FALSE;
910     }
911 
912     return NSTACKX_TRUE;
913 }
914 
CheckInterfaceInfo(const NSTACKX_InterfaceInfo * ifaces,uint32_t count)915 static int32_t CheckInterfaceInfo(const NSTACKX_InterfaceInfo *ifaces, uint32_t count)
916 {
917     for (uint32_t i = 0; i < count; ++i) {
918         if (!IsNetworkNameValid(ifaces[i].networkName, sizeof(ifaces[i].networkName)) ||
919             !IsIpAddressValid(ifaces[i].networkIpAddr, sizeof(ifaces[i].networkIpAddr)) ||
920             !IsNetworkNameValid(ifaces[i].serviceData, sizeof(ifaces[i].serviceData))) {
921             DFINDER_LOGE(TAG, "invalid network name or ip address of No.%u local iface", i);
922             return NSTACKX_EINVAL;
923         }
924     }
925 
926     return NSTACKX_EOK;
927 }
928 
CheckLocalDeviceInfo(const NSTACKX_LocalDeviceInfo * localDeviceInfo)929 static int CheckLocalDeviceInfo(const NSTACKX_LocalDeviceInfo *localDeviceInfo)
930 {
931     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
932         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
933         return NSTACKX_EFAILED;
934     }
935 
936     if (localDeviceInfo == NULL) {
937         DFINDER_LOGE(TAG, "Invalid local device info");
938         return NSTACKX_EINVAL;
939     }
940 
941     if (!StringHasEOF(localDeviceInfo->deviceId, sizeof(localDeviceInfo->deviceId)) ||
942         !StringHasEOF(localDeviceInfo->name, sizeof(localDeviceInfo->name))) {
943         DFINDER_LOGE(TAG, "device id or device name is not ended");
944         return NSTACKX_EINVAL;
945     }
946 
947     if (localDeviceInfo->ifNums > NSTACKX_MAX_LISTENED_NIF_NUM) {
948         DFINDER_LOGE(TAG, "invalid iface number %u", localDeviceInfo->ifNums);
949         return NSTACKX_EINVAL;
950     } else if (localDeviceInfo->ifNums == 0) {
951         if (!IsNetworkNameValid(localDeviceInfo->networkName, sizeof(localDeviceInfo->networkName)) ||
952             !IsIpAddressValid(localDeviceInfo->networkIpAddr, sizeof(localDeviceInfo->networkIpAddr))) {
953             DFINDER_LOGE(TAG, "invalid network name or ip address when iface number is 0");
954             return NSTACKX_EINVAL;
955         }
956     }
957 
958     return NSTACKX_EOK;
959 }
960 
DeviceInfoV2Init(NSTACKX_LocalDeviceInfoV2 * v2,const NSTACKX_LocalDeviceInfo * localDeviceInfo,bool hasDeviceHash,uint64_t deviceHash)961 static void DeviceInfoV2Init(NSTACKX_LocalDeviceInfoV2 *v2,
962     const NSTACKX_LocalDeviceInfo *localDeviceInfo, bool hasDeviceHash, uint64_t deviceHash)
963 {
964     v2->name = localDeviceInfo->name;
965     v2->deviceId = localDeviceInfo->deviceId;
966     v2->deviceType = localDeviceInfo->deviceType;
967     v2->businessType = localDeviceInfo->businessType;
968     v2->hasDeviceHash = hasDeviceHash;
969     v2->deviceHash = deviceHash;
970 }
971 
RegisterDeviceWithDeviceHash(const NSTACKX_LocalDeviceInfo * localDeviceInfo,bool hasDeviceHash,uint64_t deviceHash)972 static int32_t RegisterDeviceWithDeviceHash(const NSTACKX_LocalDeviceInfo *localDeviceInfo,
973     bool hasDeviceHash, uint64_t deviceHash)
974 {
975     int ret = CheckLocalDeviceInfo(localDeviceInfo);
976     if (ret != NSTACKX_EOK) {
977         return ret;
978     }
979 
980     NSTACKX_LocalDeviceInfoV2 v2;
981     DeviceInfoV2Init(&v2, localDeviceInfo, hasDeviceHash, deviceHash);
982 
983     NSTACKX_InterfaceInfo ifaceInfo;
984     (void)memset_s(&ifaceInfo, sizeof(ifaceInfo), 0, sizeof(ifaceInfo));
985     if (localDeviceInfo->ifNums == 0) {
986         if (strcpy_s(ifaceInfo.networkName, sizeof(ifaceInfo.networkName), localDeviceInfo->networkName) != EOK ||
987             strcpy_s(ifaceInfo.networkIpAddr, sizeof(ifaceInfo.networkIpAddr),
988             localDeviceInfo->networkIpAddr) != EOK) {
989             DFINDER_LOGE(TAG, "copy network name or ip addr failed");
990             return NSTACKX_EINVAL;
991         }
992         v2.localIfInfo = &ifaceInfo;
993         v2.ifNums = 1;
994     } else {
995         v2.localIfInfo = &localDeviceInfo->localIfInfo[0];
996         v2.ifNums = localDeviceInfo->ifNums;
997     }
998 
999     return RegisterDeviceWithType(&v2, hasDeviceHash ? REGISTER_TYPE_UPDATE_SPECIFIED : REGISTER_TYPE_UPDATE_ALL);
1000 }
1001 
NSTACKX_RegisterDevice(const NSTACKX_LocalDeviceInfo * localDeviceInfo)1002 int32_t NSTACKX_RegisterDevice(const NSTACKX_LocalDeviceInfo *localDeviceInfo)
1003 {
1004     Coverity_Tainted_Set((void *)localDeviceInfo);
1005     DFINDER_LOGI(TAG, "begin to NSTACKX_RegisterDevice!");
1006 
1007     return RegisterDeviceWithDeviceHash(localDeviceInfo, NSTACKX_FALSE, 0);
1008 }
1009 
ConfigureLocalDeviceNameInner(void * argument)1010 static void ConfigureLocalDeviceNameInner(void *argument)
1011 {
1012     char *localDevName = (char *)argument;
1013 
1014     ConfigureLocalDeviceName(localDevName);
1015     free(localDevName);
1016 }
1017 
RegisterLocalDeviceHash(void * arg)1018 static void RegisterLocalDeviceHash(void *arg)
1019 {
1020     uint64_t hash = (uint64_t)(uintptr_t)arg;
1021     SetLocalDeviceHash(hash);
1022 }
1023 
RegisterDeviceHashInner(uint64_t deviceHash)1024 static int32_t RegisterDeviceHashInner(uint64_t deviceHash)
1025 {
1026     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1027         SetLocalDeviceHash(deviceHash);
1028         return NSTACKX_EOK;
1029     }
1030 
1031     if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterLocalDeviceHash, (void *)deviceHash)) {
1032         DFINDER_LOGE(TAG, "Failed to configure local device hash!");
1033         return NSTACKX_EFAILED;
1034     }
1035 
1036     return NSTACKX_EOK;
1037 }
1038 
NSTACKX_RegisterDeviceHash(uint64_t deviceHash)1039 int32_t NSTACKX_RegisterDeviceHash(uint64_t deviceHash)
1040 {
1041     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1042         DFINDER_LOGE(TAG, "NSTACKX_CTRL is not initiated yet");
1043         return NSTACKX_EFAILED;
1044     }
1045 
1046     return RegisterDeviceHashInner(deviceHash);
1047 }
1048 
NSTACKX_RegisterDeviceName(const char * devName)1049 int32_t NSTACKX_RegisterDeviceName(const char *devName)
1050 {
1051     if (devName == NULL || devName[0] == '\0') {
1052         DFINDER_LOGE(TAG, "register local device name is invalid");
1053         return NSTACKX_EINVAL;
1054     }
1055     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1056         DFINDER_LOGE(TAG, "NSTACKX_CTRL is not initiated yet");
1057         return NSTACKX_EFAILED;
1058     }
1059     char *dupDevName = (char *)malloc(sizeof(char) * NSTACKX_MAX_DEVICE_NAME_LEN);
1060     if (dupDevName == NULL) {
1061         return NSTACKX_ENOMEM;
1062     }
1063     if (strncpy_s(dupDevName, NSTACKX_MAX_DEVICE_NAME_LEN, devName, strlen(devName)) != EOK) {
1064         DFINDER_LOGE(TAG, "strncpy dupDevName failed");
1065         free(dupDevName);
1066         return NSTACKX_EFAILED;
1067     }
1068     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1069         ConfigureLocalDeviceNameInner((void *)dupDevName);
1070         return NSTACKX_EOK;
1071     }
1072     if (PostEvent(&g_eventNodeChain, g_epollfd, ConfigureLocalDeviceNameInner, dupDevName) != NSTACKX_EOK) {
1073         DFINDER_LOGE(TAG, "Failed to configure local device name!");
1074         free(dupDevName);
1075         return NSTACKX_EFAILED;
1076     }
1077     return NSTACKX_EOK;
1078 }
1079 
NSTACKX_RegisterDeviceAn(const NSTACKX_LocalDeviceInfo * localDeviceInfo,uint64_t deviceHash)1080 int32_t NSTACKX_RegisterDeviceAn(const NSTACKX_LocalDeviceInfo *localDeviceInfo, uint64_t deviceHash)
1081 {
1082     Coverity_Tainted_Set((void *)localDeviceInfo);
1083     Coverity_Tainted_Set((void *)&deviceHash);
1084 
1085     DFINDER_LOGI(TAG, "begin to NSTACKX_RegisterDeviceAn!");
1086     return RegisterDeviceWithDeviceHash(localDeviceInfo, NSTACKX_TRUE, deviceHash);
1087 }
1088 
1089 struct NSTACKX_Sem {
1090     sem_t wait;
1091 };
1092 
1093 typedef void (*FreeArg)(void *arg);
1094 
1095 struct PostEvtBlockArgs {
1096     void *arg;
1097     FreeArg cb;
1098     EventHandle handle;
1099     struct NSTACKX_Sem *sem;
1100 };
1101 
NSTACKX_PostEventBlockHander(void * argument)1102 static void NSTACKX_PostEventBlockHander(void *argument)
1103 {
1104     if (argument == NULL) {
1105         return;
1106     }
1107 
1108     struct PostEvtBlockArgs *arg = (struct PostEvtBlockArgs *)argument;
1109     if (arg->arg != NULL && arg->handle != NULL) {
1110         arg->handle(arg->arg);
1111     }
1112     if (arg->sem != NULL) {
1113         SemPost(&(arg->sem->wait));
1114         DFINDER_LOGI(TAG, "post event is done");
1115     }
1116     if (arg->cb != NULL) {
1117         arg->cb(arg->arg);
1118     }
1119     arg->arg = NULL;
1120     free(arg);
1121 }
1122 
SemTimedWait(sem_t * sem,struct timespec expire)1123 static int32_t SemTimedWait(sem_t *sem, struct timespec expire)
1124 {
1125     struct timespec timeout;
1126 
1127     if (clock_gettime(CLOCK_REALTIME, &timeout) != NSTACKX_EOK) {
1128         DFINDER_LOGE(TAG, "clock_gettime fail");
1129         return NSTACKX_EFAILED;
1130     }
1131 
1132     timeout.tv_sec += expire.tv_sec;
1133     timeout.tv_nsec += expire.tv_nsec;
1134     if (timeout.tv_nsec >= NSEC_TICKS_PER_SEC) {
1135         timeout.tv_sec += 1;
1136         timeout.tv_nsec -= NSEC_TICKS_PER_SEC;
1137     }
1138     int ret = sem_timedwait(sem, &timeout);
1139     if (ret != 0) {
1140         return NSTACKX_EFAILED;
1141     }
1142 
1143     return NSTACKX_EOK;
1144 }
1145 
NSTACKX_BlockEvtWaitFinish(struct PostEvtBlockArgs * arg,struct NSTACKX_Sem * sem)1146 static int32_t NSTACKX_BlockEvtWaitFinish(struct PostEvtBlockArgs *arg, struct NSTACKX_Sem *sem)
1147 {
1148     int32_t ret = NSTACKX_EFAILED;
1149     struct timespec expire = {
1150         .tv_sec = DFINDER_POST_EVENT_MAX_BLOCK_SECONDS,
1151         .tv_nsec = 0,
1152     };
1153 
1154     ret = SemTimedWait(&sem->wait, expire);
1155     if (ret != NSTACKX_EOK) {
1156         DFINDER_LOGE(TAG, "sem wait failed errno %d", GetErrno());
1157     } else {
1158         DFINDER_LOGI(TAG, "sem wait success");
1159     }
1160 
1161     return ret;
1162 }
1163 
NSTACKX_CreateSem(void)1164 static struct NSTACKX_Sem *NSTACKX_CreateSem(void)
1165 {
1166     struct NSTACKX_Sem *sem = (struct NSTACKX_Sem *)calloc(1U, sizeof(struct NSTACKX_Sem));
1167     if (sem == NULL) {
1168         DFINDER_LOGE(TAG, "calloc sem failed");
1169         return NULL;
1170     }
1171     if (SemInit(&sem->wait, 0, 0)) {
1172         DFINDER_LOGE(TAG, "Failed to init sem!");
1173         free(sem);
1174         return NULL;
1175     }
1176     return sem;
1177 }
1178 
NSTACKX_FreeSem(void * arg)1179 static void NSTACKX_FreeSem(void *arg)
1180 {
1181     if (arg == NULL) {
1182         return;
1183     }
1184 
1185     struct NSTACKX_Sem *sem = (struct NSTACKX_Sem *)arg;
1186     SemDestroy(&sem->wait);
1187     free(sem);
1188     DFINDER_LOGI(TAG, "free sem end");
1189 }
1190 
NSTACKX_PostEventBlock(EventHandle handle,void * arg,FreeArg cb)1191 static int32_t NSTACKX_PostEventBlock(EventHandle handle, void *arg, FreeArg cb)
1192 {
1193     struct PostEvtBlockArgs *blockEvtArg = (struct PostEvtBlockArgs *)calloc(1U, sizeof(struct PostEvtBlockArgs));
1194     if (blockEvtArg == NULL) {
1195         if (cb != NULL) {
1196             cb(arg);
1197         }
1198         DFINDER_LOGE(TAG, "calloc failed");
1199         return NSTACKX_EFAILED;
1200     }
1201 
1202     struct NSTACKX_Sem *sem = NSTACKX_CreateSem();
1203     if (sem == NULL) {
1204         if (cb != NULL) {
1205             cb(arg);
1206         }
1207         free(blockEvtArg);
1208         DFINDER_LOGE(TAG, "calloc sem failed");
1209         return NSTACKX_EFAILED;
1210     }
1211 
1212     blockEvtArg->arg = arg;
1213     blockEvtArg->cb = cb;
1214     blockEvtArg->sem = sem;
1215     blockEvtArg->handle = handle;
1216     if (PostEvent(&g_eventNodeChain, g_epollfd,
1217         NSTACKX_PostEventBlockHander, (void *)blockEvtArg) != NSTACKX_EOK) {
1218         if (cb != NULL) {
1219             cb(arg);
1220         }
1221         NSTACKX_FreeSem((void *)sem);
1222         free(blockEvtArg);
1223         DFINDER_LOGE(TAG, "PostEvent failed");
1224         return NSTACKX_EFAILED;
1225     }
1226 
1227     if (NSTACKX_BlockEvtWaitFinish(blockEvtArg, sem) != NSTACKX_EOK) {
1228         if (PostEvent(&g_eventNodeChain, g_epollfd, NSTACKX_FreeSem, (void*)sem) != NSTACKX_EOK) {
1229             DFINDER_LOGE(TAG, "PostEvent failed");
1230             NSTACKX_FreeSem((void *)sem);
1231             return NSTACKX_EFAILED;
1232         }
1233         DFINDER_LOGE(TAG, "block wait failed");
1234         return NSTACKX_EFAILED;
1235     }
1236     NSTACKX_FreeSem((void *)sem);
1237     DFINDER_LOGI(TAG, "post event success");
1238     return NSTACKX_EOK;
1239 }
1240 
1241 struct RegDeviceInfo {
1242     NSTACKX_LocalDeviceInfoV2 *info;
1243     int registerType;
1244     int32_t err;
1245 };
1246 
RegisterDeviceV2(void * arg)1247 static void RegisterDeviceV2(void *arg)
1248 {
1249     struct RegDeviceInfo *regInfo = (struct RegDeviceInfo *)arg;
1250     regInfo->err = RegisterLocalDeviceV2(regInfo->info, regInfo->registerType);
1251     if (regInfo->err != NSTACKX_EOK) {
1252         DFINDER_LOGE(TAG, "register device failed");
1253     }
1254 }
1255 
1256 #define NSTACKX_MAX_LOCAL_IFACE_NUM 10
1257 
DeviceStrCreate(const char * str,uint32_t maxLen)1258 static char *DeviceStrCreate(const char *str, uint32_t maxLen)
1259 {
1260     char *out = (char *)calloc(1u, maxLen);
1261     if (out == NULL) {
1262         return NULL;
1263     }
1264 
1265     if (strcpy_s(out, maxLen, str) != EOK) {
1266         free(out);
1267         return NULL;
1268     }
1269     return out;
1270 }
1271 
RegisterInfoFree(NSTACKX_LocalDeviceInfoV2 * info)1272 static void RegisterInfoFree(NSTACKX_LocalDeviceInfoV2 *info)
1273 {
1274     if (info == NULL) {
1275         return;
1276     }
1277     free((void *)info->name);
1278     free((void *)info->deviceId);
1279     free((void *)info->localIfInfo);
1280     free(info);
1281 }
1282 
RegisterDeviceFree(void * arg)1283 static void RegisterDeviceFree(void *arg)
1284 {
1285     if (arg == NULL) {
1286         return;
1287     }
1288     struct RegDeviceInfo *regInfo = (struct RegDeviceInfo *)arg;
1289     RegisterInfoFree(regInfo->info);
1290     regInfo->info = NULL;
1291     free(regInfo);
1292 }
1293 
RegisterInfoCreate(const NSTACKX_LocalDeviceInfoV2 * localDeviceInfo)1294 static NSTACKX_LocalDeviceInfoV2 *RegisterInfoCreate(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo)
1295 {
1296     NSTACKX_LocalDeviceInfoV2 *infoV2 = (NSTACKX_LocalDeviceInfoV2 *)calloc(1u, sizeof(NSTACKX_LocalDeviceInfoV2));
1297     if (infoV2 == NULL) {
1298         DFINDER_LOGE(TAG, "calloc infov2 failed");
1299         return NULL;
1300     }
1301 
1302     size_t len = strnlen(localDeviceInfo->deviceId, NSTACKX_MAX_DEVICE_ID_LEN);
1303     if (len >= NSTACKX_MAX_DEVICE_ID_LEN) {
1304         DFINDER_LOGE(TAG, "deviceId is error");
1305         free(infoV2);
1306         return NULL;
1307     }
1308 
1309     len = strnlen(localDeviceInfo->name, NSTACKX_MAX_DEVICE_NAME_LEN);
1310     if (len >= NSTACKX_MAX_DEVICE_NAME_LEN) {
1311         DFINDER_LOGE(TAG, "name is error");
1312         free(infoV2);
1313         return NULL;
1314     }
1315     infoV2->deviceId = DeviceStrCreate(localDeviceInfo->deviceId, NSTACKX_MAX_DEVICE_ID_LEN);
1316     if (infoV2->deviceId == NULL) {
1317         DFINDER_LOGE(TAG, "DeviceStrCreate deviceId is error");
1318         RegisterInfoFree(infoV2);
1319         return NULL;
1320     }
1321     infoV2->name = DeviceStrCreate(localDeviceInfo->name, NSTACKX_MAX_DEVICE_NAME_LEN);
1322     if (infoV2->name == NULL) {
1323         DFINDER_LOGE(TAG, "DeviceStrCreate name is error");
1324         RegisterInfoFree(infoV2);
1325         return NULL;
1326     }
1327 
1328     NSTACKX_InterfaceInfo *info = (NSTACKX_InterfaceInfo *)calloc(localDeviceInfo->ifNums,
1329         sizeof(NSTACKX_InterfaceInfo));
1330     if (info == NULL) {
1331         DFINDER_LOGE(TAG, "calloc info is error");
1332         RegisterInfoFree(infoV2);
1333         return NULL;
1334     }
1335     (void)memcpy_s(info, localDeviceInfo->ifNums * sizeof(NSTACKX_InterfaceInfo),
1336                    localDeviceInfo->localIfInfo, localDeviceInfo->ifNums * sizeof(NSTACKX_InterfaceInfo));
1337     infoV2->localIfInfo = info;
1338     infoV2->businessType = localDeviceInfo->businessType;
1339     infoV2->deviceHash = localDeviceInfo->deviceHash;
1340     infoV2->deviceType = localDeviceInfo->deviceType;
1341     infoV2->ifNums = localDeviceInfo->ifNums;
1342     infoV2->hasDeviceHash = localDeviceInfo->hasDeviceHash;
1343     return infoV2;
1344 }
1345 
RegisterDeviceCreate(const NSTACKX_LocalDeviceInfoV2 * localDeviceInfo,int registerType)1346 static struct RegDeviceInfo *RegisterDeviceCreate(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo, int registerType)
1347 {
1348     struct RegDeviceInfo *regInfo = (struct RegDeviceInfo *)calloc(1u, sizeof(struct RegDeviceInfo));
1349     if (regInfo == NULL) {
1350         DFINDER_LOGE(TAG, "calloc register info failed");
1351         return NULL;
1352     }
1353 
1354     regInfo->info = RegisterInfoCreate(localDeviceInfo);
1355     if (regInfo->info == NULL) {
1356         DFINDER_LOGE(TAG, "calloc infov2 failed");
1357         free(regInfo);
1358         return NULL;
1359     }
1360     regInfo->registerType = registerType;
1361     return regInfo;
1362 }
1363 
RegisterDeviceWithType(const NSTACKX_LocalDeviceInfoV2 * localDeviceInfo,int registerType)1364 static int32_t RegisterDeviceWithType(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo, int registerType)
1365 {
1366     if (localDeviceInfo == NULL || localDeviceInfo->name == NULL ||
1367         localDeviceInfo->deviceId == NULL || localDeviceInfo->ifNums > NSTACKX_MAX_LOCAL_IFACE_NUM ||
1368         (localDeviceInfo->ifNums != 0 && localDeviceInfo->localIfInfo == NULL) ||
1369         CheckInterfaceInfo(localDeviceInfo->localIfInfo, localDeviceInfo->ifNums) != NSTACKX_EOK) {
1370         DFINDER_LOGE(TAG, "invalid args");
1371         return NSTACKX_EINVAL;
1372     }
1373 
1374     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1375         return (int32_t)RegisterLocalDeviceV2(localDeviceInfo, registerType);
1376     }
1377 
1378     struct RegDeviceInfo *regInfo = RegisterDeviceCreate(localDeviceInfo, registerType);
1379     if (regInfo == NULL) {
1380         DFINDER_LOGE(TAG, "Failed to create device info!");
1381         return NSTACKX_EFAILED;
1382     }
1383     // The abnormal branch regInfo is released internally.
1384     if (NSTACKX_PostEventBlock(RegisterDeviceV2, (void*)regInfo, RegisterDeviceFree) != NSTACKX_EOK) {
1385         DFINDER_LOGE(TAG, "Failed to configure local device info!");
1386         return NSTACKX_EBUSY;
1387     }
1388     return NSTACKX_EOK;
1389 }
1390 
NSTACKX_RegisterDeviceV2(const NSTACKX_LocalDeviceInfoV2 * localDeviceInfo)1391 int32_t NSTACKX_RegisterDeviceV2(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo)
1392 {
1393     Coverity_Tainted_Set((void *)localDeviceInfo);
1394     DFINDER_LOGI(TAG, "NSTACKX_RegisterDeviceV2 begin!");
1395 
1396     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1397         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1398         return NSTACKX_EFAILED;
1399     }
1400 
1401     int registerType = (localDeviceInfo != NULL &&
1402         localDeviceInfo->ifNums == SINGLE_NIC_CNT) ? REGISTER_TYPE_UPDATE_SPECIFIED : REGISTER_TYPE_UPDATE_ALL;
1403     return RegisterDeviceWithType(localDeviceInfo, registerType);
1404 }
1405 
1406 typedef struct {
1407     uint32_t capabilityBitmapNum;
1408     uint32_t capabilityBitmap[NSTACKX_MAX_CAPABILITY_NUM];
1409 } CapabilityProcessData;
1410 
RegisterCapabilityInner(void * argument)1411 static void RegisterCapabilityInner(void *argument)
1412 {
1413     CapabilityProcessData *capabilityData = argument;
1414 
1415     (void)SetLocalDeviceCapability(capabilityData->capabilityBitmapNum, capabilityData->capabilityBitmap);
1416     free(capabilityData);
1417 }
1418 
SetFilterCapabilityInner(void * argument)1419 static void SetFilterCapabilityInner(void *argument)
1420 {
1421     CapabilityProcessData *capabilityData = argument;
1422 
1423     (void)SetFilterCapability(capabilityData->capabilityBitmapNum, capabilityData->capabilityBitmap);
1424     free(capabilityData);
1425 }
1426 
NSTACKX_CapabilityHandle(uint32_t capabilityBitmapNum,uint32_t capabilityBitmap[],EventHandle handle)1427 static int32_t NSTACKX_CapabilityHandle(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[], EventHandle handle)
1428 {
1429     Coverity_Tainted_Set((void *)&capabilityBitmapNum);
1430     Coverity_Tainted_Set((void *)capabilityBitmap);
1431 
1432     CapabilityProcessData *capabilityData = NULL;
1433 
1434     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1435         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1436         return NSTACKX_EFAILED;
1437     }
1438 
1439     if (capabilityBitmapNum != 0 && capabilityBitmap == NULL) {
1440         DFINDER_LOGE(TAG, "bitmap array is null");
1441         return NSTACKX_EFAILED;
1442     }
1443 
1444     if (capabilityBitmapNum > NSTACKX_MAX_CAPABILITY_NUM) {
1445         DFINDER_LOGE(TAG, "capabilityBitmapNum (%u) exceed max number", capabilityBitmapNum);
1446         return NSTACKX_EINVAL;
1447     }
1448 
1449     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1450         if (handle == RegisterCapabilityInner) {
1451             return (int32_t)SetLocalDeviceCapability(capabilityBitmapNum, capabilityBitmap);
1452         }
1453         if (handle == SetFilterCapabilityInner) {
1454             return SetFilterCapability(capabilityBitmapNum, capabilityBitmap);
1455         }
1456     }
1457 
1458     capabilityData = calloc(1U, sizeof(CapabilityProcessData));
1459     if (capabilityData == NULL) {
1460         return NSTACKX_ENOMEM;
1461     }
1462 
1463     if ((capabilityBitmapNum != 0) && memcpy_s(capabilityData->capabilityBitmap,
1464         sizeof(capabilityData->capabilityBitmap), capabilityBitmap, capabilityBitmapNum * sizeof(uint32_t)) != EOK) {
1465         free(capabilityData);
1466         return NSTACKX_EINVAL;
1467     }
1468     capabilityData->capabilityBitmapNum = capabilityBitmapNum;
1469 
1470     if (PostEvent(&g_eventNodeChain, g_epollfd, handle, capabilityData) != NSTACKX_EOK) {
1471         DFINDER_LOGE(TAG, "Failed to register capability!");
1472         free(capabilityData);
1473         return NSTACKX_EFAILED;
1474     }
1475     return NSTACKX_EOK;
1476 }
1477 
NSTACKX_RegisterCapability(uint32_t capabilityBitmapNum,uint32_t capabilityBitmap[])1478 int32_t NSTACKX_RegisterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
1479 {
1480     DFINDER_LOGD(TAG, "begin to call NSTACKX_RegisterCapability");
1481     return NSTACKX_CapabilityHandle(capabilityBitmapNum, capabilityBitmap, RegisterCapabilityInner);
1482 }
1483 
NSTACKX_SetFilterCapability(uint32_t capabilityBitmapNum,uint32_t capabilityBitmap[])1484 int32_t NSTACKX_SetFilterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
1485 {
1486     DFINDER_LOGI(TAG, "Set Filter Capability");
1487     return NSTACKX_CapabilityHandle(capabilityBitmapNum, capabilityBitmap, SetFilterCapabilityInner);
1488 }
1489 
SetMaxDeviceNumInner(void * argument)1490 static void SetMaxDeviceNumInner(void *argument)
1491 {
1492     SetMaxDeviceNum((uint32_t)(uintptr_t)(argument));
1493 }
1494 
NSTACKX_SetMaxDeviceNum(uint32_t maxDeviceNum)1495 int32_t NSTACKX_SetMaxDeviceNum(uint32_t maxDeviceNum)
1496 {
1497     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1498         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1499         return NSTACKX_EFAILED;
1500     }
1501     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1502         SetMaxDeviceNum(maxDeviceNum);
1503         return NSTACKX_EOK;
1504     }
1505     if (NSTACKX_PostEventBlock(SetMaxDeviceNumInner, (void *)(uintptr_t)maxDeviceNum, NULL) != NSTACKX_EOK) {
1506         DFINDER_LOGE(TAG, "Failed to set max device num!");
1507         return NSTACKX_EFAILED;
1508     }
1509     return NSTACKX_EOK;
1510 }
1511 
1512 #ifdef DFINDER_SAVE_DEVICE_LIST
NSTACKX_SetDeviceListAgingTime(uint32_t agingTime)1513 int32_t NSTACKX_SetDeviceListAgingTime(uint32_t agingTime)
1514 {
1515     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1516         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1517         return NSTACKX_EFAILED;
1518     }
1519     SetDeviceListAgingTime(agingTime);
1520     return NSTACKX_EOK;
1521 }
1522 #else
NSTACKX_SetDeviceListAgingTime(uint32_t agingTime)1523 int32_t NSTACKX_SetDeviceListAgingTime(uint32_t agingTime)
1524 {
1525     (void)agingTime;
1526     DFINDER_LOGE(TAG, "device list not supported");
1527     return NSTACKX_EFAILED;
1528 }
1529 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
1530 
NSTACKX_ScreenStatusChange(bool isScreenOn)1531 int32_t NSTACKX_ScreenStatusChange(bool isScreenOn)
1532 {
1533 #ifdef DFINDER_SUPPORT_SET_SCREEN_STATUS
1534     SetScreenStatus(isScreenOn);
1535     DFINDER_LOGI(TAG, "set isScreenOn status %d", isScreenOn);
1536 #else
1537     (void)isScreenOn;
1538     DFINDER_LOGI(TAG, "do not support set screen status");
1539 #endif
1540     return NSTACKX_EOK;
1541 }
1542 
RegisterServiceDataInner(void * argument)1543 static void RegisterServiceDataInner(void *argument)
1544 {
1545     char *serviceData = argument;
1546     if (SetLocalDeviceServiceData(serviceData) != NSTACKX_EOK) {
1547         DFINDER_LOGE(TAG, "RegisterServiceData failed");
1548     }
1549     free(serviceData);
1550 }
1551 
RegisterServiceDataParamCheck(const struct NSTACKX_ServiceData * param,uint32_t cnt)1552 static bool RegisterServiceDataParamCheck(const struct NSTACKX_ServiceData *param, uint32_t cnt)
1553 {
1554     uint32_t i;
1555     if (param == NULL) {
1556         DFINDER_LOGE(TAG, "param is null");
1557         return false;
1558     }
1559 
1560     if (cnt == 0 || cnt >= MAX_COAP_SERVICE_DATA_CNT) {
1561         DFINDER_LOGE(TAG, "cnt is error");
1562         return false;
1563     }
1564 
1565     for (i = 0; i < cnt; i++) {
1566         size_t len = strnlen(param[i].serviceData, NSTACKX_MAX_SERVICE_DATA_LEN);
1567         if (len == NSTACKX_MAX_SERVICE_DATA_LEN) {
1568             DFINDER_LOGE(TAG, "param[%u] serviceData is error, no terminator", i);
1569             return false;
1570         }
1571 
1572         len = strnlen(param[i].ip, NSTACKX_MAX_IP_STRING_LEN);
1573         if (len == NSTACKX_MAX_IP_STRING_LEN) {
1574             DFINDER_LOGE(TAG, "param[%u] ip is error, no terminator", i);
1575             return false;
1576         }
1577     }
1578 
1579     return true;
1580 }
1581 
1582 struct ServiceDataInfo {
1583     struct NSTACKX_ServiceData *param;
1584     uint32_t cnt;
1585     int32_t err;
1586 };
1587 
RegisterServiceDataV2(void * arg)1588 static void RegisterServiceDataV2(void *arg)
1589 {
1590     struct ServiceDataInfo *info = (struct ServiceDataInfo *)arg;
1591     info->err = SetLocalDeviceServiceDataV2(info->param, info->cnt);
1592 }
1593 
ServiceDataV2Create(const struct NSTACKX_ServiceData * param,uint32_t cnt)1594 static struct ServiceDataInfo *ServiceDataV2Create(const struct NSTACKX_ServiceData *param,
1595     uint32_t cnt)
1596 {
1597     struct ServiceDataInfo *info = (struct ServiceDataInfo *)calloc(1u, sizeof(struct ServiceDataInfo));
1598     if (info == NULL) {
1599         DFINDER_LOGE(TAG, "create info failed");
1600         return NULL;
1601     }
1602 
1603     struct NSTACKX_ServiceData *data = (struct NSTACKX_ServiceData *)calloc(cnt, sizeof(struct NSTACKX_ServiceData));
1604     if (data == NULL) {
1605         free(info);
1606         DFINDER_LOGE(TAG, "create data failed");
1607         return NULL;
1608     }
1609     (void)memcpy_s(data, cnt * sizeof(struct NSTACKX_ServiceData),
1610                    param, cnt * sizeof(struct NSTACKX_ServiceData));
1611     info->param = data;
1612     info->cnt = cnt;
1613     return info;
1614 }
1615 
ServiceDataV2Free(void * arg)1616 static void ServiceDataV2Free(void *arg)
1617 {
1618     if (arg == NULL) {
1619         return;
1620     }
1621     struct ServiceDataInfo *info = (struct ServiceDataInfo *)arg;
1622     free(info->param);
1623     info->param = NULL;
1624     free(info);
1625 }
1626 
NSTACKX_RegisterServiceDataV2(const struct NSTACKX_ServiceData * param,uint32_t cnt)1627 int32_t NSTACKX_RegisterServiceDataV2(const struct NSTACKX_ServiceData *param, uint32_t cnt)
1628 {
1629     DFINDER_LOGI(TAG, "begin to call NSTACKX_RegisterServiceDataV2");
1630     if (!RegisterServiceDataParamCheck(param, cnt)) {
1631         return NSTACKX_EINVAL;
1632     }
1633 
1634     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1635         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1636         return NSTACKX_EFAILED;
1637     }
1638 
1639     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1640         return SetLocalDeviceServiceDataV2(param, cnt);
1641     }
1642 
1643     struct ServiceDataInfo *info = ServiceDataV2Create(param, cnt);
1644     if (info == NULL) {
1645         DFINDER_LOGE(TAG, "create info failed");
1646         return NSTACKX_EFAILED;
1647     }
1648     // The abnormal branch info is released internally.
1649     if (NSTACKX_PostEventBlock(RegisterServiceDataV2, (void *)info, ServiceDataV2Free) != NSTACKX_EOK) {
1650         DFINDER_LOGE(TAG, "Failed to register serviceDatav2!");
1651         return NSTACKX_EFAILED;
1652     }
1653 
1654     return NSTACKX_EOK;
1655 }
1656 
NSTACKX_RegisterServiceData(const char * serviceData)1657 int32_t NSTACKX_RegisterServiceData(const char *serviceData)
1658 {
1659     Coverity_Tainted_Set((void *)serviceData);
1660 
1661     DFINDER_LOGD(TAG, "begin to call NSTACKX_RegisterServiceData");
1662     char *serviceDataTmp = NULL;
1663 
1664     if (serviceData == NULL) {
1665         DFINDER_LOGE(TAG, "serviceData is null");
1666         return NSTACKX_EINVAL;
1667     }
1668     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1669         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1670         return NSTACKX_EFAILED;
1671     }
1672     if (strlen(serviceData) >= NSTACKX_MAX_SERVICE_DATA_LEN) {
1673         DFINDER_LOGE(TAG, "serviceData (%u) exceed max number", strlen(serviceData));
1674         return NSTACKX_EINVAL;
1675     }
1676     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1677         return SetLocalDeviceServiceData(serviceData);
1678     }
1679 
1680     serviceDataTmp = calloc(1U, NSTACKX_MAX_SERVICE_DATA_LEN);
1681     if (serviceDataTmp == NULL) {
1682         return NSTACKX_ENOMEM;
1683     }
1684     if (strncpy_s(serviceDataTmp, NSTACKX_MAX_SERVICE_DATA_LEN, serviceData, strlen(serviceData)) != EOK) {
1685         DFINDER_LOGE(TAG, "Failed to copy serviceData");
1686         free(serviceDataTmp);
1687         return NSTACKX_EINVAL;
1688     }
1689     if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterServiceDataInner, serviceDataTmp) != NSTACKX_EOK) {
1690         DFINDER_LOGE(TAG, "Failed to register serviceData!");
1691         free(serviceDataTmp);
1692         return NSTACKX_EFAILED;
1693     }
1694 
1695     return NSTACKX_EOK;
1696 }
1697 
RegisterBusinessDataInner(void * argument)1698 static void RegisterBusinessDataInner(void *argument)
1699 {
1700     DFINDER_LOGI(TAG, "Register Business Data Inner");
1701     char *businessData = argument;
1702     if (SetLocalDeviceBusinessData(businessData, NSTACKX_TRUE) != NSTACKX_EOK) {
1703         DFINDER_LOGE(TAG, "RegisterBusinessData failed");
1704     }
1705     free(businessData);
1706 }
1707 
NSTACKX_RegisterBusinessData(const char * businessData)1708 int32_t NSTACKX_RegisterBusinessData(const char *businessData)
1709 {
1710     DFINDER_LOGI(TAG, "begin to call NSTACKX_RegisterBusinessData");
1711 
1712     char *businessDataTmp = NULL;
1713     if (businessData == NULL) {
1714         DFINDER_LOGE(TAG, "businessData is null");
1715         return NSTACKX_EINVAL;
1716     }
1717     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1718         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1719         return NSTACKX_EFAILED;
1720     }
1721     if (strlen(businessData) >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
1722         DFINDER_LOGE(TAG, "businessData (%u) exceed max data len", strlen(businessData));
1723         return NSTACKX_EINVAL;
1724     }
1725     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1726         return (int32_t)SetLocalDeviceBusinessData(businessData, NSTACKX_TRUE);
1727     }
1728 
1729     businessDataTmp = calloc(1, NSTACKX_MAX_BUSINESS_DATA_LEN);
1730     if (businessDataTmp == NULL) {
1731         DFINDER_LOGE(TAG, "businessDataTmp is null");
1732         return NSTACKX_ENOMEM;
1733     }
1734     if (strncpy_s(businessDataTmp, NSTACKX_MAX_BUSINESS_DATA_LEN, businessData,
1735         strlen(businessData)) != EOK) {
1736         DFINDER_LOGE(TAG, "Failed to copy businessData");
1737         free(businessDataTmp);
1738         return NSTACKX_EFAILED;
1739     }
1740     if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterBusinessDataInner, businessDataTmp) != NSTACKX_EOK) {
1741         DFINDER_LOGE(TAG, "Failed to register businessData!");
1742         free(businessDataTmp);
1743         return NSTACKX_EFAILED;
1744     }
1745 
1746     return NSTACKX_EOK;
1747 }
1748 
1749 #ifndef DFINDER_USE_MINI_NSTACKX
RegisterExtendServiceDataInner(void * argument)1750 static void RegisterExtendServiceDataInner(void *argument)
1751 {
1752     char *extendServiceData = argument;
1753     if (SetLocalDeviceExtendServiceData(extendServiceData) != NSTACKX_EOK) {
1754         DFINDER_LOGE(TAG, "RegisterExtendServiceData failed");
1755     }
1756     free(extendServiceData);
1757 }
1758 #endif
1759 
NSTACKX_RegisterExtendServiceData(const char * extendServiceData)1760 int32_t NSTACKX_RegisterExtendServiceData(const char *extendServiceData)
1761 {
1762 #ifndef DFINDER_USE_MINI_NSTACKX
1763     char *extendServiceDataTmp = NULL;
1764 
1765     if (extendServiceData == NULL) {
1766         DFINDER_LOGE(TAG, "extendServiceData is null");
1767         return NSTACKX_EINVAL;
1768     }
1769     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1770         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1771         return NSTACKX_EFAILED;
1772     }
1773     if (strlen(extendServiceData) >= NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN) {
1774         DFINDER_LOGE(TAG, "extendServiceData (%u) exceed max number", strlen(extendServiceData));
1775         return NSTACKX_EINVAL;
1776     }
1777     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1778         return SetLocalDeviceExtendServiceData(extendServiceData);
1779     }
1780 
1781     extendServiceDataTmp = calloc(1, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN);
1782     if (extendServiceDataTmp == NULL) {
1783         return NSTACKX_ENOMEM;
1784     }
1785     if (strncpy_s(extendServiceDataTmp, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN, extendServiceData,
1786         strlen(extendServiceData)) != EOK) {
1787         DFINDER_LOGE(TAG, "Failed to copy extendServiceData");
1788         free(extendServiceDataTmp);
1789         return NSTACKX_EINVAL;
1790     }
1791     if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterExtendServiceDataInner, extendServiceDataTmp) != NSTACKX_EOK) {
1792         DFINDER_LOGE(TAG, "Failed to register extendServiceData!");
1793         free(extendServiceDataTmp);
1794         return NSTACKX_EFAILED;
1795     }
1796     return NSTACKX_EOK;
1797 #else
1798     (void)extendServiceData;
1799     DFINDER_LOGI(TAG, "NSTACKX_RegisterExtendServiceData not supported");
1800     return NSTACKX_EOK;
1801 #endif
1802 }
1803 
1804 #ifndef DFINDER_USE_MINI_NSTACKX
1805 struct DirectMsgCtx {
1806     MsgCtx msg;
1807     const char *ipStr;
1808     struct in_addr ip;
1809 };
1810 
SendMsgDirectInner(void * arg)1811 static void SendMsgDirectInner(void *arg)
1812 {
1813     struct DirectMsgCtx *msg = arg;
1814     DFINDER_LOGD(TAG, "Enter WifiDirect send");
1815     msg->msg.err = CoapSendServiceMsg(&msg->msg, msg->ipStr, &msg->ip);
1816     SemPost(&msg->msg.wait);
1817 }
1818 
NSTACKX_SendMsgParamCheck(const char * moduleName,const char * deviceId,const uint8_t * data,uint32_t len)1819 static int32_t NSTACKX_SendMsgParamCheck(const char *moduleName, const char *deviceId, const uint8_t *data,
1820     uint32_t len)
1821 {
1822     if (moduleName == NULL || strlen(moduleName) > NSTACKX_MAX_MODULE_NAME_LEN) {
1823         DFINDER_LOGE(TAG, "Invalid module name");
1824         return NSTACKX_EINVAL;
1825     }
1826 
1827     if (deviceId == NULL || strlen(deviceId) > NSTACKX_MAX_DEVICE_ID_LEN) {
1828         DFINDER_LOGE(TAG, "Invalid device id");
1829         return NSTACKX_EINVAL;
1830     }
1831 
1832     if (data == NULL || len == 0 || len > NSTACKX_MAX_SENDMSG_DATA_LEN) {
1833         DFINDER_LOGE(TAG, "Null data to send");
1834         return NSTACKX_EINVAL;
1835     }
1836     return NSTACKX_EOK;
1837 }
1838 
MsgCtxInit(MsgCtx * msg,const char * moduleName,const char * deviceId,const uint8_t * data,uint32_t len)1839 static int MsgCtxInit(MsgCtx *msg, const char *moduleName, const char *deviceId, const uint8_t *data, uint32_t len)
1840 {
1841     if (SemInit(&msg->wait, 0, 0)) {
1842         DFINDER_LOGE(TAG, "sem init fail");
1843         return NSTACKX_EFAILED;
1844     }
1845 
1846     msg->deviceId = deviceId;
1847     msg->moduleName = moduleName;
1848     msg->data = data;
1849     msg->len = len;
1850     msg->err = NSTACKX_EOK;
1851 
1852     return NSTACKX_EOK;
1853 }
1854 #endif
1855 
NSTACKX_SendMsgDirect(const char * moduleName,const char * deviceId,const uint8_t * data,uint32_t len,const char * ipaddr,uint8_t type)1856 int32_t NSTACKX_SendMsgDirect(const char *moduleName, const char *deviceId, const uint8_t *data,
1857     uint32_t len, const char *ipaddr, uint8_t type)
1858 {
1859 #ifndef DFINDER_USE_MINI_NSTACKX
1860     int32_t ret = NSTACKX_EOK;
1861     DFINDER_LOGD(TAG, "NSTACKX_SendMsgDirect");
1862     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1863         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1864         return NSTACKX_EFAILED;
1865     }
1866     if (ipaddr == NULL) {
1867         DFINDER_LOGE(TAG, "ipaddr needed");
1868         return NSTACKX_EINVAL;
1869     }
1870 
1871     if (type > SERVER_TYPE_USB) {
1872         DFINDER_LOGE(TAG, "invalid type %hhu", type);
1873         return NSTACKX_EINVAL;
1874     }
1875 
1876     if (NSTACKX_SendMsgParamCheck(moduleName, deviceId, data, len) != NSTACKX_EOK) {
1877         return NSTACKX_EINVAL;
1878     }
1879 
1880     struct DirectMsgCtx directMsg;
1881     if (inet_pton(AF_INET, ipaddr, &directMsg.ip) != 1 || directMsg.ip.s_addr == 0) {
1882         DFINDER_LOGE(TAG, "invalid ip addr");
1883         return NSTACKX_EINVAL;
1884     }
1885     directMsg.ipStr = ipaddr;
1886     directMsg.msg.type = type;
1887     if (MsgCtxInit(&directMsg.msg, moduleName, deviceId, data, len) != NSTACKX_EOK) {
1888         return NSTACKX_EFAILED;
1889     }
1890 
1891     if (PostEvent(&g_eventNodeChain, g_epollfd, SendMsgDirectInner, &directMsg) != NSTACKX_EOK) {
1892         DFINDER_LOGE(TAG, "Failed to send msg");
1893         ret = NSTACKX_EFAILED;
1894     }
1895     if (ret == NSTACKX_EOK) {
1896         SemWait(&directMsg.msg.wait);
1897         ret = directMsg.msg.err;
1898     }
1899     SemDestroy(&directMsg.msg.wait);
1900     return ret;
1901 #else
1902     (void)moduleName;
1903     (void)deviceId;
1904     (void)data;
1905     (void)len;
1906     (void)ipaddr;
1907     (void)type;
1908     DFINDER_LOGI(TAG, "NSTACKX_SendMsgDirect not supported");
1909     return NSTACKX_EFAILED;
1910 #endif
1911 }
1912 
1913 #if defined(DFINDER_SAVE_DEVICE_LIST) && !defined(DFINDER_USE_MINI_NSTACKX)
SendMsgInner(void * arg)1914 static void SendMsgInner(void *arg)
1915 {
1916     MsgCtx *msg = arg;
1917     const struct in_addr *remoteIp = GetRemoteDeviceIp(msg->deviceId);
1918     if (remoteIp == NULL) {
1919         DFINDER_LOGE(TAG, "no device found");
1920         msg->err = NSTACKX_EINVAL;
1921     } else {
1922         char ipStr[INET_ADDRSTRLEN] = {0};
1923         if (inet_ntop(AF_INET, remoteIp, ipStr, sizeof(ipStr)) != NULL) {
1924             msg->err = CoapSendServiceMsg(msg, ipStr, remoteIp);
1925         } else {
1926             DFINDER_LOGE(TAG, "ip format failed");
1927         }
1928     }
1929 
1930     SemPost(&msg->wait);
1931 }
1932 #endif
1933 
NSTACKX_SendMsg(const char * moduleName,const char * deviceId,const uint8_t * data,uint32_t len)1934 int32_t NSTACKX_SendMsg(const char *moduleName, const char *deviceId, const uint8_t *data, uint32_t len)
1935 {
1936     Coverity_Tainted_Set((void *)moduleName);
1937     Coverity_Tainted_Set((void *)deviceId);
1938     Coverity_Tainted_Set((void *)data);
1939     Coverity_Tainted_Set((void *)&len);
1940 #if defined(DFINDER_SAVE_DEVICE_LIST) && !defined(DFINDER_USE_MINI_NSTACKX)
1941     int32_t ret = NSTACKX_EOK;
1942     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
1943         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1944         return NSTACKX_EFAILED;
1945     }
1946     if (NSTACKX_SendMsgParamCheck(moduleName, deviceId, data, len) != NSTACKX_EOK) {
1947         return NSTACKX_EINVAL;
1948     }
1949 
1950     MsgCtx msg;
1951     msg.type = INVALID_TYPE;
1952     if (MsgCtxInit(&msg, moduleName, deviceId, data, len) != NSTACKX_EOK) {
1953         return NSTACKX_EFAILED;
1954     }
1955 
1956     if (PostEvent(&g_eventNodeChain, g_epollfd, SendMsgInner, &msg) != NSTACKX_EOK) {
1957         DFINDER_LOGE(TAG, "failed to send msg");
1958         ret = NSTACKX_EFAILED;
1959     }
1960     if (ret == NSTACKX_EOK) {
1961         SemWait(&msg.wait);
1962         ret = msg.err;
1963     }
1964     SemDestroy(&msg.wait);
1965     return ret;
1966 #else
1967     (void)moduleName;
1968     (void)deviceId;
1969     (void)data;
1970     (void)len;
1971     DFINDER_LOGI(TAG, "SendMsg not supported");
1972     return NSTACKX_EFAILED;
1973 #endif
1974 }
1975 
SendDiscoveryRspInner(void * arg)1976 static void SendDiscoveryRspInner(void *arg)
1977 {
1978     NSTACKX_ResponseSettings *responseSettings = arg;
1979     SendDiscoveryRsp(responseSettings);
1980     free(responseSettings->businessData);
1981     free(responseSettings);
1982 }
1983 
CopyResponseSettings(NSTACKX_ResponseSettings * dupResponseSettings,const NSTACKX_ResponseSettings * responseSettings)1984 static int32_t CopyResponseSettings(NSTACKX_ResponseSettings *dupResponseSettings,
1985                                     const NSTACKX_ResponseSettings *responseSettings)
1986 {
1987     dupResponseSettings->businessType = responseSettings->businessType;
1988     dupResponseSettings->length = responseSettings->length;
1989     if (responseSettings->businessData != NULL) {
1990         if (strncpy_s(dupResponseSettings->businessData, (dupResponseSettings->length + 1),
1991             responseSettings->businessData, responseSettings->length) != EOK) {
1992             DFINDER_LOGE(TAG, "businessData strncpy failed");
1993             return NSTACKX_EINVAL;
1994         }
1995     }
1996     if (strncpy_s(dupResponseSettings->localNetworkName, NSTACKX_MAX_INTERFACE_NAME_LEN,
1997         responseSettings->localNetworkName, strlen(responseSettings->localNetworkName)) != EOK) {
1998         DFINDER_LOGE(TAG, "localNetworkName strncpy failed");
1999         return NSTACKX_EINVAL;
2000     }
2001     if (strncpy_s(dupResponseSettings->remoteIp, NSTACKX_MAX_IP_STRING_LEN,
2002         responseSettings->remoteIp, strlen(responseSettings->remoteIp)) != EOK) {
2003         DFINDER_LOGE(TAG, "remoteIp strncpy failed");
2004         return NSTACKX_EINVAL;
2005     }
2006     return NSTACKX_EOK;
2007 }
2008 
CheckResponseSettings(const NSTACKX_ResponseSettings * responseSettings)2009 static int32_t CheckResponseSettings(const NSTACKX_ResponseSettings *responseSettings)
2010 {
2011     if (responseSettings == NULL) {
2012         DFINDER_LOGE(TAG, "Invalid responseSettings info");
2013         return NSTACKX_EINVAL;
2014     }
2015     if ((responseSettings->businessData == NULL) && (responseSettings->length != 0)) {
2016         DFINDER_LOGE(TAG, "Invalid responseSettings bData info");
2017         return NSTACKX_EINVAL;
2018     }
2019     if (responseSettings->length >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
2020         DFINDER_LOGE(TAG, "businessData length is too long");
2021         return NSTACKX_EINVAL;
2022     }
2023     return NSTACKX_EOK;
2024 }
2025 
NSTACKX_SendDiscoveryRsp(const NSTACKX_ResponseSettings * responseSettings)2026 int32_t NSTACKX_SendDiscoveryRsp(const NSTACKX_ResponseSettings *responseSettings)
2027 {
2028     DFINDER_LOGI(TAG, "begin to NSTACKX_SendDiscoveryRsp!");
2029     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
2030         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
2031         return NSTACKX_EFAILED;
2032     }
2033     if (CheckResponseSettings(responseSettings) != NSTACKX_EOK) {
2034         return NSTACKX_EINVAL;
2035     }
2036 
2037     DFINDER_LOGI(TAG, "response settings, business type: %hu, local network name: %s",
2038         responseSettings->businessType, responseSettings->localNetworkName);
2039 
2040     NSTACKX_ResponseSettings *dupResponseSettings = malloc(sizeof(NSTACKX_ResponseSettings));
2041     if (dupResponseSettings == NULL) {
2042         DFINDER_LOGE(TAG, "malloc failed");
2043         return NSTACKX_ENOMEM;
2044     }
2045     dupResponseSettings->businessData = (char *)calloc((responseSettings->length + 1), sizeof(char));
2046     if (dupResponseSettings->businessData == NULL) {
2047         DFINDER_LOGE(TAG, "businessData calloc failed");
2048         free(dupResponseSettings);
2049         return NSTACKX_ENOMEM;
2050     }
2051     if (CopyResponseSettings(dupResponseSettings, responseSettings) != NSTACKX_EOK) {
2052         free(dupResponseSettings->businessData);
2053         free(dupResponseSettings);
2054         return NSTACKX_EINVAL;
2055     }
2056 
2057     if (PostEvent(&g_eventNodeChain, g_epollfd, SendDiscoveryRspInner, dupResponseSettings) != NSTACKX_EOK) {
2058         DFINDER_LOGE(TAG, "Failed to send responseSettings info!");
2059         free(dupResponseSettings->businessData);
2060         free(dupResponseSettings);
2061         return NSTACKX_EFAILED;
2062     }
2063     return NSTACKX_EOK;
2064 }
2065 
2066 #ifdef DFINDER_SAVE_DEVICE_LIST
GetDeviceListInner(void * argument)2067 static void GetDeviceListInner(void *argument)
2068 {
2069     GetDeviceListMessage *message = argument;
2070 
2071     GetDeviceList(message->deviceList, message->deviceCountPtr, true);
2072     SemPost(&message->wait);
2073 }
2074 #endif
2075 
NSTACKX_GetDeviceList(NSTACKX_DeviceInfo * deviceList,uint32_t * deviceCountPtr)2076 int32_t NSTACKX_GetDeviceList(NSTACKX_DeviceInfo *deviceList, uint32_t *deviceCountPtr)
2077 {
2078 #ifdef DFINDER_SAVE_DEVICE_LIST
2079     GetDeviceListMessage message = {
2080         .deviceList = deviceList,
2081         .deviceCountPtr = deviceCountPtr,
2082     };
2083     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
2084         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
2085         return NSTACKX_EFAILED;
2086     }
2087     if (deviceList == NULL || deviceCountPtr == NULL) {
2088         DFINDER_LOGE(TAG, "Device list or count pointer is NULL");
2089         return NSTACKX_EINVAL;
2090     }
2091     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
2092         GetDeviceList(deviceList, deviceCountPtr, true);
2093         return NSTACKX_EOK;
2094     }
2095     if (SemInit(&message.wait, 0, 0)) {
2096         return NSTACKX_EFAILED;
2097     }
2098     if (PostEvent(&g_eventNodeChain, g_epollfd, GetDeviceListInner, &message) != NSTACKX_EOK) {
2099         DFINDER_LOGE(TAG, "Failed to get device list");
2100         SemDestroy(&message.wait);
2101         return NSTACKX_EFAILED;
2102     }
2103     SemWait(&message.wait);
2104     SemDestroy(&message.wait);
2105     return NSTACKX_EOK;
2106 #else
2107     (void)deviceList;
2108     (void)deviceCountPtr;
2109 
2110     DFINDER_LOGE(TAG, "device list not supported");
2111 
2112     return NSTACKX_EFAILED;
2113 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
2114 }
2115 
NotifyDeviceListChanged(const NSTACKX_DeviceInfo * deviceList,uint32_t deviceCount)2116 void NotifyDeviceListChanged(const NSTACKX_DeviceInfo *deviceList, uint32_t deviceCount)
2117 {
2118     if (g_parameter.onDeviceListChanged != NULL) {
2119         DFINDER_LOGI(TAG, "notify callback: device list changed");
2120         g_parameter.onDeviceListChanged(deviceList, deviceCount);
2121         DFINDER_LOGI(TAG, "finish to notify device list changed");
2122     } else {
2123         DFINDER_LOGI(TAG, "notify callback: device list changed callback is null");
2124     }
2125 }
2126 
NotifyDeviceFound(const NSTACKX_DeviceInfo * deviceList,uint32_t deviceCount)2127 void NotifyDeviceFound(const NSTACKX_DeviceInfo *deviceList, uint32_t deviceCount)
2128 {
2129     if (g_parameter.onDeviceFound != NULL) {
2130         DFINDER_LOGI(TAG, "notify callback: device found");
2131         g_parameter.onDeviceFound(deviceList, deviceCount);
2132         DFINDER_LOGI(TAG, "finish to notify device found");
2133     } else {
2134         DFINDER_LOGI(TAG, "notify callback: device found callback is null");
2135     }
2136 }
2137 
NotificationReceived(const NSTACKX_NotificationConfig * notification)2138 void NotificationReceived(const NSTACKX_NotificationConfig *notification)
2139 {
2140     if (g_parameter.onNotificationReceived != NULL) {
2141         DFINDER_LOGI(TAG, "notify callback: notification received");
2142         g_parameter.onNotificationReceived(notification);
2143         DFINDER_LOGI(TAG, "finish to notify notification received");
2144     } else {
2145         DFINDER_LOGI(TAG, "notify callback: notification received callback is null");
2146     }
2147 }
2148 
2149 #ifndef DFINDER_USE_MINI_NSTACKX
NotifyMsgReceived(const char * moduleName,const char * deviceId,const uint8_t * data,uint32_t len,const char * srcIp)2150 void NotifyMsgReceived(const char *moduleName, const char *deviceId, const uint8_t *data,
2151     uint32_t len, const char *srcIp)
2152 {
2153     if (g_parameter.onMsgReceived != NULL) {
2154         DFINDER_LOGI(TAG, "notify callback: message received, data length %u", len);
2155         g_parameter.onMsgReceived(moduleName, deviceId, data, len, srcIp);
2156         DFINDER_LOGI(TAG, "finish to notify msg received");
2157     } else {
2158         DFINDER_LOGI(TAG, "notify callback: message received callback is null");
2159     }
2160 }
2161 
NSTACKX_InitRestart(const NSTACKX_Parameter * parameter)2162 int32_t NSTACKX_InitRestart(const NSTACKX_Parameter *parameter)
2163 {
2164     Coverity_Tainted_Set((void *)parameter);
2165 
2166 #if defined(_WIN32) || defined(DFINDER_USE_MINI_NSTACKX)
2167     DFINDER_LOGE(TAG, "do not support init restart");
2168     (void)parameter;
2169     return NSTACKX_EFAILED;
2170 #else
2171     DFINDER_LOGI(TAG, "NSTACKX_InitRestart");
2172     int32_t ret = NSTACKX_Init(parameter);
2173     if (ret == NSTACKX_EOK) {
2174         if (PostEvent(&g_eventNodeChain, g_epollfd, DetectLocalIface, NULL) != NSTACKX_EOK) {
2175             DFINDER_LOGE(TAG, "Failed to GetLocalNetworkInterface");
2176         }
2177     }
2178     return ret;
2179 #endif
2180 }
2181 
DeviceDiscoverInnerRestart(void * argument)2182 static void DeviceDiscoverInnerRestart(void *argument)
2183 {
2184     (void)argument;
2185     CoapServiceDiscoverInner(NSTACKX_FALSE);
2186 }
2187 
NSTACKX_StartDeviceFindRestart(void)2188 void NSTACKX_StartDeviceFindRestart(void)
2189 {
2190     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
2191         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
2192         return;
2193     }
2194     DFINDER_LOGI(TAG, "start device find for restart");
2195     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerRestart, NULL) != NSTACKX_EOK) {
2196         DFINDER_LOGE(TAG, "Failed to start device discover!");
2197         return;
2198     }
2199     return;
2200 }
2201 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
2202 
2203 #ifdef ENABLE_USER_LOG
NSTACKX_DFinderRegisterLog(DFinderLogCallback userLogCallback)2204 int32_t NSTACKX_DFinderRegisterLog(DFinderLogCallback userLogCallback)
2205 {
2206     if (userLogCallback == NULL) {
2207         DFINDER_LOGE(TAG, "logImpl null");
2208         return NSTACKX_EFAILED;
2209     }
2210     int32_t ret = SetLogCallback(userLogCallback);
2211     return ret;
2212 }
2213 #endif
2214 
2215 #ifdef NSTACKX_DFINDER_HIDUMP
2216 #define MAX_DUMP_ARGC 10
NSTACKX_DFinderDump(const char ** argv,uint32_t argc,void * softObj,DFinderDumpFunc dump)2217 int NSTACKX_DFinderDump(const char **argv, uint32_t argc, void *softObj, DFinderDumpFunc dump)
2218 {
2219     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
2220         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
2221         return NSTACKX_EFAILED;
2222     }
2223 
2224     if (dump == NULL) {
2225         DFINDER_LOGE(TAG, "dump is null");
2226         return NSTACKX_EINVAL;
2227     }
2228 
2229     if (argc == 0 || argc > MAX_DUMP_ARGC) {
2230         DFINDER_LOGE(TAG, "argc is invalid %u", argc);
2231         return NSTACKX_EINVAL;
2232     }
2233 
2234     if (argv == NULL) {
2235         DFINDER_LOGE(TAG, "argv is null");
2236         return NSTACKX_EINVAL;
2237     }
2238 
2239     uint32_t i;
2240     for (i = 0; i < argc; i++) {
2241         if (argv[i] == NULL) {
2242             DFINDER_LOGE(TAG, "argv[%u] is null", i);
2243             return NSTACKX_EINVAL;
2244         }
2245     }
2246 
2247     return DFinderDump(argv, argc, softObj, dump);
2248 }
2249 #else
NSTACKX_DFinderDump(const char ** argv,uint32_t argc,void * softObj,DFinderDumpFunc dump)2250 int NSTACKX_DFinderDump(const char **argv, uint32_t argc, void *softObj, DFinderDumpFunc dump)
2251 {
2252     (void)argv;
2253     (void)argc;
2254     (void)softObj;
2255     (void)dump;
2256     DFINDER_LOGE(TAG, "unsupport dfinder dump");
2257     return NSTACKX_NOTSUPPORT;
2258 }
2259 #endif
2260 
NSTACKX_DFinderSetEventFunc(void * softobj,DFinderEventFunc func)2261 int NSTACKX_DFinderSetEventFunc(void *softobj, DFinderEventFunc func)
2262 {
2263     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
2264         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
2265         return NSTACKX_EFAILED;
2266     }
2267     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
2268         return SetEventFuncDirectly(softobj, func);
2269     }
2270 
2271     return SetEventFunc(softobj, func);
2272 }
2273 
CheckNotificationConfig(const NSTACKX_NotificationConfig * config)2274 static int32_t CheckNotificationConfig(const NSTACKX_NotificationConfig *config)
2275 {
2276     if (config == NULL) {
2277         DFINDER_LOGE(TAG, "notification config passed in is null");
2278         return NSTACKX_EINVAL;
2279     }
2280     if (config->businessType >= NSTACKX_BUSINESS_TYPE_MAX) {
2281         DFINDER_LOGE(TAG, "invalid business type %hhu in notification config", config->businessType);
2282         return NSTACKX_EINVAL;
2283     }
2284     if (config->msg == NULL) {
2285         DFINDER_LOGE(TAG, "msg in notification config is null");
2286         return NSTACKX_EINVAL;
2287     }
2288     if (strlen(config->msg) != config->msgLen || config->msgLen == 0 ||
2289         config->msgLen >= NSTACKX_MAX_NOTIFICATION_DATA_LEN) {
2290         DFINDER_LOGE(TAG, "actual msg len %zu, msg len %zu in config", strlen(config->msg), config->msgLen);
2291         return NSTACKX_EINVAL;
2292     }
2293     // advertise count: [0, 100], first interval in intervalMs should be 0
2294     if (config->intervalLen == 0 || config->intervalLen > NSTACKX_MAX_ADVERTISE_COUNT) {
2295         DFINDER_LOGE(TAG, "invalid interval len %hhu in notification config, max support %d",
2296             config->intervalLen, NSTACKX_MAX_ADVERTISE_COUNT);
2297         return NSTACKX_EINVAL;
2298     }
2299     if (config->intervalsMs == NULL) {
2300         DFINDER_LOGE(TAG, "broadcast intervals in notification config is null");
2301         return NSTACKX_EINVAL;
2302     }
2303     // interval: [0 ms, 10000 ms]
2304     if (config->intervalsMs[0] != 0) {
2305         DFINDER_LOGE(TAG, "first interval should be 0 to indicate send notification immediately");
2306         return NSTACKX_EINVAL;
2307     }
2308     for (size_t i = 1; i < config->intervalLen; ++i) {
2309         if (config->intervalsMs[i] < NSTACKX_MIN_ADVERTISE_INTERVAL ||
2310             config->intervalsMs[i] > NSTACKX_MAX_ADVERTISE_INTERVAL) {
2311             DFINDER_LOGE(TAG, "invalid interval[%zu] = %hu, support max: %d min: %d",
2312                 i, config->intervalsMs[i], NSTACKX_MAX_ADVERTISE_INTERVAL, NSTACKX_MIN_ADVERTISE_INTERVAL);
2313             return NSTACKX_EINVAL;
2314         }
2315     }
2316     return NSTACKX_EOK;
2317 }
2318 
CopyNotificationConfig(NSTACKX_NotificationConfig * dst,const NSTACKX_NotificationConfig * src)2319 static int32_t CopyNotificationConfig(NSTACKX_NotificationConfig *dst, const NSTACKX_NotificationConfig *src)
2320 {
2321     dst->businessType = src->businessType;
2322     if (strncpy_s(dst->msg, src->msgLen + 1, src->msg, src->msgLen) != EOK) {
2323         DFINDER_LOGE(TAG, "copy notification msg to duplicated one fail");
2324         return NSTACKX_EFAILED;
2325     }
2326     dst->msgLen = src->msgLen;
2327     for (size_t i = 0; i < src->intervalLen; ++i) {
2328         (dst->intervalsMs)[i] = (src->intervalsMs)[i];
2329     }
2330     dst->intervalLen = src->intervalLen;
2331     return NSTACKX_EOK;
2332 }
2333 
NotificationInner(void * argument)2334 static void NotificationInner(void *argument)
2335 {
2336     NSTACKX_NotificationConfig *config = (NSTACKX_NotificationConfig *)argument;
2337     int32_t retMsg = LocalizeNotificationMsg(config->msg);
2338     int32_t retInterval = LocalizeNotificationInterval(config->intervalsMs, config->intervalLen);
2339     free(config->intervalsMs);
2340     free(config->msg);
2341     free(config);
2342     if (retMsg != NSTACKX_EOK || retInterval != NSTACKX_EOK) {
2343         DFINDER_LOGE(TAG, "stop running service notification cause localize config fail");
2344         return;
2345     }
2346     CoapServiceNotification();
2347 }
2348 
NSTACKX_SendNotification(const NSTACKX_NotificationConfig * config)2349 int32_t NSTACKX_SendNotification(const NSTACKX_NotificationConfig *config)
2350 {
2351     DFINDER_LOGI(TAG, "begin to call NSTACKX_SendNotification");
2352 
2353     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
2354         DFINDER_LOGE(TAG, "dfinder not inited");
2355         return NSTACKX_EFAILED;
2356     }
2357     if (CheckNotificationConfig(config) != NSTACKX_EOK) {
2358         return NSTACKX_EINVAL;
2359     }
2360     NSTACKX_NotificationConfig *dupConfig = (NSTACKX_NotificationConfig *)calloc(1, sizeof(NSTACKX_NotificationConfig));
2361     if (dupConfig == NULL) {
2362         DFINDER_LOGE(TAG, "calloc for notification config fail, size wanted: %zu", sizeof(NSTACKX_NotificationConfig));
2363         return NSTACKX_ENOMEM;
2364     }
2365     dupConfig->msg = (char *)calloc((config->msgLen + 1), sizeof(char));
2366     if (dupConfig->msg == NULL) {
2367         DFINDER_LOGE(TAG, "calloc for msg in notification fail, size wanted: %zu", config->msgLen + 1);
2368         free(dupConfig);
2369         return NSTACKX_ENOMEM;
2370     }
2371     dupConfig->intervalsMs = (uint16_t *)calloc(config->intervalLen, sizeof(uint16_t));
2372     if (dupConfig->intervalsMs == NULL) {
2373         DFINDER_LOGE(TAG, "calloc for intervals fail, size wanted: %zu", sizeof(uint16_t) * (config->intervalLen));
2374         free(dupConfig->msg);
2375         free(dupConfig);
2376         return NSTACKX_ENOMEM;
2377     }
2378     if (CopyNotificationConfig(dupConfig, config) != NSTACKX_EOK) {
2379         free(dupConfig->intervalsMs);
2380         free(dupConfig->msg);
2381         free(dupConfig);
2382         return NSTACKX_EFAILED;
2383     }
2384     if (PostEvent(&g_eventNodeChain, g_epollfd, NotificationInner, dupConfig) != NSTACKX_EOK) {
2385         DFINDER_LOGE(TAG, "post event failed to run notification inner");
2386         free(dupConfig->intervalsMs);
2387         free(dupConfig->msg);
2388         free(dupConfig);
2389         return NSTACKX_EFAILED;
2390     }
2391     return NSTACKX_EOK;
2392 }
2393 
NotificationStop(void * argument)2394 static void NotificationStop(void *argument)
2395 {
2396     (void)argument;
2397     CoapServiceNotificationStop();
2398 }
2399 
NSTACKX_StopSendNotification(uint8_t businessType)2400 int32_t NSTACKX_StopSendNotification(uint8_t businessType)
2401 {
2402     DFINDER_LOGI(TAG, "begin to call NSTACKX_StopSendNotification, business type: %hhu", businessType);
2403 
2404     if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
2405         DFINDER_LOGE(TAG, "dfinder not inited");
2406         return NSTACKX_EFAILED;
2407     }
2408     if (businessType >= NSTACKX_BUSINESS_TYPE_MAX) {
2409         DFINDER_LOGE(TAG, "invalid business type %hhu to stop send notification", businessType);
2410         return NSTACKX_EINVAL;
2411     }
2412     if (PostEvent(&g_eventNodeChain, g_epollfd, NotificationStop, NULL) != NSTACKX_EOK) {
2413         DFINDER_LOGE(TAG, "post event failed to run stop device discover");
2414         return NSTACKX_EFAILED;
2415     }
2416     return NSTACKX_EOK;
2417 }
2418