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