/** * @file aiot_bootstrap_api.c * @brief Bootstrap模块的API接口实现, 提供获取阿里云物联网平台连接信息的能力 * * @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited * */ #include "bootstrap_private.h" static void _bootstrap_exec_inc(bootstrap_handle_t *bootstrap_handle) { bootstrap_handle->sysdep->core_sysdep_mutex_lock(bootstrap_handle->data_mutex); bootstrap_handle->exec_count++; bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); } static void _bootstrap_exec_dec(bootstrap_handle_t *bootstrap_handle) { bootstrap_handle->sysdep->core_sysdep_mutex_lock(bootstrap_handle->data_mutex); bootstrap_handle->exec_count--; bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); } static void _bootstrap_http_recv_handler(void *handle, const aiot_http_recv_t *packet, void *userdata) { bootstrap_handle_t *bootstrap_handle = (bootstrap_handle_t *)userdata; switch (packet->type) { case AIOT_HTTPRECV_STATUS_CODE: { bootstrap_handle->response.code = packet->data.status_code.code; } break; case AIOT_HTTPRECV_HEADER: { if ((strlen(packet->data.header.key) == strlen("Content-Length")) && (memcmp(packet->data.header.key, "Content-Length", strlen(packet->data.header.key)) == 0)) { core_str2uint(packet->data.header.value, (uint8_t)strlen(packet->data.header.value), &bootstrap_handle->response.content_total_len); } } break; case AIOT_HTTPRECV_BODY: { uint8_t *content = bootstrap_handle->sysdep->core_sysdep_malloc(bootstrap_handle->response.content_len + packet->data.body.len + 1, CORE_HTTP_MODULE_NAME); if (content == NULL) { return; } memset(content, 0, bootstrap_handle->response.content_len + packet->data.body.len + 1); if (content != NULL) { memcpy(content, bootstrap_handle->response.content, bootstrap_handle->response.content_len); if(bootstrap_handle->response.content != NULL) bootstrap_handle->sysdep->core_sysdep_free(bootstrap_handle->response.content); } memcpy(content + bootstrap_handle->response.content_len, packet->data.body.buffer, packet->data.body.len); bootstrap_handle->response.content = content; bootstrap_handle->response.content_len = bootstrap_handle->response.content_len + packet->data.body.len; } break; default: { } break; } } static int32_t _bootstrap_connection_info(bootstrap_handle_t *bootstrap_handle, char **host, uint16_t *port) { int32_t res = STATE_SUCCESS; char *tmp_host = NULL, *host_key = "host", *port_key = "port", *ip_key = "ip"; char *host_value = NULL, *port_value = NULL, *ip_value = NULL; uint32_t tmp_port = 0, host_value_len = 0, port_value_len = 0, ip_value_len = 0; if (bootstrap_handle->response.code != 200) { return STATE_BOOTSTRAP_INVALID_STATUS_CODE; } if (((res = core_json_value((char *)bootstrap_handle->response.content, bootstrap_handle->response.content_len, host_key, strlen(host_key), &host_value, &host_value_len)) < STATE_SUCCESS) || ((res = core_json_value((char *)bootstrap_handle->response.content, bootstrap_handle->response.content_len, port_key, strlen(port_key), &port_value, &port_value_len)) < STATE_SUCCESS)) { return STATE_BOOTSTRAP_INVALID_CONNECTION_INFO; } tmp_host = bootstrap_handle->sysdep->core_sysdep_malloc(host_value_len + 1, BOOTSTRAP_MODULE_NAME); if (tmp_host == NULL) { return STATE_SYS_DEPEND_MALLOC_FAILED; } memset(tmp_host, 0, host_value_len + 1); memcpy(tmp_host, host_value, host_value_len); core_str2uint(port_value, port_value_len, &tmp_port); *host = tmp_host; *port = tmp_port; /* backup ip address */ if ((res = core_json_value((char *)bootstrap_handle->response.content, bootstrap_handle->response.content_len, ip_key, strlen(ip_key), &ip_value, &ip_value_len)) >= STATE_SUCCESS && (ip_value_len < 16)) { char ip[16] = {0}; memcpy(ip, ip_value, ip_value_len); core_global_set_mqtt_backup_ip(bootstrap_handle->sysdep, ip); } return STATE_SUCCESS; } static int32_t _bootstrap_send_get_request(bootstrap_handle_t *bootstrap_handle) { int32_t res = STATE_SUCCESS; char *path = NULL; char *path_src[] = { bootstrap_handle->region_id }; char *path_fmt = BOOTSTRAP_PATH "/regionId/%s"; core_http_request_t request; memset(&request, 0, sizeof(core_http_request_t)); res = core_sprintf(bootstrap_handle->sysdep, &path, path_fmt, path_src, sizeof(path_src) / sizeof(char *), BOOTSTRAP_MODULE_NAME); if (res < STATE_SUCCESS) { return res; } request.method = "GET"; request.path = path; request.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n"; request.content = NULL; request.content_len = 0; res = core_http_send(bootstrap_handle->http_handle, &request); bootstrap_handle->sysdep->core_sysdep_free(path); if (res < STATE_SUCCESS) { return res; } return STATE_SUCCESS; } static int32_t _bootstrap_send_post_request(bootstrap_handle_t *bootstrap_handle) { int32_t res = STATE_SUCCESS; char *content = NULL; char *content_fmt = "productKey=%s&deviceName=%s&clientId=%s.%s&resources=mqtt"; char *content_src[] = { bootstrap_handle->product_key, bootstrap_handle->device_name, bootstrap_handle->product_key, bootstrap_handle->device_name }; core_http_request_t request; memset(&request, 0, sizeof(core_http_request_t)); res = core_sprintf(bootstrap_handle->sysdep, &content, content_fmt, content_src, sizeof(content_src) / sizeof(char *), BOOTSTRAP_MODULE_NAME); if (res < STATE_SUCCESS) { return res; } request.method = "POST"; request.path = BOOTSTRAP_PATH; request.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n" \ "Content-Type: application/x-www-form-urlencoded;charset=utf-8\r\n"; request.content = (uint8_t *)content; request.content_len = (uint32_t)strlen(content); res = core_http_send(bootstrap_handle->http_handle, &request); bootstrap_handle->sysdep->core_sysdep_free(content); if (res < STATE_SUCCESS) { return res; } return STATE_SUCCESS; } static void _bootstrap_alink_reply(bootstrap_handle_t *bootstrap_handle, char *id) { int32_t res = STATE_SUCCESS; char *topic = NULL, *topic_fmt = BOOTSTRAP_NOTIFY_REPLY_TOPIC_FMT; char *topic_src[] = { core_mqtt_get_product_key(bootstrap_handle->mqtt_handle), core_mqtt_get_device_name(bootstrap_handle->mqtt_handle) }; char *reply = NULL, *reply_fmt = "{\"id\":\"%s\",\"code\":200,\"data\":{}}"; char *reply_src[] = { id }; res = core_sprintf(bootstrap_handle->sysdep, &topic, topic_fmt, topic_src, sizeof(topic_src)/sizeof(char *), BOOTSTRAP_MODULE_NAME); if (res < STATE_SUCCESS) { return; } res = core_sprintf(bootstrap_handle->sysdep, &reply, reply_fmt, reply_src, sizeof(reply_src)/sizeof(char *), BOOTSTRAP_MODULE_NAME); if (res < STATE_SUCCESS) { bootstrap_handle->sysdep->core_sysdep_free(topic); return; } aiot_mqtt_pub(bootstrap_handle->mqtt_handle, topic, (uint8_t *)reply, (uint32_t)strlen(reply), 0); bootstrap_handle->sysdep->core_sysdep_free(reply); bootstrap_handle->sysdep->core_sysdep_free(topic); } static void _bootstrap_recv_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata) { bootstrap_handle_t *bootstrap_handle = (bootstrap_handle_t *)userdata; switch (packet->type) { case AIOT_MQTTRECV_PUB: { char *id_key = "id", *cmd_key = "cmd"; char *id_value = NULL, *cmd_value = NULL; uint32_t id_value_len = 0, cmd_value_len = 0; if (core_json_value((char *)packet->data.pub.payload, packet->data.pub.payload_len, id_key, (uint32_t)strlen(id_key), &id_value, &id_value_len) == STATE_SUCCESS && core_json_value((char *)packet->data.pub.payload, packet->data.pub.payload_len, cmd_key, (uint32_t)strlen(cmd_key), &cmd_value, &cmd_value_len) == STATE_SUCCESS) { uint32_t cmd = 0; if (core_str2uint(cmd_value, cmd_value_len, &cmd) >= STATE_SUCCESS) { if (bootstrap_handle->recv_handler != NULL) { aiot_bootstrap_recv_t recv; memset(&recv, 0, sizeof(aiot_bootstrap_recv_t)); recv.type = AIOT_BOOTSTRAPRECV_NOTIFY; recv.data.notify.cmd = cmd; bootstrap_handle->recv_handler(bootstrap_handle, &recv, bootstrap_handle->userdata); } char *id = bootstrap_handle->sysdep->core_sysdep_malloc(id_value_len + 1, BOOTSTRAP_MODULE_NAME); if (id != NULL) { memset(id, 0, id_value_len + 1); memcpy(id, id_value, id_value_len); _bootstrap_alink_reply(bootstrap_handle, id); bootstrap_handle->sysdep->core_sysdep_free(id); } } else { if (bootstrap_handle->event_handler != NULL) { aiot_bootstrap_event_t event; memset(&event, 0, sizeof(aiot_bootstrap_event_t)); event.type = AIOT_BOOTSTRAPEVT_INVALID_CMD; bootstrap_handle->event_handler(bootstrap_handle, &event, bootstrap_handle->userdata); } } } else { if (bootstrap_handle->event_handler != NULL) { aiot_bootstrap_event_t event; memset(&event, 0, sizeof(aiot_bootstrap_event_t)); event.type = AIOT_BOOTSTRAPEVT_INVALID_RESPONSE; bootstrap_handle->event_handler(bootstrap_handle, &event, bootstrap_handle->userdata); } } } break; default: { } break; } } static int32_t _bootstrap_operate_topic_map(bootstrap_handle_t *bootstrap_handle, aiot_mqtt_option_t option) { int32_t res = STATE_SUCCESS; aiot_mqtt_topic_map_t map; char *topic = NULL; char *topic_src[] = { core_mqtt_get_product_key(bootstrap_handle->mqtt_handle), core_mqtt_get_device_name(bootstrap_handle->mqtt_handle) }; char *topic_fmt = BOOTSTRAP_NOTIFY_TOPIC_FMT; memset(&map, 0, sizeof(aiot_mqtt_topic_map_t)); res = core_sprintf(bootstrap_handle->sysdep, &topic, topic_fmt, topic_src, sizeof(topic_src) / sizeof(char *), BOOTSTRAP_MODULE_NAME); if (res < STATE_SUCCESS) { return res; } map.topic = topic; map.handler = _bootstrap_recv_handler; map.userdata = (void *)bootstrap_handle; res = aiot_mqtt_setopt(bootstrap_handle->mqtt_handle, option, &map); bootstrap_handle->sysdep->core_sysdep_free(topic); return res; } static void _bootstrap_core_mqtt_process_handler(void *context, aiot_mqtt_event_t *event, core_mqtt_event_t *core_event) { bootstrap_handle_t *bootstrap_handle = (bootstrap_handle_t *)context; if (core_event != NULL) { switch (core_event->type) { case CORE_MQTTEVT_DEINIT: { bootstrap_handle->mqtt_handle = NULL; return; } break; default: { } break; } } } static int32_t _bootstrap_core_mqtt_operate_process_handler(bootstrap_handle_t *bootstrap_handle, core_mqtt_option_t option) { core_mqtt_process_data_t process_data; memset(&process_data, 0, sizeof(core_mqtt_process_data_t)); process_data.handler = _bootstrap_core_mqtt_process_handler; process_data.context = bootstrap_handle; return core_mqtt_setopt(bootstrap_handle->mqtt_handle, option, &process_data); } void *aiot_bootstrap_init(void) { int32_t res = STATE_SUCCESS; bootstrap_handle_t *bootstrap_handle = NULL; aiot_sysdep_portfile_t *sysdep = NULL; aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); sysdep = aiot_sysdep_get_portfile(); if (sysdep == NULL) { return NULL; } res = core_global_init(sysdep); if (res < STATE_SUCCESS) { return NULL; } bootstrap_handle = sysdep->core_sysdep_malloc(sizeof(bootstrap_handle_t), BOOTSTRAP_MODULE_NAME); if (bootstrap_handle == NULL) { core_global_deinit(sysdep); return NULL; } memset(bootstrap_handle, 0, sizeof(bootstrap_handle_t)); bootstrap_handle->sysdep = sysdep; res = core_strdup(sysdep, &bootstrap_handle->host, BOOTSTRAP_DEFAULT_HOST, BOOTSTRAP_MODULE_NAME); if (res < STATE_SUCCESS) { core_global_deinit(sysdep); return NULL; } bootstrap_handle->port = BOOTSTRAP_DEFAULT_PORT; bootstrap_handle->response_body_len = BOOTSTRAP_RESPONSE_BODY_LEN; bootstrap_handle->send_timeout_ms = BOOTSTRAP_DEFAULT_SEND_TIMEOUT; bootstrap_handle->recv_timeout_ms = BOOTSTRAP_DEFAULT_RECV_TIMEOUT; bootstrap_handle->timeout_ms = BOOTSTRAP_DEFAULT_TIMEOUT_MS; bootstrap_handle->deinit_timeout_ms = BOOTSTRAP_DEFAULT_DEINIT_TIMEOUT_MS; bootstrap_handle->data_mutex = bootstrap_handle->sysdep->core_sysdep_mutex_init(); bootstrap_handle->exec_enabled = 1; return bootstrap_handle; } int32_t aiot_bootstrap_setopt(void *handle, aiot_bootstrap_option_t option, void *data) { int32_t res = STATE_SUCCESS; bootstrap_handle_t *bootstrap_handle = (bootstrap_handle_t *)handle; if (bootstrap_handle == NULL || data == NULL) { return STATE_USER_INPUT_NULL_POINTER; } if (option >= AIOT_BOOTSTRAPOPT_MAX) { return STATE_USER_INPUT_OUT_RANGE; } if (bootstrap_handle->exec_enabled == 0) { return STATE_USER_INPUT_EXEC_DISABLED; } _bootstrap_exec_inc(bootstrap_handle); bootstrap_handle->sysdep->core_sysdep_mutex_lock(bootstrap_handle->data_mutex); switch (option) { case AIOT_BOOTSTRAPOPT_MQTT_HANDLE: { bootstrap_handle->mqtt_handle = data; bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); res = _bootstrap_operate_topic_map(bootstrap_handle, AIOT_MQTTOPT_APPEND_TOPIC_MAP); if (res >= STATE_SUCCESS) { res = _bootstrap_core_mqtt_operate_process_handler(bootstrap_handle, CORE_MQTTOPT_APPEND_PROCESS_HANDLER); } bootstrap_handle->sysdep->core_sysdep_mutex_lock(bootstrap_handle->data_mutex); } break; case AIOT_BOOTSTRAPOPT_NETWORK_CRED: { if (bootstrap_handle->cred != NULL) { bootstrap_handle->sysdep->core_sysdep_free(bootstrap_handle->cred); bootstrap_handle->cred = NULL; } bootstrap_handle->cred = bootstrap_handle->sysdep->core_sysdep_malloc(sizeof(aiot_sysdep_network_cred_t), BOOTSTRAP_MODULE_NAME); if (bootstrap_handle->cred != NULL) { memset(bootstrap_handle->cred, 0, sizeof(aiot_sysdep_network_cred_t)); memcpy(bootstrap_handle->cred, data, sizeof(aiot_sysdep_network_cred_t)); } else { res = STATE_SYS_DEPEND_MALLOC_FAILED; } } break; case AIOT_BOOTSTRAPOPT_PROFILE_IDX: bootstrap_handle->pdp = *(uint16_t *)data; // printf("%s: %d bootstrap_handle->pdp:%d \n", __func__, __LINE__, bootstrap_handle->pdp); break; case AIOT_BOOTSTRAPOPT_HOST: { res = core_strdup(bootstrap_handle->sysdep, &bootstrap_handle->host, data, BOOTSTRAP_MODULE_NAME); } break; case AIOT_BOOTSTRAPOPT_PORT: { bootstrap_handle->port = *(uint16_t *)data; } break; case AIOT_BOOTSTRAPOPT_PRODUCT_KEY: { res = core_strdup(bootstrap_handle->sysdep, &bootstrap_handle->product_key, data, BOOTSTRAP_MODULE_NAME); } break; case AIOT_BOOTSTRAPOPT_DEVICE_NAME: { res = core_strdup(bootstrap_handle->sysdep, &bootstrap_handle->device_name, data, BOOTSTRAP_MODULE_NAME); } break; case AIOT_BOOTSTRAPOPT_REGIONID: { res = core_strdup(bootstrap_handle->sysdep, &bootstrap_handle->region_id, data, BOOTSTRAP_MODULE_NAME); } break; case AIOT_BOOTSTRAPOPT_SEND_TIMEOUT_MS: { bootstrap_handle->send_timeout_ms = *(uint32_t *)data; } break; case AIOT_BOOTSTRAPOPT_RECV_TIMEOUT_MS: { bootstrap_handle->recv_timeout_ms = *(uint32_t *)data; } break; case AIOT_BOOTSTRAPOPT_RECV_HANDLER: { bootstrap_handle->recv_handler = (aiot_bootstrap_recv_handler_t)data; } break; case AIOT_BOOTSTRAPOPT_EVENT_HANDLER: { bootstrap_handle->event_handler = (aiot_bootstrap_event_handler_t)data; } break; case AIOT_BOOTSTRAPOPT_USERDATA: { bootstrap_handle->userdata = data; } break; case AIOT_BOOTSTRAPOPT_TIMEOUT_MS: { bootstrap_handle->timeout_ms = *(uint32_t *)data; } break; case AIOT_BOOTSTRAPOPT_DEINIT_TIMEOUT_MS: { bootstrap_handle->deinit_timeout_ms = *(uint32_t *)data; } break; default: { res = STATE_USER_INPUT_UNKNOWN_OPTION; } break; } bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return res; } int32_t aiot_bootstrap_deinit(void **handle) { uint32_t deinit_timeout_ms = 0; bootstrap_handle_t *bootstrap_handle = NULL; aiot_sysdep_portfile_t *sysdep = NULL; if (handle == NULL || *handle == NULL) { return STATE_USER_INPUT_NULL_POINTER; } bootstrap_handle = *(bootstrap_handle_t **)handle; sysdep = bootstrap_handle->sysdep; if (bootstrap_handle->exec_enabled == 0) { return STATE_USER_INPUT_EXEC_DISABLED; } bootstrap_handle->exec_enabled = 0; _bootstrap_core_mqtt_operate_process_handler(bootstrap_handle, CORE_MQTTOPT_REMOVE_PROCESS_HANDLER); _bootstrap_operate_topic_map(bootstrap_handle, AIOT_MQTTOPT_REMOVE_TOPIC_MAP); deinit_timeout_ms = bootstrap_handle->deinit_timeout_ms; do { if (bootstrap_handle->exec_count == 0) { break; } bootstrap_handle->sysdep->core_sysdep_sleep(BOOTSTRAP_DEINIT_INTERVAL_MS); } while ((deinit_timeout_ms > BOOTSTRAP_DEINIT_INTERVAL_MS) && (deinit_timeout_ms - BOOTSTRAP_DEINIT_INTERVAL_MS > 0)); if (bootstrap_handle->exec_count != 0) { return STATE_BOOTSTRAP_DEINIT_TIMEOUT; } *handle = NULL; if (bootstrap_handle->response.content != NULL) { sysdep->core_sysdep_free(bootstrap_handle->response.content); } memset(&bootstrap_handle->response, 0, sizeof(core_http_response_t)); if (bootstrap_handle->http_handle != NULL) { core_http_deinit(&bootstrap_handle->http_handle); } if (bootstrap_handle->host != NULL) { sysdep->core_sysdep_free(bootstrap_handle->host); } if (bootstrap_handle->product_key != NULL) { sysdep->core_sysdep_free(bootstrap_handle->product_key); } if (bootstrap_handle->device_name != NULL) { sysdep->core_sysdep_free(bootstrap_handle->device_name); } if (bootstrap_handle->region_id != NULL) { sysdep->core_sysdep_free(bootstrap_handle->region_id); } if (bootstrap_handle->cred != NULL) { sysdep->core_sysdep_free(bootstrap_handle->cred); } sysdep->core_sysdep_mutex_deinit(&bootstrap_handle->data_mutex); core_global_deinit(sysdep); sysdep->core_sysdep_free(bootstrap_handle); return STATE_SUCCESS; } int32_t aiot_bootstrap_send_request(void *handle) { int32_t res = STATE_SUCCESS; bootstrap_handle_t *bootstrap_handle = (bootstrap_handle_t *)handle; if (bootstrap_handle == NULL) { return STATE_USER_INPUT_NULL_POINTER; } if (bootstrap_handle->host == NULL) { return STATE_USER_INPUT_MISSING_HOST; } if (bootstrap_handle->product_key == NULL) { return STATE_USER_INPUT_MISSING_PRODUCT_KEY; } if (bootstrap_handle->device_name == NULL) { return STATE_USER_INPUT_MISSING_DEVICE_NAME; } if (bootstrap_handle->exec_enabled == 0) { return STATE_USER_INPUT_EXEC_DISABLED; } _bootstrap_exec_inc(bootstrap_handle); bootstrap_handle->sysdep->core_sysdep_mutex_lock(bootstrap_handle->data_mutex); if (bootstrap_handle->response.content != NULL) { bootstrap_handle->sysdep->core_sysdep_free(bootstrap_handle->response.content); } memset(&bootstrap_handle->response, 0, sizeof(core_http_response_t)); if (bootstrap_handle->http_handle != NULL) { core_http_deinit(&bootstrap_handle->http_handle); } bootstrap_handle->http_handle = core_http_init(); if (bootstrap_handle->http_handle == NULL) { bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return STATE_SYS_DEPEND_MALLOC_FAILED; } if (((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_HOST, (void *)bootstrap_handle->host)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_PORT, (void *)&bootstrap_handle->port)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_NETWORK_CRED, (void *)bootstrap_handle->cred)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_SEND_TIMEOUT_MS, (void *)&bootstrap_handle->send_timeout_ms)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_RECV_TIMEOUT_MS, (void *)&bootstrap_handle->recv_timeout_ms)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_BODY_BUFFER_MAX_LEN, (void *)&bootstrap_handle->response_body_len)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_RECV_HANDLER, (void *)_bootstrap_http_recv_handler)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_USERDATA, (void *)bootstrap_handle)) < STATE_SUCCESS) || ((res = core_http_setopt(bootstrap_handle->http_handle, CORE_HTTPOPT_PROFILE_IDX, (void *)&bootstrap_handle->pdp)) < STATE_SUCCESS)) { core_http_deinit(&bootstrap_handle->http_handle); bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return res; } res = core_http_connect(bootstrap_handle->http_handle); if (res < STATE_SUCCESS) { core_http_deinit(&bootstrap_handle->http_handle); bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return res; } { if (bootstrap_handle->region_id != NULL) { res = _bootstrap_send_get_request(bootstrap_handle); }else{ res = _bootstrap_send_post_request(bootstrap_handle); } if (res < STATE_SUCCESS) { core_http_deinit(&bootstrap_handle->http_handle); bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return res; } } bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return res; } int32_t aiot_bootstrap_recv(void *handle) { int32_t res = STATE_SUCCESS; uint64_t timenow_ms = 0; bootstrap_handle_t *bootstrap_handle = (bootstrap_handle_t *)handle; char *host = NULL; uint16_t port = 0; aiot_bootstrap_recv_t packet; if (bootstrap_handle == NULL) { return STATE_USER_INPUT_NULL_POINTER; } if (bootstrap_handle->http_handle == NULL) { return STATE_BOOTSTRAP_NEED_SEND_REQUEST; } if (bootstrap_handle->exec_enabled == 0) { return STATE_USER_INPUT_EXEC_DISABLED; } _bootstrap_exec_inc(bootstrap_handle); bootstrap_handle->sysdep->core_sysdep_mutex_lock(bootstrap_handle->data_mutex); timenow_ms = bootstrap_handle->sysdep->core_sysdep_time(); while (1) { if (timenow_ms >= bootstrap_handle->sysdep->core_sysdep_time()) { timenow_ms = bootstrap_handle->sysdep->core_sysdep_time(); } if (bootstrap_handle->sysdep->core_sysdep_time() - timenow_ms >= bootstrap_handle->timeout_ms) { break; } res = core_http_recv(bootstrap_handle->http_handle); if (res < STATE_SUCCESS) { break; } } if (res < STATE_SUCCESS) { if (res != STATE_HTTP_READ_BODY_FINISHED) { if (bootstrap_handle->response.content != NULL) { bootstrap_handle->sysdep->core_sysdep_free(bootstrap_handle->response.content); memset(&bootstrap_handle->response, 0, sizeof(core_http_response_t)); } bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return res; } else { res = STATE_SUCCESS; } } else { bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); _bootstrap_exec_dec(bootstrap_handle); return STATE_HTTP_RECV_NOT_FINISHED; } if (bootstrap_handle->recv_handler != NULL) { packet.type = AIOT_BOOTSTRAPRECV_STATUS_CODE; packet.data.status_code.code = bootstrap_handle->response.code; bootstrap_handle->recv_handler(bootstrap_handle, &packet, bootstrap_handle->userdata); } res = _bootstrap_connection_info(bootstrap_handle, &host, &port); bootstrap_handle->sysdep->core_sysdep_mutex_unlock(bootstrap_handle->data_mutex); if (res < STATE_SUCCESS) { _bootstrap_exec_dec(bootstrap_handle); return res; } memset(&packet, 0, sizeof(aiot_bootstrap_recv_t)); if (bootstrap_handle->recv_handler != NULL) { packet.type = AIOT_BOOTSTRAPRECV_CONNECTION_INFO; packet.data.connection_info.host = host; packet.data.connection_info.port = (uint16_t)port; bootstrap_handle->recv_handler(bootstrap_handle, &packet, bootstrap_handle->userdata); } bootstrap_handle->sysdep->core_sysdep_free(host); _bootstrap_exec_dec(bootstrap_handle); return STATE_SUCCESS; }