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(®Info->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(®Info.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, ®Info) != NSTACKX_EOK) {
1035 DFINDER_LOGE(TAG, "Failed to configure local device info!");
1036 SemDestroy(®Info.wait);
1037 return NSTACKX_EBUSY;
1038 }
1039
1040 SemWait(®Info.wait);
1041 SemDestroy(®Info.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