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