#include "iotx_cm_internal.h" #if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED) #include "iotx_cm_mqtt.h" #endif #ifdef COAP_COMM_ENABLED #include "iotx_cm_coap.h" #endif static void *fd_lock = NULL; static iotx_cm_connection_t *_cm_fd[CM_MAX_FD_NUM] = {NULL}; static int _get_fd(iotx_cm_connection_t *handle); static int _recycle_fd(int fd); static int inline _fd_is_valid(int fd); static int inited_conn_num = 0; #ifdef DEVICE_MODEL_MULTI_THREAD static void *_iotx_cm_yield_thread_func(void *params); static void *yield_thread = NULL; static int yield_task_leave = 1; #endif const char ERR_INVALID_PARAMS[] = "invalid parameter"; int iotx_cm_open(iotx_cm_init_param_t *params) { int fd; iotx_cm_connection_t *connection = NULL; switch (params->protocol_type) { case IOTX_CM_PROTOCOL_TYPE_MQTT: #if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED) connection = iotx_cm_open_mqtt(params); #endif break; case IOTX_CM_PROTOCOL_TYPE_COAP: #ifdef COAP_COMM_ENABLED connection = iotx_cm_open_coap(params); #endif break; default: break; } if (connection == NULL) { return STATE_DEV_MODEL_CM_OPEN_FAILED; } fd = _get_fd(connection); if (fd < 0) { connection->close_func(); return fd; } connection->fd = fd; return fd; } int iotx_cm_connect(int fd, uint32_t timeout) { iotx_cm_connect_fp connect_func; int ret; if (_fd_is_valid(fd) < 0) { return STATE_DEV_MODEL_CM_FD_ERROR; } HAL_MutexLock(fd_lock); connect_func = _cm_fd[fd]->connect_func; HAL_MutexUnlock(fd_lock); iotx_event_post(IOTX_CONN_CLOUD); ret = connect_func(timeout); if (ret == 0) { inited_conn_num++; if (inited_conn_num == 1) { #ifdef DEVICE_MODEL_MULTI_THREAD int stack_used; hal_os_thread_param_t task_parms = {0}; task_parms.stack_size = 6144; task_parms.name = "cm_yield"; ret = HAL_ThreadCreate(&yield_thread, _iotx_cm_yield_thread_func, NULL, &task_parms, &stack_used); if (ret < 0) { inited_conn_num--; } #endif } iotx_event_post(IOTX_CONN_CLOUD_SUC); } else { iotx_event_post(IOTX_CONN_CLOUD_FAIL); } return ret; } static int _iotx_cm_yield(int fd, unsigned int timeout) { iotx_cm_yield_fp yield_func; if (fd_lock == NULL) { return STATE_DEV_MODEL_INTERNAL_ERROR; } if (fd == -1) { int i; for (i = 0; i < CM_MAX_FD_NUM; i++) { yield_func = NULL; HAL_MutexLock(fd_lock); if (_cm_fd[i] != NULL) { yield_func = _cm_fd[i]->yield_func; } HAL_MutexUnlock(fd_lock); if (yield_func != NULL) { yield_func(timeout); } } return STATE_SUCCESS; } if (_fd_is_valid(fd) < 0) { return STATE_DEV_MODEL_CM_FD_ERROR; } HAL_MutexLock(fd_lock); yield_func = _cm_fd[fd]->yield_func; HAL_MutexUnlock(fd_lock); return yield_func(timeout); } #ifdef DEVICE_MODEL_MULTI_THREAD static void *_iotx_cm_yield_thread_func(void *params) { yield_task_leave = 0; while (inited_conn_num > 0) { _iotx_cm_yield(-1, CM_DEFAULT_YIELD_TIMEOUT); } yield_task_leave = 1; return NULL; } #endif int iotx_cm_yield(int fd, unsigned int timeout) { #ifdef DEVICE_MODEL_MULTI_THREAD HAL_SleepMs(timeout); return STATE_SUCCESS; #else return _iotx_cm_yield(fd, timeout); #endif } int iotx_cm_sub(int fd, iotx_cm_ext_params_t *ext, const char *topic, iotx_cm_data_handle_cb topic_handle_func, void *pcontext) { iotx_cm_sub_fp sub_func; if (_fd_is_valid(fd) < 0) { return STATE_DEV_MODEL_CM_FD_ERROR; } HAL_MutexLock(fd_lock); sub_func = _cm_fd[fd]->sub_func; HAL_MutexUnlock(fd_lock); return sub_func(ext, topic, topic_handle_func, pcontext); } int iotx_cm_unsub(int fd, const char *topic) { iotx_cm_unsub_fp unsub_func; if (_fd_is_valid(fd) < 0) { return STATE_DEV_MODEL_CM_FD_ERROR; } HAL_MutexLock(fd_lock); unsub_func = _cm_fd[fd]->unsub_func; HAL_MutexUnlock(fd_lock); return unsub_func(topic); } int iotx_cm_pub(int fd, iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len) { iotx_cm_pub_fp pub_func; if (_fd_is_valid(fd) < 0) { return STATE_DEV_MODEL_CM_FD_ERROR; } HAL_MutexLock(fd_lock); pub_func = _cm_fd[fd]->pub_func; HAL_MutexUnlock(fd_lock); return pub_func(ext, topic, payload, payload_len); } int iotx_cm_close(int fd) { iotx_cm_close_fp close_func; if (_fd_is_valid(fd) < 0) { return STATE_DEV_MODEL_CM_FD_ERROR; } if (inited_conn_num > 0) { inited_conn_num--; } if (inited_conn_num == 0) { #ifdef DEVICE_MODEL_MULTI_THREAD while (!yield_task_leave) { HAL_SleepMs(10); } yield_thread = NULL; #endif } HAL_MutexLock(fd_lock); close_func = _cm_fd[fd]->close_func; HAL_MutexUnlock(fd_lock); if (close_func == NULL) { return FAIL_RETURN; } if (close_func() != 0) { return FAIL_RETURN; } if (_recycle_fd(fd) != 0) { return FAIL_RETURN; } if (inited_conn_num == 0) { if (fd_lock != NULL) { HAL_MutexDestroy(fd_lock); fd_lock = NULL; } } return 0; } static int inline _fd_is_valid(int fd) { int ret; if (fd_lock == NULL) { return NULL_VALUE_ERROR; } HAL_MutexLock(fd_lock); ret = (fd >= 0 && fd < CM_MAX_FD_NUM && _cm_fd[fd] != NULL) ? 0 : -1; HAL_MutexUnlock(fd_lock); return ret; } static int _recycle_fd(int fd) { if (fd_lock == NULL) { fd_lock = HAL_MutexCreate(); if (fd_lock == NULL) { return -1; } } if (fd < 0 || fd > CM_MAX_FD_NUM - 1) { return -1; } HAL_MutexLock(fd_lock); _cm_fd[fd] = NULL; HAL_MutexUnlock(fd_lock); return 0; } static int _get_fd(iotx_cm_connection_t *handle) { int i; if (handle == NULL) { return NULL_VALUE_ERROR; } if (fd_lock == NULL) { fd_lock = HAL_MutexCreate(); if (fd_lock == NULL) { return STATE_SYS_DEPEND_MUTEX_CREATE; } } HAL_MutexLock(fd_lock); for (i = 0; i < CM_MAX_FD_NUM; i++) { if (_cm_fd[i] == NULL) { _cm_fd[i] = handle; HAL_MutexUnlock(fd_lock); return i; } } HAL_MutexUnlock(fd_lock); return STATE_DEV_MODEL_CM_FD_NOT_FOUND; }