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