mirror of
https://github.com/openharmony/communication_t2stack.git
synced 2026-07-21 08:45:25 -04:00
fb185021ee
Signed-off-by: yexiaokang <yexiaokang3@huawei.com>
2438 lines
78 KiB
C
2438 lines
78 KiB
C
/*
|
|
* Copyright (C) 2021-2023 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "nstackx_common.h"
|
|
|
|
#include <securec.h>
|
|
#ifndef _WIN32
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
#include <stdatomic.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
#include "cJSON.h"
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
#include <coap3/coap.h>
|
|
#endif
|
|
|
|
#include "coap_app.h"
|
|
#include "coap_discover.h"
|
|
#include "nstackx.h"
|
|
#include "nstackx_device.h"
|
|
#include "nstackx_epoll.h"
|
|
#include "nstackx_error.h"
|
|
#include "nstackx_event.h"
|
|
#include "nstackx_dfinder_log.h"
|
|
#include "nstackx_smartgenius.h"
|
|
#include "nstackx_timer.h"
|
|
#include "nstackx_util.h"
|
|
#include "nstackx_inet.h"
|
|
#include "json_payload.h"
|
|
#include "nstackx_statistics.h"
|
|
#include "nstackx_dfinder_hidump.h"
|
|
#include "nstackx_dfinder_hievent.h"
|
|
#include "nstackx_device_local.h"
|
|
#include "nstackx_device_remote.h"
|
|
|
|
#ifdef DFINDER_USE_MINI_NSTACKX
|
|
#include "cmsis_os2.h"
|
|
#include "ohos_init.h"
|
|
#define DFINDER_THREAD_STACK_SIZE (1024 * 32)
|
|
#endif
|
|
|
|
#define MAX_COAP_SERVICE_DATA_CNT 3
|
|
#define SINGLE_NIC_CNT 1
|
|
#define TAG "nStackXDFinder"
|
|
#define DFINDER_THREAD_NAME TAG
|
|
#define DFINDER_POST_EVENT_MAX_BLOCK_SECONDS 3
|
|
#define NSEC_TICKS_PER_SEC (1000000000)
|
|
|
|
enum {
|
|
NSTACKX_INIT_STATE_START = 0,
|
|
NSTACKX_INIT_STATE_ONGOING,
|
|
NSTACKX_INIT_STATE_DONE,
|
|
};
|
|
|
|
#ifdef DFINDER_USE_MINI_NSTACKX
|
|
static osThreadId_t g_threadId;
|
|
#else
|
|
static pthread_t g_tid;
|
|
#endif
|
|
|
|
static EpollDesc g_epollfd = INVALID_EPOLL_DESC;
|
|
static List g_eventNodeChain = {&(g_eventNodeChain), &(g_eventNodeChain)};
|
|
|
|
static uint8_t g_validTidFlag = NSTACKX_FALSE;
|
|
static uint8_t g_terminateFlag = NSTACKX_FALSE;
|
|
|
|
static pthread_mutex_t g_threadInitLock = PTHREAD_MUTEX_INITIALIZER;
|
|
static NSTACKX_Parameter g_parameter;
|
|
static atomic_uint_fast8_t g_nstackInitState = NSTACKX_INIT_STATE_START;
|
|
static atomic_uint_fast8_t g_nstackThreadInitState = NSTACKX_INIT_STATE_START;
|
|
static bool g_isNotifyPerDevice;
|
|
|
|
#define EVENT_COUNT_RATE_INTERVAL 2000 /* 2 SECONDS */
|
|
#define MAX_EVENT_PROCESS_NUM_PER_INTERVAL 700
|
|
#define MAX_CONTINUOUS_BUSY_INTERVAL_NUM 20
|
|
|
|
typedef struct {
|
|
uint32_t epollWaitTimeoutCount;
|
|
uint32_t epollWaitEventCount;
|
|
struct timespec measureBefore;
|
|
} EventProcessRatePara;
|
|
static EventProcessRatePara g_processRatePara;
|
|
static uint32_t g_continuousBusyIntervals;
|
|
|
|
static int32_t CheckDiscoverySettings(const NSTACKX_DiscoverySettings *discoverySettings);
|
|
static int32_t RegisterDeviceWithType(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo, int registerType);
|
|
|
|
bool GetIsNotifyPerDevice(void)
|
|
{
|
|
return g_isNotifyPerDevice;
|
|
}
|
|
|
|
#ifdef DFINDER_SUPPORT_COVERITY_TAINTED_SET
|
|
void Coverity_Tainted_Set(void *buf)
|
|
{
|
|
(void)buf;
|
|
}
|
|
#endif
|
|
|
|
List *GetEventNodeChain(void)
|
|
{
|
|
return &g_eventNodeChain;
|
|
}
|
|
|
|
EpollDesc GetEpollFD(void)
|
|
{
|
|
return g_epollfd;
|
|
}
|
|
|
|
void NotifyDFinderMsgRecver(DFinderMsgType msgType)
|
|
{
|
|
if (g_parameter.onDFinderMsgReceived != NULL) {
|
|
g_parameter.onDFinderMsgReceived(msgType);
|
|
}
|
|
}
|
|
|
|
int32_t ShouldAutoReplyUnicast(uint8_t businessType)
|
|
{
|
|
switch (businessType) {
|
|
case NSTACKX_BUSINESS_TYPE_SOFTBUS:
|
|
case NSTACKX_BUSINESS_TYPE_AUTONET:
|
|
case NSTACKX_BUSINESS_TYPE_STRATEGY:
|
|
return NSTACKX_FALSE;
|
|
case NSTACKX_BUSINESS_TYPE_NULL:
|
|
case NSTACKX_BUSINESS_TYPE_HICOM:
|
|
case NSTACKX_BUSINESS_TYPE_NEARBY:
|
|
default:
|
|
return NSTACKX_TRUE;
|
|
}
|
|
}
|
|
|
|
uint32_t GetDefaultDiscoverInterval(uint32_t discoverCount)
|
|
{
|
|
if (discoverCount < COAP_FIRST_DISCOVER_COUNT_RANGE) {
|
|
return COAP_FIRST_DISCOVER_INTERVAL;
|
|
} else if (discoverCount < COAP_SECOND_DISCOVER_COUNT_RANGE) {
|
|
return COAP_SECOND_DISCOVER_INTERVAL;
|
|
} else {
|
|
return COAP_LAST_DISCOVER_INTERVAL;
|
|
}
|
|
}
|
|
|
|
int32_t GetServiceDiscoverInfo(const uint8_t *buf, size_t size, struct DeviceInfo *deviceInfo, char **remoteUrlPtr)
|
|
{
|
|
uint8_t *newBuf = NULL;
|
|
if (size <= 0) {
|
|
DFINDER_LOGE(TAG, "buf size <= 0");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (buf[size - 1] != '\0') {
|
|
newBuf = (uint8_t *)calloc(size + 1, 1U);
|
|
if (newBuf == NULL) {
|
|
DFINDER_LOGE(TAG, "data is not end with 0 and new buf calloc error");
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (memcpy_s(newBuf, size + 1, buf, size) != EOK) {
|
|
DFINDER_LOGE(TAG, "data is not end with 0 and memcpy data error");
|
|
goto L_COAP_ERR;
|
|
}
|
|
DFINDER_LOGI(TAG, "data is not end with 0");
|
|
buf = newBuf;
|
|
}
|
|
if (ParseServiceDiscover(buf, deviceInfo, remoteUrlPtr) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "parse service discover error");
|
|
goto L_COAP_ERR;
|
|
}
|
|
|
|
if (newBuf != NULL) {
|
|
free(newBuf);
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
L_COAP_ERR:
|
|
if (newBuf != NULL) {
|
|
free(newBuf);
|
|
}
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
int32_t GetServiceNotificationInfo(const uint8_t *buf, size_t size, NSTACKX_NotificationConfig *notification)
|
|
{
|
|
uint8_t *newBuf = NULL;
|
|
if (buf[size - 1] != '\0') {
|
|
newBuf = (uint8_t *)calloc(size + 1, 1U);
|
|
if (newBuf == NULL) {
|
|
DFINDER_LOGE(TAG, "data is not end with 0 and new buf calloc error");
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (memcpy_s(newBuf, size + 1, buf, size) != EOK) {
|
|
DFINDER_LOGE(TAG, "data is not end with 0 and memcpy data error");
|
|
goto L_COAP_ERR;
|
|
}
|
|
DFINDER_LOGI(TAG, "data is not end with 0");
|
|
buf = newBuf;
|
|
}
|
|
if (ParseServiceNotification(buf, notification) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "parse service notification error");
|
|
goto L_COAP_ERR;
|
|
}
|
|
|
|
if (newBuf != NULL) {
|
|
free(newBuf);
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
L_COAP_ERR:
|
|
if (newBuf != NULL) {
|
|
free(newBuf);
|
|
}
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
static void ResetMainEpollTaskCount(uint8_t isBusy)
|
|
{
|
|
EpollTask *task = GetEpollTask(&g_eventNodeChain, g_epollfd);
|
|
if (task == NULL) {
|
|
return;
|
|
}
|
|
if (isBusy) {
|
|
DFINDER_LOGI(TAG, "in this busy interval: main epoll task count %llu", task->count);
|
|
}
|
|
task->count = 0;
|
|
}
|
|
|
|
static uint8_t IsBusyInterval(uint32_t eventCount, uint32_t timeMs)
|
|
{
|
|
uint8_t retFlag = NSTACKX_TRUE;
|
|
if ((uint64_t)eventCount * EVENT_COUNT_RATE_INTERVAL <
|
|
MAX_EVENT_PROCESS_NUM_PER_INTERVAL * (uint64_t)timeMs) {
|
|
retFlag = NSTACKX_FALSE;
|
|
}
|
|
|
|
ResetMainEpollTaskCount(retFlag);
|
|
ResetCoapSocketTaskCount(retFlag);
|
|
ResetCoapDiscoverTaskCount(retFlag);
|
|
ResetDeviceTaskCount(retFlag);
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
ResetSmartGeniusTaskCount(retFlag);
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
|
|
return retFlag;
|
|
}
|
|
|
|
static void CalculateEventProcessRate(void)
|
|
{
|
|
struct timespec now;
|
|
ClockGetTime(CLOCK_MONOTONIC, &now);
|
|
uint32_t measureElapse = GetTimeDiffMs(&now, &g_processRatePara.measureBefore);
|
|
if (measureElapse <= EVENT_COUNT_RATE_INTERVAL) {
|
|
return;
|
|
}
|
|
uint32_t totalCount = g_processRatePara.epollWaitEventCount + g_processRatePara.epollWaitTimeoutCount;
|
|
if (!IsBusyInterval(totalCount, measureElapse)) {
|
|
g_continuousBusyIntervals = 0;
|
|
} else {
|
|
DFINDER_LOGI(TAG, "main loop seems to be busy in the past interval. Timeout count %u, event count %u",
|
|
g_processRatePara.epollWaitTimeoutCount, g_processRatePara.epollWaitEventCount);
|
|
g_continuousBusyIntervals++;
|
|
if (g_continuousBusyIntervals >= MAX_CONTINUOUS_BUSY_INTERVAL_NUM) {
|
|
DFINDER_LOGE(TAG, "main loop seems to be busy in the past %u intervals. notify user to restart",
|
|
g_continuousBusyIntervals);
|
|
NotifyDFinderMsgRecver(DFINDER_ON_TOO_BUSY);
|
|
g_continuousBusyIntervals = 0;
|
|
}
|
|
}
|
|
g_processRatePara.epollWaitTimeoutCount = 0;
|
|
g_processRatePara.epollWaitEventCount = 0;
|
|
ClockGetTime(CLOCK_MONOTONIC, &g_processRatePara.measureBefore);
|
|
}
|
|
|
|
static void *NstackMainLoop(void *arg)
|
|
{
|
|
int32_t ret;
|
|
(void)arg;
|
|
(void)memset_s(&g_processRatePara, sizeof(g_processRatePara), 0, sizeof(g_processRatePara));
|
|
g_continuousBusyIntervals = 0;
|
|
ClockGetTime(CLOCK_MONOTONIC, &g_processRatePara.measureBefore);
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
SetThreadName(DFINDER_THREAD_NAME);
|
|
#endif
|
|
while (g_terminateFlag == NSTACKX_FALSE) {
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
uint32_t timeout = RegisterCoAPEpollTask(g_epollfd);
|
|
ret = EpollLoop(g_epollfd, timeout);
|
|
#else
|
|
ret = EpollLoop(g_epollfd, -1);
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
if (ret == NSTACKX_EFAILED) {
|
|
IncStatistics(STATS_EPOLL_ERROR);
|
|
DFINDER_LOGE(TAG, "epoll loop failed");
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
DeRegisterCoAPEpollTask();
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
break;
|
|
} else if (ret == NSTACKX_ETIMEOUT) {
|
|
g_processRatePara.epollWaitTimeoutCount++;
|
|
} else if (ret > 0) {
|
|
g_processRatePara.epollWaitEventCount++;
|
|
} else {
|
|
/* do nothing */
|
|
}
|
|
CalculateEventProcessRate();
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
DeRegisterCoAPEpollTask();
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
EpollDesc GetMainLoopEpollFd(void)
|
|
{
|
|
return g_epollfd;
|
|
}
|
|
|
|
List *GetMainLoopEvendChain(void)
|
|
{
|
|
return &g_eventNodeChain;
|
|
}
|
|
|
|
static int32_t InternalInit(EpollDesc epollfd, uint32_t maxDeviceNum)
|
|
{
|
|
int32_t ret = EventModuleInit(&g_eventNodeChain, g_epollfd);
|
|
if (ret != NSTACKX_EOK) {
|
|
return ret;
|
|
}
|
|
|
|
ret = DeviceModuleInit(epollfd, maxDeviceNum);
|
|
if (ret != NSTACKX_EOK) {
|
|
return ret;
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
ret = CoapThreadInit();
|
|
if (ret != NSTACKX_EOK) {
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
ret = CoapDiscoverInit(epollfd);
|
|
if (ret != NSTACKX_EOK) {
|
|
return ret;
|
|
}
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
ret = SmartGeniusInit(epollfd);
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
return ret;
|
|
}
|
|
|
|
#ifdef DFINDER_USE_MINI_NSTACKX
|
|
static void ReportMainLoopStopInner(void *argument)
|
|
{
|
|
(void)argument;
|
|
DFINDER_LOGI(TAG, "receive message to stop main loop");
|
|
}
|
|
|
|
static void ReportMainLoopStop(void)
|
|
{
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, ReportMainLoopStopInner, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to report mainloop stop!");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int32_t NSTACKX_ThreadInit(void)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "nstack is not initiated foundation yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (PthreadMutexLock(&g_threadInitLock) != 0) {
|
|
DFINDER_LOGE(TAG, "Failed to lock");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
DFINDER_LOGI(TAG, "nstack begin init thread");
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_START) {
|
|
(void)PthreadMutexUnlock(&g_threadInitLock);
|
|
DFINDER_LOGI(TAG, "nstack init thread done");
|
|
return NSTACKX_EOK;
|
|
}
|
|
g_nstackThreadInitState = NSTACKX_INIT_STATE_ONGOING;
|
|
g_terminateFlag = NSTACKX_FALSE;
|
|
g_validTidFlag = NSTACKX_FALSE;
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
int32_t ret = PthreadCreate(&g_tid, NULL, NstackMainLoop, NULL);
|
|
if (ret != 0) {
|
|
DFINDER_LOGE(TAG, "thread create failed");
|
|
g_terminateFlag = NSTACKX_TRUE;
|
|
(void)PthreadMutexUnlock(&g_threadInitLock);
|
|
return ret;
|
|
}
|
|
#else
|
|
osThreadAttr_t attr = {0};
|
|
attr.name = DFINDER_THREAD_NAME;
|
|
attr.stack_size = DFINDER_THREAD_STACK_SIZE;
|
|
// osPriorityNormal equals 24
|
|
attr.priority = osPriorityNormal;
|
|
g_threadId = osThreadNew((osThreadFunc_t)NstackMainLoop, NULL, &attr);
|
|
if (g_threadId == NULL) {
|
|
DFINDER_LOGE(TAG, "thread create failed with attribute settings");
|
|
g_terminateFlag = NSTACKX_TRUE;
|
|
(void)PthreadMutexUnlock(&g_threadInitLock);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
#endif
|
|
g_validTidFlag = NSTACKX_TRUE;
|
|
g_nstackThreadInitState = NSTACKX_INIT_STATE_DONE;
|
|
(void)PthreadMutexUnlock(&g_threadInitLock);
|
|
DFINDER_LOGI(TAG, "nstack init thread success");
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
void NSTACKX_ThreadDeinit(void)
|
|
{
|
|
if (g_nstackThreadInitState == NSTACKX_INIT_STATE_START) {
|
|
return;
|
|
}
|
|
DFINDER_LOGI(TAG, "nstack begin deinit thread");
|
|
if (PthreadMutexLock(&g_threadInitLock) != 0) {
|
|
DFINDER_LOGE(TAG, "Failed to lock");
|
|
return;
|
|
}
|
|
if (g_validTidFlag) {
|
|
g_terminateFlag = NSTACKX_TRUE;
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
PthreadJoin(g_tid, NULL);
|
|
#else
|
|
ReportMainLoopStop();
|
|
if (osThreadTerminate(g_threadId) != osOK) {
|
|
DFINDER_LOGE(TAG, "os thread terminate failed");
|
|
}
|
|
#endif
|
|
g_validTidFlag = NSTACKX_FALSE;
|
|
}
|
|
g_nstackThreadInitState = NSTACKX_INIT_STATE_START;
|
|
(void)PthreadMutexUnlock(&g_threadInitLock);
|
|
DFINDER_LOGI(TAG, "nstack deinit thread success");
|
|
}
|
|
|
|
#if !defined(DFINDER_USE_MINI_NSTACKX) && !defined(DFINDER_ENABLE_COAP_LOG)
|
|
static void CoapLogHandler(coap_log_t level, const char *message)
|
|
{
|
|
(void)level;
|
|
(void)message;
|
|
}
|
|
#endif
|
|
|
|
static void InitLogLevel(void)
|
|
{
|
|
// default log
|
|
SetLogLevel(NSTACKX_LOG_LEVEL_DEBUG);
|
|
|
|
// user defined log
|
|
#ifdef ENABLE_USER_LOG
|
|
SetDFinderLogLevel(DFINDER_LOG_LEVEL_DEBUG);
|
|
#endif
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
// opensource libcoap log
|
|
#ifdef DFINDER_ENABLE_COAP_LOG
|
|
coap_set_log_level(COAP_LOG_DEBUG);
|
|
#else
|
|
coap_set_log_handler(CoapLogHandler);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
static int32_t NstackxInitEx(const NSTACKX_Parameter *parameter, bool isNotifyPerDevice)
|
|
{
|
|
Coverity_Tainted_Set((void *)parameter);
|
|
|
|
int32_t ret;
|
|
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_START) {
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
g_nstackInitState = NSTACKX_INIT_STATE_ONGOING;
|
|
cJSON_InitHooks(NULL);
|
|
|
|
InitLogLevel();
|
|
|
|
#ifdef NSTACKX_WITH_LITEOS
|
|
EpollEventPtrInit(); /* init g_epollEventPtrMutex g_epollEventPtrArray */
|
|
#endif
|
|
|
|
g_epollfd = CreateEpollDesc();
|
|
if (!IsEpollDescValid(g_epollfd)) {
|
|
DFINDER_LOGE(TAG, "epoll creat fail! errno: %d", errno);
|
|
g_nstackInitState = NSTACKX_INIT_STATE_START;
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
DFINDER_LOGD(TAG, "nstack ctrl creat epollfd %d", REPRESENT_EPOLL_DESC(g_epollfd));
|
|
#ifdef DFINDER_SAVE_DEVICE_LIST
|
|
ret = InternalInit(g_epollfd, parameter != NULL ? parameter->maxDeviceNum : NSTACKX_DEFAULT_DEVICE_NUM);
|
|
#else
|
|
ret = InternalInit(g_epollfd, parameter != NULL ? parameter->maxDeviceNum : NSTACKX_MAX_DEVICE_NUM);
|
|
#endif
|
|
if (ret != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "internal init failed, ret=%d", ret);
|
|
goto L_ERR_INIT;
|
|
}
|
|
(void)memset_s(&g_parameter, sizeof(g_parameter), 0, sizeof(g_parameter));
|
|
if (parameter != NULL) {
|
|
(void)memcpy_s(&g_parameter, sizeof(g_parameter), parameter, sizeof(NSTACKX_Parameter));
|
|
}
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
CoapInitSubscribeModuleInner(); /* initialize subscribe module number */
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
g_isNotifyPerDevice = isNotifyPerDevice;
|
|
g_nstackInitState = NSTACKX_INIT_STATE_DONE;
|
|
DFINDER_LOGI(TAG, "DFinder init successfully");
|
|
return NSTACKX_EOK;
|
|
|
|
L_ERR_INIT:
|
|
NSTACKX_Deinit();
|
|
return ret;
|
|
}
|
|
|
|
int32_t NSTACKX_Init(const NSTACKX_Parameter *parameter)
|
|
{
|
|
return NstackxInitEx(parameter, false);
|
|
}
|
|
|
|
int32_t NSTACKX_InitV2(const NSTACKX_Parameter *parameter, bool isNotifyPerDevice)
|
|
{
|
|
return NstackxInitEx(parameter, isNotifyPerDevice);
|
|
}
|
|
|
|
void NSTACKX_Deinit(void)
|
|
{
|
|
if (g_nstackInitState == NSTACKX_INIT_STATE_START) {
|
|
return;
|
|
}
|
|
NSTACKX_ThreadDeinit();
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
SmartGeniusClean();
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
CoapDiscoverDeinit();
|
|
|
|
#ifdef _WIN32
|
|
CoapThreadDestroy();
|
|
#endif
|
|
DeviceModuleClean();
|
|
EventNodeChainClean(&g_eventNodeChain);
|
|
if (IsEpollDescValid(g_epollfd)) {
|
|
CloseEpollDesc(g_epollfd);
|
|
g_epollfd = INVALID_EPOLL_DESC;
|
|
}
|
|
ResetStatistics();
|
|
ResetEventFunc();
|
|
ResetSequenceNumber();
|
|
g_nstackInitState = NSTACKX_INIT_STATE_START;
|
|
DFINDER_LOGI(TAG, "deinit successfully");
|
|
}
|
|
|
|
static void DeviceDiscoverInner(void *argument)
|
|
{
|
|
if (!IsCoapContextReady()) {
|
|
DFINDER_LOGE(TAG, "no iface is ready, notify user with empty list");
|
|
NotifyDeviceFound(NULL, 0);
|
|
return;
|
|
}
|
|
|
|
(void)argument;
|
|
SetCoapDiscoverType(COAP_BROADCAST_TYPE_DEFAULT);
|
|
SetLocalDeviceBusinessType(NSTACKX_BUSINESS_TYPE_NULL);
|
|
CoapServiceDiscoverInner(INNER_DISCOVERY);
|
|
}
|
|
|
|
static void DeviceDiscoverInnerAn(void *argument)
|
|
{
|
|
(void)argument;
|
|
SetCoapDiscoverType(COAP_BROADCAST_TYPE_DEFAULT);
|
|
SetLocalDeviceBusinessType(NSTACKX_BUSINESS_TYPE_NULL);
|
|
CoapServiceDiscoverInnerAn(INNER_DISCOVERY);
|
|
}
|
|
|
|
static void DeviceDiscoverInnerConfigurable(void *argument)
|
|
{
|
|
NSTACKX_DiscoverySettings *discoverySettings = argument;
|
|
int32_t configResult = ConfigureDiscoverySettings(discoverySettings);
|
|
free(discoverySettings->businessData);
|
|
free(discoverySettings);
|
|
if (configResult != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "config discovery settings failed");
|
|
return;
|
|
}
|
|
CoapServiceDiscoverInnerConfigurable(INNER_DISCOVERY);
|
|
}
|
|
|
|
static void DiscConfig(void *argument)
|
|
{
|
|
DFinderDiscConfig *discConfig = argument;
|
|
uint8_t businessTypeLocal = GetLocalDeviceBusinessType();
|
|
if (discConfig->businessType != businessTypeLocal) {
|
|
DFINDER_LOGE(TAG, "business type is different, config: %hhu, local: %hhu",
|
|
discConfig->businessType, businessTypeLocal);
|
|
free(discConfig->businessData);
|
|
free(discConfig->bcastInterval);
|
|
free(discConfig);
|
|
return;
|
|
}
|
|
int32_t configResult = DiscConfigInner(discConfig);
|
|
free(discConfig->businessData);
|
|
free(discConfig->bcastInterval);
|
|
free(discConfig);
|
|
if (configResult != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "config for discover failed");
|
|
return;
|
|
}
|
|
CoapServiceDiscoverInnerConfigurable(INNER_DISCOVERY);
|
|
}
|
|
|
|
static void DeviceDiscoverStopInner(void *argument)
|
|
{
|
|
(void)argument;
|
|
CoapServiceDiscoverStopInner();
|
|
NotifyStatisticsEvent();
|
|
}
|
|
|
|
int32_t NSTACKX_StartDeviceFind(void)
|
|
{
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInner, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to start device discover!");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_StartDeviceFindAn(uint8_t mode)
|
|
{
|
|
Coverity_Tainted_Set((void *)&mode);
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
SetModeInfo(mode);
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerAn, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to start device discover!");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_StopDeviceFind(void)
|
|
{
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverStopInner, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to stop device discover!");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t CopyDiscoverySettings(NSTACKX_DiscoverySettings *dupDiscoverySettings,
|
|
const NSTACKX_DiscoverySettings *discoverySettings)
|
|
{
|
|
dupDiscoverySettings->businessType = discoverySettings->businessType;
|
|
dupDiscoverySettings->discoveryMode = discoverySettings->discoveryMode;
|
|
dupDiscoverySettings->length = discoverySettings->length;
|
|
if (discoverySettings->businessData != NULL) {
|
|
if (strncpy_s(dupDiscoverySettings->businessData, (dupDiscoverySettings->length + 1),
|
|
discoverySettings->businessData, discoverySettings->length) != EOK) {
|
|
DFINDER_LOGE(TAG, "businessData strncpy failed");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
}
|
|
dupDiscoverySettings->advertiseCount = discoverySettings->advertiseCount;
|
|
dupDiscoverySettings->advertiseDuration = discoverySettings->advertiseDuration;
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t CheckDiscoverySettings(const NSTACKX_DiscoverySettings *discoverySettings)
|
|
{
|
|
if (discoverySettings == NULL) {
|
|
DFINDER_LOGE(TAG, "Invalid discoverySettings info");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if ((discoverySettings->businessData == NULL) && (discoverySettings->length != 0)) {
|
|
DFINDER_LOGE(TAG, "Invalid discoverySettings bData info");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (discoverySettings->length >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "businessData length is too long");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
uint32_t advertiseCount = discoverySettings->advertiseCount;
|
|
uint32_t advertiseDuration = discoverySettings->advertiseDuration;
|
|
if ((advertiseCount == 0) && (advertiseDuration == 0)) {
|
|
return NSTACKX_EOK;
|
|
}
|
|
if ((advertiseCount < NSTACKX_MIN_ADVERTISE_COUNT) || (advertiseCount > NSTACKX_MAX_ADVERTISE_COUNT) ||
|
|
(advertiseDuration < NSTACKX_MIN_ADVERTISE_DURATION) || (advertiseDuration > NSTACKX_MAX_ADVERTISE_DURATION)) {
|
|
DFINDER_LOGE(TAG, "Invalid discoverySettings advertise info");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_StartDeviceDiscovery(const NSTACKX_DiscoverySettings *discoverySettings)
|
|
{
|
|
DFINDER_LOGI(TAG, "begin to NSTACKX_StartDeviceDiscovery!");
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (CheckDiscoverySettings(discoverySettings) != NSTACKX_EOK) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
NSTACKX_DiscoverySettings *dupDiscoverySettings = malloc(sizeof(NSTACKX_DiscoverySettings));
|
|
if (dupDiscoverySettings == NULL) {
|
|
DFINDER_LOGE(TAG, "malloc failed");
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
dupDiscoverySettings->businessData = (char *)calloc((discoverySettings->length + 1), sizeof(char));
|
|
if (dupDiscoverySettings->businessData == NULL) {
|
|
DFINDER_LOGE(TAG, "businessData calloc fail");
|
|
free(dupDiscoverySettings);
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (CopyDiscoverySettings(dupDiscoverySettings, discoverySettings) != NSTACKX_EOK) {
|
|
free(dupDiscoverySettings->businessData);
|
|
free(dupDiscoverySettings);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerConfigurable, dupDiscoverySettings) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to start device discover!");
|
|
free(dupDiscoverySettings->businessData);
|
|
free(dupDiscoverySettings);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t CopyDiscConfig(const DFinderDiscConfig *src, DFinderDiscConfig *dst)
|
|
{
|
|
dst->businessType = src->businessType;
|
|
dst->discoveryMode = src->discoveryMode;
|
|
dst->intervalArrLen = src->intervalArrLen;
|
|
for (size_t idx = 0; idx < dst->intervalArrLen; ++idx) {
|
|
(dst->bcastInterval)[idx] = (src->bcastInterval)[idx];
|
|
}
|
|
if (src->businessData != NULL) {
|
|
if (strncpy_s(dst->businessData, dst->businessDataLen, src->businessData, src->businessDataLen) != EOK) {
|
|
DFINDER_LOGE(TAG, "copy business data failed");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t CheckDiscInterval(uint32_t *intervalArr, uint32_t arrLen)
|
|
{
|
|
if (intervalArr == NULL || arrLen == 0) {
|
|
DFINDER_LOGE(TAG, "illegal param, arrlen: %ld", arrLen);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
// check interval values one by one
|
|
for (size_t i = 0; i < arrLen; ++i) {
|
|
if (intervalArr[i] < NSTACKX_MIN_ADVERTISE_INTERVAL || intervalArr[i] > NSTACKX_MAX_ADVERTISE_INTERVAL) {
|
|
DFINDER_LOGE(TAG, "invalid interval");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t CheckDiscConfig(const DFinderDiscConfig *discConfig)
|
|
{
|
|
if (discConfig == NULL) {
|
|
DFINDER_LOGE(TAG, "disc config passed in is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
// minus one for the first broadcast without interval
|
|
if (discConfig->bcastInterval == NULL || discConfig->intervalArrLen > (NSTACKX_MAX_ADVERTISE_COUNT - 1) ||
|
|
discConfig->intervalArrLen == 0) {
|
|
DFINDER_LOGE(TAG, "invalid broadcast interval params");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (CheckDiscInterval(discConfig->bcastInterval, discConfig->intervalArrLen) != NSTACKX_EOK) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if ((discConfig->businessData == NULL) && (discConfig->businessDataLen != 0)) {
|
|
DFINDER_LOGE(TAG, "invalid business data params");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (discConfig->businessDataLen >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "business data is too long");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_StartDeviceDiscoveryWithConfig(const DFinderDiscConfig *discConfig)
|
|
{
|
|
DFINDER_LOGI(TAG, "dfinder start disc with config");
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "nstackx ctrl is not initialed yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (CheckDiscConfig(discConfig) != NSTACKX_EOK) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
DFinderDiscConfig *dupDiscConfig = (DFinderDiscConfig *)malloc(sizeof(DFinderDiscConfig));
|
|
if (dupDiscConfig == NULL) {
|
|
DFINDER_LOGE(TAG, "malloc for duplicate disc config failed");
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
dupDiscConfig->bcastInterval = (uint32_t *)malloc(sizeof(uint32_t) * (discConfig->intervalArrLen));
|
|
if (dupDiscConfig->bcastInterval == NULL) {
|
|
DFINDER_LOGE(TAG, "malloc for duplicate broadcast interval failed");
|
|
free(dupDiscConfig);
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
dupDiscConfig->businessData = (char *)calloc((discConfig->businessDataLen + 1), sizeof(char));
|
|
if (dupDiscConfig->businessData == NULL) {
|
|
DFINDER_LOGE(TAG, "malloc for duplicate business data failed");
|
|
free(dupDiscConfig->bcastInterval);
|
|
free(dupDiscConfig);
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
// 1 to store the terminator
|
|
dupDiscConfig->businessDataLen = discConfig->businessDataLen + 1;
|
|
if (CopyDiscConfig(discConfig, dupDiscConfig) != NSTACKX_EOK) {
|
|
free(dupDiscConfig->businessData);
|
|
free(dupDiscConfig->bcastInterval);
|
|
free(dupDiscConfig);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, DiscConfig, dupDiscConfig) != NSTACKX_EOK) {
|
|
free(dupDiscConfig->businessData);
|
|
free(dupDiscConfig->bcastInterval);
|
|
free(dupDiscConfig);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
int32_t NSTACKX_SubscribeModule(void)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
CoapSubscribeModuleInner(INNER_DISCOVERY);
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_UnsubscribeModule(void)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
CoapUnsubscribeModuleInner(INNER_DISCOVERY);
|
|
return NSTACKX_EOK;
|
|
}
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
|
|
static bool IsNetworkNameValid(const char *networkName, size_t len)
|
|
{
|
|
if (!StringHasEOF(networkName, len)) {
|
|
DFINDER_LOGE(TAG, "network name is not ended");
|
|
return NSTACKX_FALSE;
|
|
}
|
|
|
|
return NSTACKX_TRUE;
|
|
}
|
|
|
|
static bool IsIpAddressValid(const char *ipStr, size_t len)
|
|
{
|
|
if (!StringHasEOF(ipStr, len)) {
|
|
DFINDER_LOGE(TAG, "ip addr is not ended");
|
|
return NSTACKX_FALSE;
|
|
}
|
|
|
|
union InetAddr addr;
|
|
if (len != 0 && ipStr[0] != '\0' && InetGetAfType(ipStr, &addr) == AF_ERROR) {
|
|
DFINDER_LOGE(TAG, "invalid ip address");
|
|
return NSTACKX_FALSE;
|
|
}
|
|
|
|
return NSTACKX_TRUE;
|
|
}
|
|
|
|
static int32_t CheckInterfaceInfo(const NSTACKX_InterfaceInfo *ifaces, uint32_t count)
|
|
{
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
if (!IsNetworkNameValid(ifaces[i].networkName, sizeof(ifaces[i].networkName)) ||
|
|
!IsIpAddressValid(ifaces[i].networkIpAddr, sizeof(ifaces[i].networkIpAddr)) ||
|
|
!IsNetworkNameValid(ifaces[i].serviceData, sizeof(ifaces[i].serviceData))) {
|
|
DFINDER_LOGE(TAG, "invalid network name or ip address of No.%u local iface", i);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int CheckLocalDeviceInfo(const NSTACKX_LocalDeviceInfo *localDeviceInfo)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (localDeviceInfo == NULL) {
|
|
DFINDER_LOGE(TAG, "Invalid local device info");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (!StringHasEOF(localDeviceInfo->deviceId, sizeof(localDeviceInfo->deviceId)) ||
|
|
!StringHasEOF(localDeviceInfo->name, sizeof(localDeviceInfo->name))) {
|
|
DFINDER_LOGE(TAG, "device id or device name is not ended");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (localDeviceInfo->ifNums > NSTACKX_MAX_LISTENED_NIF_NUM) {
|
|
DFINDER_LOGE(TAG, "invalid iface number %u", localDeviceInfo->ifNums);
|
|
return NSTACKX_EINVAL;
|
|
} else if (localDeviceInfo->ifNums == 0) {
|
|
if (!IsNetworkNameValid(localDeviceInfo->networkName, sizeof(localDeviceInfo->networkName)) ||
|
|
!IsIpAddressValid(localDeviceInfo->networkIpAddr, sizeof(localDeviceInfo->networkIpAddr))) {
|
|
DFINDER_LOGE(TAG, "invalid network name or ip address when iface number is 0");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static void DeviceInfoV2Init(NSTACKX_LocalDeviceInfoV2 *v2,
|
|
const NSTACKX_LocalDeviceInfo *localDeviceInfo, bool hasDeviceHash, uint64_t deviceHash)
|
|
{
|
|
v2->name = localDeviceInfo->name;
|
|
v2->deviceId = localDeviceInfo->deviceId;
|
|
v2->deviceType = localDeviceInfo->deviceType;
|
|
v2->businessType = localDeviceInfo->businessType;
|
|
v2->hasDeviceHash = hasDeviceHash;
|
|
v2->deviceHash = deviceHash;
|
|
}
|
|
|
|
static int32_t RegisterDeviceWithDeviceHash(const NSTACKX_LocalDeviceInfo *localDeviceInfo,
|
|
bool hasDeviceHash, uint64_t deviceHash)
|
|
{
|
|
int ret = CheckLocalDeviceInfo(localDeviceInfo);
|
|
if (ret != NSTACKX_EOK) {
|
|
return ret;
|
|
}
|
|
|
|
NSTACKX_LocalDeviceInfoV2 v2;
|
|
DeviceInfoV2Init(&v2, localDeviceInfo, hasDeviceHash, deviceHash);
|
|
|
|
NSTACKX_InterfaceInfo ifaceInfo;
|
|
(void)memset_s(&ifaceInfo, sizeof(ifaceInfo), 0, sizeof(ifaceInfo));
|
|
if (localDeviceInfo->ifNums == 0) {
|
|
if (strcpy_s(ifaceInfo.networkName, sizeof(ifaceInfo.networkName), localDeviceInfo->networkName) != EOK ||
|
|
strcpy_s(ifaceInfo.networkIpAddr, sizeof(ifaceInfo.networkIpAddr),
|
|
localDeviceInfo->networkIpAddr) != EOK) {
|
|
DFINDER_LOGE(TAG, "copy network name or ip addr failed");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
v2.localIfInfo = &ifaceInfo;
|
|
v2.ifNums = 1;
|
|
} else {
|
|
v2.localIfInfo = &localDeviceInfo->localIfInfo[0];
|
|
v2.ifNums = localDeviceInfo->ifNums;
|
|
}
|
|
|
|
return RegisterDeviceWithType(&v2, hasDeviceHash ? REGISTER_TYPE_UPDATE_SPECIFIED : REGISTER_TYPE_UPDATE_ALL);
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterDevice(const NSTACKX_LocalDeviceInfo *localDeviceInfo)
|
|
{
|
|
Coverity_Tainted_Set((void *)localDeviceInfo);
|
|
DFINDER_LOGI(TAG, "begin to NSTACKX_RegisterDevice!");
|
|
|
|
return RegisterDeviceWithDeviceHash(localDeviceInfo, NSTACKX_FALSE, 0);
|
|
}
|
|
|
|
static void ConfigureLocalDeviceNameInner(void *argument)
|
|
{
|
|
char *localDevName = (char *)argument;
|
|
|
|
ConfigureLocalDeviceName(localDevName);
|
|
free(localDevName);
|
|
}
|
|
|
|
static void RegisterLocalDeviceHash(void *arg)
|
|
{
|
|
uint64_t hash = (uint64_t)(uintptr_t)arg;
|
|
SetLocalDeviceHash(hash);
|
|
}
|
|
|
|
static int32_t RegisterDeviceHashInner(uint64_t deviceHash)
|
|
{
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
SetLocalDeviceHash(deviceHash);
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterLocalDeviceHash, (void *)deviceHash)) {
|
|
DFINDER_LOGE(TAG, "Failed to configure local device hash!");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterDeviceHash(uint64_t deviceHash)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_CTRL is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
return RegisterDeviceHashInner(deviceHash);
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterDeviceName(const char *devName)
|
|
{
|
|
if (devName == NULL || devName[0] == '\0') {
|
|
DFINDER_LOGE(TAG, "register local device name is invalid");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
size_t len = strnlen(devName, NSTACKX_MAX_DEVICE_NAME_LEN);
|
|
if (len >= NSTACKX_MAX_DEVICE_NAME_LEN) {
|
|
DFINDER_LOGE(TAG, "devName len %zu is error", len);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_CTRL is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
char *dupDevName = (char *)malloc(sizeof(char) * NSTACKX_MAX_DEVICE_NAME_LEN);
|
|
if (dupDevName == NULL) {
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (strncpy_s(dupDevName, NSTACKX_MAX_DEVICE_NAME_LEN, devName, len) != EOK) {
|
|
DFINDER_LOGE(TAG, "strncpy dupDevName failed");
|
|
free(dupDevName);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
ConfigureLocalDeviceNameInner((void *)dupDevName);
|
|
return NSTACKX_EOK;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, ConfigureLocalDeviceNameInner, dupDevName) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to configure local device name!");
|
|
free(dupDevName);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterDeviceAn(const NSTACKX_LocalDeviceInfo *localDeviceInfo, uint64_t deviceHash)
|
|
{
|
|
Coverity_Tainted_Set((void *)localDeviceInfo);
|
|
Coverity_Tainted_Set((void *)&deviceHash);
|
|
|
|
DFINDER_LOGI(TAG, "begin to NSTACKX_RegisterDeviceAn!");
|
|
return RegisterDeviceWithDeviceHash(localDeviceInfo, NSTACKX_TRUE, deviceHash);
|
|
}
|
|
|
|
struct NSTACKX_Sem {
|
|
sem_t wait;
|
|
};
|
|
|
|
typedef void (*FreeArg)(void *arg);
|
|
|
|
struct PostEvtBlockArgs {
|
|
void *arg;
|
|
FreeArg cb;
|
|
EventHandle handle;
|
|
struct NSTACKX_Sem *sem;
|
|
};
|
|
|
|
static void NSTACKX_PostEventBlockHander(void *argument)
|
|
{
|
|
if (argument == NULL) {
|
|
return;
|
|
}
|
|
|
|
struct PostEvtBlockArgs *arg = (struct PostEvtBlockArgs *)argument;
|
|
if (arg->arg != NULL && arg->handle != NULL) {
|
|
arg->handle(arg->arg);
|
|
}
|
|
if (arg->sem != NULL) {
|
|
SemPost(&(arg->sem->wait));
|
|
DFINDER_LOGI(TAG, "post event is done");
|
|
}
|
|
if (arg->cb != NULL) {
|
|
arg->cb(arg->arg);
|
|
}
|
|
arg->arg = NULL;
|
|
free(arg);
|
|
}
|
|
|
|
static int32_t SemTimedWait(sem_t *sem, struct timespec expire)
|
|
{
|
|
struct timespec timeout;
|
|
|
|
if (clock_gettime(CLOCK_REALTIME, &timeout) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "clock_gettime fail");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
timeout.tv_sec += expire.tv_sec;
|
|
timeout.tv_nsec += expire.tv_nsec;
|
|
if (timeout.tv_nsec >= NSEC_TICKS_PER_SEC) {
|
|
timeout.tv_sec += 1;
|
|
timeout.tv_nsec -= NSEC_TICKS_PER_SEC;
|
|
}
|
|
int ret = sem_timedwait(sem, &timeout);
|
|
if (ret != 0) {
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t NSTACKX_BlockEvtWaitFinish(struct PostEvtBlockArgs *arg, struct NSTACKX_Sem *sem)
|
|
{
|
|
int32_t ret = NSTACKX_EFAILED;
|
|
struct timespec expire = {
|
|
.tv_sec = DFINDER_POST_EVENT_MAX_BLOCK_SECONDS,
|
|
.tv_nsec = 0,
|
|
};
|
|
|
|
ret = SemTimedWait(&sem->wait, expire);
|
|
if (ret != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "sem wait failed errno %d", GetErrno());
|
|
} else {
|
|
DFINDER_LOGI(TAG, "sem wait success");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct NSTACKX_Sem *NSTACKX_CreateSem(void)
|
|
{
|
|
struct NSTACKX_Sem *sem = (struct NSTACKX_Sem *)calloc(1U, sizeof(struct NSTACKX_Sem));
|
|
if (sem == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc sem failed");
|
|
return NULL;
|
|
}
|
|
if (SemInit(&sem->wait, 0, 0)) {
|
|
DFINDER_LOGE(TAG, "Failed to init sem!");
|
|
free(sem);
|
|
return NULL;
|
|
}
|
|
return sem;
|
|
}
|
|
|
|
static void NSTACKX_FreeSem(void *arg)
|
|
{
|
|
if (arg == NULL) {
|
|
return;
|
|
}
|
|
|
|
struct NSTACKX_Sem *sem = (struct NSTACKX_Sem *)arg;
|
|
SemDestroy(&sem->wait);
|
|
free(sem);
|
|
DFINDER_LOGI(TAG, "free sem end");
|
|
}
|
|
|
|
static int32_t NSTACKX_PostEventBlock(EventHandle handle, void *arg, FreeArg cb)
|
|
{
|
|
struct PostEvtBlockArgs *blockEvtArg = (struct PostEvtBlockArgs *)calloc(1U, sizeof(struct PostEvtBlockArgs));
|
|
if (blockEvtArg == NULL) {
|
|
if (cb != NULL) {
|
|
cb(arg);
|
|
}
|
|
DFINDER_LOGE(TAG, "calloc failed");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
struct NSTACKX_Sem *sem = NSTACKX_CreateSem();
|
|
if (sem == NULL) {
|
|
if (cb != NULL) {
|
|
cb(arg);
|
|
}
|
|
free(blockEvtArg);
|
|
DFINDER_LOGE(TAG, "calloc sem failed");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
blockEvtArg->arg = arg;
|
|
blockEvtArg->cb = cb;
|
|
blockEvtArg->sem = sem;
|
|
blockEvtArg->handle = handle;
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd,
|
|
NSTACKX_PostEventBlockHander, (void *)blockEvtArg) != NSTACKX_EOK) {
|
|
if (cb != NULL) {
|
|
cb(arg);
|
|
}
|
|
NSTACKX_FreeSem((void *)sem);
|
|
free(blockEvtArg);
|
|
DFINDER_LOGE(TAG, "PostEvent failed");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (NSTACKX_BlockEvtWaitFinish(blockEvtArg, sem) != NSTACKX_EOK) {
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, NSTACKX_FreeSem, (void*)sem) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "PostEvent failed");
|
|
NSTACKX_FreeSem((void *)sem);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
DFINDER_LOGE(TAG, "block wait failed");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
NSTACKX_FreeSem((void *)sem);
|
|
DFINDER_LOGI(TAG, "post event success");
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
struct RegDeviceInfo {
|
|
NSTACKX_LocalDeviceInfoV2 *info;
|
|
int registerType;
|
|
int32_t err;
|
|
};
|
|
|
|
static void RegisterDeviceV2(void *arg)
|
|
{
|
|
struct RegDeviceInfo *regInfo = (struct RegDeviceInfo *)arg;
|
|
regInfo->err = RegisterLocalDeviceV2(regInfo->info, regInfo->registerType);
|
|
if (regInfo->err != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "register device failed");
|
|
}
|
|
}
|
|
|
|
#define NSTACKX_MAX_LOCAL_IFACE_NUM 10
|
|
|
|
static char *DeviceStrCreate(const char *str, uint32_t maxLen)
|
|
{
|
|
char *out = (char *)calloc(1u, maxLen);
|
|
if (out == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (strcpy_s(out, maxLen, str) != EOK) {
|
|
free(out);
|
|
return NULL;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
static void RegisterInfoFree(NSTACKX_LocalDeviceInfoV2 *info)
|
|
{
|
|
if (info == NULL) {
|
|
return;
|
|
}
|
|
free((void *)info->name);
|
|
free((void *)info->deviceId);
|
|
free((void *)info->localIfInfo);
|
|
free(info);
|
|
}
|
|
|
|
static void RegisterDeviceFree(void *arg)
|
|
{
|
|
if (arg == NULL) {
|
|
return;
|
|
}
|
|
struct RegDeviceInfo *regInfo = (struct RegDeviceInfo *)arg;
|
|
RegisterInfoFree(regInfo->info);
|
|
regInfo->info = NULL;
|
|
free(regInfo);
|
|
}
|
|
|
|
static NSTACKX_LocalDeviceInfoV2 *RegisterInfoCreate(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo)
|
|
{
|
|
NSTACKX_LocalDeviceInfoV2 *infoV2 = (NSTACKX_LocalDeviceInfoV2 *)calloc(1u, sizeof(NSTACKX_LocalDeviceInfoV2));
|
|
if (infoV2 == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc infov2 failed");
|
|
return NULL;
|
|
}
|
|
|
|
size_t len = strnlen(localDeviceInfo->deviceId, NSTACKX_MAX_DEVICE_ID_LEN);
|
|
if (len >= NSTACKX_MAX_DEVICE_ID_LEN) {
|
|
DFINDER_LOGE(TAG, "deviceId is error");
|
|
free(infoV2);
|
|
return NULL;
|
|
}
|
|
|
|
len = strnlen(localDeviceInfo->name, NSTACKX_MAX_DEVICE_NAME_LEN);
|
|
if (len >= NSTACKX_MAX_DEVICE_NAME_LEN) {
|
|
DFINDER_LOGE(TAG, "name is error");
|
|
free(infoV2);
|
|
return NULL;
|
|
}
|
|
infoV2->deviceId = DeviceStrCreate(localDeviceInfo->deviceId, NSTACKX_MAX_DEVICE_ID_LEN);
|
|
if (infoV2->deviceId == NULL) {
|
|
DFINDER_LOGE(TAG, "DeviceStrCreate deviceId is error");
|
|
RegisterInfoFree(infoV2);
|
|
return NULL;
|
|
}
|
|
infoV2->name = DeviceStrCreate(localDeviceInfo->name, NSTACKX_MAX_DEVICE_NAME_LEN);
|
|
if (infoV2->name == NULL) {
|
|
DFINDER_LOGE(TAG, "DeviceStrCreate name is error");
|
|
RegisterInfoFree(infoV2);
|
|
return NULL;
|
|
}
|
|
|
|
NSTACKX_InterfaceInfo *info = (NSTACKX_InterfaceInfo *)calloc(localDeviceInfo->ifNums,
|
|
sizeof(NSTACKX_InterfaceInfo));
|
|
if (info == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc info is error");
|
|
RegisterInfoFree(infoV2);
|
|
return NULL;
|
|
}
|
|
(void)memcpy_s(info, localDeviceInfo->ifNums * sizeof(NSTACKX_InterfaceInfo),
|
|
localDeviceInfo->localIfInfo, localDeviceInfo->ifNums * sizeof(NSTACKX_InterfaceInfo));
|
|
infoV2->localIfInfo = info;
|
|
infoV2->businessType = localDeviceInfo->businessType;
|
|
infoV2->deviceHash = localDeviceInfo->deviceHash;
|
|
infoV2->deviceType = localDeviceInfo->deviceType;
|
|
infoV2->ifNums = localDeviceInfo->ifNums;
|
|
infoV2->hasDeviceHash = localDeviceInfo->hasDeviceHash;
|
|
return infoV2;
|
|
}
|
|
|
|
static struct RegDeviceInfo *RegisterDeviceCreate(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo, int registerType)
|
|
{
|
|
struct RegDeviceInfo *regInfo = (struct RegDeviceInfo *)calloc(1u, sizeof(struct RegDeviceInfo));
|
|
if (regInfo == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc register info failed");
|
|
return NULL;
|
|
}
|
|
|
|
regInfo->info = RegisterInfoCreate(localDeviceInfo);
|
|
if (regInfo->info == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc infov2 failed");
|
|
free(regInfo);
|
|
return NULL;
|
|
}
|
|
regInfo->registerType = registerType;
|
|
return regInfo;
|
|
}
|
|
|
|
static int32_t RegisterDeviceWithType(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo, int registerType)
|
|
{
|
|
if (localDeviceInfo == NULL || localDeviceInfo->name == NULL ||
|
|
localDeviceInfo->deviceId == NULL || localDeviceInfo->ifNums > NSTACKX_MAX_LOCAL_IFACE_NUM ||
|
|
(localDeviceInfo->ifNums != 0 && localDeviceInfo->localIfInfo == NULL) ||
|
|
CheckInterfaceInfo(localDeviceInfo->localIfInfo, localDeviceInfo->ifNums) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "invalid args");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
return (int32_t)RegisterLocalDeviceV2(localDeviceInfo, registerType);
|
|
}
|
|
|
|
struct RegDeviceInfo *regInfo = RegisterDeviceCreate(localDeviceInfo, registerType);
|
|
if (regInfo == NULL) {
|
|
DFINDER_LOGE(TAG, "Failed to create device info!");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
// The abnormal branch regInfo is released internally.
|
|
if (NSTACKX_PostEventBlock(RegisterDeviceV2, (void*)regInfo, RegisterDeviceFree) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to configure local device info!");
|
|
return NSTACKX_EBUSY;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterDeviceV2(const NSTACKX_LocalDeviceInfoV2 *localDeviceInfo)
|
|
{
|
|
Coverity_Tainted_Set((void *)localDeviceInfo);
|
|
DFINDER_LOGI(TAG, "NSTACKX_RegisterDeviceV2 begin!");
|
|
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
int registerType = (localDeviceInfo != NULL &&
|
|
localDeviceInfo->ifNums == SINGLE_NIC_CNT) ? REGISTER_TYPE_UPDATE_SPECIFIED : REGISTER_TYPE_UPDATE_ALL;
|
|
return RegisterDeviceWithType(localDeviceInfo, registerType);
|
|
}
|
|
|
|
typedef struct {
|
|
uint32_t capabilityBitmapNum;
|
|
uint32_t capabilityBitmap[NSTACKX_MAX_CAPABILITY_NUM];
|
|
} CapabilityProcessData;
|
|
|
|
static void RegisterCapabilityInner(void *argument)
|
|
{
|
|
CapabilityProcessData *capabilityData = argument;
|
|
|
|
(void)SetLocalDeviceCapability(capabilityData->capabilityBitmapNum, capabilityData->capabilityBitmap);
|
|
free(capabilityData);
|
|
}
|
|
|
|
static void SetFilterCapabilityInner(void *argument)
|
|
{
|
|
CapabilityProcessData *capabilityData = argument;
|
|
|
|
(void)SetFilterCapability(capabilityData->capabilityBitmapNum, capabilityData->capabilityBitmap);
|
|
free(capabilityData);
|
|
}
|
|
|
|
static int32_t NSTACKX_CapabilityHandle(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[], EventHandle handle)
|
|
{
|
|
Coverity_Tainted_Set((void *)&capabilityBitmapNum);
|
|
Coverity_Tainted_Set((void *)capabilityBitmap);
|
|
|
|
CapabilityProcessData *capabilityData = NULL;
|
|
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (capabilityBitmapNum != 0 && capabilityBitmap == NULL) {
|
|
DFINDER_LOGE(TAG, "bitmap array is null");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (capabilityBitmapNum > NSTACKX_MAX_CAPABILITY_NUM) {
|
|
DFINDER_LOGE(TAG, "capabilityBitmapNum (%u) exceed max number", capabilityBitmapNum);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
if (handle == RegisterCapabilityInner) {
|
|
return (int32_t)SetLocalDeviceCapability(capabilityBitmapNum, capabilityBitmap);
|
|
}
|
|
if (handle == SetFilterCapabilityInner) {
|
|
return SetFilterCapability(capabilityBitmapNum, capabilityBitmap);
|
|
}
|
|
}
|
|
|
|
capabilityData = calloc(1U, sizeof(CapabilityProcessData));
|
|
if (capabilityData == NULL) {
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
|
|
if ((capabilityBitmapNum != 0) && memcpy_s(capabilityData->capabilityBitmap,
|
|
sizeof(capabilityData->capabilityBitmap), capabilityBitmap, capabilityBitmapNum * sizeof(uint32_t)) != EOK) {
|
|
free(capabilityData);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
capabilityData->capabilityBitmapNum = capabilityBitmapNum;
|
|
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, handle, capabilityData) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to register capability!");
|
|
free(capabilityData);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
|
|
{
|
|
DFINDER_LOGD(TAG, "begin to call NSTACKX_RegisterCapability");
|
|
return NSTACKX_CapabilityHandle(capabilityBitmapNum, capabilityBitmap, RegisterCapabilityInner);
|
|
}
|
|
|
|
int32_t NSTACKX_SetFilterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
|
|
{
|
|
DFINDER_LOGI(TAG, "Set Filter Capability");
|
|
return NSTACKX_CapabilityHandle(capabilityBitmapNum, capabilityBitmap, SetFilterCapabilityInner);
|
|
}
|
|
|
|
static void SetMaxDeviceNumInner(void *argument)
|
|
{
|
|
SetMaxDeviceNum((uint32_t)(uintptr_t)(argument));
|
|
}
|
|
|
|
int32_t NSTACKX_SetMaxDeviceNum(uint32_t maxDeviceNum)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
SetMaxDeviceNum(maxDeviceNum);
|
|
return NSTACKX_EOK;
|
|
}
|
|
if (NSTACKX_PostEventBlock(SetMaxDeviceNumInner, (void *)(uintptr_t)maxDeviceNum, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to set max device num!");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
#ifdef DFINDER_SAVE_DEVICE_LIST
|
|
int32_t NSTACKX_SetDeviceListAgingTime(uint32_t agingTime)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
SetDeviceListAgingTime(agingTime);
|
|
return NSTACKX_EOK;
|
|
}
|
|
#else
|
|
int32_t NSTACKX_SetDeviceListAgingTime(uint32_t agingTime)
|
|
{
|
|
(void)agingTime;
|
|
DFINDER_LOGE(TAG, "device list not supported");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
#endif /* END OF DFINDER_SAVE_DEVICE_LIST */
|
|
|
|
int32_t NSTACKX_ScreenStatusChange(bool isScreenOn)
|
|
{
|
|
#ifdef DFINDER_SUPPORT_SET_SCREEN_STATUS
|
|
SetScreenStatus(isScreenOn);
|
|
DFINDER_LOGI(TAG, "set isScreenOn status %d", isScreenOn);
|
|
#else
|
|
(void)isScreenOn;
|
|
DFINDER_LOGI(TAG, "do not support set screen status");
|
|
#endif
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static void RegisterServiceDataInner(void *argument)
|
|
{
|
|
char *serviceData = argument;
|
|
if (SetLocalDeviceServiceData(serviceData) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "RegisterServiceData failed");
|
|
}
|
|
free(serviceData);
|
|
}
|
|
|
|
static bool RegisterServiceDataParamCheck(const struct NSTACKX_ServiceData *param, uint32_t cnt)
|
|
{
|
|
uint32_t i;
|
|
if (param == NULL) {
|
|
DFINDER_LOGE(TAG, "param is null");
|
|
return false;
|
|
}
|
|
|
|
if (cnt == 0 || cnt >= MAX_COAP_SERVICE_DATA_CNT) {
|
|
DFINDER_LOGE(TAG, "cnt is error");
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
size_t len = strnlen(param[i].serviceData, NSTACKX_MAX_SERVICE_DATA_LEN);
|
|
if (len == NSTACKX_MAX_SERVICE_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "param[%u] serviceData is error, no terminator", i);
|
|
return false;
|
|
}
|
|
|
|
len = strnlen(param[i].ip, NSTACKX_MAX_IP_STRING_LEN);
|
|
if (len == NSTACKX_MAX_IP_STRING_LEN) {
|
|
DFINDER_LOGE(TAG, "param[%u] ip is error, no terminator", i);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
struct ServiceDataInfo {
|
|
struct NSTACKX_ServiceData *param;
|
|
uint32_t cnt;
|
|
int32_t err;
|
|
};
|
|
|
|
static void RegisterServiceDataV2(void *arg)
|
|
{
|
|
struct ServiceDataInfo *info = (struct ServiceDataInfo *)arg;
|
|
info->err = SetLocalDeviceServiceDataV2(info->param, info->cnt);
|
|
}
|
|
|
|
static struct ServiceDataInfo *ServiceDataV2Create(const struct NSTACKX_ServiceData *param,
|
|
uint32_t cnt)
|
|
{
|
|
struct ServiceDataInfo *info = (struct ServiceDataInfo *)calloc(1u, sizeof(struct ServiceDataInfo));
|
|
if (info == NULL) {
|
|
DFINDER_LOGE(TAG, "create info failed");
|
|
return NULL;
|
|
}
|
|
|
|
struct NSTACKX_ServiceData *data = (struct NSTACKX_ServiceData *)calloc(cnt, sizeof(struct NSTACKX_ServiceData));
|
|
if (data == NULL) {
|
|
free(info);
|
|
DFINDER_LOGE(TAG, "create data failed");
|
|
return NULL;
|
|
}
|
|
(void)memcpy_s(data, cnt * sizeof(struct NSTACKX_ServiceData),
|
|
param, cnt * sizeof(struct NSTACKX_ServiceData));
|
|
info->param = data;
|
|
info->cnt = cnt;
|
|
return info;
|
|
}
|
|
|
|
static void ServiceDataV2Free(void *arg)
|
|
{
|
|
if (arg == NULL) {
|
|
return;
|
|
}
|
|
struct ServiceDataInfo *info = (struct ServiceDataInfo *)arg;
|
|
free(info->param);
|
|
info->param = NULL;
|
|
free(info);
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterServiceDataV2(const struct NSTACKX_ServiceData *param, uint32_t cnt)
|
|
{
|
|
DFINDER_LOGI(TAG, "begin to call NSTACKX_RegisterServiceDataV2");
|
|
if (!RegisterServiceDataParamCheck(param, cnt)) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
return SetLocalDeviceServiceDataV2(param, cnt);
|
|
}
|
|
|
|
struct ServiceDataInfo *info = ServiceDataV2Create(param, cnt);
|
|
if (info == NULL) {
|
|
DFINDER_LOGE(TAG, "create info failed");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
// The abnormal branch info is released internally.
|
|
if (NSTACKX_PostEventBlock(RegisterServiceDataV2, (void *)info, ServiceDataV2Free) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to register serviceDatav2!");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterServiceData(const char *serviceData)
|
|
{
|
|
Coverity_Tainted_Set((void *)serviceData);
|
|
|
|
DFINDER_LOGD(TAG, "begin to call NSTACKX_RegisterServiceData");
|
|
char *serviceDataTmp = NULL;
|
|
|
|
if (serviceData == NULL) {
|
|
DFINDER_LOGE(TAG, "serviceData is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
size_t len = strnlen(serviceData, NSTACKX_MAX_SERVICE_DATA_LEN);
|
|
if (len >= NSTACKX_MAX_SERVICE_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "serviceData len %zu is err", len);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
return SetLocalDeviceServiceData(serviceData);
|
|
}
|
|
|
|
serviceDataTmp = calloc(1U, NSTACKX_MAX_SERVICE_DATA_LEN);
|
|
if (serviceDataTmp == NULL) {
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (strncpy_s(serviceDataTmp, NSTACKX_MAX_SERVICE_DATA_LEN, serviceData, len) != EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to copy serviceData");
|
|
free(serviceDataTmp);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterServiceDataInner, serviceDataTmp) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to register serviceData!");
|
|
free(serviceDataTmp);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static void RegisterBusinessDataInner(void *argument)
|
|
{
|
|
DFINDER_LOGI(TAG, "Register Business Data Inner");
|
|
char *businessData = argument;
|
|
if (SetLocalDeviceBusinessData(businessData, NSTACKX_TRUE) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "RegisterBusinessData failed");
|
|
}
|
|
free(businessData);
|
|
}
|
|
|
|
int32_t NSTACKX_RegisterBusinessData(const char *businessData)
|
|
{
|
|
DFINDER_LOGI(TAG, "begin to call NSTACKX_RegisterBusinessData");
|
|
|
|
char *businessDataTmp = NULL;
|
|
if (businessData == NULL) {
|
|
DFINDER_LOGE(TAG, "businessData is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
size_t len = strnlen(businessData, NSTACKX_MAX_BUSINESS_DATA_LEN);
|
|
if (len >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "businessData (%zu) exceed max number", len);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
return (int32_t)SetLocalDeviceBusinessData(businessData, NSTACKX_TRUE);
|
|
}
|
|
|
|
businessDataTmp = calloc(1, NSTACKX_MAX_BUSINESS_DATA_LEN);
|
|
if (businessDataTmp == NULL) {
|
|
DFINDER_LOGE(TAG, "businessDataTmp is null");
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (strncpy_s(businessDataTmp, NSTACKX_MAX_BUSINESS_DATA_LEN, businessData, len) != EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to copy businessData");
|
|
free(businessDataTmp);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterBusinessDataInner, businessDataTmp) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to register businessData!");
|
|
free(businessDataTmp);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
static void RegisterExtendServiceDataInner(void *argument)
|
|
{
|
|
char *extendServiceData = argument;
|
|
if (SetLocalDeviceExtendServiceData(extendServiceData) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "RegisterExtendServiceData failed");
|
|
}
|
|
free(extendServiceData);
|
|
}
|
|
#endif
|
|
|
|
int32_t NSTACKX_RegisterExtendServiceData(const char *extendServiceData)
|
|
{
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
char *extendServiceDataTmp = NULL;
|
|
|
|
if (extendServiceData == NULL) {
|
|
DFINDER_LOGE(TAG, "extendServiceData is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
size_t len = strnlen(extendServiceData, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN);
|
|
if (len >= NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "extendServiceData len %zu is error", len);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
return SetLocalDeviceExtendServiceData(extendServiceData);
|
|
}
|
|
|
|
extendServiceDataTmp = calloc(1, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN);
|
|
if (extendServiceDataTmp == NULL) {
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (strncpy_s(extendServiceDataTmp, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN, extendServiceData, len) != EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to copy extendServiceData");
|
|
free(extendServiceDataTmp);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, RegisterExtendServiceDataInner, extendServiceDataTmp) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to register extendServiceData!");
|
|
free(extendServiceDataTmp);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
#else
|
|
(void)extendServiceData;
|
|
DFINDER_LOGI(TAG, "NSTACKX_RegisterExtendServiceData not supported");
|
|
return NSTACKX_EOK;
|
|
#endif
|
|
}
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
struct DirectMsgCtx {
|
|
MsgCtx msg;
|
|
const char *ipStr;
|
|
struct in_addr ip;
|
|
};
|
|
|
|
static void SendMsgDirectInner(void *arg)
|
|
{
|
|
struct DirectMsgCtx *msg = arg;
|
|
DFINDER_LOGD(TAG, "Enter WifiDirect send");
|
|
msg->msg.err = CoapSendServiceMsg(&msg->msg, msg->ipStr, &msg->ip);
|
|
SemPost(&msg->msg.wait);
|
|
}
|
|
|
|
static int32_t NSTACKX_SendMsgParamCheck(const char *moduleName, const char *deviceId, const uint8_t *data,
|
|
uint32_t len)
|
|
{
|
|
if (moduleName == NULL || strnlen(moduleName, NSTACKX_MAX_MODULE_NAME_LEN) > NSTACKX_MAX_MODULE_NAME_LEN) {
|
|
DFINDER_LOGE(TAG, "Invalid module name");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (deviceId == NULL || strnlen(deviceId, NSTACKX_MAX_DEVICE_ID_LEN) > NSTACKX_MAX_DEVICE_ID_LEN) {
|
|
DFINDER_LOGE(TAG, "Invalid device id");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (data == NULL || len == 0 || len > NSTACKX_MAX_SENDMSG_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "Null data to send");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int MsgCtxInit(MsgCtx *msg, const char *moduleName, const char *deviceId, const uint8_t *data, uint32_t len)
|
|
{
|
|
if (SemInit(&msg->wait, 0, 0)) {
|
|
DFINDER_LOGE(TAG, "sem init fail");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
msg->deviceId = deviceId;
|
|
msg->moduleName = moduleName;
|
|
msg->data = data;
|
|
msg->len = len;
|
|
msg->err = NSTACKX_EOK;
|
|
|
|
return NSTACKX_EOK;
|
|
}
|
|
#endif
|
|
|
|
int32_t NSTACKX_SendMsgDirect(const char *moduleName, const char *deviceId, const uint8_t *data,
|
|
uint32_t len, const char *ipaddr, uint8_t type)
|
|
{
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
int32_t ret = NSTACKX_EOK;
|
|
DFINDER_LOGD(TAG, "NSTACKX_SendMsgDirect");
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (ipaddr == NULL) {
|
|
DFINDER_LOGE(TAG, "ipaddr needed");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (type > SERVER_TYPE_USB) {
|
|
DFINDER_LOGE(TAG, "invalid type %hhu", type);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (NSTACKX_SendMsgParamCheck(moduleName, deviceId, data, len) != NSTACKX_EOK) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
struct DirectMsgCtx directMsg;
|
|
if (inet_pton(AF_INET, ipaddr, &directMsg.ip) != 1 || directMsg.ip.s_addr == 0) {
|
|
DFINDER_LOGE(TAG, "invalid ip addr");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
directMsg.ipStr = ipaddr;
|
|
directMsg.msg.type = type;
|
|
if (MsgCtxInit(&directMsg.msg, moduleName, deviceId, data, len) != NSTACKX_EOK) {
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, SendMsgDirectInner, &directMsg) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to send msg");
|
|
ret = NSTACKX_EFAILED;
|
|
}
|
|
if (ret == NSTACKX_EOK) {
|
|
SemWait(&directMsg.msg.wait);
|
|
ret = directMsg.msg.err;
|
|
}
|
|
SemDestroy(&directMsg.msg.wait);
|
|
return ret;
|
|
#else
|
|
(void)moduleName;
|
|
(void)deviceId;
|
|
(void)data;
|
|
(void)len;
|
|
(void)ipaddr;
|
|
(void)type;
|
|
DFINDER_LOGI(TAG, "NSTACKX_SendMsgDirect not supported");
|
|
return NSTACKX_EFAILED;
|
|
#endif
|
|
}
|
|
|
|
#if defined(DFINDER_SAVE_DEVICE_LIST) && !defined(DFINDER_USE_MINI_NSTACKX)
|
|
static void SendMsgInner(void *arg)
|
|
{
|
|
MsgCtx *msg = arg;
|
|
const struct in_addr *remoteIp = GetRemoteDeviceIp(msg->deviceId);
|
|
if (remoteIp == NULL) {
|
|
DFINDER_LOGE(TAG, "no device found");
|
|
msg->err = NSTACKX_EINVAL;
|
|
} else {
|
|
char ipStr[INET_ADDRSTRLEN] = {0};
|
|
if (inet_ntop(AF_INET, remoteIp, ipStr, sizeof(ipStr)) != NULL) {
|
|
msg->err = CoapSendServiceMsg(msg, ipStr, remoteIp);
|
|
} else {
|
|
DFINDER_LOGE(TAG, "ip format failed");
|
|
}
|
|
}
|
|
|
|
SemPost(&msg->wait);
|
|
}
|
|
#endif
|
|
|
|
int32_t NSTACKX_SendMsg(const char *moduleName, const char *deviceId, const uint8_t *data, uint32_t len)
|
|
{
|
|
Coverity_Tainted_Set((void *)moduleName);
|
|
Coverity_Tainted_Set((void *)deviceId);
|
|
Coverity_Tainted_Set((void *)data);
|
|
Coverity_Tainted_Set((void *)&len);
|
|
#if defined(DFINDER_SAVE_DEVICE_LIST) && !defined(DFINDER_USE_MINI_NSTACKX)
|
|
int32_t ret = NSTACKX_EOK;
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (NSTACKX_SendMsgParamCheck(moduleName, deviceId, data, len) != NSTACKX_EOK) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
MsgCtx msg;
|
|
msg.type = INVALID_TYPE;
|
|
if (MsgCtxInit(&msg, moduleName, deviceId, data, len) != NSTACKX_EOK) {
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, SendMsgInner, &msg) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "failed to send msg");
|
|
ret = NSTACKX_EFAILED;
|
|
}
|
|
if (ret == NSTACKX_EOK) {
|
|
SemWait(&msg.wait);
|
|
ret = msg.err;
|
|
}
|
|
SemDestroy(&msg.wait);
|
|
return ret;
|
|
#else
|
|
(void)moduleName;
|
|
(void)deviceId;
|
|
(void)data;
|
|
(void)len;
|
|
DFINDER_LOGI(TAG, "SendMsg not supported");
|
|
return NSTACKX_EFAILED;
|
|
#endif
|
|
}
|
|
|
|
static void SendDiscoveryRspInner(void *arg)
|
|
{
|
|
NSTACKX_ResponseSettings *responseSettings = arg;
|
|
SendDiscoveryRsp(responseSettings);
|
|
free(responseSettings->businessData);
|
|
free(responseSettings);
|
|
}
|
|
|
|
static int32_t CopyResponseSettings(NSTACKX_ResponseSettings *dupResponseSettings,
|
|
const NSTACKX_ResponseSettings *responseSettings)
|
|
{
|
|
dupResponseSettings->businessType = responseSettings->businessType;
|
|
dupResponseSettings->length = responseSettings->length;
|
|
if (responseSettings->businessData != NULL) {
|
|
if (strncpy_s(dupResponseSettings->businessData, (dupResponseSettings->length + 1),
|
|
responseSettings->businessData, responseSettings->length) != EOK) {
|
|
DFINDER_LOGE(TAG, "businessData strncpy failed");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
}
|
|
// strlen is check in CheckResponseSettings
|
|
if (strncpy_s(dupResponseSettings->localNetworkName, NSTACKX_MAX_INTERFACE_NAME_LEN,
|
|
responseSettings->localNetworkName, strlen(responseSettings->localNetworkName)) != EOK) {
|
|
DFINDER_LOGE(TAG, "localNetworkName strncpy failed");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (strncpy_s(dupResponseSettings->remoteIp, NSTACKX_MAX_IP_STRING_LEN,
|
|
responseSettings->remoteIp, strlen(responseSettings->remoteIp)) != EOK) {
|
|
DFINDER_LOGE(TAG, "remoteIp strncpy failed");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t CheckResponseSettings(const NSTACKX_ResponseSettings *responseSettings)
|
|
{
|
|
if (responseSettings == NULL) {
|
|
DFINDER_LOGE(TAG, "Invalid responseSettings info");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if ((responseSettings->businessData == NULL) && (responseSettings->length != 0)) {
|
|
DFINDER_LOGE(TAG, "Invalid responseSettings bData info");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (responseSettings->length >= NSTACKX_MAX_BUSINESS_DATA_LEN) {
|
|
DFINDER_LOGE(TAG, "businessData length is too long");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (strnlen(responseSettings->localNetworkName, NSTACKX_MAX_INTERFACE_NAME_LEN) >=
|
|
NSTACKX_MAX_INTERFACE_NAME_LEN) {
|
|
DFINDER_LOGE(TAG, "businessData is error, no terminator");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (strnlen(responseSettings->remoteIp, NSTACKX_MAX_IP_STRING_LEN) >=
|
|
NSTACKX_MAX_IP_STRING_LEN) {
|
|
DFINDER_LOGE(TAG, "remoteIp is error, no terminator");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
int32_t NSTACKX_SendDiscoveryRsp(const NSTACKX_ResponseSettings *responseSettings)
|
|
{
|
|
DFINDER_LOGI(TAG, "begin to NSTACKX_SendDiscoveryRsp!");
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (CheckResponseSettings(responseSettings) != NSTACKX_EOK) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
DFINDER_LOGI(TAG, "response settings, business type: %hu, local network name: %s",
|
|
responseSettings->businessType, responseSettings->localNetworkName);
|
|
|
|
NSTACKX_ResponseSettings *dupResponseSettings = malloc(sizeof(NSTACKX_ResponseSettings));
|
|
if (dupResponseSettings == NULL) {
|
|
DFINDER_LOGE(TAG, "malloc failed");
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
dupResponseSettings->businessData = (char *)calloc((responseSettings->length + 1), sizeof(char));
|
|
if (dupResponseSettings->businessData == NULL) {
|
|
DFINDER_LOGE(TAG, "businessData calloc failed");
|
|
free(dupResponseSettings);
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (CopyResponseSettings(dupResponseSettings, responseSettings) != NSTACKX_EOK) {
|
|
free(dupResponseSettings->businessData);
|
|
free(dupResponseSettings);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, SendDiscoveryRspInner, dupResponseSettings) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to send responseSettings info!");
|
|
free(dupResponseSettings->businessData);
|
|
free(dupResponseSettings);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
#ifdef DFINDER_SAVE_DEVICE_LIST
|
|
static void GetDeviceListInner(void *argument)
|
|
{
|
|
GetDeviceListMessage *message = argument;
|
|
|
|
GetDeviceList(message->deviceList, message->deviceCountPtr, true);
|
|
SemPost(&message->wait);
|
|
}
|
|
#endif
|
|
|
|
int32_t NSTACKX_GetDeviceList(NSTACKX_DeviceInfo *deviceList, uint32_t *deviceCountPtr)
|
|
{
|
|
#ifdef DFINDER_SAVE_DEVICE_LIST
|
|
GetDeviceListMessage message = {
|
|
.deviceList = deviceList,
|
|
.deviceCountPtr = deviceCountPtr,
|
|
};
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (deviceList == NULL || deviceCountPtr == NULL) {
|
|
DFINDER_LOGE(TAG, "Device list or count pointer is NULL");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
GetDeviceList(deviceList, deviceCountPtr, true);
|
|
return NSTACKX_EOK;
|
|
}
|
|
if (SemInit(&message.wait, 0, 0)) {
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, GetDeviceListInner, &message) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to get device list");
|
|
SemDestroy(&message.wait);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
SemWait(&message.wait);
|
|
SemDestroy(&message.wait);
|
|
return NSTACKX_EOK;
|
|
#else
|
|
(void)deviceList;
|
|
(void)deviceCountPtr;
|
|
|
|
DFINDER_LOGE(TAG, "device list not supported");
|
|
|
|
return NSTACKX_EFAILED;
|
|
#endif /* END OF DFINDER_SAVE_DEVICE_LIST */
|
|
}
|
|
|
|
void NotifyDeviceListChanged(const NSTACKX_DeviceInfo *deviceList, uint32_t deviceCount)
|
|
{
|
|
if (g_parameter.onDeviceListChanged != NULL) {
|
|
DFINDER_LOGI(TAG, "notify callback: device list changed");
|
|
g_parameter.onDeviceListChanged(deviceList, deviceCount);
|
|
DFINDER_LOGI(TAG, "finish to notify device list changed");
|
|
} else {
|
|
DFINDER_LOGI(TAG, "notify callback: device list changed callback is null");
|
|
}
|
|
}
|
|
|
|
void NotifyDeviceFound(const NSTACKX_DeviceInfo *deviceList, uint32_t deviceCount)
|
|
{
|
|
if (g_parameter.onDeviceFound != NULL) {
|
|
DFINDER_LOGI(TAG, "notify callback: device found");
|
|
g_parameter.onDeviceFound(deviceList, deviceCount);
|
|
DFINDER_LOGI(TAG, "finish to notify device found");
|
|
} else {
|
|
DFINDER_LOGI(TAG, "notify callback: device found callback is null");
|
|
}
|
|
}
|
|
|
|
void NotificationReceived(const NSTACKX_NotificationConfig *notification)
|
|
{
|
|
if (g_parameter.onNotificationReceived != NULL) {
|
|
DFINDER_LOGI(TAG, "notify callback: notification received");
|
|
g_parameter.onNotificationReceived(notification);
|
|
DFINDER_LOGI(TAG, "finish to notify notification received");
|
|
} else {
|
|
DFINDER_LOGI(TAG, "notify callback: notification received callback is null");
|
|
}
|
|
}
|
|
|
|
#ifndef DFINDER_USE_MINI_NSTACKX
|
|
void NotifyMsgReceived(const char *moduleName, const char *deviceId, const uint8_t *data,
|
|
uint32_t len, const char *srcIp)
|
|
{
|
|
if (g_parameter.onMsgReceived != NULL) {
|
|
DFINDER_LOGI(TAG, "notify callback: message received, data length %u", len);
|
|
g_parameter.onMsgReceived(moduleName, deviceId, data, len, srcIp);
|
|
DFINDER_LOGI(TAG, "finish to notify msg received");
|
|
} else {
|
|
DFINDER_LOGI(TAG, "notify callback: message received callback is null");
|
|
}
|
|
}
|
|
|
|
int32_t NSTACKX_InitRestart(const NSTACKX_Parameter *parameter)
|
|
{
|
|
Coverity_Tainted_Set((void *)parameter);
|
|
|
|
#if defined(_WIN32) || defined(DFINDER_USE_MINI_NSTACKX)
|
|
DFINDER_LOGE(TAG, "do not support init restart");
|
|
(void)parameter;
|
|
return NSTACKX_EFAILED;
|
|
#else
|
|
DFINDER_LOGI(TAG, "NSTACKX_InitRestart");
|
|
int32_t ret = NSTACKX_Init(parameter);
|
|
if (ret == NSTACKX_EOK) {
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, DetectLocalIface, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to GetLocalNetworkInterface");
|
|
}
|
|
}
|
|
return ret;
|
|
#endif
|
|
}
|
|
|
|
static void DeviceDiscoverInnerRestart(void *argument)
|
|
{
|
|
(void)argument;
|
|
CoapServiceDiscoverInner(NSTACKX_FALSE);
|
|
}
|
|
|
|
void NSTACKX_StartDeviceFindRestart(void)
|
|
{
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return;
|
|
}
|
|
DFINDER_LOGI(TAG, "start device find for restart");
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, DeviceDiscoverInnerRestart, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "Failed to start device discover!");
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
#endif /* END OF DFINDER_USE_MINI_NSTACKX */
|
|
|
|
#ifdef ENABLE_USER_LOG
|
|
int32_t NSTACKX_DFinderRegisterLog(DFinderLogCallback userLogCallback)
|
|
{
|
|
if (userLogCallback == NULL) {
|
|
DFINDER_LOGE(TAG, "logImpl null");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
int32_t ret = SetLogCallback(userLogCallback);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifdef NSTACKX_DFINDER_HIDUMP
|
|
#define MAX_DUMP_ARGC 10
|
|
int NSTACKX_DFinderDump(const char **argv, uint32_t argc, void *softObj, DFinderDumpFunc dump)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
|
|
if (dump == NULL) {
|
|
DFINDER_LOGE(TAG, "dump is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (argc == 0 || argc > MAX_DUMP_ARGC) {
|
|
DFINDER_LOGE(TAG, "argc is invalid %u", argc);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
if (argv == NULL) {
|
|
DFINDER_LOGE(TAG, "argv is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
|
|
uint32_t i;
|
|
for (i = 0; i < argc; i++) {
|
|
if (argv[i] == NULL) {
|
|
DFINDER_LOGE(TAG, "argv[%u] is null", i);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
}
|
|
|
|
return DFinderDump(argv, argc, softObj, dump);
|
|
}
|
|
#else
|
|
int NSTACKX_DFinderDump(const char **argv, uint32_t argc, void *softObj, DFinderDumpFunc dump)
|
|
{
|
|
(void)argv;
|
|
(void)argc;
|
|
(void)softObj;
|
|
(void)dump;
|
|
DFINDER_LOGE(TAG, "unsupport dfinder dump");
|
|
return NSTACKX_NOTSUPPORT;
|
|
}
|
|
#endif
|
|
|
|
int NSTACKX_DFinderSetEventFunc(void *softobj, DFinderEventFunc func)
|
|
{
|
|
if (g_nstackInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "NSTACKX_Ctrl is not initiated yet");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
return SetEventFuncDirectly(softobj, func);
|
|
}
|
|
|
|
return SetEventFunc(softobj, func);
|
|
}
|
|
|
|
static int32_t CheckNotificationConfig(const NSTACKX_NotificationConfig *config)
|
|
{
|
|
if (config == NULL) {
|
|
DFINDER_LOGE(TAG, "notification config passed in is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (config->businessType >= NSTACKX_BUSINESS_TYPE_MAX) {
|
|
DFINDER_LOGE(TAG, "invalid business type %hhu in notification config", config->businessType);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (config->msg == NULL) {
|
|
DFINDER_LOGE(TAG, "msg in notification config is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
size_t len = strnlen(config->msg, NSTACKX_MAX_NOTIFICATION_DATA_LEN);
|
|
if (len >= NSTACKX_MAX_NOTIFICATION_DATA_LEN || len != config->msgLen || config->msgLen == 0) {
|
|
DFINDER_LOGE(TAG, "actual msg len %zu, msg len %zu in config", len, config->msgLen);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
// advertise count: [0, 100], first interval in intervalMs should be 0
|
|
if (config->intervalLen == 0 || config->intervalLen > NSTACKX_MAX_ADVERTISE_COUNT) {
|
|
DFINDER_LOGE(TAG, "invalid interval len %hhu in notification config, max support %d",
|
|
config->intervalLen, NSTACKX_MAX_ADVERTISE_COUNT);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (config->intervalsMs == NULL) {
|
|
DFINDER_LOGE(TAG, "broadcast intervals in notification config is null");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
// interval: [0 ms, 10000 ms]
|
|
if (config->intervalsMs[0] != 0) {
|
|
DFINDER_LOGE(TAG, "first interval should be 0 to indicate send notification immediately");
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
for (size_t i = 1; i < config->intervalLen; ++i) {
|
|
if (config->intervalsMs[i] < NSTACKX_MIN_ADVERTISE_INTERVAL ||
|
|
config->intervalsMs[i] > NSTACKX_MAX_ADVERTISE_INTERVAL) {
|
|
DFINDER_LOGE(TAG, "invalid interval[%zu] = %hu, support max: %d min: %d",
|
|
i, config->intervalsMs[i], NSTACKX_MAX_ADVERTISE_INTERVAL, NSTACKX_MIN_ADVERTISE_INTERVAL);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static int32_t CopyNotificationConfig(NSTACKX_NotificationConfig *dst, const NSTACKX_NotificationConfig *src)
|
|
{
|
|
dst->businessType = src->businessType;
|
|
if (strncpy_s(dst->msg, src->msgLen + 1, src->msg, src->msgLen) != EOK) {
|
|
DFINDER_LOGE(TAG, "copy notification msg to duplicated one fail");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
dst->msgLen = src->msgLen;
|
|
for (size_t i = 0; i < src->intervalLen; ++i) {
|
|
(dst->intervalsMs)[i] = (src->intervalsMs)[i];
|
|
}
|
|
dst->intervalLen = src->intervalLen;
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static void NotificationInner(void *argument)
|
|
{
|
|
NSTACKX_NotificationConfig *config = (NSTACKX_NotificationConfig *)argument;
|
|
int32_t retMsg = LocalizeNotificationMsg(config->msg);
|
|
int32_t retInterval = LocalizeNotificationInterval(config->intervalsMs, config->intervalLen);
|
|
free(config->intervalsMs);
|
|
free(config->msg);
|
|
free(config);
|
|
if (retMsg != NSTACKX_EOK || retInterval != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "stop running service notification cause localize config fail");
|
|
return;
|
|
}
|
|
CoapServiceNotification();
|
|
}
|
|
|
|
int32_t NSTACKX_SendNotification(const NSTACKX_NotificationConfig *config)
|
|
{
|
|
DFINDER_LOGI(TAG, "begin to call NSTACKX_SendNotification");
|
|
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "dfinder not inited");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (CheckNotificationConfig(config) != NSTACKX_EOK) {
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
NSTACKX_NotificationConfig *dupConfig = (NSTACKX_NotificationConfig *)calloc(1, sizeof(NSTACKX_NotificationConfig));
|
|
if (dupConfig == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc for notification config fail, size wanted: %zu", sizeof(NSTACKX_NotificationConfig));
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
dupConfig->msg = (char *)calloc((config->msgLen + 1), sizeof(char));
|
|
if (dupConfig->msg == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc for msg in notification fail, size wanted: %zu", config->msgLen + 1);
|
|
free(dupConfig);
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
dupConfig->intervalsMs = (uint16_t *)calloc(config->intervalLen, sizeof(uint16_t));
|
|
if (dupConfig->intervalsMs == NULL) {
|
|
DFINDER_LOGE(TAG, "calloc for intervals fail, size wanted: %zu", sizeof(uint16_t) * (config->intervalLen));
|
|
free(dupConfig->msg);
|
|
free(dupConfig);
|
|
return NSTACKX_ENOMEM;
|
|
}
|
|
if (CopyNotificationConfig(dupConfig, config) != NSTACKX_EOK) {
|
|
free(dupConfig->intervalsMs);
|
|
free(dupConfig->msg);
|
|
free(dupConfig);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, NotificationInner, dupConfig) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "post event failed to run notification inner");
|
|
free(dupConfig->intervalsMs);
|
|
free(dupConfig->msg);
|
|
free(dupConfig);
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|
|
|
|
static void NotificationStop(void *argument)
|
|
{
|
|
(void)argument;
|
|
CoapServiceNotificationStop();
|
|
}
|
|
|
|
int32_t NSTACKX_StopSendNotification(uint8_t businessType)
|
|
{
|
|
DFINDER_LOGI(TAG, "begin to call NSTACKX_StopSendNotification, business type: %hhu", businessType);
|
|
|
|
if (g_nstackThreadInitState != NSTACKX_INIT_STATE_DONE) {
|
|
DFINDER_LOGE(TAG, "dfinder not inited");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
if (businessType >= NSTACKX_BUSINESS_TYPE_MAX) {
|
|
DFINDER_LOGE(TAG, "invalid business type %hhu to stop send notification", businessType);
|
|
return NSTACKX_EINVAL;
|
|
}
|
|
if (PostEvent(&g_eventNodeChain, g_epollfd, NotificationStop, NULL) != NSTACKX_EOK) {
|
|
DFINDER_LOGE(TAG, "post event failed to run stop device discover");
|
|
return NSTACKX_EFAILED;
|
|
}
|
|
return NSTACKX_EOK;
|
|
}
|