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