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