• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
42 #ifdef DFINDER_USE_MINI_NSTACKX
43 #include "cmsis_os2.h"
44 #include "ohos_init.h"
45 #define DFINDER_THREAD_STACK_SIZE (1024 * 32)
46 #endif
47 
48 #define TAG "nStackXDFinder"
49 #define DFINDER_THREAD_NAME TAG
50 
51 enum {
52     NSTACKX_INIT_STATE_START = 0,
53     NSTACKX_INIT_STATE_ONGOING,
54     NSTACKX_INIT_STATE_DONE,
55 };
56 
57 #ifdef DFINDER_USE_MINI_NSTACKX
58 static osThreadId_t g_threadId;
59 #else
60 static pthread_t g_tid;
61 #endif
62 
63 static EpollDesc g_epollfd = INVALID_EPOLL_DESC;
64 static List g_eventNodeChain = {&(g_eventNodeChain), &(g_eventNodeChain)};
65 
66 static uint8_t g_validTidFlag = NSTACKX_FALSE;
67 static uint8_t g_terminateFlag = NSTACKX_FALSE;
68 
69 static NSTACKX_Parameter g_parameter;
70 static uint8_t g_nstackInitState;
71 
72 #define EVENT_COUNT_RATE_INTERVAL 2000 /* 2 SECONDS */
73 #define MAX_EVENT_PROCESS_NUM_PER_INTERVAL 700
74 #define MAX_CONTINUOUS_BUSY_INTERVAL_NUM 20
75 
76 typedef struct {
77     uint32_t epollWaitTimeoutCount;
78     uint32_t epollWaitEventCount;
79     struct timespec measureBefore;
80 } EventProcessRatePara;
81 static EventProcessRatePara g_processRatePara;
82 static uint32_t g_continuousBusyIntervals;
83 
84 static int32_t CheckDiscoverySettings(const NSTACKX_DiscoverySettings *discoverySettings);
85 
GetEventNodeChain(void)86 List *GetEventNodeChain(void)
87 {
88     return &g_eventNodeChain;
89 }
90 
GetEpollFD(void)91 EpollDesc GetEpollFD(void)
92 {
93     return g_epollfd;
94 }
95 
NotifyDFinderMsgRecver(DFinderMsgType msgType)96 void NotifyDFinderMsgRecver(DFinderMsgType msgType)
97 {
98     if (g_parameter.onDFinderMsgReceived != NULL) {
99         g_parameter.onDFinderMsgReceived(msgType);
100     }
101 }
102 
103 /* check if we need to reply a unicast based on businessType. */
CheckBusinessTypeReplyUnicast(uint8_t businessType)104 int32_t CheckBusinessTypeReplyUnicast(uint8_t businessType)
105 {
106     switch (businessType) {
107         case NSTACKX_BUSINESS_TYPE_NULL:
108             return NSTACKX_EOK;
109 
110         case NSTACKX_BUSINESS_TYPE_HICOM:
111             return NSTACKX_EOK;
112 
113         case NSTACKX_BUSINESS_TYPE_SOFTBUS:
114             return NSTACKX_EFAILED;
115 
116         case NSTACKX_BUSINESS_TYPE_NEARBY:
117             return NSTACKX_EOK;
118 
119         default: /* Unknown businessType */
120             return NSTACKX_EOK;
121     }
122 }
123 
GetDefaultDiscoverInterval(uint32_t discoverCount)124 uint32_t GetDefaultDiscoverInterval(uint32_t discoverCount)
125 {
126     if (discoverCount < COAP_FIRST_DISCOVER_COUNT_RANGE) {
127         return COAP_FIRST_DISCOVER_INTERVAL;
128     } else if (discoverCount < COAP_SECOND_DISCOVER_COUNT_RANGE) {
129         return COAP_SECOND_DISCOVER_INTERVAL;
130     } else {
131         return COAP_LAST_DISCOVER_INTERVAL;
132     }
133 }
134 
GetServiceDiscoverInfo(const uint8_t * buf,size_t size,DeviceInfo * deviceInfo,char ** remoteUrlPtr)135 int32_t GetServiceDiscoverInfo(const uint8_t *buf, size_t size, DeviceInfo *deviceInfo, char **remoteUrlPtr)
136 {
137     uint8_t *newBuf = NULL;
138     if (size <= 0) {
139         return NSTACKX_EFAILED;
140     }
141     if (buf[size - 1] != '\0') {
142         newBuf = (uint8_t *)calloc(size + 1, 1U);
143         if (newBuf == NULL) {
144             DFINDER_LOGE(TAG, "data is not end with 0 and new buf calloc error");
145             return NSTACKX_ENOMEM;
146         }
147         if (memcpy_s(newBuf, size + 1, buf, size) != EOK) {
148             DFINDER_LOGE(TAG, "data is not end with 0 and memcpy data error");
149             goto L_COAP_ERR;
150         }
151         DFINDER_LOGI(TAG, "data is not end with 0");
152         buf = newBuf;
153     }
154     if (ParseServiceDiscover(buf, deviceInfo, remoteUrlPtr) != NSTACKX_EOK) {
155         DFINDER_LOGE(TAG, "parse service discover error");
156         goto L_COAP_ERR;
157     }
158 
159     if (newBuf != NULL) {
160         free(newBuf);
161     }
162 
163     return NSTACKX_EOK;
164 L_COAP_ERR:
165     if (newBuf != NULL) {
166         free(newBuf);
167     }
168     return NSTACKX_EFAILED;
169 }
170 
ResetMainEpollTaskCount(uint8_t isBusy)171 static void ResetMainEpollTaskCount(uint8_t isBusy)
172 {
173     EpollTask *task = GetEpollTask(&g_eventNodeChain, g_epollfd);
174     if (task == NULL) {
175         return;
176     }
177     if (isBusy) {
178         DFINDER_LOGI(TAG, "in this busy interval: main epoll task count %llu", task->count);
179     }
180     task->count = 0;
181 }
182 
IsBusyInterval(uint32_t eventCount,uint32_t timeMs)183 static uint8_t IsBusyInterval(uint32_t eventCount, uint32_t timeMs)
184 {
185     uint8_t retFlag;
186     if ((uint64_t)eventCount * EVENT_COUNT_RATE_INTERVAL <
187         MAX_EVENT_PROCESS_NUM_PER_INTERVAL * (uint64_t)timeMs) {
188         retFlag = NSTACKX_FALSE;
189     } else {
190         retFlag = NSTACKX_TRUE;
191     }
192 
193     ResetMainEpollTaskCount(retFlag);
194     ResetCoapSocketTaskCount(retFlag);
195     ResetCoapDiscoverTaskCount(retFlag);
196     ResetDeviceTaskCount(retFlag);
197 #ifndef DFINDER_USE_MINI_NSTACKX
198     ResetSmartGeniusTaskCount(retFlag);
199 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
200 
201     return retFlag;
202 }
203 
CalculateEventProcessRate(void)204 static void CalculateEventProcessRate(void)
205 {
206     struct timespec now;
207     ClockGetTime(CLOCK_MONOTONIC, &now);
208     uint32_t measureElapse = GetTimeDiffMs(&now, &g_processRatePara.measureBefore);
209     if (measureElapse > EVENT_COUNT_RATE_INTERVAL) {
210         uint32_t totalCount = g_processRatePara.epollWaitEventCount + g_processRatePara.epollWaitTimeoutCount;
211         if (!IsBusyInterval(totalCount, measureElapse)) {
212             g_continuousBusyIntervals = 0;
213         } else {
214             DFINDER_LOGI(TAG, "main loop seems to be busy in the past interval. Timeout count %u, event count %u",
215                          g_processRatePara.epollWaitTimeoutCount, g_processRatePara.epollWaitEventCount);
216             g_continuousBusyIntervals++;
217             if (g_continuousBusyIntervals >= MAX_CONTINUOUS_BUSY_INTERVAL_NUM) {
218                 DFINDER_LOGE(TAG, "main loop seems to be busy in the past %u intervals. notify user to restart",
219                              g_continuousBusyIntervals);
220                 NotifyDFinderMsgRecver(DFINDER_ON_TOO_BUSY);
221                 g_continuousBusyIntervals = 0;
222             }
223         }
224         g_processRatePara.epollWaitTimeoutCount = 0;
225         g_processRatePara.epollWaitEventCount = 0;
226         ClockGetTime(CLOCK_MONOTONIC, &g_processRatePara.measureBefore);
227     }
228 }
229 
NstackMainLoop(void * arg)230 static void *NstackMainLoop(void *arg)
231 {
232     int32_t ret;
233     (void)arg;
234     (void)memset_s(&g_processRatePara, sizeof(g_processRatePara), 0, sizeof(g_processRatePara));
235     g_continuousBusyIntervals = 0;
236     ClockGetTime(CLOCK_MONOTONIC, &g_processRatePara.measureBefore);
237 #ifndef DFINDER_USE_MINI_NSTACKX
238     SetThreadName(DFINDER_THREAD_NAME);
239 #endif
240     while (g_terminateFlag == NSTACKX_FALSE) {
241 #ifndef DFINDER_USE_MINI_NSTACKX
242         uint32_t timeout = RegisterCoAPEpollTask(g_epollfd);
243         ret = EpollLoop(g_epollfd, timeout);
244 #else
245         ret = EpollLoop(g_epollfd, -1);
246 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
247         if (ret == NSTACKX_EFAILED) {
248             IncStatistics(STATS_EPOLL_ERROR);
249             DFINDER_LOGE(TAG, "epoll loop failed");
250 #ifndef DFINDER_USE_MINI_NSTACKX
251             DeRegisterCoAPEpollTask();
252 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
253             break;
254         } else if (ret == NSTACKX_ETIMEOUT) {
255             g_processRatePara.epollWaitTimeoutCount++;
256         } else if (ret > 0) {
257             g_processRatePara.epollWaitEventCount++;
258         } else {
259             /* do nothing */
260         }
261         CalculateEventProcessRate();
262 #ifndef DFINDER_USE_MINI_NSTACKX
263         DeRegisterCoAPEpollTask();
264 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
265     }
266     return NULL;
267 }
268 
GetMainLoopEpollFd(void)269 EpollDesc GetMainLoopEpollFd(void)
270 {
271     return g_epollfd;
272 }
273 
GetMainLoopEvendChain(void)274 List *GetMainLoopEvendChain(void)
275 {
276     return &g_eventNodeChain;
277 }
278 
InternalInit(EpollDesc epollfd,uint32_t maxDeviceNum)279 static int32_t InternalInit(EpollDesc epollfd, uint32_t maxDeviceNum)
280 {
281     int32_t ret = EventModuleInit(&g_eventNodeChain, g_epollfd);
282     if (ret != NSTACKX_EOK) {
283         return ret;
284     }
285 
286     ret = DeviceModuleInit(epollfd, maxDeviceNum);
287     if (ret != NSTACKX_EOK) {
288         return ret;
289     }
290 
291 #if !defined(DFINDER_SUPPORT_MULTI_NIF) && !defined(DFINDER_USE_MINI_NSTACKX)
292     ret = P2pUsbTimerInit(epollfd);
293     if (ret != NSTACKX_EOK) {
294         return ret;
295     }
296 #endif
297 
298 #ifdef _WIN32
299     ret = CoapThreadInit();
300     if (ret != NSTACKX_EOK) {
301         return ret;
302     }
303 #endif
304 
305 #ifndef DFINDER_SUPPORT_MULTI_NIF
306     ret = CoapServerInit(NULL);
307     if (ret != NSTACKX_EOK) {
308         return ret;
309     }
310 #endif
311 
312     ret = CoapDiscoverInit(epollfd);
313     if (ret != NSTACKX_EOK) {
314         return ret;
315     }
316 
317 #ifndef DFINDER_USE_MINI_NSTACKX
318     ret = SmartGeniusInit(epollfd);
319 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
320     return ret;
321 }
322 
NstackxInitInner(uint32_t maxDeviceNum)323 static int32_t NstackxInitInner(uint32_t maxDeviceNum)
324 {
325     int32_t ret;
326 #ifdef DFINDER_USE_MINI_NSTACKX
327     ret = InternalInit(g_epollfd, maxDeviceNum);
328     if (ret != NSTACKX_EOK) {
329         DFINDER_LOGE(TAG, "internal init failed");
330         return ret;
331     }
332 #endif
333     g_terminateFlag = NSTACKX_FALSE;
334     g_validTidFlag = NSTACKX_FALSE;
335 #ifndef DFINDER_USE_MINI_NSTACKX
336     ret = PthreadCreate(&g_tid, NULL, NstackMainLoop, NULL);
337     if (ret != 0) {
338         DFINDER_LOGE(TAG, "thread create failed");
339         return ret;
340     }
341 #else
342     osThreadAttr_t attr = {0};
343     attr.name = DFINDER_THREAD_NAME;
344     attr.stack_size = DFINDER_THREAD_STACK_SIZE;
345     // osPriorityNormal equals 24
346     attr.priority = osPriorityNormal;
347     g_threadId = osThreadNew((osThreadFunc_t)NstackMainLoop, NULL, &attr);
348     if (g_threadId == NULL) {
349         DFINDER_LOGE(TAG, "thread create failed with attribute settings");
350         return NSTACKX_EFAILED;
351     }
352 #endif
353     g_validTidFlag = NSTACKX_TRUE;
354 #ifndef DFINDER_USE_MINI_NSTACKX
355     ret = InternalInit(g_epollfd, maxDeviceNum);
356     if (ret != NSTACKX_EOK) {
357         DFINDER_LOGE(TAG, "internal init failed");
358         return ret;
359     }
360 #endif
361     return ret;
362 }
363 
NSTACKX_Init(const NSTACKX_Parameter * parameter)364 int32_t NSTACKX_Init(const NSTACKX_Parameter *parameter)
365 {
366     int32_t ret;
367 
368     if (g_nstackInitState != NSTACKX_INIT_STATE_START) {
369         return NSTACKX_EOK;
370     }
371 
372     g_nstackInitState = NSTACKX_INIT_STATE_ONGOING;
373     cJSON_InitHooks(NULL);
374 #ifdef ENABLE_USER_LOG
375     SetDFinderLogLevel(DFINDER_LOG_LEVEL_DEBUG);
376 #endif
377     SetLogLevel(NSTACKX_LOG_LEVEL_DEBUG);
378 
379 #ifdef NSTACKX_WITH_LITEOS
380     EpollEventPtrInit(); /* init g_epollEventPtrMutex g_epollEventPtrArray */
381 #endif
382 
383     g_epollfd = CreateEpollDesc();
384     if (!IsEpollDescValid(g_epollfd)) {
385         DFINDER_LOGE(TAG, "epoll creat fail! errno: %d", errno);
386         g_nstackInitState = NSTACKX_INIT_STATE_START;
387         return NSTACKX_EFAILED;
388     }
389 
390     DFINDER_LOGD(TAG, "nstack ctrl creat epollfd %d", REPRESENT_EPOLL_DESC(g_epollfd));
391 #ifdef DFINDER_SAVE_DEVICE_LIST
392     ret = NstackxInitInner(parameter != NULL ? parameter->maxDeviceNum : NSTACKX_DEFAULT_DEVICE_NUM);
393 #else
394     ret = NstackxInitInner(parameter != NULL ? parameter->maxDeviceNum : NSTACKX_MAX_DEVICE_NUM);
395 #endif
396     if (ret != NSTACKX_EOK) {
397         goto L_ERR_INIT;
398     }
399     (void)memset_s(&g_parameter, sizeof(g_parameter), 0, sizeof(g_parameter));
400     if (parameter != NULL) {
401         (void)memcpy_s(&g_parameter, sizeof(g_parameter), parameter, sizeof(NSTACKX_Parameter));
402     }
403 
404 #ifndef DFINDER_USE_MINI_NSTACKX
405     CoapInitSubscribeModuleInner(); /* initialize subscribe module number */
406 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
407 
408     g_nstackInitState = NSTACKX_INIT_STATE_DONE;
409     DFINDER_LOGI(TAG, "DFinder init successfully");
410     return NSTACKX_EOK;
411 
412 L_ERR_INIT:
413     NSTACKX_Deinit();
414     return ret;
415 }
416 
417 #ifdef DFINDER_USE_MINI_NSTACKX
ReportMainLoopStopInner(void * argument)418 static void ReportMainLoopStopInner(void *argument)
419 {
420     (void)argument;
421     LOGI(TAG, "receive message to stop main loop");
422 }
423 
ReportMainLoopStop(void)424 static void ReportMainLoopStop(void)
425 {
426     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
427         LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
428         return;
429     }
430     if (PostEvent(&g_eventNodeChain, g_epollfd, ReportMainLoopStopInner, NULL) != NSTACKX_EOK) {
431         LOGE(TAG, "Failed to report mainloop stop!");
432     }
433 }
434 #endif
435 
NSTACKX_Deinit(void)436 void NSTACKX_Deinit(void)
437 {
438     if (g_nstackInitState == NSTACKX_INIT_STATE_START) {
439         return;
440     }
441     if (g_validTidFlag) {
442         g_terminateFlag = NSTACKX_TRUE;
443 #ifndef DFINDER_USE_MINI_NSTACKX
444         PthreadJoin(g_tid, NULL);
445 #else
446         ReportMainLoopStop();
447         if (osThreadTerminate(g_threadId) != osOK) {
448             LOGE(TAG, "os thread terminate failed");
449         }
450 #endif
451         g_validTidFlag = NSTACKX_FALSE;
452     }
453 #ifndef DFINDER_USE_MINI_NSTACKX
454     SmartGeniusClean();
455 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
456     CoapDiscoverDeinit();
457 #ifdef DFINDER_SUPPORT_MULTI_NIF
458     for (uint32_t i = 0; i < NSTACKX_MAX_LISTENED_NIF_NUM; ++i) {
459         DFINDER_LOGE(TAG, "nstackx_deinit nif with idx-%u", i);
460         CoapServerDestroyWithIdx(i);
461     }
462 #else
463 #ifndef DFINDER_USE_MINI_NSTACKX
464     DestroyP2pUsbServerInitRetryTimer();
465 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
466     CoapServerDestroy();
467 #ifndef DFINDER_USE_MINI_NSTACKX
468     CoapP2pServerDestroy();
469     CoapUsbServerDestroy();
470 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
471 #endif /* END OF DFINDER_SUPPORT_MULTI_NIF */
472 #ifdef _WIN32
473     CoapThreadDestory();
474 #endif
475     DeviceModuleClean();
476     EventNodeChainClean(&g_eventNodeChain);
477     if (IsEpollDescValid(g_epollfd)) {
478         CloseEpollDesc(g_epollfd);
479         g_epollfd = INVALID_EPOLL_DESC;
480     }
481     ResetStatistics();
482     ResetEventFunc();
483     g_nstackInitState = NSTACKX_INIT_STATE_START;
484     DFINDER_LOGI(TAG, "deinit successfully");
485 }
486 
DeviceDiscoverInner(void * argument)487 static void DeviceDiscoverInner(void *argument)
488 {
489     (void)argument;
490     CoapServiceDiscoverInner(INNER_DISCOVERY);
491 
492 #ifdef DFINDER_SUPPORT_MULTI_NIF
493     if (!IsApConnected()) {
494         DFINDER_LOGE(TAG, "all ap not connected, notify user with empty list");
495         NotifyDeviceFound(NULL, 0);
496     }
497 #else
498     /* If both Wifi AP and BLE are disabled, we should also notify user, with empty list. */
499     if (!IsWifiApConnected()) {
500         NotifyDeviceFound(NULL, 0);
501     }
502 #endif
503 }
504 
DeviceDiscoverInnerAn(void * argument)505 static void DeviceDiscoverInnerAn(void *argument)
506 {
507     (void)argument;
508     CoapServiceDiscoverInnerAn(INNER_DISCOVERY);
509 }
510 
DeviceDiscoverInnerConfigurable(void * argument)511 static void DeviceDiscoverInnerConfigurable(void *argument)
512 {
513     NSTACKX_DiscoverySettings *discoverySettings = argument;
514     if (discoverySettings->businessType != GetLocalDeviceInfoPtr()->businessType) {
515         DFINDER_LOGE(TAG, "businessType is diff when check discover settings");
516         free(discoverySettings->businessData);
517         free(discoverySettings);
518         return;
519     }
520     ConfigureDiscoverySettings(discoverySettings);
521     free(discoverySettings->businessData);
522     free(discoverySettings);
523     CoapServiceDiscoverInnerConfigurable(INNER_DISCOVERY);
524 }
525 
DeviceDiscoverStopInner(void * argument)526 static void DeviceDiscoverStopInner(void *argument)
527 {
528     (void)argument;
529     CoapServiceDiscoverStopInner();
530     NotifyStatisticsEvent();
531 }
532 
NSTACKX_StartDeviceFind(void)533 int32_t NSTACKX_StartDeviceFind(void)
534 {
535     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
536         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
537         return NSTACKX_EFAILED;
538     }
539     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInner, NULL) != NSTACKX_EOK) {
540         DFINDER_LOGE(TAG, "Failed to start device discover!");
541         return NSTACKX_EFAILED;
542     }
543     return NSTACKX_EOK;
544 }
545 
NSTACKX_StartDeviceFindAn(uint8_t mode)546 int32_t NSTACKX_StartDeviceFindAn(uint8_t mode)
547 {
548     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
549         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
550         return NSTACKX_EFAILED;
551     }
552     SetModeInfo(mode);
553     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerAn, NULL) != NSTACKX_EOK) {
554         DFINDER_LOGE(TAG, "Failed to start device discover!");
555         return NSTACKX_EFAILED;
556     }
557     return NSTACKX_EOK;
558 }
559 
NSTACKX_StopDeviceFind(void)560 int32_t NSTACKX_StopDeviceFind(void)
561 {
562     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
563         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
564         return NSTACKX_EFAILED;
565     }
566     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverStopInner, NULL) != NSTACKX_EOK) {
567         DFINDER_LOGE(TAG, "Failed to stop device discover!");
568         return NSTACKX_EFAILED;
569     }
570     return NSTACKX_EOK;
571 }
572 
CopyDiscoverySettings(NSTACKX_DiscoverySettings * dupDiscoverySettings,const NSTACKX_DiscoverySettings * discoverySettings)573 static int32_t CopyDiscoverySettings(NSTACKX_DiscoverySettings *dupDiscoverySettings,
574                                      const NSTACKX_DiscoverySettings *discoverySettings)
575 {
576     dupDiscoverySettings->businessType = discoverySettings->businessType;
577     dupDiscoverySettings->discoveryMode = discoverySettings->discoveryMode;
578     dupDiscoverySettings->length = discoverySettings->length;
579     if (discoverySettings->businessData != NULL) {
580         if (strncpy_s(dupDiscoverySettings->businessData, (dupDiscoverySettings->length + 1),
581             discoverySettings->businessData, discoverySettings->length) != EOK) {
582             DFINDER_LOGE(TAG, "businessData strncpy failed");
583             return NSTACKX_EINVAL;
584         }
585     }
586     dupDiscoverySettings->advertiseCount = discoverySettings->advertiseCount;
587     dupDiscoverySettings->advertiseDuration = discoverySettings->advertiseDuration;
588     return NSTACKX_EOK;
589 }
590 
CheckDiscoverySettings(const NSTACKX_DiscoverySettings * discoverySettings)591 static int32_t CheckDiscoverySettings(const NSTACKX_DiscoverySettings *discoverySettings)
592 {
593     if (discoverySettings == NULL) {
594         DFINDER_LOGE(TAG, "Invalid discoverySettings info");
595         return NSTACKX_EINVAL;
596     }
597     if ((discoverySettings->businessData == NULL) && (discoverySettings->length != 0)) {
598         DFINDER_LOGE(TAG, "Invalid discoverySettings bData info");
599         return NSTACKX_EINVAL;
600     }
601     if (discoverySettings->length >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
602         DFINDER_LOGE(TAG, "businessData length is too long");
603         return NSTACKX_EINVAL;
604     }
605     uint32_t advertiseCount = discoverySettings->advertiseCount;
606     uint32_t advertiseDuration = discoverySettings->advertiseDuration;
607     if ((advertiseCount == 0) && (advertiseDuration == 0)) {
608         return NSTACKX_EOK;
609     }
610     if ((advertiseCount < NSTACKX_MIN_ADVERTISE_COUNT) || (advertiseCount > NSTACKX_MAX_ADVERTISE_COUNT) ||
611         (advertiseDuration < NSTACKX_MIN_ADVERTISE_DURATION) || (advertiseDuration > NSTACKX_MAX_ADVERTISE_DURATION)) {
612         DFINDER_LOGE(TAG, "Invalid discoverySettings advertise info");
613         return NSTACKX_EINVAL;
614     }
615     return NSTACKX_EOK;
616 }
617 
NSTACKX_StartDeviceDiscovery(const NSTACKX_DiscoverySettings * discoverySettings)618 int32_t NSTACKX_StartDeviceDiscovery(const NSTACKX_DiscoverySettings *discoverySettings)
619 {
620     DFINDER_LOGI(TAG, "begin to NSTACKX_StartDeviceDiscovery!");
621     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
622         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
623         return NSTACKX_EFAILED;
624     }
625     if (CheckDiscoverySettings(discoverySettings) != NSTACKX_EOK) {
626         return NSTACKX_EINVAL;
627     }
628 
629     NSTACKX_DiscoverySettings *dupDiscoverySettings = malloc(sizeof(NSTACKX_DiscoverySettings));
630     if (dupDiscoverySettings == NULL) {
631         DFINDER_LOGE(TAG, "malloc failed");
632         return NSTACKX_ENOMEM;
633     }
634     dupDiscoverySettings->businessData = (char *)calloc((discoverySettings->length + 1), sizeof(char));
635     if (dupDiscoverySettings->businessData == NULL) {
636         DFINDER_LOGE(TAG, "businessData calloc fail");
637         free(dupDiscoverySettings);
638         return NSTACKX_ENOMEM;
639     }
640     if (CopyDiscoverySettings(dupDiscoverySettings, discoverySettings) != NSTACKX_EOK) {
641         free(dupDiscoverySettings->businessData);
642         free(dupDiscoverySettings);
643         return NSTACKX_EINVAL;
644     }
645 
646     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerConfigurable, dupDiscoverySettings) != NSTACKX_EOK) {
647         DFINDER_LOGE(TAG, "Failed to start device discover!");
648         free(dupDiscoverySettings->businessData);
649         free(dupDiscoverySettings);
650         return NSTACKX_EFAILED;
651     }
652     return NSTACKX_EOK;
653 }
654 
655 #ifndef DFINDER_USE_MINI_NSTACKX
SubscribeModuleInner(void * argument)656 static void SubscribeModuleInner(void *argument)
657 {
658     (void)argument;
659     CoapSubscribeModuleInner(INNER_DISCOVERY);
660 }
661 
NSTACKX_SubscribeModule(void)662 int32_t NSTACKX_SubscribeModule(void)
663 {
664     if (g_nstackInitState != 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, SubscribeModuleInner, NULL) != NSTACKX_EOK) {
669         DFINDER_LOGE(TAG, "Failed to subscribe module!");
670         return NSTACKX_EFAILED;
671     }
672     return NSTACKX_EOK;
673 }
674 
UnsubscribeModuleInner(void * argument)675 static void UnsubscribeModuleInner(void *argument)
676 {
677     (void)argument;
678     CoapUnsubscribeModuleInner(INNER_DISCOVERY);
679 }
680 
NSTACKX_UnsubscribeModule(void)681 int32_t NSTACKX_UnsubscribeModule(void)
682 {
683     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
684         return NSTACKX_EFAILED;
685     }
686 
687     if (PostEvent(&g_eventNodeChain, g_epollfd, UnsubscribeModuleInner, NULL) != NSTACKX_EOK) {
688         return NSTACKX_EFAILED;
689     }
690     return NSTACKX_EOK;
691 }
692 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
693 
ConfigureLocalDeviceInfoInner(void * argument)694 static void ConfigureLocalDeviceInfoInner(void *argument)
695 {
696     NSTACKX_LocalDeviceInfo *localDeviceInfo = argument;
697 
698     ConfigureLocalDeviceInfo(localDeviceInfo);
699     free(localDeviceInfo);
700 }
701 
ConfigureLocalDeviceNameInner(void * argument)702 static void ConfigureLocalDeviceNameInner(void *argument)
703 {
704     char *localDevName = (char *)argument;
705 
706     ConfigureLocalDeviceName(localDevName);
707     free(localDevName);
708 }
709 
710 #ifndef _WIN32
VerifyNifNameIp(const char * networkName,const char * networkIp,uint32_t * matchCnt)711 static int32_t VerifyNifNameIp(const char *networkName, const char *networkIp, uint32_t *matchCnt)
712 {
713     if (networkName == NULL || networkIp == NULL || matchCnt == NULL) {
714         DFINDER_LOGE(TAG, "invalid nif info passed in");
715         return NSTACKX_EINVAL;
716     }
717     struct in_addr ipAddr;
718     if (inet_pton(AF_INET, networkIp, &ipAddr) != 1) {
719         return NSTACKX_EINVAL;
720     }
721     ++(*matchCnt);
722     return NSTACKX_EOK;
723 }
724 
CheckNifInfoPassedIn(const NSTACKX_LocalDeviceInfo * localDeviceInfo)725 static int32_t CheckNifInfoPassedIn(const NSTACKX_LocalDeviceInfo *localDeviceInfo)
726 {
727     uint32_t matchCnt = 0;
728 #ifdef DFINDER_SUPPORT_MULTI_NIF
729     for (uint32_t i = 0; i < localDeviceInfo->ifNums; ++i) {
730         if (VerifyNifNameIp(localDeviceInfo->localIfInfo[i].networkName,
731             localDeviceInfo->localIfInfo[i].networkIpAddr, &matchCnt) != NSTACKX_EOK) {
732             return NSTACKX_EFAILED;
733         }
734     }
735     return (matchCnt == localDeviceInfo->ifNums) ? NSTACKX_EOK : NSTACKX_EFAILED;
736 #else
737     int32_t verifyResult;
738     if (localDeviceInfo->ifNums == 0) {
739         verifyResult = VerifyNifNameIp(localDeviceInfo->networkName, localDeviceInfo->networkIpAddr, &matchCnt);
740         return verifyResult;
741     } else {
742         verifyResult = VerifyNifNameIp(localDeviceInfo->localIfInfo[0].networkName,
743             localDeviceInfo->localIfInfo[0].networkIpAddr, &matchCnt);
744         if ((verifyResult == NSTACKX_EOK) && (matchCnt == localDeviceInfo->ifNums)) {
745             return NSTACKX_EOK;
746         }
747         return NSTACKX_EFAILED;
748     }
749 #endif
750 }
751 #endif
752 
753 #ifndef DFINDER_SUPPORT_MULTI_NIF
CopyNifNameAndIp(NSTACKX_LocalDeviceInfo * destDev,const NSTACKX_LocalDeviceInfo * srcDev)754 static int32_t CopyNifNameAndIp(NSTACKX_LocalDeviceInfo *destDev, const NSTACKX_LocalDeviceInfo *srcDev)
755 {
756     if (destDev == NULL || srcDev == NULL) {
757         DFINDER_LOGE(TAG, "invalid device info passed in");
758         return NSTACKX_EINVAL;
759     }
760     if (srcDev->ifNums != 0) {
761         if (strcpy_s(destDev->networkName, NSTACKX_MAX_INTERFACE_NAME_LEN, srcDev->localIfInfo[0].networkName) != EOK) {
762             DFINDER_LOGE(TAG, "network name strcpy failed");
763             return NSTACKX_EFAILED;
764         }
765         if (strcpy_s(destDev->networkIpAddr, NSTACKX_MAX_IP_STRING_LEN, srcDev->localIfInfo[0].networkIpAddr) != EOK) {
766             DFINDER_LOGE(TAG, "network ip strcpy failed");
767             return NSTACKX_EFAILED;
768         }
769     }
770     return NSTACKX_EOK;
771 }
772 #endif
773 
NSTACKX_RegisterDevice(const NSTACKX_LocalDeviceInfo * localDeviceInfo)774 int32_t NSTACKX_RegisterDevice(const NSTACKX_LocalDeviceInfo *localDeviceInfo)
775 {
776     DFINDER_LOGI(TAG, "begin to NSTACKX_RegisterDevice!");
777     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
778         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
779         return NSTACKX_EFAILED;
780     }
781 
782     if (localDeviceInfo == NULL) {
783         DFINDER_LOGE(TAG, "Invalid local device info");
784         return NSTACKX_EINVAL;
785     }
786 
787 #ifdef DFINDER_SUPPORT_MULTI_NIF
788     if (localDeviceInfo->ifNums > NSTACKX_MAX_LISTENED_NIF_NUM || localDeviceInfo->ifNums == 0) {
789 #else
790     if (localDeviceInfo->ifNums > NSTACKX_MAX_LISTENED_NIF_NUM) {
791 #endif
792         DFINDER_LOGE(TAG, "Invalid ifNums %hhu", localDeviceInfo->ifNums);
793         return NSTACKX_EINVAL;
794     }
795 #ifndef _WIN32
796     if (CheckNifInfoPassedIn(localDeviceInfo) != NSTACKX_EOK) {
797         DFINDER_LOGE(TAG, "check nif info passed in return fail");
798         return NSTACKX_EFAILED;
799     }
800 #endif
801     NSTACKX_LocalDeviceInfo *dupLocalDeviceInfo = malloc(sizeof(NSTACKX_LocalDeviceInfo));
802     if (dupLocalDeviceInfo == NULL) {
803         return NSTACKX_ENOMEM;
804     }
805 
806     if (memcpy_s(dupLocalDeviceInfo, sizeof(NSTACKX_LocalDeviceInfo),
807         localDeviceInfo, sizeof(NSTACKX_LocalDeviceInfo)) != EOK) {
808         DFINDER_LOGE(TAG, "memcpy failed");
809         goto L_ERROR;
810     }
811 #ifndef DFINDER_SUPPORT_MULTI_NIF
812     if (CopyNifNameAndIp(dupLocalDeviceInfo, localDeviceInfo) != NSTACKX_EOK) {
813         goto L_ERROR;
814     }
815 #endif
816     if (PostEvent(&g_eventNodeChain, g_epollfd, ConfigureLocalDeviceInfoInner, dupLocalDeviceInfo) != NSTACKX_EOK) {
817         DFINDER_LOGE(TAG, "Failed to configure local device info!");
818         goto L_ERROR;
819     }
820     return NSTACKX_EOK;
821 L_ERROR:
822     free(dupLocalDeviceInfo);
823     return NSTACKX_EFAILED;
824 }
825 
826 int32_t NSTACKX_RegisterDeviceName(const char *devName)
827 {
828     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
829         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
830         return NSTACKX_EFAILED;
831     }
832     if (devName == NULL || devName[0] == '\0') {
833         DFINDER_LOGE(TAG, "register local device name is invalid");
834         return NSTACKX_EFAILED;
835     }
836     char *dupDevName = (char *)malloc(sizeof(char) * NSTACKX_MAX_DEVICE_NAME_LEN);
837     if (dupDevName == NULL) {
838         return NSTACKX_ENOMEM;
839     }
840     if (strncpy_s(dupDevName, NSTACKX_MAX_DEVICE_NAME_LEN, devName, strlen(devName)) != EOK) {
841         DFINDER_LOGE(TAG, "strncpy dupDevName failed");
842         free(dupDevName);
843         return NSTACKX_EFAILED;
844     }
845     if (PostEvent(&g_eventNodeChain, g_epollfd, ConfigureLocalDeviceNameInner, dupDevName) != NSTACKX_EOK) {
846         DFINDER_LOGE(TAG, "Failed to configure local device name!");
847         free(dupDevName);
848         return NSTACKX_EFAILED;
849     }
850     return NSTACKX_EOK;
851 }
852 
853 int32_t NSTACKX_RegisterDeviceAn(const NSTACKX_LocalDeviceInfo *localDeviceInfo, uint64_t deviceHash)
854 {
855     NSTACKX_LocalDeviceInfo *dupLocalDeviceInfo = NULL;
856 
857     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
858         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
859         return NSTACKX_EFAILED;
860     }
861 
862     if (localDeviceInfo == NULL) {
863         DFINDER_LOGE(TAG, "Invalid local device info");
864         return NSTACKX_EINVAL;
865     }
866 
867     dupLocalDeviceInfo = malloc(sizeof(NSTACKX_LocalDeviceInfo));
868     if (dupLocalDeviceInfo == NULL) {
869         return NSTACKX_ENOMEM;
870     }
871 
872     if (memcpy_s(dupLocalDeviceInfo, sizeof(NSTACKX_LocalDeviceInfo),
873         localDeviceInfo, sizeof(NSTACKX_LocalDeviceInfo)) != EOK) {
874         free(dupLocalDeviceInfo);
875         return NSTACKX_EFAILED;
876     }
877     if (PostEvent(&g_eventNodeChain, g_epollfd, ConfigureLocalDeviceInfoInner, dupLocalDeviceInfo) != NSTACKX_EOK) {
878         DFINDER_LOGE(TAG, "Failed to configure local device info!");
879         free(dupLocalDeviceInfo);
880         return NSTACKX_EFAILED;
881     }
882     SetDeviceHash(deviceHash);
883     return NSTACKX_EOK;
884 }
885 
886 typedef struct {
887     uint32_t capabilityBitmapNum;
888     uint32_t capabilityBitmap[NSTACKX_MAX_CAPABILITY_NUM];
889 } CapabilityProcessData;
890 
891 static void RegisterCapabilityInner(void *argument)
892 {
893     LOGI(TAG, "Register Capability Inner");
894     CapabilityProcessData *capabilityData = argument;
895 
896     RegisterCapability(capabilityData->capabilityBitmapNum, capabilityData->capabilityBitmap);
897     free(capabilityData);
898 }
899 
900 static void SetFilterCapabilityInner(void *argument)
901 {
902     CapabilityProcessData *capabilityData = argument;
903 
904     SetFilterCapability(capabilityData->capabilityBitmapNum, capabilityData->capabilityBitmap);
905     free(capabilityData);
906 }
907 
908 static int32_t NSTACKX_CapabilityHandle(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[], EventHandle handle)
909 {
910     CapabilityProcessData *capabilityData = NULL;
911 
912     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
913         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
914         return NSTACKX_EFAILED;
915     }
916 
917     if (capabilityBitmapNum > NSTACKX_MAX_CAPABILITY_NUM) {
918         DFINDER_LOGE(TAG, "capabilityBitmapNum (%u) exceed max number", capabilityBitmapNum);
919         return NSTACKX_EINVAL;
920     }
921 
922     capabilityData = calloc(1U, sizeof(CapabilityProcessData));
923     if (capabilityData == NULL) {
924         return NSTACKX_ENOMEM;
925     }
926 
927     if ((capabilityBitmapNum != 0) && memcpy_s(capabilityData->capabilityBitmap,
928         sizeof(capabilityData->capabilityBitmap), capabilityBitmap, capabilityBitmapNum * sizeof(uint32_t)) != EOK) {
929         free(capabilityData);
930         return NSTACKX_EINVAL;
931     }
932     capabilityData->capabilityBitmapNum = capabilityBitmapNum;
933 
934     if (PostEvent(&g_eventNodeChain, g_epollfd, handle, capabilityData) != NSTACKX_EOK) {
935         DFINDER_LOGE(TAG, "Failed to register capability!");
936         free(capabilityData);
937         return NSTACKX_EFAILED;
938     }
939     return NSTACKX_EOK;
940 }
941 
942 int32_t NSTACKX_RegisterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
943 {
944     DFINDER_LOGI(TAG, "Register Capability");
945     return NSTACKX_CapabilityHandle(capabilityBitmapNum, capabilityBitmap, RegisterCapabilityInner);
946 }
947 
948 int32_t NSTACKX_SetFilterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
949 {
950     DFINDER_LOGI(TAG, "Set Filter Capability");
951     return NSTACKX_CapabilityHandle(capabilityBitmapNum, capabilityBitmap, SetFilterCapabilityInner);
952 }
953 
954 static void RegisterServiceDataInner(void *argument)
955 {
956     LOGI(TAG, "Register Service Data Inner");
957     char *serviceData = argument;
958     if (RegisterServiceData(serviceData) != NSTACKX_EOK) {
959         DFINDER_LOGE(TAG, "RegisterServiceData failed");
960     }
961     free(serviceData);
962 }
963 
964 int32_t NSTACKX_RegisterServiceData(const char *serviceData)
965 {
966     LOGI(TAG, "Register Service Data");
967     char *serviceDataTmp = NULL;
968 
969     if (serviceData == NULL) {
970         DFINDER_LOGE(TAG, "serviceData is null");
971         return NSTACKX_EINVAL;
972     }
973     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
974         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
975         return NSTACKX_EFAILED;
976     }
977     if (strlen(serviceData) >= NSTACKX_MAX_SERVICE_DATA_LEN) {
978         DFINDER_LOGE(TAG, "serviceData (%u) exceed max number", strlen(serviceData));
979         return NSTACKX_EINVAL;
980     }
981 
982     serviceDataTmp = calloc(1U, NSTACKX_MAX_SERVICE_DATA_LEN);
983     if (serviceDataTmp == NULL) {
984         return NSTACKX_ENOMEM;
985     }
986     if (strncpy_s(serviceDataTmp, NSTACKX_MAX_SERVICE_DATA_LEN, serviceData, strlen(serviceData)) != EOK) {
987         DFINDER_LOGE(TAG, "Failed to copy serviceData");
988         free(serviceDataTmp);
989         return NSTACKX_EINVAL;
990     }
991     if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterServiceDataInner, serviceDataTmp) != NSTACKX_EOK) {
992         DFINDER_LOGE(TAG, "Failed to register serviceData!");
993         free(serviceDataTmp);
994         return NSTACKX_EFAILED;
995     }
996     return NSTACKX_EOK;
997 }
998 
999 #ifndef DFINDER_USE_MINI_NSTACKX
1000 static void RegisterExtendServiceDataInner(void *argument)
1001 {
1002     char *extendServiceData = argument;
1003     if (RegisterExtendServiceData(extendServiceData) != NSTACKX_EOK) {
1004         DFINDER_LOGE(TAG, "RegisterExtendServiceData failed");
1005     }
1006     free(extendServiceData);
1007 }
1008 
1009 int32_t NSTACKX_RegisterExtendServiceData(const char *extendServiceData)
1010 {
1011     char *extendServiceDataTmp = NULL;
1012 
1013     if (extendServiceData == NULL) {
1014         DFINDER_LOGE(TAG, "extendServiceData is null");
1015         return NSTACKX_EINVAL;
1016     }
1017     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1018         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1019         return NSTACKX_EFAILED;
1020     }
1021     if (strlen(extendServiceData) >= NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN) {
1022         DFINDER_LOGE(TAG, "extendServiceData (%u) exceed max number", strlen(extendServiceData));
1023         return NSTACKX_EINVAL;
1024     }
1025 
1026     extendServiceDataTmp = calloc(1, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN);
1027     if (extendServiceDataTmp == NULL) {
1028         return NSTACKX_ENOMEM;
1029     }
1030     if (strncpy_s(extendServiceDataTmp, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN, extendServiceData,
1031         strlen(extendServiceData)) != EOK) {
1032         DFINDER_LOGE(TAG, "Failed to copy extendServiceData");
1033         free(extendServiceDataTmp);
1034         return NSTACKX_EINVAL;
1035     }
1036     if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterExtendServiceDataInner, extendServiceDataTmp) != NSTACKX_EOK) {
1037         DFINDER_LOGE(TAG, "Failed to register extendServiceData!");
1038         free(extendServiceDataTmp);
1039         return NSTACKX_EFAILED;
1040     }
1041     return NSTACKX_EOK;
1042 }
1043 
1044 #ifndef DFINDER_SUPPORT_MULTI_NIF
1045 static void SendMsgInner(void *arg)
1046 {
1047     MsgCtx *msg = arg;
1048     if (msg == NULL) {
1049         DFINDER_LOGE(TAG, "SendMsgInner: msg is NULL");
1050         return;
1051     }
1052     if (strlen(msg->p2pAddr) != 0) {
1053         DFINDER_LOGD(TAG, "Enter WifiDirect send");
1054         msg->err = CoapSendServiceMsgWithDefiniteTargetIp(msg, NULL);
1055     } else {
1056 #ifdef DFINDER_SAVE_DEVICE_LIST
1057         DeviceInfo *deviceInfo = GetDeviceInfoById(msg->deviceId, GetDeviceDB());
1058         if (deviceInfo == NULL) {
1059             DFINDER_LOGW(TAG, "no device found in device list, try to find in backup");
1060             deviceInfo = GetDeviceInfoById(msg->deviceId, GetDeviceDBBackup());
1061             if (deviceInfo == NULL) {
1062                 DFINDER_LOGE(TAG, "no device found in device list backup yet");
1063             }
1064         }
1065         msg->err = CoapSendServiceMsg(msg, deviceInfo);
1066 #else
1067         DFINDER_LOGE(TAG, "Invalid p2pAddr");
1068         msg->err = NSTACKX_EINVAL;
1069 #endif /* #ifdef DFINDER_SAVE_DEVICE_LIST */
1070     }
1071     SemPost(&msg->wait);
1072 }
1073 
1074 static int32_t NSTACKX_SendMsgParamCheck(const char *moduleName, const char *deviceId, const uint8_t *data,
1075     uint32_t len)
1076 {
1077     if (moduleName == NULL || strlen(moduleName) > NSTACKX_MAX_MODULE_NAME_LEN) {
1078         DFINDER_LOGE(TAG, "Invalid module name");
1079         return NSTACKX_EINVAL;
1080     }
1081 
1082     if (deviceId == NULL || strlen(deviceId) > NSTACKX_MAX_DEVICE_ID_LEN) {
1083         DFINDER_LOGE(TAG, "Invalid device id");
1084         return NSTACKX_EINVAL;
1085     }
1086 
1087     if (data == NULL || len == 0 || len > NSTACKX_MAX_SENDMSG_DATA_LEN) {
1088         DFINDER_LOGE(TAG, "Null data to send");
1089         return NSTACKX_EINVAL;
1090     }
1091     return NSTACKX_EOK;
1092 }
1093 
1094 static MsgCtx *NSTACKX_GetMsgCtx(const char *moduleName, const char *deviceId, const uint8_t *data,
1095     uint32_t len, const char *ipaddr, uint8_t type)
1096 {
1097     MsgCtx *msg = NULL;
1098 
1099     msg = calloc(1U, sizeof(MsgCtx));
1100     if (msg == NULL) {
1101         DFINDER_LOGE(TAG, "MsgCtx malloc fail");
1102         return NULL;
1103     }
1104     if ((strcpy_s(msg->deviceId, sizeof(msg->deviceId), deviceId) != EOK) ||
1105         (strcpy_s(msg->moduleName, sizeof(msg->moduleName), moduleName) != EOK)) {
1106         DFINDER_LOGE(TAG, "Cpy deviceId fail");
1107         goto FAILED;
1108     }
1109     if (ipaddr != NULL) {
1110         if (strcpy_s(msg->p2pAddr, sizeof(msg->p2pAddr), ipaddr) != EOK) {
1111             DFINDER_LOGE(TAG, "Cpy p2pAddr fail.");
1112             goto FAILED;
1113         }
1114     }
1115     msg->data = malloc(len);
1116     if (msg->data == NULL) {
1117         DFINDER_LOGE(TAG, "Msg data malloc fail");
1118         goto FAILED;
1119     }
1120     if (memcpy_s(msg->data, len, data, len) != EOK) {
1121         DFINDER_LOGE(TAG, "Msg data memcpy error");
1122         goto FAILED;
1123     }
1124     msg->len = len;
1125     msg->type = type;
1126     msg->err = NSTACKX_EOK;
1127     if (SemInit(&(msg->wait), 0, 0)) {
1128         DFINDER_LOGE(TAG, "sem init fail");
1129         goto FAILED;
1130     }
1131 
1132     return msg;
1133 FAILED:
1134     free(msg->data);
1135     free(msg);
1136     return NULL;
1137 }
1138 #endif /* #ifndef DFINDER_SUPPORT_MULTI_NIF */
1139 
1140 int32_t NSTACKX_SendMsgDirect(const char *moduleName, const char *deviceId, const uint8_t *data,
1141     uint32_t len, const char *ipaddr, uint8_t type)
1142 {
1143 #ifdef DFINDER_SUPPORT_MULTI_NIF
1144     (void)moduleName;
1145     (void)deviceId;
1146     (void)data;
1147     (void)len;
1148     (void)ipaddr;
1149     (void)type;
1150     DFINDER_LOGE(TAG, "Do not support SendMsgDirect");
1151     return NSTACKX_EFAILED;
1152 #else
1153     MsgCtx *msg = NULL;
1154     int32_t ret = NSTACKX_EOK;
1155     DFINDER_LOGD(TAG, "NSTACKX_SendMsgDirect");
1156     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1157         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1158         return NSTACKX_EFAILED;
1159     }
1160     if (ipaddr == NULL) {
1161         DFINDER_LOGE(TAG, "ipaddr needed");
1162         return NSTACKX_EINVAL;
1163     }
1164     if (NSTACKX_SendMsgParamCheck(moduleName, deviceId, data, len) != NSTACKX_EOK) {
1165         return NSTACKX_EINVAL;
1166     }
1167     msg = NSTACKX_GetMsgCtx(moduleName, deviceId, data, len, ipaddr, type);
1168     if (msg == NULL) {
1169         return NSTACKX_EFAILED;
1170     }
1171     if (PostEvent(&g_eventNodeChain, g_epollfd, SendMsgInner, msg) != NSTACKX_EOK) {
1172         DFINDER_LOGE(TAG, "Failed to send msg");
1173         ret = NSTACKX_EFAILED;
1174     }
1175     if (ret == NSTACKX_EOK) {
1176         SemWait(&(msg->wait));
1177         ret = msg->err;
1178     }
1179     SemDestroy(&(msg->wait));
1180     free(msg->data);
1181     free(msg);
1182     return ret;
1183 #endif /* #ifdef DFINDER_SUPPORT_MULTI_NIF */
1184 }
1185 
1186 int32_t NSTACKX_SendMsg(const char *moduleName, const char *deviceId, const uint8_t *data, uint32_t len)
1187 {
1188 #ifdef DFINDER_SUPPORT_MULTI_NIF
1189     (void)moduleName;
1190     (void)deviceId;
1191     (void)data;
1192     (void)len;
1193     DFINDER_LOGE(TAG, "Do not support SendMsgDirect");
1194     return NSTACKX_EFAILED;
1195 #else
1196 #ifdef DFINDER_SAVE_DEVICE_LIST
1197     int32_t ret = NSTACKX_EOK;
1198     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1199         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1200         return NSTACKX_EFAILED;
1201     }
1202     if (NSTACKX_SendMsgParamCheck(moduleName, deviceId, data, len) != NSTACKX_EOK) {
1203         return NSTACKX_EINVAL;
1204     }
1205     MsgCtx *msg = NSTACKX_GetMsgCtx(moduleName, deviceId, data, len, NULL, SERVER_TYPE_WLANORETH);
1206     if (msg == NULL) {
1207         return NSTACKX_EFAILED;
1208     }
1209     if (PostEvent(&g_eventNodeChain, g_epollfd, SendMsgInner, msg) != NSTACKX_EOK) {
1210         DFINDER_LOGE(TAG, "failed to send msg");
1211         ret = NSTACKX_EFAILED;
1212     }
1213     if (ret == NSTACKX_EOK) {
1214         SemWait(&(msg->wait));
1215         ret = msg->err;
1216     }
1217     SemDestroy(&(msg->wait));
1218     free(msg->data);
1219     free(msg);
1220     return ret;
1221 #else
1222     (void)moduleName;
1223     (void)deviceId;
1224     (void)data;
1225     (void)len;
1226 
1227     DFINDER_LOGE(TAG, "SendMsg not supported");
1228 
1229     return NSTACKX_EFAILED;
1230 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
1231 #endif /* #ifdef DFINDER_SUPPORT_MULTI_NIF */
1232 }
1233 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
1234 
1235 static void SendDiscoveryRspInner(void *arg)
1236 {
1237     NSTACKX_ResponseSettings *responseSettings = arg;
1238     if (responseSettings->businessType != GetLocalDeviceInfoPtr()->businessType) {
1239         DFINDER_LOGE(TAG, "businessType is diff when check response settings");
1240         free(responseSettings->businessData);
1241         free(responseSettings);
1242         return;
1243     }
1244     SendDiscoveryRsp(responseSettings);
1245     free(responseSettings->businessData);
1246     free(responseSettings);
1247 }
1248 
1249 static int32_t CopyResponseSettings(NSTACKX_ResponseSettings *dupResponseSettings,
1250                                     const NSTACKX_ResponseSettings *responseSettings)
1251 {
1252     dupResponseSettings->businessType = responseSettings->businessType;
1253     dupResponseSettings->length = responseSettings->length;
1254     if (responseSettings->businessData != NULL) {
1255         if (strncpy_s(dupResponseSettings->businessData, (dupResponseSettings->length + 1),
1256             responseSettings->businessData, responseSettings->length) != EOK) {
1257             DFINDER_LOGE(TAG, "businessData strncpy failed");
1258             return NSTACKX_EINVAL;
1259         }
1260     }
1261     if (strncpy_s(dupResponseSettings->localNetworkName, NSTACKX_MAX_INTERFACE_NAME_LEN,
1262         responseSettings->localNetworkName, strlen(responseSettings->localNetworkName)) != EOK) {
1263         DFINDER_LOGE(TAG, "localNetworkName strncpy failed");
1264         return NSTACKX_EINVAL;
1265     }
1266     if (strncpy_s(dupResponseSettings->remoteIp, NSTACKX_MAX_IP_STRING_LEN,
1267         responseSettings->remoteIp, strlen(responseSettings->remoteIp)) != EOK) {
1268         DFINDER_LOGE(TAG, "remoteIp strncpy failed");
1269         return NSTACKX_EINVAL;
1270     }
1271     return NSTACKX_EOK;
1272 }
1273 
1274 static int32_t CheckResponseSettings(const NSTACKX_ResponseSettings *responseSettings)
1275 {
1276     if (responseSettings == NULL) {
1277         DFINDER_LOGE(TAG, "Invalid responseSettings info");
1278         return NSTACKX_EINVAL;
1279     }
1280     if ((responseSettings->businessData == NULL) && (responseSettings->length != 0)) {
1281         DFINDER_LOGE(TAG, "Invalid responseSettings bData info");
1282         return NSTACKX_EINVAL;
1283     }
1284     if (responseSettings->length >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
1285         DFINDER_LOGE(TAG, "businessData length is too long");
1286         return NSTACKX_EINVAL;
1287     }
1288     return NSTACKX_EOK;
1289 }
1290 
1291 int32_t NSTACKX_SendDiscoveryRsp(const NSTACKX_ResponseSettings *responseSettings)
1292 {
1293     DFINDER_LOGI(TAG, "begin to NSTACKX_SendDiscoveryRsp!");
1294     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1295         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1296         return NSTACKX_EFAILED;
1297     }
1298     if (CheckResponseSettings(responseSettings) != NSTACKX_EOK) {
1299         return NSTACKX_EINVAL;
1300     }
1301 
1302     NSTACKX_ResponseSettings *dupResponseSettings = malloc(sizeof(NSTACKX_ResponseSettings));
1303     if (dupResponseSettings == NULL) {
1304         DFINDER_LOGE(TAG, "malloc failed");
1305         return NSTACKX_ENOMEM;
1306     }
1307     dupResponseSettings->businessData = (char *)calloc((responseSettings->length + 1), sizeof(char));
1308     if (dupResponseSettings->businessData == NULL) {
1309         DFINDER_LOGE(TAG, "businessData calloc failed");
1310         free(dupResponseSettings);
1311         return NSTACKX_ENOMEM;
1312     }
1313     if (CopyResponseSettings(dupResponseSettings, responseSettings) != NSTACKX_EOK) {
1314         free(dupResponseSettings->businessData);
1315         free(dupResponseSettings);
1316         return NSTACKX_EINVAL;
1317     }
1318 
1319     if (PostEvent(&g_eventNodeChain, g_epollfd, SendDiscoveryRspInner, dupResponseSettings) != NSTACKX_EOK) {
1320         DFINDER_LOGE(TAG, "Failed to send responseSettings info!");
1321         free(dupResponseSettings->businessData);
1322         free(dupResponseSettings);
1323         return NSTACKX_EFAILED;
1324     }
1325     return NSTACKX_EOK;
1326 }
1327 
1328 #ifdef DFINDER_SAVE_DEVICE_LIST
1329 static void GetDeviceListInner(void *argument)
1330 {
1331     GetDeviceListMessage *message = argument;
1332 
1333     GetDeviceListWrapper(message->deviceList, message->deviceCountPtr, true);
1334     SemPost(&message->wait);
1335 }
1336 #endif
1337 
1338 int32_t NSTACKX_GetDeviceList(NSTACKX_DeviceInfo *deviceList, uint32_t *deviceCountPtr)
1339 {
1340 #ifdef DFINDER_SAVE_DEVICE_LIST
1341     GetDeviceListMessage message = {
1342         .deviceList = deviceList,
1343         .deviceCountPtr = deviceCountPtr,
1344     };
1345     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1346         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1347         return NSTACKX_EFAILED;
1348     }
1349     if (deviceList == NULL || deviceCountPtr == NULL) {
1350         DFINDER_LOGE(TAG, "Device list or count pointer is NULL");
1351         return NSTACKX_EINVAL;
1352     }
1353     if (SemInit(&message.wait, 0, 0)) {
1354         return NSTACKX_EFAILED;
1355     }
1356     if (PostEvent(&g_eventNodeChain, g_epollfd, GetDeviceListInner, &message) != NSTACKX_EOK) {
1357         DFINDER_LOGE(TAG, "Failed to get device list");
1358         SemDestroy(&message.wait);
1359         return NSTACKX_EFAILED;
1360     }
1361     SemWait(&message.wait);
1362     SemDestroy(&message.wait);
1363     return NSTACKX_EOK;
1364 #else
1365     (void)deviceList;
1366     (void)deviceCountPtr;
1367 
1368     DFINDER_LOGE(TAG, "device list not supported");
1369 
1370     return NSTACKX_EFAILED;
1371 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
1372 }
1373 
1374 void NotifyDeviceListChanged(const NSTACKX_DeviceInfo *deviceList, uint32_t deviceCount)
1375 {
1376     if (g_parameter.onDeviceListChanged != NULL) {
1377         DFINDER_LOGI(TAG, "notify callback: device list changed");
1378         g_parameter.onDeviceListChanged(deviceList, deviceCount);
1379         DFINDER_LOGI(TAG, "finish to notify device list changed");
1380     } else {
1381         DFINDER_LOGI(TAG, "notify callback: device list changed callback is null");
1382     }
1383 }
1384 
1385 void NotifyDeviceFound(const NSTACKX_DeviceInfo *deviceList, uint32_t deviceCount)
1386 {
1387     if (g_parameter.onDeviceFound != NULL) {
1388         DFINDER_LOGI(TAG, "notify callback: device found");
1389         g_parameter.onDeviceFound(deviceList, deviceCount);
1390         DFINDER_LOGI(TAG, "finish to notify device found");
1391     } else {
1392         DFINDER_LOGI(TAG, "notify callback: device found callback is null");
1393     }
1394 }
1395 
1396 #ifndef DFINDER_USE_MINI_NSTACKX
1397 void NotifyMsgReceived(const char *moduleName, const char *deviceId, const uint8_t *data, uint32_t len)
1398 {
1399     if (g_parameter.onMsgReceived != NULL) {
1400         DFINDER_LOGI(TAG, "notify callback: message received, data length %u", len);
1401         g_parameter.onMsgReceived(moduleName, deviceId, data, len);
1402         DFINDER_LOGI(TAG, "finish to notify msg received");
1403     } else {
1404         DFINDER_LOGI(TAG, "notify callback: message received callback is null");
1405     }
1406 }
1407 
1408 int32_t NSTACKX_InitRestart(const NSTACKX_Parameter *parameter)
1409 {
1410 #ifdef DFINDER_SUPPORT_MULTI_NIF
1411     (void)parameter;
1412     return NSTACKX_EOK;
1413 #else
1414     DFINDER_LOGI(TAG, "NSTACKX_InitRestart");
1415     int32_t ret = NSTACKX_Init(parameter);
1416     if (ret == NSTACKX_EOK) {
1417         if (PostEvent(&g_eventNodeChain, g_epollfd, GetLocalNetworkInterface, NULL) != NSTACKX_EOK) {
1418             DFINDER_LOGE(TAG, "Failed to GetLocalNetworkInterface");
1419         }
1420     }
1421     return ret;
1422 #endif
1423 }
1424 
1425 static void DeviceDiscoverInnerRestart(void *argument)
1426 {
1427     (void)argument;
1428     CoapServiceDiscoverInner(NSTACKX_FALSE);
1429 }
1430 
1431 void NSTACKX_StartDeviceFindRestart(void)
1432 {
1433     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1434         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1435         return;
1436     }
1437     DFINDER_LOGI(TAG, "start device find for restart");
1438     if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerRestart, NULL) != NSTACKX_EOK) {
1439         DFINDER_LOGE(TAG, "Failed to start device discover!");
1440         return;
1441     }
1442     return;
1443 }
1444 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
1445 
1446 #ifdef ENABLE_USER_LOG
1447 int32_t NSTACKX_DFinderRegisterLog(DFinderLogCallback userLogCallback)
1448 {
1449     if (userLogCallback == NULL) {
1450         DFINDER_LOGE(TAG, "logImpl null");
1451         return NSTACKX_EFAILED;
1452     }
1453     int32_t ret = SetLogCallback(userLogCallback);
1454     return ret;
1455 }
1456 #endif
1457 
1458 #ifdef NSTACKX_DFINDER_HIDUMP
1459 #define MAX_DUMP_ARGC 10
1460 int NSTACKX_DFinderDump(const char **argv, uint32_t argc, void *softObj, DFinderDumpFunc dump)
1461 {
1462     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1463         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1464         return NSTACKX_EFAILED;
1465     }
1466 
1467     if (dump == NULL) {
1468         DFINDER_LOGE(TAG, "dump is null");
1469         return NSTACKX_EINVAL;
1470     }
1471 
1472     if (argc == 0 || argc > MAX_DUMP_ARGC) {
1473         DFINDER_LOGE(TAG, "argc is invalid %u", argc);
1474         return NSTACKX_EINVAL;
1475     }
1476 
1477     if (argv == NULL) {
1478         DFINDER_LOGE(TAG, "argv is null");
1479         return NSTACKX_EINVAL;
1480     }
1481 
1482     uint32_t i;
1483     for (i = 0; i < argc; i++) {
1484         if (argv[i] == NULL) {
1485             DFINDER_LOGE(TAG, "argv[%u] is null", i);
1486             return NSTACKX_EINVAL;
1487         }
1488     }
1489 
1490     return DFinderDump(argv, argc, softObj, dump);
1491 }
1492 #else
1493 int NSTACKX_DFinderDump(const char **argv, uint32_t argc, void *softObj, DFinderDumpFunc dump)
1494 {
1495     (void)argv;
1496     (void)argc;
1497     (void)softObj;
1498     (void)dump;
1499     DFINDER_LOGE(TAG, "Unsupport dfinder dump");
1500     return NSTACKX_NOTSUPPORT;
1501 }
1502 #endif
1503 
1504 int NSTACKX_DFinderSetEventFunc(void *softobj, DFinderEventFunc func)
1505 {
1506     if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
1507         DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
1508         return NSTACKX_EFAILED;
1509     }
1510 
1511     if (func == NULL) {
1512         DFINDER_LOGE(TAG, "func is null");
1513         return NSTACKX_EINVAL;
1514     }
1515 
1516     return SetEventFunc(softobj, func);
1517 }
1518