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