remove old tencentcloud_sdk and abandoned EVB boards

This commit is contained in:
daishengdong
2020-05-07 16:22:17 +08:00
parent b74cf8d598
commit 08e5f7b3ec
441 changed files with 648 additions and 266237 deletions

View File

@@ -1,51 +0,0 @@
#ifndef _QCLOUD_H_
#define _QCLOUD_H_
#include "qcloud_config_def.h"
#include "qcloud_config.h"
#include "qcloud_config_default.h"
#include "qcloud_config_check.h"
#include "qcloud_types.h"
#include "qcloud_err.h"
#include "qcloud_lib.h"
#include "qcloud_log.h"
#include "qcloud_device_config.h"
#include "qcloud_device.h"
#include "qcloud_tls.h"
#include "qcloud_network.h"
#include "qcloud_utils/qcloud_list.h"
#include "qcloud_utils/qcloud_lite_list.h"
#include "qcloud_utils/qcloud_lite.h"
#include "qcloud_utils/qcloud_aes.h"
#include "qcloud_utils/qcloud_base64.h"
#include "qcloud_utils/qcloud_hmac.h"
#include "qcloud_utils/qcloud_httpc.h"
#include "qcloud_utils/qcloud_json.h"
#include "qcloud_utils/qcloud_md5.h"
#include "qcloud_utils/qcloud_sha1.h"
#include "qcloud_osal/osal_tcp.h"
#include "qcloud_osal/osal_udp.h"
#include "qcloud_osal/osal_tls.h"
#include "qcloud_osal/osal_dtls.h"
#include "qcloud_osal/osal_timer.h"
#include "qcloud_osal/osal_os.h"
#include "qcloud_mqtt_config.h"
#include "qcloud_mqtt/mqtt_common.h"
#include "qcloud_mqtt.h"
#include "qcloud_shadow_config.h"
#include "qcloud_shadow.h"
#include "qcloud_event.h"
#include "qcloud_coap_config.h"
#include "qcloud_coap.h"
#endif/*_QCLOUD_H_*/

View File

@@ -1,323 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef _QCLOUD_COAP_H_
#define _QCLOUD_COAP_H_
#ifdef __cplusplus
extern "C" {
#endif
static const char *qcloud_coap_server = "iotcloud.tencentdevices.com";
static const int qcloud_coap_port = 5684;
typedef enum qcloud_coap_auth_state_en {
QCLOUD_COAP_AUTH_STATE_NONE,
QCLOUD_COAP_AUTH_STATE_SUCCESS,
QCLOUD_COAP_AUTH_STATE_FAIL,
} qcloud_coap_auth_state_t;
/**
* @brief COAP消息分类
*/
typedef enum coap_code_class_en {
COAP_CODE_CLASS_REQ = 0, // 请求包
COAP_CODE_CLASS_SUCCESS = 2, // 成功回包
COAP_CODE_CLASS_CLIENT_ERR = 4, // 客户端错误回包
COAP_CODE_CLASS_SERVER_ERR = 5, // 后台错误回包
COAP_CODE_CLASS_INTERNAL_ERR = 6,
} coap_code_class_t;
/**
* @brief COAP消息请求方法
*/
typedef enum coap_request_method_en {
COAP_REQUEST_METHOD_GET = 1, // GET请求
COAP_REQUEST_METHOD_POST = 2, // POST请求
COAP_REQUEST_METHOD_PUT = 3,
COAP_REQUEST_METHOD_DELETE = 4,
} coap_request_method_t;
typedef enum coap_code_detail_en {
/* CoAP Success Response code detail */
COAP_CODE_DETAIL_201_CREATED = 01, /* Mapping to CoAP codeClass.codeDetail 2.01 */
COAP_CODE_DETAIL_202_DELETED = 02, /* Mapping to CoAP codeClass.codeDetail 2.02 */
COAP_CODE_DETAIL_203_VALID = 03, /* Mapping to CoAP codeClass.codeDetail 2.03 */
COAP_CODE_DETAIL_204_CHANGED = 04, /* Mapping to CoAP codeClass.codeDetail 2.04 */
COAP_CODE_DETAIL_205_CONTENT = 05, /* Mapping to CoAP codeClass.codeDetail 2.05 */
COAP_CODE_DETAIL_231_CONTINUE = 31, /* Mapping to CoAP codeClass.codeDetail 2.31 */
/* CoAP Client Error Response code detail */
COAP_CODE_DETAIL_400_BAD_REQUEST = 00, /* Mapping to CoAP codeClass.codeDetail 4.00 */
COAP_CODE_DETAIL_401_UNAUTHORIZED = 01, /* Mapping to CoAP codeClass.codeDetail 4.01 */
COAP_CODE_DETAIL_402_BAD_OPTION = 02, /* Mapping to CoAP codeClass.codeDetail 4.02 */
COAP_CODE_DETAIL_403_FORBIDDEN = 03, /* Mapping to CoAP codeClass.codeDetail 4.03 */
COAP_CODE_DETAIL_404_NOT_FOUND = 04, /* Mapping to CoAP codeClass.codeDetail 4.04 */
COAP_CODE_DETAIL_405_METHOD_NOT_ALLOWED = 05, /* Mapping to CoAP codeClass.codeDetail 4.05 */
COAP_CODE_DETAIL_406_NOT_ACCEPTABLE = 06, /* Mapping to CoAP codeClass.codeDetail 4.06 */
COAP_CODE_DETAIL_408_REQUEST_ENTITY_INCOMPLETE = 8, /* Mapping to CoAP codeClass.codeDetail 4.08 */
COAP_CODE_DETAIL_412_PRECONDITION_FAILED = 12, /* Mapping to CoAP codeClass.codeDetail 4.12 */
COAP_CODE_DETAIL_413_REQUEST_ENTITY_TOO_LARGE = 13, /* Mapping to CoAP codeClass.codeDetail 4.13 */
COAP_CODE_DETAIL_415_UNSUPPORTED_CONTENT_FORMAT = 15, /* Mapping to CoAP codeClass.codeDetail 4.15 */
/* CoAP Server Error Response code detail */
COAP_CODE_DETAIL_500_INTERNAL_SERVER_ERROR = 00, /* Mapping to CoAP codeClass.codeDetail 5.00 */
COAP_CODE_DETAIL_501_NOT_IMPLEMENTED = 01, /* Mapping to CoAP codeClass.codeDetail 5.01 */
COAP_CODE_DETAIL_502_BAD_GATEWAY = 02, /* Mapping to CoAP codeClass.codeDetail 5.02 */
COAP_CODE_DETAIL_503_SERVICE_UNAVAILABLE = 03, /* Mapping to CoAP codeClass.codeDetail 5.03 */
COAP_CODE_DETAIL_504_GATEWAY_TIMEOUT = 04, /* Mapping to CoAP codeClass.codeDetail 5.04 */
COAP_CODE_DETAIL_505_PROXYING_NOT_SUPPORTED = 05, /* Mapping to CoAP codeClass.codeDetail 5.05 */
COAP_CODE_DETAIL_600_TIMEOUT = 00, /* Mapping to self define CoAP codeClass.codeDetail 6.00 */
} coap_code_detail_t;
/**
* @brief Option number enumeration
*/
typedef enum coap_message_option_code_en {
COAP_MSG_OPTION_CODE_IF_MATCH = 1, // If-Match option number
COAP_MSG_OPTION_CODE_URI_HOST = 3, // URI-Host option number
COAP_MSG_OPTION_CODE_ETAG = 4, // Entity-Tag option number
COAP_MSG_OPTION_CODE_IF_NONE_MATCH = 5, // If-None-Match option number
COAP_MSG_OPTION_CODE_URI_PORT = 7, // URI-Port option number
COAP_MSG_OPTION_CODE_LOCATION_PATH = 8, // Location-Path option number
COAP_MSG_OPTION_CODE_URI_PATH = 11, // URI-Path option number
COAP_MSG_OPTION_CODE_CONTENT_FORMAT = 12, // Content-Format option number
COAP_MSG_OPTION_CODE_MAX_AGE = 14, // Max-Age option number
COAP_MSG_OPTION_CODE_URI_QUERY = 15, // URI-Query option number
COAP_MSG_OPTION_CODE_ACCEPT = 17, // Accept option number
COAP_MSG_OPTION_CODE_LOCATION_QUERY = 20, // Location-Query option number
COAP_MSG_OPTION_CODE_BLOCK2 = 23, // Block2 option number
COAP_MSG_OPTION_CODE_BLOCK1 = 27, // Block1 option number
COAP_MSG_OPTION_CODE_SIZE2 = 28, // Size2 option number
COAP_MSG_OPTION_CODE_PROXY_URI = 35, // Proxy-URI option number
COAP_MSG_OPTION_CODE_PROXY_SCHEME = 39, // Proxy-Scheme option number
COAP_MSG_OPTION_CODE_SIZE1 = 60, // Size1 option number
COAP_MSG_OPTION_CODE_AUTH_TOKEN = 61, // 设备鉴权token option number
COAP_MSG_OPTION_CODE_NEED_RESP = 62, // CoAP消息是否需要content response option number
} coap_msg_opt_code_t;
typedef enum coap_incoming_msg_type_en {
COAP_INCOMING_MSG_TYPE_PIGGY,
COAP_INCOMING_MSG_TYPE_ACK,
COAP_INCOMING_MSG_TYPE_RESP,
} coap_incoming_msg_type_t;
/**
* @brief CoAP needResp类型消息回调处理函数指针定义
*
* @param message CoAP消息
* @param userContext 发送消息时携带的用户上下文
*/
typedef void (*coap_resp_callback_t)(void *message, void *context);
/**
* @brief COAP发布消息结构体
*/
typedef struct coap_send_option_st {
char *payload; // COAP 消息负载
size_t payload_len; // MQTT 消息负载长度
void *context; // 用于用户传递的消息上下文SDK不做处理在callback时返回
coap_resp_callback_t resp_cb; // 消息回包callback仅对need_resp: true 有效
} coap_send_opt_t;
/**
* @brief CoAP Option结构体
*/
typedef struct coap_message_option_st {
qcloud_list_t list;
uint16_t option_code; // Option code
uint32_t val_len; // Option length
char *val; // Pointer to a buffer containing the option value
} coap_msg_option_t;
typedef struct coap_message_sent_info_st {
qcloud_list_t list;
void *context;
int is_acked;
uint8_t token_len;
uint8_t token[COAP_MSG_TOKEN_MAX];
uint8_t transmit_count;
osal_timer_t timer;
void *message;
uint16_t message_id;
uint32_t message_len;
coap_resp_callback_t resp_cb;
} coap_msg_sent_info_t;
/**
* @brief COAP消息类型
*/
typedef enum coap_msg_type_en {
COAP_MSG_TYPE_CON = 0x0, /**< 需要等待回包确认的消息 */
COAP_MSG_TYPE_NON = 0x1, /**< 无需等待回包确认的消息 */
COAP_MSG_TYPE_ACK = 0x2, /**< ACK消息 */
COAP_MSG_TYPE_RST = 0x3, /**< Reset消息 */
} coap_msg_type_t;
/**
* @brief CoAP消息结构体
*/
typedef struct coap_message_st {
uint32_t version; // CoAP协议版本号
uint8_t type; // 消息类型
uint32_t code_class; // Code class
uint32_t code_detail; // Code detail
uint16_t id; // 消息id
char *payload; // 消息负载
size_t payload_len; // 消息负载长度
char token[COAP_MSG_TOKEN_MAX]; // 消息token
uint8_t token_len; // 消息token长度
coap_resp_callback_t resp_cb; // CoAP Response消息回调处理函数
void *context; // 用户上下文
qcloud_list_t option_list;
} coap_message_t;
#define COAP_MESSAGE_INITIALIZER {COAP_VERSION, COAP_MSG_TYPE_CON, COAP_CODE_CLASS_REQ, COAP_REQUEST_METHOD_POST, 0, NULL, 0, {0}, 0, NULL, NULL, {NULL, NULL}}
/**
* CoAP 事件类型
*/
typedef enum coap_event_type_en {
COAP_EVENT_TYPE_RECEIVE_ACK = 0, // 收到消息ACK
COAP_EVENT_TYPE_RECEIVE_RESPCONTENT = 1, // 收到消息回包响应
COAP_EVENT_TYPE_UNAUTHORIZED = -1, // 设备鉴权失败或鉴权token过期
COAP_EVENT_TYPE_FORBIDDEN = -2, // 设备topic无权限
COAP_EVENT_TYPE_INTERNAL_SERVER_ERROR = -3, // 服务端错误
COAP_EVENT_TYPE_ACK_TIMEOUT = -4, // 消息ACK超时
COAP_EVENT_TYPE_SEPRESP_TIMEOUT = -5, // 消息回包响应超时
} coap_event_type_t;
typedef struct coap_event_st {
coap_event_type_t type; /* 事件类型 */
void *message; /* 事件消息 or 内容消息 */
} coap_event_t;
typedef void (*coap_event_handler_fn_t)(void *context, coap_event_t *event);
typedef struct coap_event_handler_st {
coap_event_handler_fn_t handler;
void *context;
} coap_event_handler_t;
typedef struct qcloud_coap_client_st {
qcloud_coap_auth_state_t auth_state;
uint32_t message_token; // 标识请求响应条消息对应
uint16_t packet_id; // COAP报文标识符
uint8_t tx_buffer[QCLOUD_COAP_CLIENT_TX_BUF_LEN];
uint8_t rx_buffer[QCLOUD_COAP_CLIENT_RX_BUF_LEN];
void *tx_lock; // 输出流的锁
void *message_list_lock; // 等待发布消息ack列表的锁
qcloud_list_t message_list; // 请求消息列表
qcloud_network_t network; // 网络调用数据结构
uint32_t command_timeout; // CoAP消息超时时间, 单位:ms
uint8_t retransmit_max; // CoAP消息最大重试次数
coap_event_handler_t event_handler; // 事件回调
char *auth_token; // 鉴权token
int auth_token_len;
char auth_id[QCLOUD_COAP_AUTH_ID_MAX + 1];
char auth_uri[QCLOUD_COAP_AUTH_URI_MAX + 1];
} qcloud_coap_client_t;
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_create(qcloud_coap_client_t *client, qcloud_device_t *device, coap_event_handler_fn_t handler);
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_destroy(qcloud_coap_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_connect(qcloud_coap_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_yield(qcloud_coap_client_t *client, uint32_t timeout_ms);
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_msg_send(qcloud_coap_client_t *client,
char *topic,
coap_send_opt_t *send_opt);
__QCLOUD_API__ uint16_t qcloud_coap_msg_id_get(coap_message_t *message);
__QCLOUD_API__ qcloud_err_t qcloud_coap_msg_payload_get(coap_message_t *message, char **payload, int *payload_len);
__QCLOUD_API__ coap_event_type_t qcloud_coap_event_type_get(coap_message_t *message);
__QCLOUD_INTERNAL__ int coap_message_token_get(qcloud_coap_client_t *client, char *buf);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_type_set(coap_message_t *message, uint8_t type);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_code_set(coap_message_t *message, uint32_t code_class, uint32_t code_detail);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_id_set(coap_message_t *message, uint16_t id);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_token_set(coap_message_t *message, char *buf, uint8_t len);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_payload_set(coap_message_t *message, char *buf, size_t len);
__QCLOUD_INTERNAL__ coap_msg_option_t *coap_message_option_construct(uint16_t option_code, uint32_t len, const char *val);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_option_add(coap_message_t *message, coap_msg_opt_code_t option_code, uint32_t len, const char *val);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_callback_set(coap_message_t *message, coap_resp_callback_t callback);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_context_set(coap_message_t *message, void *context);
__QCLOUD_INTERNAL__ void coap_message_init(coap_message_t *message);
__QCLOUD_INTERNAL__ void coap_message_destroy(coap_message_t *message);
__QCLOUD_INTERNAL__ void coap_message_dump(coap_message_t* message);
__QCLOUD_INTERNAL__ void coap_glue_connect_id_generate(char *conn_id);
__QCLOUD_INTERNAL__ uint16_t coap_glue_packet_id_generate(qcloud_coap_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t coap_glue_message_list_destroy(qcloud_coap_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t coap_glue_spin(qcloud_coap_client_t *client, uint32_t timeout_ms);
__QCLOUD_INTERNAL__ qcloud_err_t coap_glue_msg_send(qcloud_coap_client_t *client, coap_message_t *message);
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_deserialize(coap_message_t *message, char *buf, size_t buf_len);
__QCLOUD_INTERNAL__ int coap_message_serialize(coap_message_t *message, char *buf, size_t buf_len);
__QCLOUD_INTERNAL__ qcloud_err_t coap_auth(qcloud_coap_client_t *client, char *connection_id);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,75 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef _QCLOUD_COAP_CONFIG_H_
#define _QCLOUD_COAP_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
static const char *qcloud_coap_server_domain = "iotcloud.tencentdevices.com";
/* 判断COAP消息是否为空 */
#define COAP_MSG_IS_EMPTY(message) (((message)->code_class == 0) && ((message)->code_detail == 0))
/* 判断COAP消息是否为空 ACK*/
#define COAP_MSG_IS_EMPTY_ACK(message) (((message)->code_class == 2) && ((message)->code_detail == 3))
/* 判断COAP消息是否为RESP */
#define COAP_MSG_IS_EMPTY_RSP(message) (((message)->code_class == 2) && ((message)->code_detail == 5))
/* COAP协议版本号 */
#define COAP_VERSION (0x01)
/* token最大长度 */
#define COAP_MSG_TOKEN_MAX (8)
/* Message id最大值 */
#define COAP_MSG_ID_MAX ((1 << 16) - 1)
/* COAP 消息最大code class */
#define COAP_MSG_CODE_CLASS_MAX (7)
/* COAP 消息最大code detail */
#define COAP_MSG_CODE_DETAIL_MAX (31)
#define QCLOUD_COAP_COMMAND_TIMEOUT (15 * 1000)
/* CoAP 最大链接ID的长度 */
#define QCLOUD_COAP_CONNECT_ID_MAX (6)
/* COAP 发送消息buffer大小最大支持64*1024字节 */
#define QCLOUD_COAP_CLIENT_TX_BUF_LEN (512)
/* COAP 接收消息buffer大小最大支持64*1024字节 */
#define QCLOUD_COAP_CLIENT_RX_BUF_LEN (512)
/* 设备鉴权URI该URI唯一禁止设备创建该URI topic */
#define QCLOUD_COAP_AUTH_URI ("txauth9w0BAQsFA")
/* Topic最大长度 */
#define QCLOUD_COAP_URI_MAX (128)
#define QCLOUD_COAP_AUTH_ID_MAX (sizeof(QCLOUD_APPID) + QCLOUD_COAP_CONNECT_ID_MAX + 2)
#define QCLOUD_COAP_AUTH_URI_MAX (QCLOUD_DEVICE_PRODUCT_ID_MAX + QCLOUD_DEVICE_DEVICE_NAME_MAX + sizeof(QCLOUD_COAP_AUTH_URI) + 4)
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,27 +0,0 @@
#ifndef _QCLOUD_CONFIG_
#define _QCLOUD_CONFIG_
#define QCLOUD_CFG_AUTH_MODE QCLOUD_AUTH_MODE_KEY
#define QCLOUD_CFG_TLS_EN 1u
#define QCLOUD_CFG_COAP_EN 0u
#define QCLOUD_CFG_MQTT_EN 1u
#define QCLOUD_CFG_EVENT_EN 0u
#define QCLOUD_CFG_DEVICE_DYN_REG_EN 0u
#define QCLOUD_CFG_DEVELOP_DEBUG_EN 0u
#define QCLOUD_CFG_LOG_LEVEL QCLOUD_LOG_LEVEL_DEBUG
#define QCLOUD_CFG_LOG_UPLOAD_LEVEL QCLOUD_LOG_LEVEL_DEBUG
#define QCLOUD_CFG_DUPLICATED_MSG_REMOVE_EN 0u
#define QCLOUD_PATH_MAX 128
#endif

View File

@@ -1,5 +0,0 @@
#ifndef _QCLOUD_CONFIG_CHECK_
#define _QCLOUD_CONFIG_CHECK_
#endif

View File

@@ -1,28 +0,0 @@
#ifndef _QCLOUD_CONFIG_DEF_
#define _QCLOUD_CONFIG_DEF_
#define QCLOUD_AUTH_MODE_KEY 1
#define QCLOUD_AUTH_MODE_CERT 2
typedef enum qcloud_log_level_en {
QCLOUD_LOG_LEVEL_DISABLE = 0,
QCLOUD_LOG_LEVEL_DEBUG = 1,
QCLOUD_LOG_LEVEL_INFO = 2,
QCLOUD_LOG_LEVEL_WARN = 3,
QCLOUD_LOG_LEVEL_ERROR = 4,
} qcloud_log_level_t;
#define QCLOUD_APPID "21010406"
#define QCLOUD_SDK_VERSION "3.0.0"
#define QCLOUD_SERVER_DOMAIN_MAX 64
#define QCLOUD_TLS_HANDSHAKE_TIMEOUT (5 * 1000)
#define QCLOUD_PSK_MAX 48
#define QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX 80
#endif

View File

@@ -1,45 +0,0 @@
#ifndef _QCLOUD_CONFIG_DEFAULT_
#define _QCLOUD_CONFIG_DEFAULT_
#ifndef QCLOUD_CFG_DEVELOP_DEBUG_EN
#define QCLOUD_CFG_DEVELOP_DEBUG_EN 0u
#endif
#ifndef QCLOUD_CFG_AUTH_MODE
#define QCLOUD_CFG_AUTH_MODE QCLOUD_AUTH_MODE_KEY
#endif
#ifndef QCLOUD_CFG_TLS_EN
#define QCLOUD_CFG_TLS_EN ` 0u
#endif
#ifndef QCLOUD_CFG_COAP_EN
#define QCLOUD_CFG_COAP_EN 0u
#endif
#ifndef QCLOUD_CFG_MQTT_EN
#define QCLOUD_CFG_MQTT_EN 0u
#endif
#ifndef QCLOUD_CFG_EVENT_EN
#define QCLOUD_CFG_EVENT_EN 0u
#endif
#ifndef QCLOUD_CFG_DEVICE_DYN_REG_EN
#define QCLOUD_CFG_DEVICE_DYN_REG_EN 0u
#endif
#ifndef QCLOUD_CFG_LOG_LEVEL
#define QCLOUD_CFG_LOG_LEVEL QCLOUD_LOG_LEVEL_ERROR
#endif
#ifndef QCLOUD_CFG_LOG_UPLOAD_LEVEL
#define QCLOUD_CFG_LOG_UPLOAD_LEVEL QCLOUD_LOG_LEVEL_ERROR
#endif
#ifndef QCLOUD_CFG_DUPLICATED_MSG_REMOVE_EN
#define QCLOUD_CFG_DUPLICATED_MSG_REMOVE_EN 0u
#endif
#endif

View File

@@ -1,32 +0,0 @@
#ifndef _QCLOUD_DEVICE_H
#define _QCLOUD_DEVICE_H_
typedef struct qcloud_device_st {
const char *product_id;
const char *device_name;
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
const char *cert_path;
const char *priv_key_path;
#else
const char *key;
#endif
#if (QCLOUD_CFG_DEVICE_DYN_REG_EN > 0u)
char product_key[QCLOUD_DEVICE_PRODUCT_KEY_MAX + 1];
#endif
} qcloud_device_t;
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
__QCLOUD_API__ qcloud_err_t qcloud_device_create(qcloud_device_t *device,
const char *product_id,
const char *device_name,
const char *cert_path,
const char *priv_key_path);
#else
__QCLOUD_API__ qcloud_err_t qcloud_device_create(qcloud_device_t *device,
const char *product_id,
const char *device_name,
const char *key);
#endif
#endif

View File

@@ -1,19 +0,0 @@
#ifndef _QCLOUD_DEVICE_CONFIG_
#define _QCLOUD_DEVICE_CONFIG_
#define QCLOUD_DEVICE_PRODUCT_ID_MAX 14
#define QCLOUD_DEVICE_DEVICE_NAME_MAX 48
#define QCLOUD_DEVICE_USERNAME_MAX (QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX + 8 + QCLOUD_MQTT_CONNECT_ID_MAX + 10 + 4 + 5)
#define QCLOUD_DEVICE_PASSWORD_MAX 52
#define QCLOUD_DEVICE_KEY_MAX 32
#if (QCLOUD_CFG_DEVICE_DYN_REG_EN > 0u)
#define QCLOUD_DEVICE_PRODUCT_KEY_MAX 32
#endif
#endif

View File

@@ -1,112 +0,0 @@
#ifndef _QCLOUD_ERR_H_
#define _QCLOUD_ERR_H_
typedef enum qcloud_err_en {
QCLOUD_ERR_MQTT_ALREADY_CONNECTED = 4, // 表示与MQTT服务器已经建立连接
QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED = 3, // 表示服务器接受客户端MQTT连接
QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED = 2, // 表示与MQTT服务器已经手动断开
QCLOUD_ERR_MQTT_RECONNECTED = 1, // 表示与MQTT服务器重连成功
QCLOUD_ERR_HTTP_CLOSED = -3, // 远程主机关闭连接
QCLOUD_ERR_HTTP = -4, // HTTP未知错误
QCLOUD_ERR_HTTP_PRTCL = -5, // 协议错误
QCLOUD_ERR_HTTP_UNRESOLVED_DNS = -6, // 域名解析失败
QCLOUD_ERR_HTTP_PARSE = -7, // URL解析失败
QCLOUD_ERR_HTTP_CONN = -8, // HTTP连接失败
QCLOUD_ERR_HTTP_AUTH = -9, // HTTP鉴权问题
QCLOUD_ERR_HTTP_NOT_FOUND = -10, // HTTP 404
QCLOUD_ERR_HTTP_TIMEOUT = -11, // HTTP 超时
QCLOUD_ERR_SUCCESS = 0, // 表示成功返回
QCLOUD_ERR_FAILURE = -1001, // 表示失败返回
QCLOUD_ERR_INVAL = -1002, // 表示参数无效错误
QCLOUD_ERR_DEV_INFO = -1003, // 获取设备信息失败
QCLOUD_ERR_MQTT_PUSH_TO_LIST_FAILED = -102, // 表示往等待 ACK 列表中添加元素失败
QCLOUD_ERR_MQTT_NO_CONN = -103, // 表示未与MQTT服务器建立连接或已经断开连接
QCLOUD_ERR_MQTT_UNKNOWN = -104, // 表示MQTT相关的未知错误
QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT = -105, // 表示正在与MQTT服务重新建立连接
QCLOUD_ERR_MQTT_RECONNECT_TIMEOUT = -106, // 表示重连已经超时
QCLOUD_ERR_MQTT_MAX_SUBSCRIPTIONS = -107, // 表示超过可订阅的主题数
QCLOUD_ERR_MQTT_SUB = -108, // 表示订阅主题失败, 即服务器拒绝
QCLOUD_ERR_MQTT_NOTHING_TO_READ = -109, // 表示无MQTT相关报文可以读取
QCLOUD_ERR_MQTT_PACKET_READ = -110, // 表示读取的MQTT报文有问题
QCLOUD_ERR_MQTT_REQUEST_TIMEOUT = -111, // 表示MQTT相关操作请求超时
QCLOUD_ERR_MQTT_CONNACK_UNKNOWN = -112, // 表示客户端MQTT连接未知错误
QCLOUD_ERR_MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION = -113, // 表示客户端MQTT版本错误
QCLOUD_ERR_MQTT_CONNACK_IDENTIFIER_REJECTED = -114, // 表示客户端标识符错误
QCLOUD_ERR_MQTT_CONNACK_SERVER_UNAVAILABLE = -115, // 表示服务器不可用
QCLOUD_ERR_MQTT_CONNACK_BAD_USERDATA = -116, // 表示客户端连接参数中的username或password错误
QCLOUD_ERR_MQTT_CONNACK_NOT_AUTHORIZED = -117, // 表示客户端连接认证失败
QCLOUD_ERR_RX_MESSAGE_INVAL = -118, // 表示收到的消息无效
QCLOUD_ERR_BUF_TOO_SHORT = -119, // 表示消息接收缓冲区的长度小于消息的长度
QCLOUD_ERR_MQTT_QOS_NOT_SUPPORT = -120, // 表示该QOS级别不支持
QCLOUD_ERR_MQTT_UNSUB_FAIL = -121, // 表示取消订阅主题失败,比如该主题不存在
QCLOUD_ERR_JSON_PARSE = -132, // 表示JSON解析错误
QCLOUD_ERR_JSON_BUFFER_TRUNCATED = -133, // 表示JSON文档会被截断
QCLOUD_ERR_JSON_BUFFER_TOO_SHORT = -134, // 表示存储JSON文档的缓冲区太小
QCLOUD_ERR_JSON = -135, // 表示JSON文档生成错误
QCLOUD_ERR_MAX_JSON_TOKEN = -136, // 表示超过JSON文档中的最大Token数
QCLOUD_ERR_MAX_APPENDING_REQUEST = -137, // 表示超过同时最大的文档请求
QCLOUD_ERR_MAX_TOPIC_LENGTH = -138, // 表示超过规定最大的topic长度
QCLOUD_ERR_COAP_CONNRESET = -150, // COAP参数错误
QCLOUD_ERR_COAP_NULL = -151, // 空指针
QCLOUD_ERR_COAP_INVALID_LENGTH = -152, // COAP参数长度错误
QCLOUD_ERR_COAP_DATA_SIZE = -153, // COAP数据大小超出限制
QCLOUD_ERR_COAP_NOT_FOUND = -154, // COAP查找失败
QCLOUD_ERR_COAP_NET_INIT_FAILED = -155, // COAP初始化失败
QCLOUD_ERR_COAP_INTERNAL = -156, // COAP内部错误
QCLOUD_ERR_COAP_WRITE_FAILED = -157, // COAP写数据失败
QCLOUD_ERR_COAP_READ_FAILED = -158, // COAP读数据失败
QCLOUD_ERR_COAP_BADMSG = -159, // COAPbad消息
QCLOUD_ERR_COAP_TIMEOUT = -160, // COAP超时错误
QCLOUD_ERR_DTLS_PEER_CLOSE_NOTIFY = -161, // 表示DTLS通道被关闭
QCLOUD_ERR_SHADOW_PROPERTY_EXIST = -201, // 表示注册的属性已经存在
QCLOUD_ERR_SHADOW_NOT_PROPERTY_EXIST = -202, // 表示注册的属性不存在
QCLOUD_ERR_SHADOW_UPDATE_TIMEOUT = -203, // 表示更新设备影子文档超时
QCLOUD_ERR_SHADOW_UPDATE_REJECTED = -204, // 表示更新设备影子文档被拒绝
QCLOUD_ERR_SHADOW_GET_TIMEOUT = -205, // 表示拉取设备影子文档超时
QCLOUD_ERR_SHADOW_GET_REJECTED = -206, // 表示拉取设备影子文档被拒绝
QCLOUD_ERR_GATEWAY_CREATE_SESSION_FAIL = -221, //创建子设备session失败
QCLOUD_ERR_GATEWAY_SESSION_NO_EXIST = -222, //子设备session不存在
QCLOUD_ERR_GATEWAY_SESSION_TIMEOUT = -223, //子设备session超时
QCLOUD_ERR_GATEWAY_SUBDEV_ONLINE = -224, //子设备已在线
QCLOUD_ERR_GATEWAY_SUBDEV_OFFLINE = -225, //子设备已不在线
QCLOUD_ERR_TCP_SOCKET_FAILED = -601, // 表示TCP连接建立套接字失败
QCLOUD_ERR_TCP_UNKNOWN_HOST = -602, // 表示无法通过主机名获取IP地址
QCLOUD_ERR_TCP_CONNECT = -603, // 表示建立TCP连接失败
QCLOUD_ERR_TCP_READ_TIMEOUT = -604, // 表示TCP读超时
QCLOUD_ERR_TCP_WRITE_TIMEOUT = -605, // 表示TCP写超时
QCLOUD_ERR_TCP_READ_FAIL = -606, // 表示TCP读错误
QCLOUD_ERR_TCP_WRITE_FAIL = -607, // 表示TCP写错误
QCLOUD_ERR_TCP_PEER_SHUTDOWN = -608, // 表示TCP对端关闭了连接
QCLOUD_ERR_TCP_NOTHING_TO_READ = -609, // 表示底层没有数据可以读取
QCLOUD_ERR_SSL_INIT = -701, // 表示SSL初始化失败
QCLOUD_ERR_SSL_CERT = -702, // 表示SSL证书相关问题
QCLOUD_ERR_SSL_CONNECT = -703, // 表示SSL连接失败
QCLOUD_ERR_SSL_CONNECT_TIMEOUT = -704, // 表示SSL连接超时
QCLOUD_ERR_SSL_WRITE_TIMEOUT = -705, // 表示SSL写超时
QCLOUD_ERR_SSL_WRITE = -706, // 表示SSL写错误
QCLOUD_ERR_SSL_READ_TIMEOUT = -707, // 表示SSL读超时
QCLOUD_ERR_SSL_READ = -708, // 表示SSL读错误
QCLOUD_ERR_SSL_NOTHING_TO_READ = -709, // 表示底层没有数据可以读取
QCLOUD_ERR_UDP_SOCKET_FAILED = -601, // 表示UDP连接建立套接字失败
QCLOUD_ERR_UDP_UNKNOWN_HOST = -602, // 表示无法通过主机名获取IP地址
QCLOUD_ERR_UDP_CONNECT = -603, // 表示建立UDP连接失败
QCLOUD_ERR_UDP_READ_TIMEOUT = -604, // 表示UDP读超时
QCLOUD_ERR_UDP_WRITE_TIMEOUT = -605, // 表示UDP写超时
QCLOUD_ERR_UDP_READ_FAIL = -606, // 表示UDP读错误
QCLOUD_ERR_UDP_WRITE_FAIL = -607, // 表示UDP写错误
QCLOUD_ERR_UDP_NOTHING_TO_READ = -609, // 表示底层没有数据可以读取
} qcloud_err_t;
#endif

View File

@@ -1,129 +0,0 @@
#ifndef _QCLOUD_EVENT_H_
#define _QCLOUD_EVENT_H_
#define QCLOUD_EVENT_TOKEN_MAX (32)
#define EVENT_FIELD_POST "event_post"
#define EVENT_FIELD_POSTS "events_post"
#define EVENT_FIELD_REPLY "event_reply"
#define EVENT_REPLY_FIELD_CODE "code"
#define EVENT_REPLY_FIELD_STATUS "status"
typedef void (*event_reply_handler_fn_t)(void *client, mqtt_incoming_msg_t *msg);
typedef struct qcloud_event_reply_st {
qcloud_list_t list;
char client_token[QCLOUD_EVENT_TOKEN_MAX]; // 标识该请求的clientToken字段
osal_timer_t timer; // 请求超时定时器
event_reply_handler_fn_t handler; // 事件上报回复回调
} qcloud_event_reply_t;
typedef enum event_sync_state_en {
QCLOUD_EVENT_SYNC_STATE_NONE,
QCLOUD_EVENT_SYNC_STATE_PENDACK,
QCLOUD_EVENT_SYNC_STATE_SUCCESS,
QCLOUD_EVENT_SYNC_STATE_TIMEOUT,
QCLOUD_EVENT_SYNC_STATE_NACK,
} event_sync_state_t;
typedef struct qcloud_event_st {
char *event_name; // event name
char *type; // event type
uint32_t timestamp; // timestamp
uint8_t event_payload_count; // count of event_payload
shadow_dev_property_t *event_payload; // payload of the event
} qcloud_event_t;
typedef struct qcloud_event_client_st {
void *reply_list_lock;
qcloud_list_t reply_list;
char down_topic[QCLOUD_MQTT_TOPIC_SIZE_MAX];
char up_topic[QCLOUD_MQTT_TOPIC_SIZE_MAX];
event_sync_state_t sync_state;
qcloud_shadow_client_t *shadow_client;
} qcloud_event_client_t;
__QCLOUD_API__ qcloud_err_t qcloud_event_client_create(qcloud_event_client_t *client, qcloud_shadow_client_t *shadow_client, qcloud_device_t *device);
__QCLOUD_API__ qcloud_err_t qcloud_event_client_destroy(qcloud_event_client_t *client);
/**
* @brief <20>¼<EFBFBD><C2BC>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>飬SDK<44><4B><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>json<6F><6E>ʽ<EFBFBD><CABD>װ
* @param pClient shadow ʵ<><CAB5>ָ<EFBFBD><D6B8>
* @param pJsonDoc <20><><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>json<6F><6E>ʽ<EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>Ϣ<EFBFBD><CFA2>buffer
* @param sizeOfBuffer <20><><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>json<6F><6E>ʽ<EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>Ϣ<EFBFBD><CFA2>buffer<65><72>С
* @param event_count <20><><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>
* @param pEventArry <20><><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>ָ
* @param replyCb <20>¼<EFBFBD><C2BC>ظ<EFBFBD><D8B8><EFBFBD>Ϣ<EFBFBD>Ļص<C4BB>
* @return @see IoT_Error_Code
*/
__QCLOUD_API__ qcloud_err_t qcloud_event_client_post(qcloud_event_client_t *client,
char *json_doc,
size_t json_doc_size,
int event_count,
qcloud_event_t *events[],
event_reply_handler_fn_t handler);
/**
* @brief <20>¼<EFBFBD><C2BC>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>¼<EFBFBD><C2BC><EFBFBD>json<6F><6E>ʽ<EFBFBD><CABD>SDK<44><4B><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>
* @param pClient shadow ʵ<><CAB5>ָ<EFBFBD><D6B8>
* @param pJsonDoc <20><><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>json<6F><6E>ʽ<EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>Ϣ<EFBFBD><CFA2>buffer
* @param sizeOfBuffer <20><><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>json<6F><6E>ʽ<EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>Ϣ<EFBFBD><CFA2>buffer<65><72>С
* @param pEventMsg <20><><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD>¼<EFBFBD>json<6F><6E>Ϣ
* json<6F>¼<EFBFBD><C2BC><EFBFBD>ʽ<EFBFBD><CABD>
* <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
* {"method": "event_post",
* "clientToken": "123",
* "version": "1.0",
* "eventId": "PowerAlarm",
* "type": "fatal",
* "timestamp": 1212121221,
* "params": {
* "Voltage": 2.8,
* "Percent": 20
* }
* }
*
* <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
* {
* "eventId": "PowerAlarm",
* "type": "fatal",
* "timestamp": 1212121221,
* "params": {
* "Voltage": 2.8,
* "Percent": 20
* }
* },
* {
* "name": "PowerAlarm",
* "type": "fatal",
* "timestamp": 1212121223,
* "params": {
* "Voltage": 2.1,
* "Percent": 10
* }
* },
* ....
*
* @param replyCb <20>¼<EFBFBD><C2BC>ظ<EFBFBD><D8B8><EFBFBD>Ϣ<EFBFBD>Ļص<C4BB>
* @return @see IoT_Error_Code
*/
__QCLOUD_API__ qcloud_err_t qcloud_event_client_post_raw(qcloud_event_client_t *client,
char *json_doc,
size_t json_doc_size,
char *event_msg,
event_reply_handler_fn_t handler);
__QCLOUD_INTERNAL__ qcloud_err_t event_json_node_add(char *json_doc, size_t json_doc_size, const char *key, void *data, json_data_type_t type);
__QCLOUD_INTERNAL__ int event_json_return_code_parse(char *json_doc, int32_t *return_code);
__QCLOUD_INTERNAL__ int event_json_status_parse(char *json_doc, char **return_status);
#endif

View File

@@ -1,150 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef _QCLOUD_LIB_H_
#define _QCLOUD_LIB_H_
#if defined(__cplusplus)
extern "C" {
#endif
#define __QCLOUD_API__
#define __QCLOUD_INTERNAL__
#define __QCLOUD_STATIC__ static
#define __QCLOUD_OSAL__
#define QCLOUD_MAX(a,b) ((a) > (b) ? (a) : (b))
#define QCLOUD_MIN(a,b) ((a) < (b) ? (a) : (b))
#if (QCLOUD_CFG_DEVELOP_DEBUG_EN > 0u)
#define QCLOUD_FUNC_ENTRY \
{ \
printf("FUNC_ENTRY: %s L#%d \n", __FUNCTION__, __LINE__); \
}
#define QCLOUD_FUNC_EXIT \
{ \
printf("FUNC_EXIT: %s L#%d \n", __FUNCTION__, __LINE__); \
return; \
}
#define QCLOUD_FUNC_EXIT_RC(x) \
{ \
printf("FUNC_EXIT: %s L#%d Return Code : %ld \n", __FUNCTION__, __LINE__, (long)(x)); \
return x; \
}
#define QCLOUD_FUNC_EXIT_RC_IF(exp, expected, x) \
if ((exp) == (expected)) { \
printf("FUNC_EXIT: %s L#%d Return Code : %ld \n", __FUNCTION__, __LINE__, (long)(x)); \
return (x); \
}
#define QCLOUD_FUNC_EXIT_RC_IF_NOT(exp, expected, x) \
if ((exp) != (expected)) { \
printf("FUNC_EXIT: %s L#%d Return Code : %ld \n", __FUNCTION__, __LINE__, (long)(x)); \
return (x); \
}
#else
#define QCLOUD_FUNC_ENTRY
#define QCLOUD_FUNC_EXIT \
{ \
return;\
}
#define QCLOUD_FUNC_EXIT_RC(x) \
{ \
return x; \
}
#define QCLOUD_FUNC_EXIT_RC_IF(exp, expected, x) \
if ((exp) == (expected)) { \
return (x); \
}
#define QCLOUD_FUNC_EXIT_RC_IF_NOT(exp, expected, x) \
if ((exp) != (expected)) { \
return (x); \
}
#endif
#define QCLOUD_NUMBERIC_SANITY_CHECK(num, err) \
do { \
if (0 == (num)) { \
QCLOUD_LOG_E("Invalid argument, numeric 0"); \
return (err); \
} \
} while(0)
#define QCLOUD_NUMBERIC_SANITY_CHECK_RTN(num) \
do { \
if (0 == (num)) { \
QCLOUD_LOG_E("Invalid argument, numeric 0"); \
return; \
} \
} while(0)
#define QCLOUD_POINTER_SANITY_CHECK(ptr, err) \
do { \
if (NULL == (ptr)) { \
QCLOUD_LOG_E("Invalid argument, %s = %p", #ptr, ptr); \
return (err); \
} \
} while(0)
#define QCLOUD_POINTER_SANITY_CHECK_RTN(ptr) \
do { \
if (NULL == (ptr)) { \
QCLOUD_LOG_E("Invalid argument, %s = %p", #ptr, ptr); \
return; \
} \
} while(0)
#define QCLOUD_STRING_PTR_SANITY_CHECK(ptr, err) \
do { \
if (NULL == (ptr)) { \
QCLOUD_LOG_E("Invalid argument, %s = %p", #ptr, (ptr)); \
return (err); \
} \
if (0 == strlen((ptr))) { \
QCLOUD_LOG_E("Invalid argument, %s = '%s'", #ptr, (ptr)); \
return (err); \
} \
} while(0)
#define QCLOUD_STRING_PTR_SANITY_CHECK_RTN(ptr) \
do { \
if (NULL == (ptr)) { \
QCLOUD_LOG_E("Invalid argument, %s = %p", #ptr, (ptr)); \
return; \
} \
if (0 == strlen((ptr))) { \
QCLOUD_LOG_E("Invalid argument, %s = '%s'", #ptr, (ptr)); \
return; \
} \
} while(0)
#if defined(__cplusplus)
}
#endif
#endif

View File

@@ -1,57 +0,0 @@
#ifndef _QCLOUD_LOG_H_
#define _QCLOUD_LOG_H_
/* 单条日志最大长度 */
#define QCLOUD_LOG_LEN_MAX (1024)
/*用户自定义日志打印函数回调*/
typedef int (*qcloud_log_handler_t)(const char *message);
/**
* @brief 设置日志回调函数,用户接管日志内容用于输出到文件等操作
*
* @param handler 回调函数指针
*
*/
void qcloud_log_handler_set(qcloud_log_handler_t handler);
/**
* @brief 日志打印及上报函数默认打印到标准输出当用户设置日志打印handler时回调handler
*
* 当日志上报功能打开时,会将日志缓存后上报到云端日志服务器
*
* @param file 源文件名
* @param func 函数名
* @param line 行号
* @param level 日志等级
*/
void qcloud_log_write(const char *file, const char *func, const int line, const int level, const char *fmt, ...);
/* 日志打印及上报对外接口*/
#if (QCLOUD_CFG_LOG_LEVEL >= QCLOUD_LOG_LEVEL_DEBUG)
#define QCLOUD_LOG_D(args...) qcloud_log_write(__FILE__, __FUNCTION__, __LINE__, QCLOUD_LOG_LEVEL_DEBUG, args)
#else
#define QCLOUD_LOG_D(args...)
#endif
#if (QCLOUD_CFG_LOG_LEVEL >= QCLOUD_LOG_LEVEL_INFO)
#define QCLOUD_LOG_I(args...) qcloud_log_write(__FILE__, __FUNCTION__, __LINE__, QCLOUD_LOG_LEVEL_INFO, args)
#else
#define QCLOUD_LOG_I(args...)
#endif
#if (QCLOUD_CFG_LOG_LEVEL >= QCLOUD_LOG_LEVEL_WARN)
#define QCLOUD_LOG_W(args...) qcloud_log_write(__FILE__, __FUNCTION__, __LINE__, QCLOUD_LOG_LEVEL_WARN, args)
#else
#define QCLOUD_LOG_W(args...)
#endif
#if (QCLOUD_CFG_LOG_LEVEL >= QCLOUD_LOG_LEVEL_ERROR)
#define QCLOUD_LOG_E(args...) qcloud_log_write(__FILE__, __FUNCTION__, __LINE__, QCLOUD_LOG_LEVEL_ERROR, args)
#else
#define QCLOUD_LOG_E(args...)
#endif
#endif

View File

@@ -1,173 +0,0 @@
#ifndef _QCLOUD_MQTT_
#define _QCLOUD_MQTT_
static const char *qcloud_mqtt_server = "iotcloud.tencentdevices.com";
#if (QCLOUD_CFG_TLS_EN > 0u)
static const int qcloud_mqtt_port = 8883;
#else
static const int qcloud_mqtt_port = 1883;
#endif
typedef enum qcloud_mqtt_connection_status_en {
QCLOUD_MQTT_CONNECTION_STATE_DISCONNECTED = 0,
QCLOUD_MQTT_CONNECTION_STATE_CONNECTED = 1,
} qcloud_mqtt_con_status_t;
/**
* @brief 订阅主题对应的消息处理结构体定义
*/
typedef struct qcloud_mqtt_message_handler_st {
qcloud_list_t list;
char *topic_filter_mutable; // 订阅主题名, 可包含通配符
mqtt_message_handler_fn_t handler; // 订阅主题消息回调函数指针
mqtt_qos_t qos;
void *private_data; // 用户数据, 通过回调函数返回
} qcloud_mqtt_msg_handler_t;
typedef enum qcloud_mqtt_ack_type_en {
QCLOUD_MQTT_ACK_TYPE_PUBACK,
QCLOUD_MQTT_ACK_TYPE_SUBACK,
QCLOUD_MQTT_ACK_TYPE_UNSUBACK,
} qcloud_mqtt_ack_type_t;
typedef struct qcloud_mqtt_ack_info_st {
qcloud_list_t list;
osal_timer_t ack_timer;
qcloud_mqtt_ack_type_t type;
qcloud_mqtt_msg_handler_t *handler; // when type == suback, handler is not null
uint16_t packet_id;
uint16_t packet_len;
uint8_t *packet_body;
} qcloud_mqtt_ack_info_t;
typedef enum qcloud_auto_connect_state_en {
QCLOUD_AUTO_CONN_STATE_DISABLED = 0,
QCLOUD_AUTO_CONN_STATE_ENABLED = 1,
} qcloud_auto_connect_state_t;
/**
* @brief IoT Client结构体定义
*/
typedef struct qcloud_mqtt_client_st {
qcloud_auto_connect_state_t auto_connect_state;
uint16_t keep_alive_interval;
qcloud_mqtt_con_status_t connection_state; // 网络是否连接
uint8_t is_manually_disconnected; // 是否手动断开连接
uint8_t ping_outstanding; // 心跳包是否未完成, 即未收到服务器响应
uint16_t packet_id; // MQTT报文标识符
uint32_t command_timeout; // MQTT消息超时时间, 单位:ms
uint32_t reconnect_try_duration; // MQTT重连周期, 单位:ms
uint32_t network_disconnect_counter; // 网络断开连接次数
uint8_t tx_buffer[QCLOUD_MQTT_CLIENT_TX_BUF_LEN]; // MQTT消息发送buffer
uint8_t rx_buffer[QCLOUD_MQTT_CLIENT_RX_BUF_LEN]; // MQTT消息接收buffer
void *global_lock; // client原子锁
void *tx_lock; // 输出流的锁
void *ack_pend_list_lock;
qcloud_list_t ack_pend_list;
mqtt_event_handler_t event_handler; // 事件句柄
qcloud_network_t network; // MQTT底层使用的网络参数
osal_timer_t ping_timer; // MQTT心跳包发送定时器
osal_timer_t reconnect_timer; // MQTT重连定时器, 判断是否已到重连时间
void *msg_handler_list_lock;
qcloud_list_t msg_handler_list;
} qcloud_mqtt_client_t;
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_connect_opt_create(mqtt_connect_opt_t *connect_opt,
qcloud_device_t *device,
mqtt_version_t mqtt_version,
uint16_t keep_alive_interval,
mqtt_clean_session_state_t clean_session);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_create(qcloud_mqtt_client_t *client,
qcloud_device_t *device,
mqtt_event_handler_fn_t handler,
void *handler_context,
qcloud_auto_connect_state_t auto_connect_state);
__QCLOUD_API__ void qcloud_mqtt_client_destroy(qcloud_mqtt_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_connect(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_disconnect(qcloud_mqtt_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_publish(qcloud_mqtt_client_t *client, char *topic, mqtt_publish_opt_t *publish_opt);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_subscribe(qcloud_mqtt_client_t *client, const char *topic_filter, mqtt_subscribe_opt_t *subscribe_opt);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_unsubscribe(qcloud_mqtt_client_t *client, const char *topic_filter);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_yield(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt, uint32_t timeout_ms);
__QCLOUD_API__ int qcloud_mqtt_client_is_connected(qcloud_mqtt_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_connect(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_disconnect(qcloud_mqtt_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_publish(qcloud_mqtt_client_t *client, char *topic, mqtt_publish_opt_t *publish_opt);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_subscribe(qcloud_mqtt_client_t *client, const char *topic_filter, mqtt_subscribe_opt_t *subscribe_opt);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_unsubscribe(qcloud_mqtt_client_t *client, const char *topic_filter);
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_yield(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt, uint32_t timeout_ms);
__QCLOUD_INTERNAL__ void mqtt_client_connection_state_set(qcloud_mqtt_client_t *client, qcloud_mqtt_con_status_t state);
__QCLOUD_INTERNAL__ char *mqtt_glue_string_const2mutable(const char *orig_str, size_t orig_str_len);
__QCLOUD_INTERNAL__ void mqtt_glue_string_mutable_free(char *str_mutable);
__QCLOUD_INTERNAL__ uint16_t mqtt_glue_packet_id_generate(qcloud_mqtt_client_t *client);
__QCLOUD_INTERNAL__ void mqtt_glue_connect_id_generate(char *conn_id);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_packet_send(qcloud_mqtt_client_t *client, size_t length, osal_timer_t *timer);
__QCLOUD_INTERNAL__ int mqtt_glue_is_topic_equals(const char *topic_filter, char *topic);
__QCLOUD_INTERNAL__ int mqtt_glue_is_topic_matches(const char *topic_filter, char *topic, uint16_t topic_len);
__QCLOUD_INTERNAL__ void mqtt_glue_packet_id_cache_reset(void);
__QCLOUD_INTERNAL__ void mqtt_glue_msg_handler_destory(qcloud_mqtt_msg_handler_t *msg_handler);
__QCLOUD_INTERNAL__ qcloud_mqtt_msg_handler_t * mqtt_glue_msg_handler_create(char *topic_filter_mutable, mqtt_subscribe_opt_t *subscribe_opt);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_msg_handler_list_destroy(qcloud_mqtt_client_t *client);
__QCLOUD_INTERNAL__ void mqtt_glue_msg_handler_uninstall(qcloud_mqtt_client_t *client, const char *topic_filter, int *is_subscribed);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_ack_list_scan(qcloud_mqtt_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_ack_list_destroy(qcloud_mqtt_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_ack_list_record(qcloud_mqtt_client_t *client,
qcloud_mqtt_ack_type_t type,
qcloud_mqtt_msg_handler_t *handler,
uint16_t packet_id,
uint16_t packet_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_callback_involve(qcloud_mqtt_client_t *client, mqtt_event_type_t event_type, void *msg);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_spin(qcloud_mqtt_client_t *client, osal_timer_t *timer, uint8_t *packet_type);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_glue_spin4ack(qcloud_mqtt_client_t *client, osal_timer_t *timer, uint8_t packet_type);
#endif

View File

@@ -1,310 +0,0 @@
#ifndef _QCLOUD_MQTT_COMMON_H_
#define _QCLOUD_MQTT_COMMON_H_
typedef enum mqtt_version_en {
MQTT_VERSION_3_1_1 = 4,
} mqtt_version_t;
typedef enum mqtt_clean_session_state_en {
MQTT_CLEAN_SESSION_STATE_DISABLED = 0,
MQTT_CLEAN_SESSION_STATE_ENABLED = 1,
} mqtt_clean_session_state_t;
typedef enum mqtt_quality_of_service_en {
MQTT_QOS0 = 0, // 至多分发一次
MQTT_QOS1 = 1, // 至少分发一次, 消息的接收者需回复PUBACK报文
MQTT_QOS2 = 2, // 仅分发一次, 目前腾讯物联云不支持该等级
} mqtt_qos_t;
typedef enum mqtt_packet_suback_return_code_en {
MQTT_PACKET_SUBACK_RC_QOS0 = 0x00,
MQTT_PACKET_SUBACK_RC_QOS1 = 0x01,
MQTT_PACKET_SUBACK_RC_QOS2 = 0x02,
MQTT_PACKET_SUBACK_RC_FAILURE = 0x80,
} mqtt_packet_suback_rc_t;
typedef enum mqtt_packet_type_en {
MQTT_PACKET_TYPE_RESERVED = 0, // Reserved
MQTT_PACKET_TYPE_CONNECT = 1, // Client request to connect to Server
MQTT_PACKET_TYPE_CONNACK = 2, // Connect Acknowledgment
MQTT_PACKET_TYPE_PUBLISH = 3, // Publish message
MQTT_PACKET_TYPE_PUBACK = 4, // Publish Acknowledgment
MQTT_PACKET_TYPE_PUBREC = 5, // Publish Received
MQTT_PACKET_TYPE_PUBREL = 6, // Publish Release
MQTT_PACKET_TYPE_PUBCOMP = 7, // Publish Complete
MQTT_PACKET_TYPE_SUBSCRIBE = 8, // Client Subscribe request
MQTT_PACKET_TYPE_SUBACK = 9, // Subscribe Acknowledgment
MQTT_PACKET_TYPE_UNSUBSCRIBE = 10, // Client Unsubscribe request
MQTT_PACKET_TYPE_UNSUBACK = 11, // Unsubscribe Acknowledgment
MQTT_PACKET_TYPE_PINGREQ = 12, // PING Request
MQTT_PACKET_TYPE_PINGRESP = 13, // PING Response
MQTT_PACKET_TYPE_DISCONNECT = 14, // Client is Disconnecting
} mqtt_packet_t;
/**
* Bitfields for the MQTT header byte.
*/
typedef union mqtt_header_un {
uint8_t byte; /**< the whole byte */
#if defined(REVERSED)
struct {
unsigned int type : 4; /**< message type nibble */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int retain : 1; /**< retained flag bit */
} bits;
#else
struct {
unsigned int retain : 1; /**< retained flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int type : 4; /**< message type nibble */
} bits;
#endif
} mqtt_header_t;
typedef union mqtt_connect_flags_un {
uint8_t all; /**< all connect flags */
#if defined(REVERSED)
struct {
unsigned int username : 1; /**< 3.1 user name */
unsigned int password : 1; /**< 3.1 password */
unsigned int willRetain : 1; /**< will retain setting */
unsigned int willQoS : 2; /**< will QoS value */
unsigned int will : 1; /**< will flag */
unsigned int cleansession : 1; /**< clean session flag */
unsigned int : 1; /**< unused */
} bits;
#else
struct {
unsigned int : 1; /**< unused */
unsigned int cleansession : 1; /**< cleansession flag */
unsigned int will : 1; /**< will flag */
unsigned int willQoS : 2; /**< will QoS value */
unsigned int willRetain : 1; /**< will retain setting */
unsigned int password : 1; /**< 3.1 password */
unsigned int username : 1; /**< 3.1 user name */
} bits;
#endif
} mqtt_connect_flag_t; /**< connect flags byte */
typedef union mqtt_connack_flags_un {
uint8_t all; /**< all connack flags */
#if defined(REVERSED)
struct {
unsigned int reserved : 7; /**< unused */
unsigned int sessionpresent : 1; /**< session present flag */
} bits;
#else
struct {
unsigned int sessionpresent : 1; /**< session present flag */
unsigned int reserved: 7; /**< unused */
} bits;
#endif
} mqtt_connack_flags_t; /**< connack flags byte */
/**
* connect return code
*/
typedef enum mqtt_connack_return_code_en {
MQTT_CONNACK_CONNECTION_ACCEPTED = 0, // connection accepted
MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1, // connection refused: unaccpeted protocol verison
MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = 2, // connection refused: identifier rejected
MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR = 3, // connection refused: server unavailable
MQTT_CONNACK_BAD_USERDATA_ERROR = 4, // connection refused: bad user name or password
MQTT_CONNACK_NOT_AUTHORIZED_ERROR = 5 // connection refused: not authorized
} mqtt_connack_rc_t;
typedef struct mqtt_connect_option_st {
/* The eyecatcher for this structure. must be MQTC. */
char struct_id[4];
/* The version number of this structure. Must be 0 */
int struct_version;
/* Version of MQTT to be used. 3 = 3.1 4 = 3.1.1
*/
mqtt_version_t mqtt_version;
char client_id[QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX + 1];
uint16_t keep_alive_interval;
mqtt_clean_session_state_t clean_session;
char username[QCLOUD_DEVICE_USERNAME_MAX + 1];
size_t username_len;
char password[QCLOUD_DEVICE_PASSWORD_MAX + 1];
size_t password_len;
} mqtt_connect_opt_t;
/**
* @brief 发布或接收已订阅消息的结构体定义
*/
typedef struct mqtt_publish_option_st {
mqtt_qos_t qos; // MQTT 服务质量等级
uint8_t retained; // RETAIN 标识位
uint8_t dup; // DUP 标识位
uint16_t id; // MQTT 消息标识符
const char *topic; // MQTT topic
size_t topic_len; // topic 长度
void *payload; // MQTT 消息负载
size_t payload_len; // MQTT 消息负载长度
} mqtt_publish_opt_t;
typedef mqtt_publish_opt_t mqtt_incoming_msg_t;
/**
* @brief MQTT PUBLISH 消息回调处理函数指针定义
*/
typedef void (*mqtt_message_handler_fn_t)(void *client, mqtt_incoming_msg_t *message, void *private_data);
/**
* @brief 订阅主题的结构体定义
*/
typedef struct mqtt_subscribe_option_st {
mqtt_qos_t qos; // 服务质量等级, 目前支持QOS0和QOS1
mqtt_message_handler_fn_t message_handler; // 接收已订阅消息的回调函数
void *private_data; // 用户数据, 通过callback返回
} mqtt_subscribe_opt_t;
typedef enum mqtt_event_type_en {
/* 未定义事件 */
MQTT_EVENT_UNDEF = 0,
/* MQTT 断开连接 */
MQTT_EVENT_DISCONNECT = 1,
/* MQTT 重连 */
MQTT_EVENT_RECONNECT = 2,
/* 订阅成功 */
MQTT_EVENT_SUBCRIBE_SUCCESS = 3,
/* 订阅超时 */
MQTT_EVENT_SUBCRIBE_TIMEOUT = 4,
/* 订阅失败 */
MQTT_EVENT_SUBCRIBE_NACK = 5,
/* 取消订阅成功 */
MQTT_EVENT_UNSUBCRIBE_SUCCESS = 6,
/* 取消订阅超时 */
MQTT_EVENT_UNSUBCRIBE_TIMEOUT = 7,
/* 取消订阅失败 */
MQTT_EVENT_UNSUBCRIBE_NACK = 8,
/* 发布成功 */
MQTT_EVENT_PUBLISH_SUCCESS = 9,
/* 发布超时 */
MQTT_EVENT_PUBLISH_TIMEOUT = 10,
/* 发布失败 */
MQTT_EVENT_PUBLISH_NACK = 11,
/* SDK订阅的topic收到后台push消息 */
MQTT_EVENT_PUBLISH_RECVEIVED = 12,
} mqtt_event_type_t;
typedef struct mqtt_event_st {
/* 事件类型 */
mqtt_event_type_t type;
void *message;
} mqtt_event_t;
typedef void (*mqtt_event_handler_fn_t)(void *client, void *context, mqtt_event_t *event);
/* The structure of MQTT event handle */
typedef struct mqtt_event_handler_st {
mqtt_event_handler_fn_t handler;
void *context;
} mqtt_event_handler_t;
__QCLOUD_INTERNAL__ int mqtt_common_packet_encode(uint8_t *buf, int length);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_ack_packet(uint8_t *packet_type,
uint8_t *dup,
uint16_t *packet_id,
uint8_t *buf,
size_t buf_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_suback_packet(uint16_t *packet_id,
uint32_t max_count,
uint32_t *count,
int granted_qoss[],
uint8_t *buf,
size_t buf_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_unsuback_packet(uint16_t *packet_id,
uint8_t *buf,
size_t buf_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_connect_packet(uint8_t *buf,
size_t buf_len,
mqtt_connect_opt_t *connect_opt,
uint32_t *serialized_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_connack_packet(uint8_t *session_present,
uint8_t *connack_rc,
uint8_t *buf,
size_t buf_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_zero_payload_packet(uint8_t *buf,
size_t buf_len,
mqtt_packet_t packet_type,
uint32_t *serialized_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_publish_packet(uint8_t *dup, int *qos,
uint8_t *retained, uint16_t *packet_id,
char **topic, uint16_t *topic_len,
uint8_t **payload, size_t *payload_len,
uint8_t *buf, size_t buf_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_puback_packet(uint8_t *buf,
size_t buf_len,
uint16_t packet_id,
uint32_t *serialized_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_pubrel_packet(uint8_t *buf,
size_t buf_len,
uint8_t dup,
uint16_t packet_id,
uint32_t *serialized_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_pubrec_packet(uint8_t *buf,
size_t buf_len,
uint16_t packet_id,
uint32_t *serialized_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_publish_packet(uint8_t *buf,
size_t buf_len,
uint8_t dup,
int qos,
uint8_t retained,
uint16_t packet_id,
char *topic,
uint8_t *payload,
size_t payload_len,
uint32_t *serialized_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_subscribe_packet(uint8_t *buf,
size_t buf_len,
uint8_t dup,
uint16_t packet_id,
uint32_t count,
char *topic_filters[],
int requested_qoss[],
uint32_t *serialized_len);
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_unsubscribe_packet(uint8_t *buf, size_t buf_len,
uint8_t dup, uint16_t packet_id,
uint32_t count, char *topic_filters[],
uint32_t *serialized_len);
#endif

View File

@@ -1,34 +0,0 @@
#ifndef _QCLOUD_MQTT_CONFIG_
#define _QCLOUD_MQTT_CONFIG_
#define QCLOUD_MQTT_COMMAND_TIMEOUT (15 * 1000)
#define QCLOUD_MQTT_TX_BUFFER_SIZE (2048)
#define QCLOUD_MQTT_RX_BUFFER_SIZE (2048)
#define QCLOUD_MQTT_REMAIN_WAIT_MS_MAX (2000)
#define QCLOUD_MQTT_CONNECT_ID_MAX (6)
#define QCLOUD_MQTT_ACCESS_EXPIRE_TIMEOUT_MAX (0)
/* 重连最大等待时间 */
#define QCLOUD_MQTT_RECONNECT_TRY_THRESHOLD (60 * 1000)
/* 重连最小等待时间 */
#define QCLOUD_MQTT_RECONNECT_TRY_INITIAL (1000)
#define QCLOUD_MQTT_REPUB_PACKET_MAX 20
/* 云端保留主题的最大长度 */
#define QCLOUD_MQTT_TOPIC_SIZE_MAX (QCLOUD_DEVICE_DEVICE_NAME_MAX + QCLOUD_DEVICE_PRODUCT_ID_MAX + 64 + 6)
/* MQTT消息发送buffer大小, 支持最大256*1024 */
#define QCLOUD_MQTT_CLIENT_TX_BUF_LEN (2048)
/* MQTT消息接收buffer大小, 支持最大256*1024 */
#define QCLOUD_MQTT_CLIENT_RX_BUF_LEN (2048)
#endif

View File

@@ -1,36 +0,0 @@
#ifndef _QCLOUD_NETWORK_H_
#define _QCLOUD_NETWORK_H_
typedef struct qcloud_network_st qcloud_network_t;
typedef struct qcloud_network_st {
qcloud_err_t (*connect) (qcloud_network_t *);
qcloud_err_t (*read) (qcloud_network_t *, void *buf, size_t len, uint32_t timeout, size_t *read_len);
qcloud_err_t (*write) (qcloud_network_t *, const void *buf, size_t len, uint32_t timeout, size_t *write_len);
void (*disconnect) (qcloud_network_t *);
int (*is_connected) (qcloud_network_t *);
int fd;
#if (QCLOUD_CFG_TLS_EN > 0u)
qcloud_tls_opt_t tls_opt;
#endif
char host[QCLOUD_SERVER_DOMAIN_MAX]; // 服务器地址
int port; // 服务器端口
} qcloud_network_t;
__QCLOUD_API__ qcloud_err_t qcloud_network_tcp_init(qcloud_network_t *network);
__QCLOUD_API__ qcloud_err_t qcloud_network_udp_init(qcloud_network_t *network);
__QCLOUD_INTERNAL__ qcloud_err_t qcloud_network_tls_init(qcloud_network_t *network);
__QCLOUD_INTERNAL__ qcloud_err_t qcloud_network_dtls_init(qcloud_network_t *network);
#endif

View File

@@ -1,13 +0,0 @@
#ifndef _OSAL_DTLS_H_
#define _OSAL_DTLS_H_
__QCLOUD_OSAL__ void *osal_dtls_connect(qcloud_tls_opt_t *tls_opt, const char *host, int port);
__QCLOUD_OSAL__ void osal_dtls_disconnect(void *handle);
__QCLOUD_OSAL__ qcloud_err_t osal_dtls_write(void *handle, const void *buf, size_t len, size_t *write_len);
__QCLOUD_OSAL__ qcloud_err_t osal_dtls_read(void *handle, void *buf, size_t len, uint32_t timeout, size_t *read_len);
#endif

View File

@@ -1,29 +0,0 @@
#ifndef _OSAL_OS_H_
#define _OSAL_OS_H_
__QCLOUD_OSAL__ void *osal_mutex_create(void);
__QCLOUD_OSAL__ void osal_mutex_destroy(void *mutex);
__QCLOUD_OSAL__ void osal_mutex_lock(void *mutex);
__QCLOUD_OSAL__ int osal_mutex_trylock(void *mutex);
__QCLOUD_OSAL__ void osal_mutex_unlock(void *mutex);
__QCLOUD_OSAL__ void *osal_malloc(uint32_t size);
__QCLOUD_OSAL__ void osal_free(void *ptr);
__QCLOUD_OSAL__ void osal_printf(const char *fmt, ...);
__QCLOUD_OSAL__ int osal_snprintf(char *str, const int len, const char *fmt, ...);
__QCLOUD_OSAL__ int osal_vsnprintf(char *str, const int len, const char *format, va_list ap);
__QCLOUD_OSAL__ uint32_t osal_uptime_ms(void);
__QCLOUD_OSAL__ void osal_sleep_ms(uint32_t ms);
#endif

View File

@@ -1,13 +0,0 @@
#ifndef _OSAL_TCP_
#define _OSAL_TCP_
__QCLOUD_OSAL__ int osal_tcp_connect(const char *host, uint16_t port);
__QCLOUD_OSAL__ int osal_tcp_disconnect(int fd);
__QCLOUD_OSAL__ qcloud_err_t osal_tcp_write(int fd, const void *buf, size_t len, uint32_t timeout, size_t *write_len);
__QCLOUD_OSAL__ qcloud_err_t osal_tcp_read(int fd, void *buf, size_t len, uint32_t timeout, size_t *read_len);
#endif

View File

@@ -1,23 +0,0 @@
#ifndef _OSAL_TIMER_H_
#define _OSAL_TIMER_H_
typedef struct osal_timer_st {
uint32_t end_time;
} osal_timer_t;
__QCLOUD_OSAL__ int osal_timer_is_expired(osal_timer_t *timer);
__QCLOUD_OSAL__ void osal_timer_countdown_ms(osal_timer_t *timer, uint32_t timeout);
__QCLOUD_OSAL__ void osal_timer_countdown(osal_timer_t *timer, uint32_t timeout);
__QCLOUD_OSAL__ uint32_t osal_timer_remain(osal_timer_t *timer);
__QCLOUD_OSAL__ void osal_timer_init(osal_timer_t *timer);
__QCLOUD_OSAL__ char *osal_timer_current(void);
__QCLOUD_OSAL__ long osal_timer_current_sec(void);
#endif

View File

@@ -1,13 +0,0 @@
#ifndef _OSAL_TLS_H_
#define _OSAL_TLS_H_
__QCLOUD_OSAL__ void *osal_tls_connect(qcloud_tls_opt_t *tls_opt, const char *host, int port);
__QCLOUD_OSAL__ void osal_tls_disconnect(void *handle);
__QCLOUD_OSAL__ qcloud_err_t osal_tls_write(void *handle, const void *buf, size_t len, uint32_t timeout, size_t *write_len);
__QCLOUD_OSAL__ qcloud_err_t osal_tls_read(void *handle, void *buf, size_t len, uint32_t timeout, size_t *read_len) ;
#endif

View File

@@ -1,13 +0,0 @@
#ifndef _OSAL_UDP_H_
#define _OSAL_UDP_H_
__QCLOUD_OSAL__ int osal_udp_connect(const char *host, unsigned short port);
__QCLOUD_OSAL__ void osal_udp_disconnect(int sockfd);
__QCLOUD_OSAL__ qcloud_err_t osal_udp_write(int sockfd, const void *buf, size_t len, uint32_t timeout, size_t *write_len);
__QCLOUD_OSAL__ qcloud_err_t osal_udp_read(int sockfd, void *buf, size_t len, uint32_t timeout, size_t *read_len);
#endif

View File

@@ -1,273 +0,0 @@
#ifndef _QCLOUD_SHADOW_H_
#define _QCLOUD_SHADOW_H_
/**
* @brief <20>豸Ӱ<E8B1B8><D3B0><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>һЩ<D2BB>ӿ<EFBFBD>
*
* <20><><EFBFBD><EFBFBD><EFBFBD>һЩ<D2BB>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD><EFBFBD>豸Ӱ<E8B1B8><D3B0><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>豸Ӱ<E8B1B8><D3B0><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>н<EFBFBD><D0BD><EFBFBD>; ͨ<><CDA8>DeviceName,
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>豸Ӱ<E8B1B8>ӽ<EFBFBD><D3BD>н<EFBFBD><D0BD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><E8B1B8><EFBFBD>豸Ӱ<E8B1B8>Ӻ<EFBFBD><D3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD>豸Ӱ<E8B1B8><D3B0>; һ
* <20><><EFBFBD>һ<E8B1B8><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>豸Ӱ<E8B1B8>ӽ<EFBFBD><D3BD><EFBFBD>:
* 1. Get
* 2. Update
* 3. Delete
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD>, <20>ײ㻹<D7B2>ǻ<EFBFBD><C7BB><EFBFBD>MQTTЭ<54><D0AD>, <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>Ҳ<EFBFBD>ǻ<EFBFBD><C7BB>ڷ<EFBFBD><DAB7><EFBFBD>/<2F><><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>, <20><>ִ<EFBFBD><D6B4>
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>Ӧ: 1. accepted; 2. rejected<65><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>
* Get<65><74><EFBFBD>豸Ӱ<E8B1B8>ӽ<EFBFBD><D3BD>н<EFBFBD><D0BD><EFBFBD>, <20><EFBFBD>˽<EFBFBD><CBBD><EFBFBD><EFBFBD>ͺͽ<CDBA><CDBD>յ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ϣ:
* 1. <20><><EFBFBD><EFBFBD>MQTT<54><54><EFBFBD><EFBFBD>: $shadow/get/{productName}/{deviceName};
* 2. <20><><EFBFBD><EFBFBD>MQTT<54><54><EFBFBD><EFBFBD>: $shadow/get/accepted/{productName}/{deviceName} <20><> $shadow/get/rejected/{productName}/{deviceName}
* 3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9>Ļ<EFBFBD>, <20><EFBFBD>˻<EFBFBD><CBBB>յ<EFBFBD>accepted<65><64><EFBFBD><EFBFBD>, <20>Լ<EFBFBD><D4BC><EFBFBD>Ӧ<EFBFBD><EFBFBD><E8B1B8>json<6F>ĵ<EFBFBD><C4B5><EFBFBD>
*/
#define SHADOW_FIELD_VERSION "version"
#define SHADOW_FIELD_TYPE "type"
#define SHADOW_FIELD_CLIENT_TOKEN "clientToken"
#define SHADOW_FIELD_RESULT "result"
#define SHADOW_OPERATION_DELTA "delta"
#define SHADOW_OPERATION_GET "get"
#define SHADOW_OPERATION_UPDATE "update"
#define SHADOW_PAYLOAD_STATE "payload.state"
#define SHADOW_PAYLOAD_VERSION "payload.version"
#define SHADOW_PAYLOAD_STATE_DELTA "payload.state.delta"
typedef int32_t template_int_t;
typedef float template_float_t;
typedef int8_t template_bool_t;
typedef char template_string_t;
typedef uint32_t template_time_t;
typedef void * template_object_t;
typedef enum json_data_type_en {
JSON_DATA_TYPE_INT32,
JSON_DATA_TYPE_INT16,
JSON_DATA_TYPE_INT8,
JSON_DATA_TYPE_UINT32,
JSON_DATA_TYPE_UINT16,
JSON_DATA_TYPE_UINT8,
JSON_DATA_TYPE_FLOAT,
JSON_DATA_TYPE_DOUBLE,
JSON_DATA_TYPE_BOOL,
JSON_DATA_TYPE_STRING,
JSON_DATA_TYPE_OBJECT,
} json_data_type_t;
typedef enum shadow_type_en {
SHADOW_TYPE_SHADOW,
SHADOW_TYPE_TEMPLATE,
} shadow_type_t;
typedef enum shadow_sync_state_en {
QCLOUD_SHADOW_SYNC_STATE_NONE,
QCLOUD_SHADOW_SYNC_STATE_PENDACK,
QCLOUD_SHADOW_SYNC_STATE_SUCCESS,
QCLOUD_SHADOW_SYNC_STATE_TIMEOUT,
QCLOUD_SHADOW_SYNC_STATE_NACK,
} shadow_sync_state_t;
typedef struct shadow_device_property_st {
const char *key;
json_data_type_t type;
void *data;
} shadow_dev_property_t;
/**
* @brief Define callback when device property change
*
* @param pJsonValueBuffer property JSON buffer
* @param valueLength property length
* @param DeviceProperty reference to device property
*/
typedef void (*shadow_property_delta_handler_fn_t)(void *client, const char *json_doc, uint32_t json_doc_len, shadow_dev_property_t *property);
typedef struct qcloud_shadow_property_info_st {
qcloud_list_t list;
shadow_dev_property_t *dev_property;
shadow_property_delta_handler_fn_t handler;
} qcloud_shadow_prop_info_t;
typedef enum qcloud_shadow_request_state_en {
QCLOUD_SHADOW_REQUEST_STATE_NONE,
QCLOUD_SHADOW_REQUEST_STATE_ACCEPTED,
QCLOUD_SHADOW_REQUEST_STATE_REJECTED,
QCLOUD_SHADOW_REQUEST_STATE_TIMEOUT,
} qcloud_shadow_req_state_t;
typedef enum qcloud_shadow_request_method_en {
QCLOUD_SHADOW_REQUEST_METHOD_GET,
QCLOUD_SHADOW_REQUEST_METHOD_UPDATE,
QCLOUD_SHADOW_REQUEST_METHOD_DELETE,
} qcloud_shadow_req_method_t;
/**
* @brief Define MQTT shadow callback when request response arrived
*
* @param method type of request
* @param requestAck response type
* @param pJsonDocument JSON document from server
* @param userContext User context
*
*/
typedef void (*shadow_requset_handler_fn_t)(void *client, qcloud_shadow_req_method_t method, qcloud_shadow_req_state_t req_state, const char *json_doc, void *context);
typedef struct qcloud_shadow_request_option_st {
qcloud_shadow_req_method_t method;
uint32_t timeout;
shadow_requset_handler_fn_t handler;
void *context;
} qcloud_shadow_req_opt_t;
typedef struct qcloud_shadow_request_st {
qcloud_list_t list;
char client_token[QCLOUD_SHADOW_CLIENT_TOKEN_MAX];
qcloud_shadow_req_method_t method;
void *context;
osal_timer_t timer;
shadow_requset_handler_fn_t handler;
} qcloud_shadow_request_t;
typedef struct qcloud_shadow_request_info_st {
qcloud_list_t list;
qcloud_shadow_request_t *shadow_request;
} qcloud_shadow_req_info_t;
typedef struct qcloud_shadow_client_st {
qcloud_mqtt_client_t mqtt_client;
mqtt_connect_opt_t mqtt_connect_opt;
mqtt_event_handler_t event_handler;
shadow_type_t shadow_type;
void *global_lock;
uint32_t version;
uint32_t token_num;
shadow_sync_state_t sync_state;
char device_product_id[QCLOUD_DEVICE_PRODUCT_ID_MAX + 1];
char request_topic_subscribe[QCLOUD_MQTT_TOPIC_SIZE_MAX + 1];
char request_topic_publish[QCLOUD_MQTT_TOPIC_SIZE_MAX + 1];
qcloud_list_t request_list;
uint32_t request_list_counter;
qcloud_list_t property_list;
} qcloud_shadow_client_t;
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_create(qcloud_shadow_client_t *client,
qcloud_device_t *device,
mqtt_event_handler_fn_t handler,
shadow_type_t shadow_type);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_create(qcloud_shadow_client_t *client,
qcloud_device_t *device,
mqtt_event_handler_fn_t handler,
shadow_type_t shadow_type);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_yield(qcloud_shadow_client_t *client, uint32_t timeout);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_publish(qcloud_shadow_client_t *client, char *topic, mqtt_publish_opt_t *publish_opt);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_subscribe(qcloud_shadow_client_t *client, const char *topic_filter, mqtt_subscribe_opt_t *subscribe_opt);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_unsubscribe(qcloud_shadow_client_t *client, const char *topic_filter);
__QCLOUD_API__ int qcloud_shadow_client_is_connected(qcloud_shadow_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_destroy(qcloud_shadow_client_t *client);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_device_property_register(qcloud_shadow_client_t *client,
shadow_dev_property_t *dev_property,
shadow_property_delta_handler_fn_t handler);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_device_property_unregister(qcloud_shadow_client_t *client, shadow_dev_property_t *dev_property);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_update_async(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
shadow_requset_handler_fn_t handler,
void *context,
uint32_t timeout);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_update_sync(qcloud_shadow_client_t *client, char *json_doc, size_t json_doc_size, uint32_t timeout);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_get_async(qcloud_shadow_client_t *client,
shadow_requset_handler_fn_t handler,
void *context,
uint32_t timeout);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_get_sync(qcloud_shadow_client_t *client, uint32_t timeout);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_report_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_report_construct_array(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count,
shadow_dev_property_t *dev_propertys[]);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_overwrite_report_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_report_with_desire_null_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_desire_null_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size);
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_desire_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_operation_request_subscribe(qcloud_shadow_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_operation_request_unsubscribe(qcloud_shadow_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_request_list_scan(qcloud_shadow_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_request_post(qcloud_shadow_client_t *client,
qcloud_shadow_req_opt_t *request_opt,
char *json_doc,
size_t json_doc_size);
__QCLOUD_INTERNAL__ void shadow_glue_delta_handle(qcloud_shadow_client_t *client, char *delta);
__QCLOUD_INTERNAL__ void shadow_glue_property_list_destroy(qcloud_shadow_client_t *client);
__QCLOUD_INTERNAL__ void shadow_glue_request_list_destroy(qcloud_shadow_client_t *client);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_snprintf_rc2errno(int rc, size_t write_max);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_client_token_generate(char *json_doc, size_t json_doc_size, uint32_t token_num, char *device_product_id);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_node_add(char *json_doc, size_t json_doc_size, const char *key, void *data, json_data_type_t type);
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_empty_doc_build(char *json_doc, uint32_t token_num, char *device_product_id);
__QCLOUD_INTERNAL__ int shadow_json_client_token_parse(char *json_doc, char **client_token);
__QCLOUD_INTERNAL__ int shadow_json_version_parse(char *json_doc, uint32_t *version);
__QCLOUD_INTERNAL__ int shadow_json_operation_type_parse(char *json_doc, char **pType);
__QCLOUD_INTERNAL__ int shadow_json_operation_result_code_parse(char *json_doc, int16_t *result_code);
__QCLOUD_INTERNAL__ int shadow_json_delta_parse(char *json_doc, char **delta);
__QCLOUD_INTERNAL__ int shadow_json_operation_delta_get(char *json_doc, char **delta);
__QCLOUD_INTERNAL__ int shadow_json_value_update(char *json, shadow_dev_property_t *dev_property);
__QCLOUD_INTERNAL__ int shadow_state_parse(char *json_doc, char **state);
#endif

View File

@@ -1,15 +0,0 @@
#ifndef _QCLOUD_SHADOW_CONFIG_
#define _QCLOUD_SHADOW_CONFIG_
/* 接收云端返回的JSON文档的buffer大小 */
#define QCLOUD_SHADOW_JSON_BUF_MAX (QCLOUD_MQTT_CLIENT_RX_BUF_LEN + 1)
#define QCLOUD_SHADOW_CLIENT_TOKEN_MAX (QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX + 10)
/* 一个仅包含clientToken字段的JSON文档的最大长度 */
#define QCLOUD_SHADOW_JSON_WITH_CLIENT_TOKEN_MAX (QCLOUD_SHADOW_CLIENT_TOKEN_MAX + 20)
#define QCLOUD_SHADOW_REQUEST_PENDING_MAX (10)
#endif

View File

@@ -1,104 +0,0 @@
#ifndef _QCLOUD_TLS_H_
#define _QCLOUD_TLS_H_
static const char *qcloud_ca_cert = \
{
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDxTCCAq2gAwIBAgIJALM1winYO2xzMA0GCSqGSIb3DQEBCwUAMHkxCzAJBgNV\r\n" \
"BAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxETAPBgNVBAcMCFNoZW5aaGVuMRAw\r\n" \
"DgYDVQQKDAdUZW5jZW50MRcwFQYDVQQLDA5UZW5jZW50IElvdGh1YjEYMBYGA1UE\r\n" \
"AwwPd3d3LnRlbmNlbnQuY29tMB4XDTE3MTEyNzA0MjA1OVoXDTMyMTEyMzA0MjA1\r\n" \
"OVoweTELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzERMA8GA1UEBwwI\r\n" \
"U2hlblpoZW4xEDAOBgNVBAoMB1RlbmNlbnQxFzAVBgNVBAsMDlRlbmNlbnQgSW90\r\n" \
"aHViMRgwFgYDVQQDDA93d3cudGVuY2VudC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\r\n" \
"A4IBDwAwggEKAoIBAQDVxwDZRVkU5WexneBEkdaKs4ehgQbzpbufrWo5Lb5gJ3i0\r\n" \
"eukbOB81yAaavb23oiNta4gmMTq2F6/hAFsRv4J2bdTs5SxwEYbiYU1teGHuUQHO\r\n" \
"iQsZCdNTJgcikga9JYKWcBjFEnAxKycNsmqsq4AJ0CEyZbo//IYX3czEQtYWHjp7\r\n" \
"FJOlPPd1idKtFMVNG6LGXEwS/TPElE+grYOxwB7Anx3iC5ZpE5lo5tTioFTHzqbT\r\n" \
"qTN7rbFZRytAPk/JXMTLgO55fldm4JZTP3GQsPzwIh4wNNKhi4yWG1o2u3hAnZDv\r\n" \
"UVFV7al2zFdOfuu0KMzuLzrWrK16SPadRDd9eT17AgMBAAGjUDBOMB0GA1UdDgQW\r\n" \
"BBQrr48jv4FxdKs3r0BkmJO7zH4ALzAfBgNVHSMEGDAWgBQrr48jv4FxdKs3r0Bk\r\n" \
"mJO7zH4ALzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDRSjXnBc3T\r\n" \
"d9VmtTCuALXrQELY8KtM+cXYYNgtodHsxmrRMpJofsPGiqPfb82klvswpXxPK8Xx\r\n" \
"SuUUo74Fo+AEyJxMrRKlbJvlEtnpSilKmG6rO9+bFq3nbeOAfat4lPl0DIscWUx3\r\n" \
"ajXtvMCcSwTlF8rPgXbOaSXZidRYNqSyUjC2Q4m93Cv+KlyB+FgOke8x4aKAkf5p\r\n" \
"XR8i1BN1OiMTIRYhGSfeZbVRq5kTdvtahiWFZu9DGO+hxDZObYGIxGHWPftrhBKz\r\n" \
"RT16Amn780rQLWojr70q7o7QP5tO0wDPfCdFSc6CQFq/ngOzYag0kJ2F+O5U6+kS\r\n" \
"QVrcRBDxzx/G\r\n" \
"-----END CERTIFICATE-----"
};
static const char *qcloud_https_ca_cert = \
{
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n"
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n"
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\r\n"
"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n"
"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\r\n"
"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\r\n"
"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\r\n"
"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\r\n"
"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\r\n"
"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\r\n"
"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\r\n"
"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\r\n"
"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\r\n"
"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\r\n"
"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\r\n"
"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\r\n"
"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\r\n"
"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\r\n"
"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n"
"-----END CERTIFICATE-----\r\n"
"-----BEGIN CERTIFICATE-----\r\n"
"MIIEaTCCA1GgAwIBAgILBAAAAAABRE7wQkcwDQYJKoZIhvcNAQELBQAwVzELMAkG\r\n"
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n"
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xNDAyMjAxMDAw\r\n"
"MDBaFw0yNDAyMjAxMDAwMDBaMGYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n"
"YWxTaWduIG52LXNhMTwwOgYDVQQDEzNHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBW\r\n"
"YWxpZGF0aW9uIENBIC0gU0hBMjU2IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IB\r\n"
"DwAwggEKAoIBAQDHDmw/I5N/zHClnSDDDlM/fsBOwphJykfVI+8DNIV0yKMCLkZc\r\n"
"C33JiJ1Pi/D4nGyMVTXbv/Kz6vvjVudKRtkTIso21ZvBqOOWQ5PyDLzm+ebomchj\r\n"
"SHh/VzZpGhkdWtHUfcKc1H/hgBKueuqI6lfYygoKOhJJomIZeg0k9zfrtHOSewUj\r\n"
"mxK1zusp36QUArkBpdSmnENkiN74fv7j9R7l/tyjqORmMdlMJekYuYlZCa7pnRxt\r\n"
"Nw9KHjUgKOKv1CGLAcRFrW4rY6uSa2EKTSDtc7p8zv4WtdufgPDWi2zZCHlKT3hl\r\n"
"2pK8vjX5s8T5J4BO/5ZS5gIg4Qdz6V0rvbLxAgMBAAGjggElMIIBITAOBgNVHQ8B\r\n"
"Af8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUlt5h8b0cFilT\r\n"
"HMDMfTuDAEDmGnwwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0\r\n"
"dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMDMGA1UdHwQsMCow\r\n"
"KKAmoCSGImh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5uZXQvcm9vdC5jcmwwPQYIKwYB\r\n"
"BQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNv\r\n"
"bS9yb290cjEwHwYDVR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZI\r\n"
"hvcNAQELBQADggEBAEYq7l69rgFgNzERhnF0tkZJyBAW/i9iIxerH4f4gu3K3w4s\r\n"
"32R1juUYcqeMOovJrKV3UPfvnqTgoI8UV6MqX+x+bRDmuo2wCId2Dkyy2VG7EQLy\r\n"
"XN0cvfNVlg/UBsD84iOKJHDTu/B5GqdhcIOKrwbFINihY9Bsrk8y1658GEV1BSl3\r\n"
"30JAZGSGvip2CTFvHST0mdCF/vIhCPnG9vHQWe3WVjwIKANnuvD58ZAWR65n5ryA\r\n"
"SOlCdjSXVWkkDoPWoC209fN5ikkodBpBocLTJIg1MGCUF7ThBCIxPTsvFwayuJ2G\r\n"
"K1pp74P1S8SqtCr4fKGxhZSM9AyHDPSsQPhZSZg=\r\n"
"-----END CERTIFICATE-----"
};
typedef struct qcloud_tls_option_st {
const char *ca_cert;
size_t ca_cert_len;
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
const char *cert_path;
const char *priv_key_path;
#else
uint8_t psk[QCLOUD_PSK_MAX];
char psk_id[QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX + 1];
size_t psk_len;
#endif
void *handle;
uint32_t timeout;
} qcloud_tls_opt_t;
__QCLOUD_INTERNAL__ qcloud_err_t qcloud_tls_init(qcloud_tls_opt_t *tls_opt, qcloud_device_t *device);
#endif

View File

@@ -1,16 +0,0 @@
#ifndef _QCLOUD_TYPES_H_
#define _QCLOUD_TYPES_H_
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
#define QCLOUD_TRUE (1u)
#define QCLOUD_FALSE (0u)
#endif

View File

@@ -1,317 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef QCLOUD_IOT_UTILS_AES_H_
#define QCLOUD_IOT_UTILS_AES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
//========Platform================================//
#define UTILS_AES_C
#define UTILS_CIPHER_MODE_CBC
//#define UTILS_SELF_TEST
#define UTILS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */
#define UTILS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */
/* Internal macros meant to be called only from within the library. */
#define UTILS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 )
#define UTILS_INTERNAL_VALIDATE( cond ) do { } while( 0 )
//==============================================//
/* padlock.c and aesni.c rely on these values! */
#define UTILS_AES_ENCRYPT 1 /**< AES encryption. */
#define UTILS_AES_DECRYPT 0 /**< AES decryption. */
#define UTILS_AES_BLOCK_LEN 16
#define AES_KEY_BITS_128 128
#define AES_KEY_BITS_192 192
#define AES_KEY_BITS_256 256
/* Error codes in range 0x0020-0x0022 */
#define UTILS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define UTILS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/* Error codes in range 0x0021-0x0025 */
#define UTILS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */
/* UTILS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */
#define UTILS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */
/* UTILS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */
#define UTILS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */
#if !defined(UTILS_AES_ALT)
// Regular implementation
//
/**
* \brief The AES context-type definition.
*/
typedef struct utils_aes_context
{
int nr; /*!< The number of rounds. */
uint32_t *rk; /*!< AES round keys. */
uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can
hold 32 extra Bytes, which can be used for
one of the following purposes:
<ul><li>Alignment if VIA padlock is
used.</li>
<li>Simplifying key expansion in the 256-bit
case by generating an extra round key.
</li></ul> */
}
utils_aes_context;
#else /* UTILS_AES_ALT */
#include "aes_alt.h"
#endif /* UTILS_AES_ALT */
/**
* \brief This function initializes the specified AES context.
*
* It must be the first API called before using
* the context.
*
* \param ctx The AES context to initialize. This must not be \c NULL.
*/
void utils_aes_init( utils_aes_context *ctx );
/**
* \brief This function releases and clears the specified AES context.
*
* \param ctx The AES context to clear.
* If this is \c NULL, this function does nothing.
* Otherwise, the context must have been at least initialized.
*/
void utils_aes_free( utils_aes_context *ctx );
/**
* \brief This function sets the encryption key.
*
* \param ctx The AES context to which the key should be bound.
* It must be initialized.
* \param key The encryption key.
* This must be a readable buffer of size \p keybits bits.
* \param keybits The size of data passed in bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
* \return \c 0 on success.
* \return #UTILS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int utils_aes_setkey_enc( utils_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief This function sets the decryption key.
*
* \param ctx The AES context to which the key should be bound.
* It must be initialized.
* \param key The decryption key.
* This must be a readable buffer of size \p keybits bits.
* \param keybits The size of data passed. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
* \return \c 0 on success.
* \return #UTILS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int utils_aes_setkey_dec( utils_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief This function performs an AES single-block encryption or
* decryption operation.
*
* It performs the operation defined in the \p mode parameter
* (encrypt or decrypt), on the input data buffer defined in
* the \p input parameter.
*
* utils_aes_init(), and either utils_aes_setkey_enc() or
* utils_aes_setkey_dec() must be called before the first
* call to this API with the same context.
*
* \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param mode The AES operation: #UTILS_AES_ENCRYPT or
* #UTILS_AES_DECRYPT.
* \param input The buffer holding the input data.
* It must be readable and at least \c 16 Bytes long.
* \param output The buffer where the output data will be written.
* It must be writeable and at least \c 16 Bytes long.
* \return \c 0 on success.
*/
int utils_aes_crypt_ecb( utils_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
#if defined(UTILS_CIPHER_MODE_CBC)
/**
* \brief This function performs an AES-CBC encryption or decryption operation
* on full blocks.
*
* It performs the operation defined in the \p mode
* parameter (encrypt/decrypt), on the input data buffer defined in
* the \p input parameter.
*
* It can be called as many times as needed, until all the input
* data is processed. utils_aes_init(), and either
* utils_aes_setkey_enc() or utils_aes_setkey_dec() must be called
* before the first call to this API with the same context.
*
* \note This function operates on full blocks, that is, the input size
* must be a multiple of the AES block size of \c 16 Bytes.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the same function again on the next
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If you need to retain the contents of the IV, you should
* either save it manually or use the cipher module instead.
*
*
* \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param mode The AES operation: #UTILS_AES_ENCRYPT or
* #UTILS_AES_DECRYPT.
* \param length The length of the input data in Bytes. This must be a
* multiple of the block size (\c 16 Bytes).
* \param iv Initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
* \return #UTILS_ERR_AES_INVALID_INPUT_LENGTH
* on failure.
*/
int utils_aes_crypt_cbc( utils_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /* UTILS_CIPHER_MODE_CBC */
/**
* \brief Internal AES block encryption function. This is only
* exposed to allow overriding it using
* \c UTILS_AES_ENCRYPT_ALT.
*
* \param ctx The AES context to use for encryption.
* \param input The plaintext block.
* \param output The output (ciphertext) block.
*
* \return \c 0 on success.
*/
int utils_internal_aes_encrypt( utils_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal AES block decryption function. This is only
* exposed to allow overriding it using see
* \c UTILS_AES_DECRYPT_ALT.
*
* \param ctx The AES context to use for decryption.
* \param input The ciphertext block.
* \param output The output (plaintext) block.
*
* \return \c 0 on success.
*/
int utils_internal_aes_decrypt( utils_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
#if !defined(UTILS_DEPRECATED_REMOVED)
#if defined(UTILS_DEPRECATED_WARNING)
#define UTILS_DEPRECATED __attribute__((deprecated))
#else
#define UTILS_DEPRECATED
#endif
/**
* \brief Deprecated internal AES block encryption function
* without return value.
*
* \deprecated Superseded by utils_internal_aes_encrypt()
*
* \param ctx The AES context to use for encryption.
* \param input Plaintext block.
* \param output Output (ciphertext) block.
*/
UTILS_DEPRECATED void utils_aes_encrypt( utils_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Deprecated internal AES block decryption function
* without return value.
*
* \deprecated Superseded by utils_internal_aes_decrypt()
*
* \param ctx The AES context to use for decryption.
* \param input Ciphertext block.
* \param output Output (plaintext) block.
*/
UTILS_DEPRECATED void utils_aes_decrypt( utils_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
#undef UTILS_DEPRECATED
#endif /* !UTILS_DEPRECATED_REMOVED */
#if defined(UTILS_SELF_TEST)
/**
* \brief Checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int utils_aes_self_test( int verbose );
#endif /* UTILS_SELF_TEST */
int aes_sample(int verbose);
int utils_aes_cbc(uint8_t *pInData, uint32_t datalen,
uint8_t *pOutData, uint32_t outBuffLen,
uint8_t mode, uint8_t *pKey,
uint16_t keybits, uint8_t *iv);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,36 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef QCLOUD_IOT_UTILS_BASE64_H_
#define QCLOUD_IOT_UTILS_BASE64_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include "qcloud.h"
int qcloud_utils_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen );
int qcloud_utils_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen );
#ifdef __cplusplus
}
#endif
#endif /* QCLOUD_IOT_UTILS_BASE64_H_ */

View File

@@ -1,26 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef QCLOUD_IOT_UTILS_HMAC_H_
#define QCLOUD_IOT_UTILS_HMAC_H_
#include <string.h>
void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len);
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
#endif

View File

@@ -1,80 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef QCLOUD_IOT_UTILS_HTTPC_H_
#define QCLOUD_IOT_UTILS_HTTPC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#define HTTP_PORT 80
#define HTTPS_PORT 443
typedef enum {
HTTP_GET,
HTTP_POST,
HTTP_PUT,
HTTP_DELETE,
HTTP_HEAD
} HttpMethod;
typedef struct {
int remote_port; // 端口号
int response_code; // 响应码
char *header; // 自定义头部
char *auth_user; // 身份验证的用户名
char *auth_password; // 身份验证的密码
qcloud_network_t network;
} HTTPClient;
typedef struct {
bool is_more; // 是否需要检索更多的数据
bool is_chunked; // 响应数据是否以分块进行编码
int retrieve_len; // 要检索的内容长度
int response_content_len; // 响应内容长度
int post_buf_len; // post data length
int response_buf_len; // 响应包缓冲区长度
char *post_content_type; // post数据的内容类型
char *post_buf; // post的数据
char *response_buf; // 存储响应数据的缓冲区
} HTTPClientData;
/**
* @brief http 网络请求
*
* @param client http client
* @param url 请求url
* @param port 请求端口
* @param ca_crt_dir ca证书路径
* @param method 请求方法
* @param client_data http数据负载
* @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功
*/
int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method, HTTPClientData *client_data);
int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data);
int qcloud_http_client_connect(HTTPClient *client, const char *url, int port, const char *ca_crt);
void qcloud_http_client_close(HTTPClient *client);
#ifdef __cplusplus
}
#endif
#endif /* QCLOUD_IOT_UTILS_HTTPC_H_ */

View File

@@ -1,157 +0,0 @@
/*
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
* License-Identifier: Apache-2.0
*
* 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.
*
*/
#ifndef __JSON_PARSER_H__
#define __JSON_PARSER_H__
/**
The descriptions of the json value node type
**/
enum JSONTYPE {
JSNONE = -1,
JSSTRING = 0,
JSOBJECT,
JSARRAY,
JSNUMBER,
JSBOOLEAN,
JSNULL,
JSTYPEMAX
};
/**
The error codes produced by the JSON parsers
**/
enum JSON_PARSE_CODE {
JSON_PARSE_ERR,
JSON_PARSE_OK,
JSON_PARSE_FINISH
};
/**
The return codes produced by the JSON parsers
**/
enum JSON_PARSE_RESULT {
JSON_RESULT_ERR = -1,
JSON_RESULT_OK
};
typedef int (*json_parse_cb)(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
void *p_Result);
/**
* @brief Parse the JSON string, and iterate through all keys and values,
* then handle the keys and values by callback function.
*
* @param[in] p_cJsonStr @n The JSON string
* @param[in] iStrLen @n The JSON string length
* @param[in] pfnCB @n Callback function
* @param[out] p_CBData @n User data
* @return JSON_RESULT_OK success, JSON_RESULT_ERR failed
* @see None.
* @note None.
**/
int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData);
/**
* @brief Get the value by a specified key from a json string
*
* @param[in] p_cJsonStr @n the JSON string
* @param[in] iStrLen @n the JSON string length
* @param[in] p_cName @n the specified key string
* @param[out] p_iValueLen @n the value length
* @param[out] p_iValueType @n the value type
* @return A pointer to the value
* @see None.
* @note None.
**/
char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType);
/**
* @brief Get the JSON object point associate with a given type.
*
* @param[in] type @n The object type
* @param[in] str @n The JSON string
* @returns The json object point with the given field type.
* @see None.
* @note None.
*/
char *json_get_object(int type, char *str);
char *json_get_next_object(int type, char *str, char **key, int *key_len, char **val, int *val_len, int *val_type);
/**
* @brief retrieve each key&value pair from the json string
*
* @param[in] str @n Json string to revolve
* @param[in] pos @n cursor
* @param[out] key @n pointer to the next Key object
* @param[out] klen @n Key object length
* @param[out] val @n pointer to the next Value object
* @param[out] vlen @n Value object length
* @param[out] vtype @n Value object type(digital, string, object, array)
* @see None.
* @note None.
*/
#define json_object_for_each_kv(str, pos, key, klen, val, vlen, vtype) \
for (pos = json_get_object(JSOBJECT, str); \
pos!=0 && *pos!=0 && (pos=json_get_next_object(JSOBJECT, pos, &key, &klen, &val, &vlen, &vtype))!=0; )
/**
* @brief retrieve each entry from the json array
*
* @param[in] str @n Json array to revolve
* @param[in] pos @n cursor
* @param[out] entry @n pointer to the next entry from the array
* @param[out] len @n entry length
* @param[out] type @n entry type(digital, string, object, array)
* @see None.
* @note None.
*/
#define json_array_for_each_entry(str, pos, entry, len, type) \
for (pos = json_get_object(JSARRAY, str); \
pos!=0 && *pos!=0 && (pos=json_get_next_object(JSARRAY, ++pos, 0, 0, &entry, &len, &type))!=0; )
/**
* @brief backup the last character to register parameters,
* and set the end character with '\0'
*
* @param[in] json_str @n json string
* @param[in] str_len @n json string lenth
* @param[out] register @n used to backup the last character
* @see None.
* @note None.
*/
#define backup_json_str_last_char(json_str, str_len, register) { \
register = *((char *)json_str + str_len); \
*((char *)json_str + str_len) = '\0'; \
}
/**
* @brief restore the last character from register parameters
*
* @param[in] json_str @n json string
* @param[in] str_len @n json string lenth
* @param[in] register @n used to restore the last character
* @see None.
* @note None.
*/
#define restore_json_str_last_char(json_str, str_len, register) { \
*((char *)json_str + str_len) = register; \
}
#endif /* __JSON_PARSER_H__ */

View File

@@ -1,109 +0,0 @@
#ifndef _QCLOUD_LIST_H_
#define _QCLOUD_LIST_H_
typedef struct qcloud_list_node_st {
struct qcloud_list_node_st *next;
struct qcloud_list_node_st *prev;
} qcloud_list_t;
#define QCLOUD_OFFSET_OF_FIELD(type, field) \
((uint32_t)&(((type *)0)->field))
#define QCLOUD_CONTAINER_OF_FIELD(ptr, type, field) \
((type *)((uint8_t *)(ptr) - QCLOUD_OFFSET_OF_FIELD(type, field)))
#define QCLOUD_LIST_NODE(node) \
{ &(node), &(node) }
#define QCLOUD_LIST_DEFINE(list) \
qcloud_list_t list = { &(list), &(list) }
#define QCLOUD_LIST_ENTRY(list, type, field) \
QCLOUD_CONTAINER_OF_FIELD(list, type, field)
#define QCLOUD_LIST_FIRST_ENTRY(list, type, field) \
QCLOUD_LIST_ENTRY((list)->next, type, field)
#define QCLOUD_LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
(qcloud_list_empty(list) ? NULL : QCLOUD_LIST_FIRST_ENTRY(list, type, field))
#define QCLOUD_LIST_FOR_EACH(curr, list) \
for (curr = (list)->next; curr != (list); curr = curr->next)
#define QCLOUD_LIST_FOR_EACH_PREV(curr, list) \
for (curr = (list)->prev; curr != (list); curr = curr->prev)
#define QCLOUD_LIST_FOR_EACH_SAFE(curr, next, list) \
for (curr = (list)->next, next = curr->next; curr != (list); \
curr = next, next = curr->next)
#define QCLOUD_LIST_FOR_EACH_PREV_SAFE(curr, next, list) \
for (curr = (list)->prev, next = curr->prev; \
curr != (list); \
curr = next, next = curr->prev)
__QCLOUD_STATIC__ void _qcloud_list_add(qcloud_list_t *node, qcloud_list_t *prev, qcloud_list_t *next)
{
next->prev = node;
node->next = next;
node->prev = prev;
prev->next = node;
}
__QCLOUD_STATIC__ void _qcloud_list_del(qcloud_list_t *prev, qcloud_list_t *next)
{
next->prev = prev;
prev->next = next;
}
__QCLOUD_STATIC__ void _qcloud_list_del_entry(qcloud_list_t *entry)
{
_qcloud_list_del(entry->prev, entry->next);
}
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_init(qcloud_list_t *list)
{
list->next = list;
list->prev = list;
}
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_add(qcloud_list_t *node, qcloud_list_t *list)
{
_qcloud_list_add(node, list, list->next);
}
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_add_tail(qcloud_list_t *node, qcloud_list_t *list)
{
_qcloud_list_add(node, list->prev, list);
}
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_del(qcloud_list_t *entry)
{
_qcloud_list_del(entry->prev, entry->next);
}
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_del_init(qcloud_list_t *entry)
{
_qcloud_list_del_entry(entry);
qcloud_list_init(entry);
}
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_move(qcloud_list_t *node, qcloud_list_t *list)
{
_qcloud_list_del_entry(node);
qcloud_list_add(node, list);
}
__QCLOUD_API__ __QCLOUD_STATIC__ void qcloud_list_move_tail(qcloud_list_t *node, qcloud_list_t *list)
{
_qcloud_list_del_entry(node);
qcloud_list_add_tail(node, list);
}
__QCLOUD_API__ __QCLOUD_STATIC__ int qcloud_list_empty(const qcloud_list_t *list)
{
return list->next == list;
}
#endif /* _QCLOUD_LIST_H_ */

View File

@@ -1,92 +0,0 @@
/*
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
* License-Identifier: Apache-2.0
*
* 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.
*
*/
#ifndef __LITE_UTILS_H__
#define __LITE_UTILS_H__
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#if defined(_PLATFORM_IS_LINUX_)
#include <assert.h>
#endif
#include "qcloud_lite_list.h"
#define LITE_TRUE (1)
#define LITE_FALSE (0)
#ifndef container_of
#define container_of(ptr, type, member) \
((type *) ((char *) (ptr) - offsetof(type, member)))
#endif
#define LITE_MINIMUM(a, b) (((a) <= (b)) ? (a) : (b))
#define LITE_MAXIMUM(a, b) (((a) >= (b)) ? (a) : (b))
#define LITE_isdigit(c) (((c) <= '9' && (c) >= '0') ? (LITE_TRUE) : (LITE_FALSE))
#if defined(_PLATFORM_IS_LINUX_)
#define LITE_ASSERT(expr) assert(expr)
#else
#define LITE_ASSERT(expr) \
do { \
if (!(expr)) { \
osal_printf("### %s | %s(%d): ASSERT FAILED ###: %s is FALSE\r\n", \
__FILE__, __func__, __LINE__, #expr); \
} \
} while(0)
#endif
char *LITE_strdup(const char *src);
char *LITE_format_string(const char *fmt, ...);
char *LITE_format_nstring(const int len, const char *fmt, ...);
void LITE_hexbuf_convert(unsigned char *digest, char *out, int buflen, int uppercase);
void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int len);
void LITE_replace_substr(char orig[], char key[], char swap[]);
char *LITE_json_value_of(char *key, char *src);
list_head_t *LITE_json_keys_of(char *src, char *prefix);
void LITE_json_keys_release(list_head_t *keylist);
qcloud_err_t LITE_get_int32(int32_t *value, char *src);
qcloud_err_t LITE_get_int16(int16_t *value, char *src);
qcloud_err_t LITE_get_int8(int8_t *value, char *src);
qcloud_err_t LITE_get_uint32(uint32_t *value, char *src);
qcloud_err_t LITE_get_uint16(uint16_t *value, char *src);
qcloud_err_t LITE_get_uint8(uint8_t *value, char *src);
qcloud_err_t LITE_get_float(float *value, char *src);
qcloud_err_t LITE_get_double(double *value, char *src);
qcloud_err_t LITE_get_boolean(bool *value, char *src);
typedef struct _json_key_t {
char *key;
list_head_t list;
} json_key_t;
#define foreach_json_keys_in(src, iter_key, keylist, pos) \
for(keylist = (void *)LITE_json_keys_of((char *)src, ""), \
pos = (void *)list_first_entry((list_head_t *)keylist, json_key_t, list), \
iter_key = ((json_key_t *)pos)->key; \
(iter_key = ((json_key_t *)pos)->key); \
pos = list_next_entry((json_key_t *)pos, list, json_key_t))
#endif /* __LITE_UTILS_H__ */

View File

@@ -1,495 +0,0 @@
/*
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
* License-Identifier: Apache-2.0
*
* 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.
*
*/
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
#define inline __inline
typedef struct list_head list_head_t;
struct list_head {
struct list_head *next, *prev;
};
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new_ptr entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new_ptr,
struct list_head *prev,
struct list_head *next)
{
next->prev = new_ptr;
new_ptr->next = next;
new_ptr->prev = prev;
prev->next = new_ptr;
}
/**
* list_add - add a new_ptr entry
* @new_ptr: new_ptr entry to be added
* @head: list head to add it after
*
* Insert a new_ptr entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new_ptr, struct list_head *head)
{
__list_add(new_ptr, head, head->next);
}
/**
* list_add_tail - add a new_ptr entry
* @new_ptr: new_ptr entry to be added
* @head: list head to add it before
*
* Insert a new_ptr entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new_ptr, struct list_head *head)
{
__list_add(new_ptr, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
/**
* list_replace - replace old entry by new_ptr one
* @old : the element to be replaced
* @new_ptr : the new_ptr element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new_ptr)
{
new_ptr->next = old->next;
new_ptr->next->prev = new_ptr;
new_ptr->prev = old->prev;
new_ptr->prev->next = new_ptr;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new_ptr)
{
list_replace(old, new_ptr);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del_entry(list);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del_entry(list);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_rotate_left - rotate the list to the left
* @head: the head of the list
*/
static inline void list_rotate_left(struct list_head *head)
{
struct list_head *first;
if (!list_empty(head)) {
first = head->next;
list_move_tail(first, head);
}
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_last_entry - get the last element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
/**
* list_first_entry_or_null - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note that if the list is empty, it returns NULL.
*/
#define list_first_entry_or_null(ptr, type, member) \
(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor
* @member: the name of the list_struct within the struct.
*/
#define list_next_entry(pos, member, type) \
list_entry((pos)->member.next, type, member)
/**
* list_prev_entry - get the prev element in list
* @pos: the type * to cursor
* @member: the name of the list_struct within the struct.
*/
#define list_prev_entry(pos, member, type) \
list_entry((pos)->member.prev, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* This variant doesn't differ from list_for_each() any more.
* We don't do prefetching in either case.
*/
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member, type) \
for (pos = list_entry((head)->next, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member, type) \
for (pos = list_entry((head)->prev, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, type, member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member, type) \
((pos) ? : list_entry(head, type, member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member, type) \
for (pos = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member, type) \
for (pos = list_entry(pos->member.prev, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, type, member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member, type) \
for (; &pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
/**
* list_for_each_entry_safe_continue - continue list iteration safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member, type) \
for (pos = list_entry(pos->member.next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
/**
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member, type) \
for (n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
/**
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member, type) \
for (pos = list_entry((head)->prev, type, member), \
n = list_entry(pos->member.prev, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, type, member))
/**
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
* @pos: the loop cursor used in the list_for_each_entry_safe loop
* @n: temporary storage used in list_for_each_entry_safe
* @member: the name of the list_struct within the struct.
*
* list_safe_reset_next is not safe to use in general if the list may be
* modified concurrently (eg. the lock is dropped in the loop body). An
* exception to this is if the cursor element (pos) is pinned in the list,
* and list_safe_reset_next is called after re-taking the lock and before
* completing the current iteration of the loop body.
*/
#define list_safe_reset_next(pos, n, member, type) \
n = list_entry(pos->member.next, type, member)
#endif

View File

@@ -1,92 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef QCLOUD_IOT_UTILS_MD5_H_
#define QCLOUD_IOT_UTILS_MD5_H_
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
} iot_md5_context;
/**
* @brief 初始化MD5上下文
*
* @param ctx MD5上下文指针
*/
void utils_md5_init(iot_md5_context *ctx);
/**
* @brief 清空MD5上下文
*
* @param ctx MD5上下文指针
*/
void utils_md5_free(iot_md5_context *ctx);
/**
* @brief 拷贝MD5上下文
*
* @param dst 目标MD5上下文
* @param src 源MD5上下文
*/
void utils_md5_clone(iot_md5_context *dst,
const iot_md5_context *src);
/**
* @brief 设置MD5上下文
*
* @param ctx MD5上下文指针
*/
void utils_md5_starts(iot_md5_context *ctx);
/**
* @brief MD5过程缓冲区
*
* @param ctx MD5上下文指针
* @param input 输入数据
* @param ilen 输入数据长度
*/
void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t ilen);
/**
* @brief MD5数据
*
* @param ctx MD5上下文指针
* @param output MD5校验和结果
*/
void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]);
/* 内部使用 */
void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]);
/**
* @brief Output = MD5( input buffer )
*
* @param input 输入数据
* @param ilen 输入数据长度
* @param output MD5校验和结果
*/
void utils_md5(const unsigned char *input, size_t ilen, unsigned char output[16]);
int8_t utils_hb2hex(uint8_t hb);
#endif

View File

@@ -1,87 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifndef QCLOUD_IOT_UTILS_SHA1_H_
#define QCLOUD_IOT_UTILS_SHA1_H_
/**
* \brief SHA-1 context structure
*/
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
} iot_sha1_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void utils_sha1_init(iot_sha1_context *ctx);
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void utils_sha1_free(iot_sha1_context *ctx);
/**
* \brief Clone (the state of) a SHA-1 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void utils_sha1_clone(iot_sha1_context *dst,
const iot_sha1_context *src);
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void utils_sha1_starts(iot_sha1_context *ctx);
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen);
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]);
/* Internal use */
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]);
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]);
#endif

View File

@@ -1,106 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_STATIC__ void coap_auth_callback(void *message, void *context)
{
QCLOUD_FUNC_ENTRY
QCLOUD_POINTER_SANITY_CHECK_RTN(message);
QCLOUD_POINTER_SANITY_CHECK_RTN(context);
coap_message_t *msg = NULL;
qcloud_coap_client_t *client = NULL;
msg = (coap_message_t *)message;
client = (qcloud_coap_client_t *)context;
if (msg->code_class != COAP_CODE_CLASS_SUCCESS ||
msg->code_detail != COAP_CODE_DETAIL_205_CONTENT) {
client->auth_state = QCLOUD_COAP_AUTH_STATE_FAIL;
QCLOUD_LOG_E("auth token failed, code_class: %d code_detail: %d", msg->code_class, msg->code_detail);
return;
}
QCLOUD_LOG_I("auth token success, code_class: %d code_detail: %d", msg->code_class, msg->code_detail);
if (msg->payload_len == 0 ||
msg->payload == NULL ||
strlen(msg->payload) == 0) {
client->auth_state = QCLOUD_COAP_AUTH_STATE_FAIL;
QCLOUD_LOG_E("auth token response empty");
} else {
client->auth_token_len = msg->payload_len;
client->auth_token = osal_malloc(client->auth_token_len);
strncpy(client->auth_token, msg->payload,client->auth_token_len);
client->auth_state = QCLOUD_COAP_AUTH_STATE_SUCCESS;
QCLOUD_LOG_D("auth_token_len = %d, auth_token = %.*s", client->auth_token_len, client->auth_token_len, client->auth_token);
}
QCLOUD_FUNC_EXIT
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_auth(qcloud_coap_client_t *client, char *connection_id)
{
QCLOUD_FUNC_ENTRY
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_COAP_NULL);
int len;
qcloud_err_t rc;
char message_token[8] = {0};
coap_message_t connect_msg = COAP_MESSAGE_INITIALIZER;
coap_message_init(&connect_msg);
coap_message_type_set(&connect_msg, COAP_MSG_TYPE_CON);
coap_message_code_set(&connect_msg, COAP_CODE_CLASS_REQ, COAP_REQUEST_METHOD_POST);
coap_message_id_set(&connect_msg, coap_glue_packet_id_generate(client));
len = coap_message_token_get(client, message_token);
coap_message_token_set(&connect_msg, message_token, len);
coap_message_option_add(&connect_msg, COAP_MSG_OPTION_CODE_URI_PATH, strlen(client->auth_uri), client->auth_uri);
coap_message_option_add(&connect_msg, COAP_MSG_OPTION_CODE_NEED_RESP, 1, "0");
coap_message_callback_set(&connect_msg, coap_auth_callback);
coap_message_context_set(&connect_msg, client);
connect_msg.payload_len = sizeof(client->auth_id);
connect_msg.payload = (char *)osal_malloc(connect_msg.payload_len);
if (!connect_msg.payload) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
coap_message_payload_set(&connect_msg, client->auth_id, connect_msg.payload_len);
rc = coap_glue_msg_send(client, &connect_msg);
osal_free(connect_msg.payload);
QCLOUD_FUNC_EXIT_RC(rc)
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,306 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_STATIC__ qcloud_err_t coap_client_network_host_construct(qcloud_network_t *network, qcloud_device_t *device)
{
int server_len;
char coap_server[QCLOUD_SERVER_DOMAIN_MAX];
memset(network->host, 0, sizeof(network->host));
server_len = osal_snprintf(coap_server, sizeof(coap_server), "%s.%s", device->product_id, qcloud_coap_server);
if (server_len < 0 || server_len > QCLOUD_SERVER_DOMAIN_MAX - 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
memcpy(network->host, coap_server, sizeof(network->host));
network->port = qcloud_coap_port;
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_STATIC__ qcloud_err_t coap_client_network_init(qcloud_network_t *network, qcloud_device_t *device)
{
#if (QCLOUD_CFG_TLS_EN > 0u)
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_tls_init(&network->tls_opt, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_network_dtls_init(network), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#else
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_network_udp_init(network), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#endif
QCLOUD_FUNC_EXIT_RC_IF_NOT(coap_client_network_host_construct(network, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_STATIC__ uint16_t coap_client_random_packet_id_generate(void)
{
#define PACKET_ID_MAX (65535)
srand((unsigned)osal_timer_current_sec());
return rand() % (PACKET_ID_MAX + 1) + 1;
}
__QCLOUD_STATIC__ qcloud_err_t coap_client_construct(qcloud_coap_client_t *client,
qcloud_device_t *device,
coap_event_handler_fn_t handler)
{
int len = 0;
client->auth_state = QCLOUD_COAP_AUTH_STATE_NONE;
client->command_timeout = QCLOUD_COAP_COMMAND_TIMEOUT;
client->message_token = 0;
client->event_handler.handler = handler;
// packet id 取随机数 1- 65536
client->packet_id = coap_client_random_packet_id_generate();
client->auth_token = NULL;
client->auth_token_len = 0;
client->retransmit_max = 1;
len = osal_snprintf(client->auth_uri, sizeof(client->auth_uri), "%s/%s/%s", device->product_id, device->device_name, QCLOUD_COAP_AUTH_URI);
if (len < 0 || len >= QCLOUD_COAP_AUTH_URI_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
qcloud_list_init(&client->message_list);
if ((client->message_list_lock = osal_mutex_create()) == NULL) {
goto errout;
}
if ((client->tx_lock = osal_mutex_create()) == NULL) {
goto errout;
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
errout:
if (client->message_list_lock) {
osal_mutex_destroy(client->message_list_lock);
}
if (client->tx_lock) {
osal_mutex_destroy(client->tx_lock);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE)
}
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_create(qcloud_coap_client_t *client,
qcloud_device_t *device,
coap_event_handler_fn_t handler)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_INVAL);
memset(client, 0, sizeof(qcloud_coap_client_t));
QCLOUD_FUNC_EXIT_RC_IF_NOT(coap_client_network_init(&client->network, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC_IF_NOT(coap_client_construct(client, device, handler), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_connect(qcloud_coap_client_t *client)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
int len;
qcloud_err_t rc;
char connection_id[QCLOUD_COAP_CONNECT_ID_MAX + 1];
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc = client->network.connect(&client->network), QCLOUD_ERR_SUCCESS, rc);
coap_glue_connect_id_generate(connection_id);
len = osal_snprintf(client->auth_id, sizeof(client->auth_id), "%s;%s", QCLOUD_APPID, connection_id);
if (len < 0 || len >= QCLOUD_COAP_AUTH_ID_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
coap_auth(client, connection_id);
while (client->auth_state == QCLOUD_COAP_AUTH_STATE_NONE) {
qcloud_coap_client_yield(client, 200);
}
if (client->auth_state != QCLOUD_COAP_AUTH_STATE_SUCCESS) {
QCLOUD_LOG_I("auth failed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_yield(qcloud_coap_client_t *client, uint32_t timeout_ms)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
return coap_glue_spin(client, timeout_ms);
}
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_destroy(qcloud_coap_client_t *client)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
if (client->network.is_connected && client->network.is_connected(&client->network)) {
client->network.disconnect(&client->network);
}
coap_glue_message_list_destroy(client);
osal_mutex_destroy(client->tx_lock);
osal_mutex_destroy(client->message_list_lock);
if (client->auth_token) {
osal_free(client->auth_token);
client->auth_token = NULL;
}
client->auth_token_len = 0;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ qcloud_err_t qcloud_coap_client_msg_send(qcloud_coap_client_t *client,
char *topic,
coap_send_opt_t *send_opt)
{
QCLOUD_FUNC_ENTRY
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(topic, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(send_opt, QCLOUD_ERR_INVAL);
int len;
qcloud_err_t rc;
char message_token[8] = {0};
coap_message_t send_msg = COAP_MESSAGE_INITIALIZER;
if (strlen(topic) > QCLOUD_COAP_URI_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH);
}
coap_message_init(&send_msg);
coap_message_type_set(&send_msg, COAP_MSG_TYPE_CON);
coap_message_code_set(&send_msg, COAP_CODE_CLASS_REQ, COAP_REQUEST_METHOD_POST);
coap_message_id_set(&send_msg, coap_glue_packet_id_generate(client));
len = coap_message_token_get(client, message_token);
coap_message_token_set(&send_msg, message_token, len);
send_msg.payload = (char *)osal_malloc(send_opt->payload_len);
if (!send_msg.payload) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
coap_message_payload_set(&send_msg, send_opt->payload, send_opt->payload_len);
coap_message_option_add(&send_msg, COAP_MSG_OPTION_CODE_URI_PATH, strlen(topic), topic);
coap_message_option_add(&send_msg, COAP_MSG_OPTION_CODE_AUTH_TOKEN, client->auth_token_len, client->auth_token);
if (send_opt->resp_cb) {
coap_message_option_add(&send_msg, COAP_MSG_OPTION_CODE_NEED_RESP, 1, "1");
coap_message_callback_set(&send_msg, send_opt->resp_cb);
} else {
coap_message_option_add(&send_msg, COAP_MSG_OPTION_CODE_NEED_RESP, 1, "0");
}
coap_message_context_set(&send_msg, send_opt->context);
rc = coap_glue_msg_send(client, &send_msg);
osal_free(send_msg.payload);
QCLOUD_FUNC_EXIT_RC(rc)
}
__QCLOUD_API__ uint16_t qcloud_coap_msg_id_get(coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
if (!message) {
return COAP_MSG_ID_MAX;
}
return message->id;
}
__QCLOUD_API__ qcloud_err_t qcloud_coap_msg_payload_get(coap_message_t *message, char **payload, int *payload_len)
{
QCLOUD_FUNC_ENTRY
QCLOUD_POINTER_SANITY_CHECK(message, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(payload, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(payload_len, QCLOUD_ERR_INVAL);
if (message->code_class != COAP_CODE_CLASS_SUCCESS ||
message->code_detail != COAP_CODE_DETAIL_205_CONTENT) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE)
}
*payload = message->payload;
*payload_len = message->payload_len;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_API__ coap_event_type_t qcloud_coap_event_type_get(coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
QCLOUD_POINTER_SANITY_CHECK(message, COAP_EVENT_TYPE_UNAUTHORIZED);
switch (message->code_class) {
case COAP_CODE_CLASS_SUCCESS:
return COAP_EVENT_TYPE_RECEIVE_RESPCONTENT;
case COAP_CODE_CLASS_SERVER_ERR:
return COAP_EVENT_TYPE_INTERNAL_SERVER_ERROR;
case COAP_CODE_CLASS_INTERNAL_ERR:
return COAP_EVENT_TYPE_SEPRESP_TIMEOUT;
case COAP_CODE_CLASS_CLIENT_ERR:
if (message->code_detail == COAP_CODE_DETAIL_401_UNAUTHORIZED) {
return COAP_EVENT_TYPE_UNAUTHORIZED;
} else {
return COAP_EVENT_TYPE_FORBIDDEN;
}
default:
QCLOUD_LOG_E("not supported code class: %d", message->code_class);
return COAP_EVENT_TYPE_ACK_TIMEOUT;
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,276 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
/**
* @brief Free an option structure that was allocated by coap_msg_op_new
*
* @param[in,out] op Pointer to the option structure
*/
__QCLOUD_STATIC__ void coap_message_option_destroy(coap_msg_option_t *option)
{
QCLOUD_FUNC_ENTRY
if (option->val) {
osal_free(option->val);
}
osal_free(option);
QCLOUD_FUNC_EXIT
}
/**
* @brief Deinitialise an option linked-list structure
*
* @param[in,out] list Pointer to an option linked-list structure
*/
__QCLOUD_STATIC__ void coap_message_option_list_destroy(coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
QCLOUD_POINTER_SANITY_CHECK_RTN(message);
qcloud_list_t *curr, *next;
coap_msg_option_t *option;
if (qcloud_list_empty(&message->option_list)) {
QCLOUD_FUNC_EXIT;
}
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &message->option_list) {
option = QCLOUD_LIST_ENTRY(curr, coap_msg_option_t, list);
coap_message_option_destroy(option);
}
QCLOUD_FUNC_EXIT;
}
__QCLOUD_INTERNAL__ void coap_message_init(coap_message_t *message)
{
message->version = COAP_VERSION;
qcloud_list_init(&message->option_list);
}
__QCLOUD_INTERNAL__ int coap_message_token_get(qcloud_coap_client_t *client, char *buf)
{
uint32_t token;
token = client->message_token;
buf[0] = ((token & 0x00FF) >> 0);
buf[1] = ((token & 0xFF00) >> 8);
buf[2] = ((token & 0xFF0000) >> 16);
buf[3] = ((token & 0xFF000000) >> 24);
++client->message_token;
return sizeof(uint32_t);
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_type_set(coap_message_t *message, uint8_t type)
{
QCLOUD_FUNC_ENTRY
message->type = type;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_code_set(coap_message_t *message, uint32_t code_class, uint32_t code_detail)
{
QCLOUD_FUNC_ENTRY
if (code_class > COAP_MSG_CODE_CLASS_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL)
}
if (code_detail > COAP_MSG_CODE_DETAIL_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL)
}
message->code_class = code_class;
message->code_detail = code_detail;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_id_set(coap_message_t *message, uint16_t id)
{
QCLOUD_FUNC_ENTRY
if (id > COAP_MSG_ID_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL)
}
message->id = id;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_token_set(coap_message_t *message, char *buf, uint8_t len)
{
QCLOUD_FUNC_ENTRY
if (len > COAP_MSG_TOKEN_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL)
}
memcpy(message->token, buf, len);
message->token_len = len;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_payload_set(coap_message_t *message, char *buf, size_t len)
{
QCLOUD_FUNC_ENTRY
if (len > 0 && !message->payload) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE)
}
message->payload_len = 0;
if (len > 0) {
memcpy(message->payload, buf, len);
message->payload_len = len;
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ coap_msg_option_t *coap_message_option_construct(uint16_t option_code, uint32_t len, const char *val)
{
QCLOUD_FUNC_ENTRY
char *this_val = NULL;
coap_msg_option_t *option = NULL;
option = (coap_msg_option_t *)osal_malloc(sizeof(coap_msg_option_t));
if (!option) {
QCLOUD_LOG_E("memory alloc failed");
return NULL;
}
this_val = (char *)osal_malloc(len);
if (!this_val) {
osal_free(option);
QCLOUD_LOG_E("memory alloc failed");
return NULL;
}
option->option_code = option_code;
option->val_len = len;
option->val = this_val;
memcpy(option->val, val, len);
qcloud_list_init(&option->list);
return option;
}
__QCLOUD_STATIC__ void coap_message_option_do_add(coap_message_t *message, coap_msg_option_t *option)
{
coap_msg_option_t *iter;
qcloud_list_t *curr, *option_list;
option_list = &message->option_list;
/* keep option_code in ascending order */
QCLOUD_LIST_FOR_EACH(curr, option_list) {
iter = QCLOUD_LIST_ENTRY(curr, coap_msg_option_t, list);
if (option->option_code <= iter->option_code) {
break;
}
}
qcloud_list_add_tail(&option->list, curr);
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_option_add(coap_message_t *message, coap_msg_opt_code_t option_code, uint32_t len, const char *val)
{
QCLOUD_FUNC_ENTRY
QCLOUD_POINTER_SANITY_CHECK(message, QCLOUD_ERR_INVAL);
coap_msg_option_t *option = NULL;
option = coap_message_option_construct(option_code, len, val);
if (!option) {
QCLOUD_LOG_E("option alloc failed.");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE)
}
coap_message_option_do_add(message, option);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_callback_set(coap_message_t *message, coap_resp_callback_t callback)
{
QCLOUD_FUNC_ENTRY
message->resp_cb = callback;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_context_set(coap_message_t *message, void *context)
{
QCLOUD_FUNC_ENTRY
message->context = context;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_INTERNAL__ void coap_message_destroy(coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
coap_message_option_list_destroy(message);
if (message->payload) {
osal_free(message->payload);
}
memset(message, 0, sizeof(coap_message_t));
QCLOUD_FUNC_EXIT
}
__QCLOUD_INTERNAL__ void coap_message_dump(coap_message_t* message)
{
QCLOUD_LOG_I("version = %u", message->version);
QCLOUD_LOG_I("type = %d", message->type);
QCLOUD_LOG_I("code_class = %u", message->code_class);
QCLOUD_LOG_I("code_detail = %u", message->code_detail);
QCLOUD_LOG_I("id = %d", message->id);
QCLOUD_LOG_I("payload_len = %d", message->payload_len);
QCLOUD_LOG_I("payload: %s", message->payload);
QCLOUD_LOG_I("token_len = %u", message->token_len);
QCLOUD_LOG_I("token: %s", message->token);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,368 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
#define COAP_SWAP_UINT16(n) ((((uint16_t)(n) & 0xff00) >> 8) | (((uint16_t)(n) & 0x00ff) << 8))
/**
* @brief Check a message for correctness
*
* The following checks from RFC7252 are performed:
*
* An Empty message has the Code field set to 0.00. The Token Length
* field MUST be set to 0 and bytes of data MUST NOT be present after
* the Message ID field. If there are any bytes, they MUST be processed
* as a message format error.
*
* The Reset message MUST echo the Message ID of the Confirmable message
* and MUST be Empty.
*
* A Non-confirmable message always carries either a request or response
* and MUST NOT be Empty.
*
* @param[in] msg Pointer to a message structure
* @returns Operation status
* @retval 0 Success
* @retval <0 Error
*/
__QCLOUD_STATIC__ qcloud_err_t coap_message_verify(coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
if (COAP_MSG_IS_EMPTY(message)) {
/* empty message */
if (message->type == COAP_MSG_TYPE_NON ||
message->token_len != 0 ||
!qcloud_list_empty(&message->option_list) ||
message->payload_len != 0) {
QCLOUD_LOG_E("message option not empty");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
}
/* non-empty message */
if (message->type == COAP_MSG_TYPE_RST) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
/**
* @brief Allocate an option structure and add it to the end of an option linked-list structure
*
* @param[in,out] list Pointer to an option linked-list structure
* @param[in] num Option number
* @param[in] len Option length
* @param[in] val Pointer to a buffer containing the option value
*
* @returns Operation status
* @retval 0 Success
* @retval <0 Error
*/
__QCLOUD_STATIC__ qcloud_err_t coap_message_option_list_add(coap_message_t *message, uint16_t option_code, uint32_t len, const char *val)
{
QCLOUD_FUNC_ENTRY
coap_msg_option_t *option = NULL;
option = coap_message_option_construct(option_code, len, val);
if (!option) {
QCLOUD_LOG_E("allocate new option failed.");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE)
}
qcloud_list_add_tail(&option->list, &message->option_list);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
/**
* @brief Parse the header in a message
*
* @param[out] msg Pointer to a message structure
* @param[in] buf Pointer to a buffer containing the message
* @param[in] len Length of the buffer
*
* @returns Number of bytes parsed or error code
* @retval >0 Number of bytes parsed
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_deserialize_header(coap_message_t *message, char *buf, size_t len)
{
QCLOUD_FUNC_ENTRY
char *p = buf;
if (len < 4) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE);
}
message->version = (p[0] >> 6) & 0x03;
if (message->version != COAP_VERSION) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
message->type = (p[0] >> 4) & 0x03;
message->token_len = p[0] & 0x0f;
if (message->token_len > sizeof(message->token)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
message->code_detail = p[1] & 0x1f;
message->code_class = (p[1] >> 5) & 0x07;
if (message->code_class != COAP_CODE_CLASS_REQ &&
message->code_class != COAP_CODE_CLASS_SUCCESS &&
message->code_class != COAP_CODE_CLASS_CLIENT_ERR &&
message->code_class != COAP_CODE_CLASS_SERVER_ERR) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_BADMSG)
}
message->id = COAP_SWAP_UINT16(*((uint16_t *)(&p[2])));
p += 4;
len -= 4;
QCLOUD_FUNC_EXIT_RC(p - buf)
}
/**
* @brief Parse the token in a message
*
* @param[out] msg Pointer to a message structure
* @param[in] buf Pointer to a buffer containing the message
* @param[in] len Length of the buffer
*
* @returns Number of bytes parsed or error code
* @retval >0 Number of bytes parsed
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_deserialize_token(coap_message_t *message, char *buf, size_t len)
{
QCLOUD_FUNC_ENTRY
if (len < message->token_len) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
memcpy(message->token, buf, message->token_len);
QCLOUD_FUNC_EXIT_RC(message->token_len)
}
/**
* @brief Parse an option in a message
*
* @param[in,out] msg Pointer to a message structure
* @param[in] buf Pointer to a buffer containing the message
* @param[in] len Length of the buffer
*
* @returns Number of bytes parsed or error code
* @retval >0 Number of bytes parsed
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_deserialize_option(coap_message_t *message, char *buf, size_t len)
{
QCLOUD_FUNC_ENTRY
char *p = buf;
qcloud_err_t rc;
uint16_t option_code_delta = 0, option_len = 0, option_code = 0;
if (len < 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
option_code_delta = (p[0] >> 4) & 0x0f;
option_len = p[0] & 0x0f;
if ((option_code_delta == 15) || (option_len == 15)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
p++;
len--;
if (option_code_delta == 13) {
if (len < 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
option_code_delta += p[0];
p++;
len--;
} else if (option_code_delta == 14) {
if (len < 2) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
option_code_delta = 269 + COAP_SWAP_UINT16(*((uint16_t *)(&p[0])));
p += 2;
len -= 2;
}
if (option_len == 13) {
if (len < 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
option_len += p[0];
p++;
len--;
} else if (option_len == 14) {
if (len < 2) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
option_len = 269 + COAP_SWAP_UINT16(*((uint16_t *)(&p[0])));
p += 2;
len -= 2;
}
if (len < option_len) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
option_code += option_code_delta;
rc = coap_message_option_list_add(message, option_code, option_len, p);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, -1);
p += option_len;
QCLOUD_FUNC_EXIT_RC(p - buf)
}
/**
* @brief Parse the options in a message
*
* @param[in,out] msg Pointer to a message structure
* @param[in] buf Pointer to a buffer containing the message
* @param[in] len Length of the buffer
*
* @returns Number of bytes parsed or error code
* @retval >0 Number of bytes parsed
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_deserialize_options(coap_message_t *message, char *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY
int len = 0;
char *p = buf;
while ((p[0] & 0xff) != 0xff && buf_len != 0) {
len = coap_message_deserialize_option(message, p, buf_len);
if (len < 0) {
return len;
}
p += len;
buf_len -= len;
}
QCLOUD_FUNC_EXIT_RC(p - buf)
}
/**
* @brief Parse the payload in a message
*
* @param[out] msg Pointer to a message structure
* @param[in] buf Pointer to a buffer containing the message
* @param[in] len Length of the buffer
*
* @returns Number of bytes parsed or error code
* @retval >0 Number of bytes parsed
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_deserialize_payload(coap_message_t *message, char *buf, size_t len)
{
QCLOUD_FUNC_ENTRY
char *p = buf;
if (len == 0) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
if ((p[0] & 0xff) != 0xff) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
p++;
len--;
if (len == 0) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE)
}
message->payload = (char *)osal_malloc(len);
if (!message->payload){
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL)
}
memcpy(message->payload, p, len);
message->payload_len = len;
p += len;
QCLOUD_FUNC_EXIT_RC(p - buf)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_message_deserialize(coap_message_t *message, char *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY
int len = 0;
char *p = buf;
len = coap_message_deserialize_header(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("coap_message_deserialize_header failed, num:%lu", len);
goto errout;
}
p += len;
buf_len -= len;
len = coap_message_deserialize_token(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("coap_message_deserialize_token failed, num:%lu", len);
goto errout;
}
p += len;
buf_len -= len;
len = coap_message_deserialize_options(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("coap_message_deserialize_options failed, num:%lu", len);
goto errout;
}
p += len;
buf_len -= len;
len = coap_message_deserialize_payload(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("coap_message_deserialize_payload failed, num:%lu", len);
goto errout;
}
QCLOUD_FUNC_EXIT_RC(coap_message_verify(message))
errout:
coap_message_destroy(message);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_COAP_INTERNAL)
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,489 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_INTERNAL__ void coap_glue_connect_id_generate(char *conn_id)
{
int i = 0, flag;
srand((unsigned)osal_timer_current_sec());
for (i = 0; i < QCLOUD_COAP_CONNECT_ID_MAX - 1; ++i) {
flag = rand() % 3;
switch (flag) {
case 0:
conn_id[i] = (rand() % 26) + 'a';
break;
case 1:
conn_id[i] = (rand() % 26) + 'A';
break;
case 2:
conn_id[i] = (rand() % 10) + '0';
break;
}
}
conn_id[QCLOUD_COAP_CONNECT_ID_MAX - 1] = '\0';
}
__QCLOUD_INTERNAL__ uint16_t coap_glue_packet_id_generate(qcloud_coap_client_t *client)
{
#define PACKET_ID_MAX (65535)
uint16_t packet_id = client->packet_id;
client->packet_id = (packet_id == PACKET_ID_MAX ? 1 : (packet_id + 1));
return client->packet_id;
}
__QCLOUD_STATIC__ coap_event_type_t coap_glue_event_type_get(coap_message_t *message, coap_incoming_msg_type_t msg_type)
{
if (message->code_class == COAP_CODE_CLASS_SUCCESS &&
message->code_detail == COAP_CODE_DETAIL_205_CONTENT) {
if (msg_type == COAP_INCOMING_MSG_TYPE_RESP) {
return COAP_EVENT_TYPE_RECEIVE_RESPCONTENT;
} else {
return COAP_EVENT_TYPE_RECEIVE_ACK;
}
} else if (message->code_class == COAP_CODE_CLASS_CLIENT_ERR &&
message->code_detail == COAP_CODE_DETAIL_401_UNAUTHORIZED) {
return COAP_EVENT_TYPE_UNAUTHORIZED;
} else if (message->code_class == COAP_CODE_CLASS_CLIENT_ERR &&
message->code_detail == COAP_CODE_DETAIL_403_FORBIDDEN) {
return COAP_EVENT_TYPE_FORBIDDEN;
} else {
return COAP_EVENT_TYPE_INTERNAL_SERVER_ERROR;
}
}
__QCLOUD_STATIC__ void coap_glue_msg_sent_info_destroy(coap_msg_sent_info_t *msg_sent_info)
{
qcloud_list_del(&msg_sent_info->list);
osal_free(msg_sent_info->message);
osal_free(msg_sent_info);
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_glue_message_list_destroy(qcloud_coap_client_t *client)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
qcloud_list_t *curr, *next;
coap_msg_sent_info_t *msg_sent_info = NULL;
if (qcloud_list_empty(&client->message_list)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
osal_mutex_lock(client->message_list_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->message_list) {
msg_sent_info = QCLOUD_LIST_ENTRY(curr, coap_msg_sent_info_t, list);
coap_glue_msg_sent_info_destroy(msg_sent_info);
}
osal_mutex_unlock(client->message_list_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_message_list_scan(qcloud_coap_client_t *client)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
int ret;
size_t write_len;
qcloud_list_t *curr, *next;
coap_event_t event;
coap_message_t message = {0};
coap_msg_sent_info_t *msg_sent_info = NULL;
if (qcloud_list_empty(&client->message_list)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
osal_mutex_lock(client->message_list_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->message_list) {
msg_sent_info = QCLOUD_LIST_ENTRY(curr, coap_msg_sent_info_t, list);
if (!osal_timer_is_expired(&msg_sent_info->timer)) {
continue;
}
if (msg_sent_info->transmit_count < client->retransmit_max &&
!msg_sent_info->is_acked) {
osal_timer_init(&msg_sent_info->timer);
osal_timer_countdown_ms(&msg_sent_info->timer, client->command_timeout);
++msg_sent_info->transmit_count;
ret = client->network.write(&client->network, msg_sent_info->message, msg_sent_info->message_len,
osal_timer_remain(&msg_sent_info->timer), &write_len);
if (ret == QCLOUD_ERR_SUCCESS) {
continue;
}
QCLOUD_LOG_E("retansmit the message id %d failed.", msg_sent_info->message_id);
} else if (msg_sent_info->resp_cb) {
message.type = COAP_MSG_TYPE_ACK;
message.context = msg_sent_info->context;
message.code_class = COAP_CODE_CLASS_INTERNAL_ERR;
message.code_detail = COAP_CODE_DETAIL_600_TIMEOUT;
message.id = msg_sent_info->message_id;
msg_sent_info->resp_cb(&message, msg_sent_info->context);
} else if (client->event_handler.handler) {
if (msg_sent_info->is_acked) {
event.type = COAP_EVENT_TYPE_SEPRESP_TIMEOUT;
} else {
event.type = COAP_EVENT_TYPE_ACK_TIMEOUT;
}
event.message = (void *)(&msg_sent_info->message_id);
client->event_handler.handler(client->event_handler.context, &event);
} else {
QCLOUD_LOG_E("response and event callback both null");
}
coap_glue_msg_sent_info_destroy(msg_sent_info);
}
osal_mutex_unlock(client->message_list_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_message_list_unrecord(qcloud_coap_client_t *client, coap_message_t *message, coap_incoming_msg_type_t msg_type)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
coap_event_t event;
coap_event_type_t event_type;
qcloud_list_t *curr, *next;
coap_msg_sent_info_t *msg_sent_info = NULL;
if (qcloud_list_empty(&client->message_list)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
osal_mutex_lock(client->message_list_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->message_list) {
msg_sent_info = QCLOUD_LIST_ENTRY(curr, coap_msg_sent_info_t, list);
if (msg_type == COAP_INCOMING_MSG_TYPE_ACK &&
msg_sent_info->message_id == message->id) {
msg_sent_info->is_acked = QCLOUD_TRUE;
osal_timer_init(&msg_sent_info->timer);
osal_timer_countdown_ms(&msg_sent_info->timer, client->command_timeout);
}
if (msg_type == COAP_INCOMING_MSG_TYPE_RESP) {
if (msg_sent_info->token_len != 0 &&
msg_sent_info->token_len == message->token_len &&
memcmp(msg_sent_info->token, message->token, message->token_len) == 0) {
message->context = msg_sent_info->context;
if (msg_sent_info->resp_cb) {
msg_sent_info->resp_cb(message, msg_sent_info->context);
} else if (client->event_handler.handler) { // event handle process
event_type = coap_glue_event_type_get(message, COAP_INCOMING_MSG_TYPE_RESP);
event.type = event_type;
event.message = message;
message->id = msg_sent_info->message_id;
client->event_handler.handler(client->event_handler.context, &event);
} else {
QCLOUD_LOG_E("response and event callback both null");
}
coap_glue_msg_sent_info_destroy(msg_sent_info);
}
}
if (msg_type == COAP_INCOMING_MSG_TYPE_PIGGY) {
if (msg_sent_info->message_id == message->id) {
message->context = msg_sent_info->context;
if (msg_sent_info->resp_cb) {
msg_sent_info->resp_cb(message, msg_sent_info->context);
} else if (client->event_handler.handler) { // event handle process
event_type = coap_glue_event_type_get(message, COAP_INCOMING_MSG_TYPE_PIGGY);
event.type = event_type;
event.message = (void *)(&message->id);
client->event_handler.handler(client->event_handler.context, &event);
} else {
QCLOUD_LOG_E("response and event callback both null");
}
coap_glue_msg_sent_info_destroy(msg_sent_info);
}
}
}
osal_mutex_unlock(client->message_list_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* @brief 向服务器发送确认消息
*
* @param[in,out] client 指向客户端结构的指针
* @param[in] msg 指向消息结构的指针
*
* @returns Operation status
* @retval 0 Success
* @retval <0 Error
*/
__QCLOUD_STATIC__ qcloud_err_t coap_glue_resp_ack_send(qcloud_coap_client_t *client, uint16_t id)
{
QCLOUD_FUNC_ENTRY
qcloud_err_t rc;
coap_message_t ack_msg = COAP_MESSAGE_INITIALIZER;
coap_message_init(&ack_msg);
rc = coap_message_type_set(&ack_msg, COAP_MSG_TYPE_ACK);
if (rc != QCLOUD_ERR_SUCCESS) {
goto out;
}
rc = coap_message_id_set(&ack_msg, id);
if (rc != QCLOUD_ERR_SUCCESS) {
goto out;
}
rc = coap_glue_msg_send(client, &ack_msg);
out:
coap_message_destroy(&ack_msg);
QCLOUD_FUNC_EXIT_RC(rc)
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_piggy_message_handle(qcloud_coap_client_t *client, coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
QCLOUD_FUNC_EXIT_RC(coap_glue_message_list_unrecord(client, message, COAP_INCOMING_MSG_TYPE_PIGGY));
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_ack_message_handle(qcloud_coap_client_t *client, coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
QCLOUD_FUNC_EXIT_RC(coap_glue_message_list_unrecord(client, message, COAP_INCOMING_MSG_TYPE_ACK));
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_resp_message_handle(qcloud_coap_client_t *client, coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
qcloud_err_t rc;
if (message->type == COAP_MSG_TYPE_CON) {
rc = coap_glue_resp_ack_send(client, message->id);
QCLOUD_LOG_D("send ack message for id: %d, rc: %d", message->id, rc);
}
QCLOUD_FUNC_EXIT_RC(coap_glue_message_list_unrecord(client, message, COAP_INCOMING_MSG_TYPE_RESP));
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_incoming_message_handle(qcloud_coap_client_t *client, uint8_t *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY
qcloud_err_t rc = QCLOUD_ERR_SUCCESS;
coap_message_t incoming_msg;
memset(&incoming_msg, 0x00, sizeof(coap_message_t));
rc = coap_message_deserialize(&incoming_msg, (char *)buf, buf_len);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("deserialize msg failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if (incoming_msg.type == COAP_MSG_TYPE_ACK && COAP_MSG_IS_EMPTY_ACK(&incoming_msg)) { // empty ACK
QCLOUD_LOG_D("receive ACK msg, id %d", incoming_msg.id);
coap_glue_ack_message_handle(client, &incoming_msg);
} else if (incoming_msg.type == COAP_MSG_TYPE_ACK && !COAP_MSG_IS_EMPTY(&incoming_msg)) { // piggy Response
QCLOUD_LOG_D("receive piggy ACK msg, id %d", incoming_msg.id);
coap_glue_piggy_message_handle(client, &incoming_msg);
} else if (incoming_msg.type == COAP_MSG_TYPE_CON && COAP_MSG_IS_EMPTY_RSP(&incoming_msg)) { // payload Response
QCLOUD_LOG_D("receive response msg, id: %d", incoming_msg.id);
coap_glue_resp_message_handle(client, &incoming_msg);
} else if (incoming_msg.type == COAP_MSG_TYPE_NON && COAP_MSG_IS_EMPTY_RSP(&incoming_msg)) { // payload Response
QCLOUD_LOG_D("receive response msg, id: %d", incoming_msg.id);
coap_glue_resp_message_handle(client, &incoming_msg);
} else {
QCLOUD_LOG_E("msg type not recgonized");
}
if (incoming_msg.payload) {
osal_free(incoming_msg.payload);
incoming_msg.payload_len = 0;
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ coap_msg_sent_info_t *coap_glue_message_sent_info_construct(qcloud_coap_client_t *client, coap_message_t *message, int len)
{
coap_msg_sent_info_t *msg_sent_info = NULL;
msg_sent_info = (coap_msg_sent_info_t *)osal_malloc(sizeof(coap_msg_sent_info_t));
if (!msg_sent_info) {
QCLOUD_LOG_E("memory alloc failed");
return NULL;
}
msg_sent_info->message = osal_malloc(len);
if (!msg_sent_info->message) {
QCLOUD_LOG_E("memory alloc failed");
osal_free(msg_sent_info);
return NULL;
}
msg_sent_info->is_acked = QCLOUD_FALSE;
msg_sent_info->context = message->context;
msg_sent_info->message_id = message->id;
msg_sent_info->resp_cb = message->resp_cb;
msg_sent_info->message_len = len;
msg_sent_info->token_len = message->token_len;
memcpy(msg_sent_info->token, message->token, message->token_len);
memcpy(msg_sent_info->message, client->tx_buffer, len);
if (message->type == COAP_MSG_TYPE_CON) {
msg_sent_info->transmit_count = 0;
osal_timer_init(&msg_sent_info->timer);
osal_timer_countdown_ms(&msg_sent_info->timer, client->command_timeout);
}
return msg_sent_info;
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_message_list_record(qcloud_coap_client_t *client, coap_message_t *message, int len)
{
QCLOUD_FUNC_ENTRY
coap_msg_sent_info_t *msg_sent_info = NULL;
msg_sent_info = coap_glue_message_sent_info_construct(client, message, len);
if (!msg_sent_info) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
osal_mutex_lock(client->message_list_lock);
qcloud_list_add(&msg_sent_info->list, &client->message_list);
osal_mutex_unlock(client->message_list_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_STATIC__ qcloud_err_t coap_glue_recv(qcloud_coap_client_t *client, uint32_t timeout_ms)
{
QCLOUD_FUNC_ENTRY
size_t read_len = 0;
qcloud_err_t rc;
rc = client->network.read(&client->network, client->rx_buffer, sizeof(client->rx_buffer), timeout_ms, &read_len);
switch (rc) {
case QCLOUD_ERR_SUCCESS:
rc = coap_glue_incoming_message_handle(client, client->rx_buffer, read_len);
break;
case QCLOUD_ERR_SSL_READ_TIMEOUT:
break;
default:
break;
}
QCLOUD_FUNC_EXIT_RC(rc)
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_glue_spin(qcloud_coap_client_t *client, uint32_t timeout_ms)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
rc = coap_glue_recv(client, timeout_ms);
if (rc != QCLOUD_ERR_SUCCESS && rc != QCLOUD_ERR_SSL_READ_TIMEOUT) {
QCLOUD_FUNC_EXIT_RC(rc)
}
QCLOUD_FUNC_EXIT_RC(coap_glue_message_list_scan(client));
}
__QCLOUD_INTERNAL__ qcloud_err_t coap_glue_msg_send(qcloud_coap_client_t *client, coap_message_t *message)
{
QCLOUD_FUNC_ENTRY
int len = 0;
qcloud_err_t rc;
size_t write_len = 0;
osal_mutex_lock(client->tx_lock);
len = coap_message_serialize(message, (char*)client->tx_buffer, sizeof(client->tx_buffer));
if (len < 0) {
QCLOUD_LOG_E("failed to serialize coap message");
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE)
}
rc = client->network.write(&client->network, client->tx_buffer, len, 0, &write_len);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("coap net fail to write rc: %d", rc);
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc)
}
if (message->type == COAP_MSG_TYPE_CON &&
message->code_class == COAP_CODE_CLASS_REQ) {
rc = coap_glue_message_list_record(client, message, write_len);
QCLOUD_LOG_I("add message id: %d, rc: %d", message->id, rc);
} else {
QCLOUD_LOG_I("message donot need retransmit");
}
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc)
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,292 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
/**
* @brief Format the header in a message
*
* @param[in] message Pointer to a message structure
* @param[out] buf Pointer to a buffer to contain the formatted message
* @param[in] len Length of the buffer
*
* @returns Length of the formatted message or error code
* @retval >0 Length of the formatted message
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_serialize_header(coap_message_t *message, char *buf, size_t len)
{
QCLOUD_FUNC_ENTRY
if (len < 4) {
return -1;
}
buf[0] = (char)((COAP_VERSION << 6)
| ((message->type & 0x03) << 4)
| (message->token_len & 0x0f));
buf[1] = (char)(((message->code_class & 0x07) << 5)
| (message->code_detail & 0x1f));
buf[2] = (message->id & 0xFF00) >> 8;
buf[3] = (message->id & 0x00FF);
QCLOUD_FUNC_EXIT_RC(4)
}
/**
* @brief Format the token in a message
*
* @param[in] message Pointer to a message structure
* @param[out] buf Pointer to a buffer to contain the formatted message
* @param[in] len Length of the buffer
*
* @returns Length of the formatted message or error code
* @retval >0 Length of the formatted message
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_serialize_token(coap_message_t *message, char *buf, size_t len)
{
QCLOUD_FUNC_ENTRY
if (len < message->token_len) {
return -1;
}
memcpy(buf, message->token, message->token_len);
return message->token_len;
}
/**
* @brief Format an option in a message
*
* @param[in] op Pointer to an option structure
* @param[in] prev_num option number of the previous option
* @param[out] buf Pointer to a buffer to contain the formatted message
* @param[in] len Length of the buffer
*
* @returns Length of the formatted message or error code
* @retval >0 Length of the formatted message
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_option_format(coap_msg_option_t *option, uint16_t prev_option_code, char *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY
char *p = NULL;
uint32_t len = 0;
uint16_t option_code_delta = 0;
p = buf;
option_code_delta = option->option_code - prev_option_code;
len++;
/* option delta */
if (option_code_delta >= 269) {
len += 2;
} else if (option_code_delta >= 13) {
len += 1;
}
/* option length */
if (option->val_len >= 269) {
len += 2;
} else if (option->option_code >= 13) {
len += 1;
}
/* option value */
len += option->val_len;
if (len > buf_len) {
return QCLOUD_ERR_COAP_DATA_SIZE;
}
/* option delta */
if (option_code_delta >= 269) {
p[0] = 14 << 4;
} else if (option_code_delta >= 13) {
p[0] = 13 << 4;
} else {
p[0] = option_code_delta << 4;
}
/* option length */
if (option->val_len >= 269) {
p[0] |= 14;
} else if (option->val_len >= 13) {
p[0] |= 13;
} else {
p[0] |= option->val_len;
}
p++;
buf_len--;
/* option delta extended */
if (option_code_delta >= 269) {
*p = (uint8_t)(((option_code_delta - 269) & 0xFF00) >> 8);
*(p + 1) = (uint8_t)(((option_code_delta - 269) & 0x00FF));
p += 2;
buf_len -= 2;
} else if (option_code_delta >= 13) {
p[0] = option_code_delta - 13;
p++;
buf_len--;
}
/* option length extended */
if (option->val_len >= 269) {
*p = (unsigned char)(((option->val_len - 269) & 0xFF00) >> 8);
*(p + 1) = (unsigned char)(((option->val_len - 269) & 0x00FF));
p += 2;
buf_len -= 2;
} else if (option->val_len >= 13) {
p[0] = option->val_len - 13;
p++;
buf_len--;
}
/* option value */
memcpy(p, option->val, option->val_len);
p += option->val_len;
return p - buf;
}
/**
* @brief Format the options in a message
*
* @param[in] message Pointer to a message structure
* @param[out] buf Pointer to a buffer to contain the formatted message
* @param[in] len Length of the buffer
*
* @returns Length of the formatted message or error code
* @retval >0 Length of the formatted message
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_serialize_options(coap_message_t *message, char *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
int len;
char *p = NULL;
uint16_t prev_option_code = 0;
qcloud_list_t *curr;
coap_msg_option_t *option;
p = buf;
QCLOUD_LIST_FOR_EACH(curr, &message->option_list) {
option = QCLOUD_LIST_ENTRY(curr, coap_msg_option_t, list);
// coap_message_option_destroy(option);
len = coap_message_option_format(option, prev_option_code, p, buf_len);
if (len < 0) {
return len;
}
p += len;
buf_len -= len;
prev_option_code = option->option_code;
}
return p - buf;
}
/**
* @brief Format the payload in a message
*
* @param[in] message Pointer to a message structure
* @param[out] buf Pointer to a buffer to contain the formatted message
* @param[in] len Length of the buffer
*
* @returns Length of the formatted message or error code
* @retval >0 Length of the formatted message
* @retval <0 Error
*/
__QCLOUD_STATIC__ int coap_message_serialize_payload(coap_message_t *message, char *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
if (message->payload_len == 0) {
return 0;
}
if (message->payload_len + 1 > buf_len) {
return -1;
}
buf[0] = 0xff;
memcpy(&buf[1], message->payload, message->payload_len);
return message->payload_len + 1;
}
__QCLOUD_INTERNAL__ int coap_message_serialize(coap_message_t *message, char *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
int len = 0;
char *p = buf;
if (!message || !buf) {
return -1;
}
len = coap_message_serialize_header(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("serialize header fail len: %lu", len);
return -1;
}
p += len;
buf_len -= len;
len = coap_message_serialize_token(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("erialize token fail len: %lu", len);
return -1;
}
p += len;
buf_len -= len;
len = coap_message_serialize_options(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("serialize options fail len: %lu", len);
return -1;
}
p += len;
buf_len -= len;
len = coap_message_serialize_payload(message, p, buf_len);
if (len < 0) {
QCLOUD_LOG_E("coap_message_serialize_payload fail num=%lu", len);
return -1;
}
p += len;
return p - buf;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,553 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_STATIC__ void event_reply_destroy(qcloud_event_reply_t *reply)
{
qcloud_list_del(&reply->list);
osal_free(reply);
}
__QCLOUD_STATIC__ void event_reply_list_destroy(qcloud_event_client_t *client)
{
qcloud_list_t *curr, *next;
qcloud_event_reply_t *reply;
if (qcloud_list_empty(&client->reply_list)) {
return;
}
osal_mutex_lock(client->reply_list_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->reply_list) {
reply = QCLOUD_LIST_ENTRY(curr, qcloud_event_reply_t, list);
event_reply_destroy(reply);
}
osal_mutex_unlock(client->reply_list_lock);
}
__QCLOUD_STATIC__ void event_reply_handler(void *client, mqtt_incoming_msg_t *message, void *private_data)
{
QCLOUD_POINTER_SANITY_CHECK_RTN(message);
QCLOUD_POINTER_SANITY_CHECK_RTN(private_data);
int32_t return_code;
char *client_token = NULL, *status = NULL;
qcloud_list_t *curr, *next;
qcloud_event_client_t *event_client;
qcloud_event_reply_t *reply;
event_client = (qcloud_event_client_t *)private_data;
QCLOUD_LOG_I("msg recved, topic: %.*s, payload: %.*s", message->topic_len, message->topic, message->payload_len, (char *) message->payload);
// 解析事件回复中的clientToken
if (!shadow_json_client_token_parse((char *)message->payload, &client_token)) {
QCLOUD_LOG_E("client token parse fail!");
return;
}
// 解析事件回复中的处理结果
if (!event_json_return_code_parse((char *)message->payload, &return_code)) {
return;
}
if (!event_json_status_parse((char *)message->payload, &status)) {
QCLOUD_LOG_D("no status return");
}
QCLOUD_LOG_D("event token:%s code:%d status:%s", client_token, return_code, status);
if (qcloud_list_empty(&event_client->reply_list)) {
return;
}
osal_mutex_lock(event_client->reply_list_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &event_client->reply_list) {
reply = QCLOUD_LIST_ENTRY(curr, qcloud_event_reply_t, list);
if (osal_timer_is_expired(&reply->timer)) {
QCLOUD_LOG_E("event[%s] timeout", reply->client_token);
event_reply_destroy(reply);
continue;
}
if (strcmp(client_token, reply->client_token) == 0) { // client_token matches
if (reply->handler) {
reply->handler(client, message);
}
event_reply_destroy(reply);
}
}
osal_mutex_unlock(event_client->reply_list_lock);
}
__QCLOUD_STATIC__ qcloud_event_reply_t *event_reply_construct(qcloud_event_client_t *client,
uint32_t timeout_ms,
event_reply_handler_fn_t handler)
{
qcloud_err_t rc;
int rc_snprintf;
qcloud_event_reply_t *event_reply;
qcloud_shadow_client_t *shadow_client;
shadow_client = client->shadow_client;
event_reply = (qcloud_event_reply_t *)osal_malloc(sizeof(qcloud_event_reply_t));
if (!event_reply) {
return NULL;
}
event_reply->handler = handler;
osal_timer_init(&event_reply->timer);
osal_timer_countdown_ms(&event_reply->timer, timeout_ms);
memset(event_reply->client_token, 0, sizeof(event_reply->client_token));
++shadow_client->token_num;
rc_snprintf = osal_snprintf(event_reply->client_token, QCLOUD_EVENT_TOKEN_MAX, "%s-%u",
shadow_client->device_product_id, shadow_client->token_num);
rc = shadow_json_snprintf_rc2errno(rc_snprintf, QCLOUD_EVENT_TOKEN_MAX);
if (rc != QCLOUD_ERR_SUCCESS) {
return NULL;
}
qcloud_list_init(&event_reply->list);
qcloud_list_add(&event_reply->list, &client->reply_list);
return event_reply;
}
__QCLOUD_STATIC__ qcloud_err_t event_json_init(qcloud_event_client_t *client,
char *json_doc,
size_t json_doc_size,
int event_count,
event_reply_handler_fn_t handler,
uint32_t reply_timeout_ms)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
int rc_snprintf = 0;
qcloud_event_reply_t *event_reply = NULL;
event_reply = event_reply_construct(client, reply_timeout_ms, handler);
QCLOUD_FUNC_EXIT_RC_IF(event_reply, NULL, QCLOUD_ERR_INVAL);
memset(json_doc, 0, json_doc_size);
if (event_count > 1) {
rc_snprintf = osal_snprintf(json_doc, json_doc_size, "{\"method\":\"%s\", \"clientToken\":\"%s\", ", \
EVENT_FIELD_POSTS, event_reply->client_token);
} else {
rc_snprintf = osal_snprintf(json_doc, json_doc_size, "{\"method\":\"%s\", \"clientToken\":\"%s\", ", \
EVENT_FIELD_POST, event_reply->client_token);
}
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, json_doc_size));
}
__QCLOUD_STATIC__ qcloud_err_t event_multi_json_construct(char *json_doc,
size_t json_doc_size,
size_t remain_size,
int event_count,
qcloud_event_t *events[])
{
int i = 0, j = 0;
qcloud_err_t rc;
int rc_snprintf;
qcloud_event_t *event;
shadow_dev_property_t *dev_property;
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"events\":[");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
for (i = 0; i < event_count; ++i) {
event = events[i];
if (!event) {
QCLOUD_LOG_E("%dth/%d null event", i, event_count);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size,
"{\"eventId\":\"%s\", \"type\":\"%s\", \"timestamp\":%u000, \"params\":{",\
event->event_name, event->type, event->timestamp);
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
for (j = 0; j < event->event_payload_count; ++j) {
dev_property = &event->event_payload[i];
if (!dev_property || !dev_property->key) {
QCLOUD_LOG_E("%dth/%d null event property data", i, event->event_payload_count);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = event_json_node_add(json_doc, remain_size, dev_property->key, dev_property->data, dev_property->type);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc)-1, remain_size, "}}," );
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "]");
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, remain_size));
}
__QCLOUD_STATIC__ qcloud_err_t event_single_json_construct(char *json_doc,
size_t json_doc_size,
size_t remain_size,
int event_count,
qcloud_event_t *events[])
{
int i = 0;
qcloud_err_t rc;
int rc_snprintf;
qcloud_event_t *event;
shadow_dev_property_t *dev_property;
event = events[0];
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size,
"\"eventId\":\"%s\", \"type\":\"%s\", \"timestamp\":%u000, \"params\":{",\
event->event_name, event->type, event->timestamp);
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
for (i = 0; i < event->event_payload_count; ++i) {
dev_property = &event->event_payload[i];
if (!dev_property || !dev_property->key) {
QCLOUD_LOG_E("%dth/%d null event property data", i, event->event_payload_count);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = event_json_node_add(json_doc, remain_size, dev_property->key, dev_property->data, dev_property->type);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "}" );
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, remain_size));
}
__QCLOUD_STATIC__ qcloud_err_t event_json_construct(qcloud_event_client_t *client,
char *json_doc,
size_t json_doc_size,
int event_count,
qcloud_event_t *events[],
event_reply_handler_fn_t handler,
uint32_t reply_timeout_ms)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(events, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
int rc_snprintf = 0;
size_t remain_size = 0;
rc = event_json_init(client, json_doc, json_doc_size, event_count, handler, reply_timeout_ms);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("event json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
if (event_count > 1) { //多个事件
event_multi_json_construct(json_doc, json_doc_size, remain_size, event_count, events);
} else { //单个事件
event_single_json_construct(json_doc, json_doc_size, remain_size, event_count, events);
}
// finish json
if ((remain_size = json_doc_size - strlen(json_doc)) < 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "}");
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, remain_size));
}
__QCLOUD_STATIC__ qcloud_err_t event_publish(qcloud_event_client_t *client, char *json_doc)
{
QCLOUD_FUNC_ENTRY;
mqtt_publish_opt_t publish_opt;
qcloud_shadow_client_t *shadow_client = NULL;
shadow_client = client->shadow_client;
memset(&publish_opt, 0, sizeof(mqtt_publish_opt_t));
publish_opt.qos = MQTT_QOS0;
publish_opt.payload = json_doc;
publish_opt.payload_len = strlen(json_doc);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_client_publish(&shadow_client->mqtt_client, client->up_topic, &publish_opt));
}
__QCLOUD_STATIC__ qcloud_err_t event_subscribe(qcloud_event_client_t *client)
{
mqtt_subscribe_opt_t subscribe_opt;
qcloud_shadow_client_t *shadow_client = NULL;
shadow_client = client->shadow_client;
subscribe_opt.qos = MQTT_QOS0;
subscribe_opt.private_data = (void *)client;
subscribe_opt.message_handler = event_reply_handler;
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_client_subscribe(&shadow_client->mqtt_client, client->down_topic, &subscribe_opt));
}
__QCLOUD_STATIC__ qcloud_err_t event_unsubscribe(qcloud_event_client_t *client)
{
qcloud_shadow_client_t *shadow_client = NULL;
shadow_client = client->shadow_client;
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_client_unsubscribe(&shadow_client->mqtt_client, client->down_topic));
}
__QCLOUD_STATIC__ qcloud_err_t event_client_construct(qcloud_event_client_t *client,
qcloud_shadow_client_t *shadow_client,
qcloud_device_t *device)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(shadow_client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_INVAL);
int size;
size = osal_snprintf(client->down_topic, QCLOUD_MQTT_TOPIC_SIZE_MAX, "$thing/down/event/%s/%s", device->product_id, device->device_name);
if (size < 0 || size > QCLOUD_MQTT_TOPIC_SIZE_MAX - 1) {
QCLOUD_LOG_E("topic size overflow, %d", size);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
size = osal_snprintf(client->up_topic, QCLOUD_MQTT_TOPIC_SIZE_MAX, "$thing/up/event/%s/%s", device->product_id, device->device_name);
if (size < 0 || size > QCLOUD_MQTT_TOPIC_SIZE_MAX - 1) {
QCLOUD_LOG_E("topic size overflow, %d", size);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
if ((client->reply_list_lock = osal_mutex_create()) == NULL) {
QCLOUD_LOG_E("write buf lock failed.");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
qcloud_list_init(&client->reply_list);
client->shadow_client = shadow_client;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ void event_incoming_msg_handler(void *client, void *context, mqtt_event_t *event)
{
uint16_t packet_id;
qcloud_event_client_t *event_client = NULL;
event_client = (qcloud_event_client_t *)context;
switch (event->type) {
case MQTT_EVENT_SUBCRIBE_SUCCESS:
packet_id = *(uint16_t *)event->message;
QCLOUD_LOG_D("subscribe success, packet id=%u", (uint32_t)packet_id);
event_client->sync_state = QCLOUD_EVENT_SYNC_STATE_SUCCESS;
break;
case MQTT_EVENT_SUBCRIBE_TIMEOUT:
packet_id = *(uint16_t *)event->message;
QCLOUD_LOG_D("subscribe wait ack timeout, packet id=%u", (uint32_t)packet_id);
event_client->sync_state = QCLOUD_EVENT_SYNC_STATE_TIMEOUT;
break;
case MQTT_EVENT_SUBCRIBE_NACK:
packet_id = *(uint16_t *)event->message;
QCLOUD_LOG_D("subscribe nack, packet id=%u", (uint32_t)packet_id);
event_client->sync_state = QCLOUD_EVENT_SYNC_STATE_NACK;
break;
default:
break;
}
}
__QCLOUD_API__ qcloud_err_t qcloud_event_client_create(qcloud_event_client_t *client,
qcloud_shadow_client_t *shadow_client,
qcloud_device_t *device)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(shadow_client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
void *shadow_context = NULL;
mqtt_event_handler_fn_t shadow_handler = NULL;
if (!qcloud_shadow_client_is_connected(shadow_client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
rc = event_client_construct(client, shadow_client, device);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
rc = event_subscribe(client);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
shadow_context = shadow_client->event_handler.context;
shadow_handler = shadow_client->event_handler.handler;
shadow_client->event_handler.context = (void *)client;;
shadow_client->event_handler.handler = event_incoming_msg_handler;
client->sync_state = QCLOUD_EVENT_SYNC_STATE_PENDACK;
while (client->sync_state == QCLOUD_EVENT_SYNC_STATE_PENDACK) {
qcloud_shadow_client_yield(client->shadow_client, 100);
}
shadow_client->event_handler.context = shadow_context;
shadow_client->event_handler.handler = shadow_handler;
if (client->sync_state != QCLOUD_SHADOW_SYNC_STATE_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ qcloud_err_t qcloud_event_client_destroy(qcloud_event_client_t *client)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
event_unsubscribe(client);
event_reply_list_destroy(client);
if (client->reply_list_lock) {
osal_mutex_destroy(client->reply_list_lock);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_API__ qcloud_err_t qcloud_event_client_post(qcloud_event_client_t *client,
char *json_doc,
size_t json_doc_size,
int event_count,
qcloud_event_t *events[],
event_reply_handler_fn_t handler)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(events, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
rc = event_json_construct(client, json_doc, json_doc_size, event_count, events, handler, 5000);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("construct event json fail, %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
rc = event_publish(client, json_doc);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("publish event to cloud fail, %d",rc);
}
QCLOUD_FUNC_EXIT_RC(rc);
}
__QCLOUD_API__ qcloud_err_t qcloud_event_client_post_raw(qcloud_event_client_t *client,
char *json_doc,
size_t json_doc_size,
char *event_msg,
event_reply_handler_fn_t handler)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(event_msg, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
int rc_snprintf;
size_t remain_size = 0;
rc = event_json_init(client, json_doc, json_doc_size, 2, handler, 5000);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("event json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"events\":[%s]}", event_msg);
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
QCLOUD_LOG_D("json doc: %s", json_doc);
rc = event_publish(client, json_doc);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("publish event raw fail, %d",rc);
}
QCLOUD_FUNC_EXIT_RC(rc);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,150 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
#define PRIi32 "i"
#define PRIi16 "i"
#define PRIi8 "i"
#define PRIu32 "u"
#define PRIu16 "u"
#define PRIu8 "u"
#define SCNi8 "hhi"
#define SCNu8 "hhu"
#define SCNi16 "hi"
#define SCNu16 "hu"
#define SCNi32 "i"
#define SCNu32 "u"
__QCLOUD_INTERNAL__ qcloud_err_t event_json_node_add(char *json_doc, size_t json_doc_size, const char *key, void *data, json_data_type_t type)
{
qcloud_err_t rc;
int32_t rc_snprintf = 0;
size_t remain_size = 0;
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"%s\":", key);
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
if (!data) {
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "null,");
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, remain_size));
}
switch (type) {
case JSON_DATA_TYPE_INT32:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIi32
",", *(int32_t *)(data));
break;
case JSON_DATA_TYPE_INT16:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIi16
",", *(int16_t *)(data));
break;
case JSON_DATA_TYPE_INT8:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIi8
",", *(int8_t *)(data));
break;
case JSON_DATA_TYPE_UINT32:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIu32
",", *(uint32_t *)(data));
break;
case JSON_DATA_TYPE_UINT16:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIu16
",", *(uint16_t *)(data));
break;
case JSON_DATA_TYPE_UINT8:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIu8
",", *(uint8_t *)(data));
break;
case JSON_DATA_TYPE_DOUBLE:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%f,", *(double *)(data));
break;
case JSON_DATA_TYPE_FLOAT:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%f,", *(float *)(data));
break;
case JSON_DATA_TYPE_BOOL:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%u,",
*(bool *) (data) ? 1 : 0);
break;
case JSON_DATA_TYPE_STRING:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"%s\",", (char *)(data));
break;
case JSON_DATA_TYPE_OBJECT:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%s,", (char *)(data));
break;
}
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, remain_size));
}
__QCLOUD_INTERNAL__ int event_json_return_code_parse(char *json_doc, int32_t *return_code)
{
int rc = QCLOUD_TRUE;
char *return_code_str;
return_code_str = LITE_json_value_of(EVENT_REPLY_FIELD_CODE, json_doc);
if (!return_code_str) {
return QCLOUD_FALSE;
}
if (sscanf(return_code_str, "%" SCNi32, return_code) != 1) {
QCLOUD_LOG_E("parse code failed, rc: %d", QCLOUD_ERR_JSON_PARSE);
rc = QCLOUD_FALSE;
}
osal_free(return_code_str);
return rc;
}
__QCLOUD_INTERNAL__ int event_json_status_parse(char *json_doc, char **status)
{
*status = LITE_json_value_of(EVENT_REPLY_FIELD_STATUS, json_doc);
return *status != NULL;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,352 +0,0 @@
#include "qcloud.h"
__QCLOUD_STATIC__ qcloud_err_t mqtt_client_network_host_construct(qcloud_network_t *network, qcloud_device_t *device)
{
int server_len;
char mqtt_server[QCLOUD_SERVER_DOMAIN_MAX];
memset(network->host, 0, sizeof(network->host));
server_len = osal_snprintf(mqtt_server, sizeof(mqtt_server), "%s.%s", device->product_id, qcloud_mqtt_server);
if (server_len < 0 || server_len > QCLOUD_SERVER_DOMAIN_MAX - 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
memcpy(network->host, mqtt_server, sizeof(network->host));
network->port = qcloud_mqtt_port;
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_STATIC__ qcloud_err_t mqtt_client_network_init(qcloud_network_t *network, qcloud_device_t *device)
{
#if (QCLOUD_CFG_TLS_EN > 0u)
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_tls_init(&network->tls_opt, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_network_tls_init(network), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#else
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_network_tcp_init(network), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#endif
QCLOUD_FUNC_EXIT_RC_IF_NOT(mqtt_client_network_host_construct(network, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_STATIC__ uint16_t mqtt_client_random_packet_id_generate(void)
{
#define PACKET_ID_MAX (65535)
srand((unsigned)osal_timer_current_sec());
return rand() % (PACKET_ID_MAX + 1) + 1;
}
__QCLOUD_STATIC__ qcloud_err_t mqtt_client_construct(qcloud_mqtt_client_t *client,
mqtt_event_handler_fn_t handler,
void *handler_context,
qcloud_auto_connect_state_t auto_connect_state)
{
client->event_handler.handler = handler;
client->event_handler.context = handler_context;
client->auto_connect_state = auto_connect_state;
client->command_timeout = QCLOUD_MQTT_COMMAND_TIMEOUT;
client->connection_state = QCLOUD_MQTT_CONNECTION_STATE_DISCONNECTED;
// packet id 取随机数 1- 65536
client->packet_id = mqtt_client_random_packet_id_generate();
client->ping_outstanding = 0;
client->is_manually_disconnected = QCLOUD_FALSE;
client->network_disconnect_counter = 0;
if ((client->global_lock = osal_mutex_create()) == NULL) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
if ((client->tx_lock = osal_mutex_create()) == NULL) {
QCLOUD_LOG_E("write buf lock failed.");
goto errout;
}
if ((client->ack_pend_list_lock = osal_mutex_create()) == NULL) {
QCLOUD_LOG_E("ack list lock failed.");
goto errout;
}
if ((client->msg_handler_list_lock = osal_mutex_create()) == NULL) {
QCLOUD_LOG_E("handler list lock failed.");
goto errout;
}
qcloud_list_init(&client->ack_pend_list);
qcloud_list_init(&client->msg_handler_list);
// ping定时器以及重连延迟定时器相关初始化
osal_timer_init(&client->ping_timer);
osal_timer_init(&client->reconnect_timer);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
errout:
if (client->global_lock) {
osal_mutex_destroy(client->global_lock);
client->global_lock = NULL;
}
if (client->tx_lock) {
osal_mutex_destroy(client->tx_lock);
client->tx_lock = NULL;
}
if (client->ack_pend_list_lock) {
osal_mutex_destroy(client->ack_pend_list_lock);
client->ack_pend_list_lock = NULL;
}
if (client->msg_handler_list_lock) {
osal_mutex_destroy(client->msg_handler_list_lock);
client->msg_handler_list_lock = NULL;
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE)
}
#if (QCLOUD_CFG_TLS_EN == 0u) && (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_KEY)
__QCLOUD_STATIC__ qcloud_err_t mqtt_client_key_decode(uint8_t *decoded_buf, size_t decoded_buf_size, const char *key, size_t *decoded_key_len)
{
QCLOUD_POINTER_SANITY_CHECK(decoded_buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(key, QCLOUD_ERR_INVAL);
int key_len = 0;
memset(decoded_buf, 0, decoded_buf_size);
key_len = strlen(key);
if (qcloud_utils_base64_decode(decoded_buf, decoded_buf_size, decoded_key_len,
(unsigned char *)key, key_len) != 0) {
QCLOUD_LOG_E("psk decode failed!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ qcloud_err_t mqtt_client_password_encode(mqtt_connect_opt_t *connect_opt, uint8_t *key, size_t key_len)
{
char digest[41];
int password_len = 0;
memset(digest, 0, sizeof(digest));
utils_hmac_sha1(connect_opt->username, strlen(connect_opt->username), digest, (const char *)key, key_len);
password_len = osal_snprintf(connect_opt->password, sizeof(connect_opt->password), "%s;hmacsha1", digest);
if (password_len < 0 || password_len >= QCLOUD_DEVICE_PASSWORD_MAX) {
QCLOUD_LOG_E("password encode failed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_DEV_INFO);
}
connect_opt->password_len = password_len;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
#endif
__QCLOUD_STATIC__ qcloud_err_t mqtt_client_id_generate(mqtt_connect_opt_t *connect_opt, qcloud_device_t *device)
{
int client_id_len = 0;
memset(connect_opt->client_id, 0, sizeof(connect_opt->client_id));
client_id_len = osal_snprintf(connect_opt->client_id, sizeof(connect_opt->client_id), "%s%s", device->product_id, device->device_name);
if (client_id_len < 0 || client_id_len >= QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX) {
QCLOUD_LOG_E("client id generate failed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_DEV_INFO);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ qcloud_err_t mqtt_client_username_generate(mqtt_connect_opt_t *connect_opt)
{
uint32_t now;
int username_len = 0;
char connection_id[QCLOUD_MQTT_CONNECT_ID_MAX + 1];
now = osal_timer_current_sec() + QCLOUD_MQTT_ACCESS_EXPIRE_TIMEOUT_MAX / 1000;
mqtt_glue_connect_id_generate(connection_id);
memset(connect_opt->username, 0, sizeof(connect_opt->username));
username_len = osal_snprintf(connect_opt->username, sizeof(connect_opt->username), "%s;%s;%s;%ld",
connect_opt->client_id, QCLOUD_APPID, connection_id, now);
if (username_len < 0 || username_len >= QCLOUD_DEVICE_USERNAME_MAX) {
QCLOUD_LOG_E("username generate failed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_DEV_INFO);
}
connect_opt->username_len = username_len;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_INTERNAL__ void mqtt_client_connection_state_set(qcloud_mqtt_client_t *client, qcloud_mqtt_con_status_t state)
{
osal_mutex_lock(client->global_lock);
client->connection_state = state;
osal_mutex_unlock(client->global_lock);
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_connect_opt_create(mqtt_connect_opt_t *connect_opt,
qcloud_device_t *device,
mqtt_version_t mqtt_version,
uint16_t keep_alive_interval,
mqtt_clean_session_state_t clean_session)
{
QCLOUD_POINTER_SANITY_CHECK(connect_opt, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_INVAL);
#if (QCLOUD_CFG_TLS_EN == 0u)
uint8_t decoded_key[QCLOUD_PSK_MAX];
size_t decoded_key_len;
#endif
memset(connect_opt, 0, sizeof(mqtt_connect_opt_t));
// 1. client id
QCLOUD_FUNC_EXIT_RC_IF_NOT(mqtt_client_id_generate(connect_opt, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
// 2. username
QCLOUD_FUNC_EXIT_RC_IF_NOT(mqtt_client_username_generate(connect_opt), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#if (QCLOUD_CFG_TLS_EN == 0u) && (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_KEY)
// 3. key(temporary)
QCLOUD_FUNC_EXIT_RC_IF_NOT(mqtt_client_key_decode(decoded_key, sizeof(decoded_key), device->key, &decoded_key_len), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
// 4. password
QCLOUD_FUNC_EXIT_RC_IF_NOT(mqtt_client_password_encode(connect_opt, decoded_key, decoded_key_len), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#endif
connect_opt->mqtt_version = mqtt_version;
// keep alive interval is in second, no long than 11.5 minutes(11.5 * 60 seconds)
connect_opt->keep_alive_interval = QCLOUD_MIN(keep_alive_interval, 11.5 * 60);
connect_opt->clean_session = clean_session;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_create(qcloud_mqtt_client_t *client,
qcloud_device_t *device,
mqtt_event_handler_fn_t handler,
void *handler_context,
qcloud_auto_connect_state_t auto_connect_state)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_INVAL);
memset(client, 0, sizeof(qcloud_mqtt_client_t));
QCLOUD_FUNC_EXIT_RC_IF_NOT(mqtt_client_network_init(&client->network, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC_IF_NOT(mqtt_client_construct(client, handler, handler_context, auto_connect_state), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ void qcloud_mqtt_client_destroy(qcloud_mqtt_client_t *client)
{
#if (QCLOUD_CFG_DUPLICATED_MSG_REMOVE_EN > 0u)
mqtt_glue_packet_id_cache_reset();
#endif
if (qcloud_mqtt_client_is_connected(client)) {
qcloud_mqtt_client_disconnect(client);
}
mqtt_glue_ack_list_destroy(client);
osal_mutex_destroy(client->ack_pend_list_lock);
osal_mutex_destroy(client->global_lock);
osal_mutex_destroy(client->tx_lock);
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_publish(qcloud_mqtt_client_t *client, char *topic, mqtt_publish_opt_t *publish_opt)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(topic, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(publish_opt, QCLOUD_ERR_INVAL);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_publish(client, topic, publish_opt));
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_subscribe(qcloud_mqtt_client_t *client, const char *topic_filter, mqtt_subscribe_opt_t *subscribe_opt)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(subscribe_opt, QCLOUD_ERR_INVAL);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_subscribe(client, topic_filter, subscribe_opt));
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_unsubscribe(qcloud_mqtt_client_t *client, const char *topic_filter)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_unsubscribe(client, topic_filter));
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_yield(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt, uint32_t timeout_ms)
{
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_yield(client, connect_opt, timeout_ms));
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_disconnect(qcloud_mqtt_client_t *client)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_disconnect(client));
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_client_connect(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(connect_opt, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
QCLOUD_FUNC_EXIT_RC_IF(client->connection_state, QCLOUD_MQTT_CONNECTION_STATE_CONNECTED, QCLOUD_ERR_MQTT_ALREADY_CONNECTED);
rc = qcloud_mqtt_connect(client, connect_opt);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("mqtt connect failed: %d", rc);
} else {
QCLOUD_LOG_I("mqtt connect success");
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ int qcloud_mqtt_client_is_connected(qcloud_mqtt_client_t *client)
{
int is_connected = 0;
if (!client) {
return QCLOUD_FALSE;
}
osal_mutex_lock(client->global_lock);
is_connected = client->connection_state == QCLOUD_MQTT_CONNECTION_STATE_CONNECTED;
osal_mutex_unlock(client->global_lock);
return is_connected ? QCLOUD_TRUE : QCLOUD_FALSE;
}

View File

@@ -1,962 +0,0 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Sergio R. Caprile - non-blocking packet read functions for stream transport
*******************************************************************************/
#include "qcloud.h"
__QCLOUD_STATIC__ int mqtt_common_packet_length_get(int rem_len)
{
rem_len += 1; /* header byte */
/* now remaining_length field */
if (rem_len < 128) {
rem_len += 1;
} else if (rem_len < 16384) {
rem_len += 2;
} else if (rem_len < 2097151) {
rem_len += 3;
} else {
rem_len += 4;
}
return rem_len;
}
/**
* Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
* @param options the options to be used to build the connect packet
* @param the length of buffer needed to contain the serialized version of the packet
* @return int indicating function execution status
*/
__QCLOUD_STATIC__ int mqtt_common_serialize_connect_packet_length(mqtt_connect_opt_t *connect_opt)
{
int len = 0;
/* variable depending on MQTT or MQIsdp */
if (connect_opt->mqtt_version == 3) {
len = 12;
} else if (connect_opt->mqtt_version == 4) {
len = 10;
}
len += strlen(connect_opt->client_id) + 2;
if (connect_opt->username_len) {
len += connect_opt->username_len + 2;
}
if (connect_opt->password_len) {
len += connect_opt->password_len + 2;
}
return len;
}
/**
* Determines the length of the MQTT publish packet that would be produced using the supplied parameters
* @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
* @param topicName the topic name to be used in the publish
* @param payload_len the length of the payload to be sent
* @return the length of buffer needed to contain the serialized version of the packet
*/
__QCLOUD_STATIC__ int mqtt_common_serialize_publish_packet_length(int qos, char *topic, size_t payload_len)
{
int len = 0;
len += 2 + strlen(topic) + payload_len;
if (qos > MQTT_QOS0) {
len += 2; /* packet id */
}
return len;
}
/**
* Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
* @param count the number of topic filter strings in topicFilters
* @param topicFilters the array of topic filter strings to be used in the publish
* @return the length of buffer needed to contain the serialized version of the packet
*/
__QCLOUD_STATIC__ int mqtt_common_serialize_subscribe_packet_length(uint32_t count, char *topic_filters[])
{
int i;
int len = 2; /* packet id */
for (i = 0; i < count; ++i) {
len += 2 + strlen(topic_filters[i]) + 1; /* length + topic + req_qos */
}
return len;
}
/**
* Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
* @param count the number of topic filter strings in topicFilters
* @param topicFilters the array of topic filter strings to be used in the publish
* @return the length of buffer needed to contain the serialized version of the packet
*/
__QCLOUD_STATIC__ int mqtt_common_serialize_unsubscribe_packet_length(uint32_t count, char *topic_filters[])
{
int i = 0;
int len = 2; /* packet id */
for (i = 0; i < count; ++i) {
len += 2 + strlen(topic_filters[i]); /* length + topic*/
}
return len;
}
/**
* Decodes the message length according to the MQTT algorithm
* @param getcharfn pointer to function to read the next character from the data source
* @param value the decoded length returned
* @return the number of bytes read from the socket
*/
__QCLOUD_STATIC__ qcloud_err_t mqtt_common_packet_do_decode_from_buf(uint32_t (*getcharfn)(uint8_t *, uint32_t), uint32_t *value, uint32_t *read_bytes_len)
{
QCLOUD_FUNC_ENTRY;
uint8_t c;
uint32_t multiplier = 1;
uint32_t len = 0, get_len;
*value = 0;
do {
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) {
/* bad data */
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_PACKET_READ);
}
get_len = 0;
get_len = (*getcharfn)(&c, 1);
if (1 != get_len) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
*value += (c & 127) * multiplier;
multiplier *= 128;
} while ((c & 128) != 0);
*read_bytes_len = len;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
static uint8_t *bufptr;
__QCLOUD_STATIC__ uint32_t __bufchar(uint8_t *c, uint32_t count)
{
uint32_t i;
for (i = 0; i < count; ++i) {
*c = *bufptr++;
}
return count;
}
/**
* Encodes the message length according to the MQTT algorithm
* @param buf the buffer into which the encoded data is written
* @param length the length to be encoded
* @return the number of bytes written to buffer
*/
__QCLOUD_INTERNAL__ int mqtt_common_packet_encode(uint8_t *buf, int length)
{
QCLOUD_FUNC_ENTRY;
int rc = 0;
uint8_t encode_byte;
do {
encode_byte = (uint8_t)(length % 128);
length /= 128;
/* if there are more digits to encode, set the top bit of this digit */
if (length > 0) {
encode_byte |= 0x80;
}
buf[rc++] = encode_byte;
} while (length > 0);
return rc;
}
__QCLOUD_STATIC__ qcloud_err_t mqtt_common_packet_decode_from_buf(uint8_t *buf, uint32_t *value, uint32_t *read_bytes_len)
{
bufptr = buf;
return mqtt_common_packet_do_decode_from_buf(__bufchar, value, read_bytes_len);
}
/**
* Calculates uint16 packet id from two bytes read from the input buffer
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return the value calculated
*/
__QCLOUD_STATIC__ uint16_t mqtt_common_packet_read_dbyte(uint8_t **pptr)
{
uint8_t *ptr = *pptr;
uint8_t firstByte = (uint8_t) (*ptr);
uint8_t secondByte = (uint8_t) (*(ptr + 1));
uint16_t len = (uint16_t) (secondByte + (256 * firstByte));
*pptr += 2;
return len;
}
/**
* Reads one character from the input buffer.
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return the character read
*/
__QCLOUD_STATIC__ uint8_t mqtt_common_packet_read_byte(uint8_t **pptr)
{
uint8_t c = **pptr;
(*pptr)++;
return c;
}
/**
* @param mqttstring the MQTTString structure into which the data is to be read
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param enddata pointer to the end of the data: do not read beyond
* @return SUCCESS if successful, FAILURE if not
*/
__QCLOUD_STATIC__ qcloud_err_t mqtt_common_packet_read_string(char **string, uint16_t *string_len, uint8_t **pptr, uint8_t *enddata)
{
/* the first two bytes are the length of the string */
if (enddata - (*pptr) <= 1) { /* enough length to read the integer? */
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
*string_len = mqtt_common_packet_read_dbyte(pptr); /* increments pptr to point past length */
if (*string_len > QCLOUD_MQTT_CLIENT_RX_BUF_LEN){
QCLOUD_LOG_E("string length overflow!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
if (&(*pptr)[*string_len] > enddata) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
*string = (char *)*pptr;
*pptr += *string_len;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Writes one character to an output buffer.
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param c the character to write
*/
__QCLOUD_STATIC__ void mqtt_common_packet_write_byte(uint8_t **pptr, uint8_t c)
{
**pptr = c;
(*pptr)++;
}
/**
* Writes an integer as 2 bytes to an output buffer.
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param anInt the integer to write
*/
__QCLOUD_STATIC__ void mqtt_common_packet_write_dbyte(uint8_t **pptr, uint16_t dbyte)
{
**pptr = (uint8_t)(dbyte / 256);
(*pptr)++;
**pptr = (uint8_t)(dbyte % 256);
(*pptr)++;
}
/**
* Writes a "UTF" string to an output buffer. Converts C string to length-delimited.
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param string the C string to write
*/
__QCLOUD_STATIC__ void mqtt_common_packet_write_string(uint8_t **pptr, const char *string)
{
size_t len = strlen(string);
mqtt_common_packet_write_dbyte(pptr, (uint16_t)len);
memcpy(*pptr, string, len);
*pptr += len;
}
/**
* Serializes the ack packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buf_len the length in bytes of the supplied buffer
* @param packet_type the MQTT packet type: 1.PUBACK; 2.PUBREL; 3.PUBCOMP
* @param dup the MQTT dup flag
* @param packet_id the MQTT packet identifier
* @return serialized length, or error if 0
*/
__QCLOUD_STATIC__ qcloud_err_t mqtt_common_serialize_ack_packet(uint8_t *buf,
size_t buf_len,
mqtt_packet_t packet_type,
uint8_t dup,
uint16_t packet_id,
uint32_t *serialized_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL);
mqtt_header_t header = {0};
uint8_t *ptr = buf;
/* Minimum byte length required by ACK headers is
* 2 for fixed and 2 for variable part */
if (buf_len < 4) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
header.bits.type = packet_type;
header.bits.dup = dup;
header.bits.qos = (packet_type == MQTT_PACKET_TYPE_PUBREL) ? 1 : 0;
mqtt_common_packet_write_byte(&ptr, header.byte); /* write header */
ptr += mqtt_common_packet_encode(ptr, 2); /* write remaining length */
mqtt_common_packet_write_dbyte(&ptr, packet_id);
*serialized_len = ptr - buf;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Deserializes the supplied (wire) buffer into an ack
* @param packet_type returned integer - the MQTT packet type
* @param dup returned integer - the MQTT dup flag
* @param packet_id returned integer - the MQTT packet identifier
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buf_len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_ack_packet(uint8_t *packet_type,
uint8_t *dup,
uint16_t *packet_id,
uint8_t *buf,
size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(packet_type, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(dup, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(packet_id, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
mqtt_header_t header = {0};
uint8_t ack_code;
uint8_t *curdata = buf, *enddata = NULL;
uint32_t decoded_len = 0, read_bytes_len = 0;
/* PUBACK fixed header size is two bytes, variable header is 2 bytes, MQTT v3.1.1 Specification 3.4.1 */
if (buf_len < 4) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
header.byte = mqtt_common_packet_read_byte(&curdata);
*dup = header.bits.dup;
*packet_type = header.bits.type;
/* read remaining length */
rc = mqtt_common_packet_decode_from_buf(curdata, &decoded_len, &read_bytes_len);
if (QCLOUD_ERR_SUCCESS != rc) {
QCLOUD_FUNC_EXIT_RC(rc);
}
curdata += read_bytes_len;
enddata = curdata + decoded_len;
if (enddata - curdata < 2) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
*packet_id = mqtt_common_packet_read_dbyte(&curdata);
// 返回错误码处理
if (enddata - curdata >= 1) {
ack_code = mqtt_common_packet_read_byte(&curdata);
if (ack_code != 0) {
QCLOUD_LOG_E("deserialize ack packet failure! 0x%02x", ack_code);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Deserializes the supplied (wire) buffer into suback data
* @param packet_id returned integer - the MQTT packet identifier
* @param max_count - the maximum number of members allowed in the grantedQoSs array
* @param count returned integer - number of members in the grantedQoSs array
* @param grantedQoSs returned array of integers - the granted qualities of service
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buf_len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_suback_packet(uint16_t *packet_id,
uint32_t max_count,
uint32_t *count,
int granted_qoss[],
uint8_t *buf,
size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(packet_id, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(count, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(granted_qoss, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
mqtt_header_t header = {0};
uint8_t *curdata = buf, *enddata = NULL;
uint32_t decoded_len = 0, read_bytes_len = 0;
// SUBACK头部大小为4字节, 负载部分至少为1字节QOS返回码
if (buf_len < 5) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
// 读取报文固定头部的第一个字节
header.byte = mqtt_common_packet_read_byte(&curdata);
if (header.bits.type != MQTT_PACKET_TYPE_SUBACK) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
// 读取报文固定头部的剩余长度
rc = mqtt_common_packet_decode_from_buf(curdata, &decoded_len, &read_bytes_len);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
}
curdata += read_bytes_len;
enddata = curdata + decoded_len;
if (enddata - curdata < 2) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
// 读取报文可变头部的报文标识符
*packet_id = mqtt_common_packet_read_dbyte(&curdata);
// 读取报文的负载部分
*count = 0;
while (curdata < enddata) {
if (*count > max_count) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
granted_qoss[(*count)++] = mqtt_common_packet_read_byte(&curdata);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Deserializes the supplied (wire) buffer into unsuback data
* @param packet_id returned integer - the MQTT packet identifier
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buf_len the length in bytes of the data in the supplied buffer
* @return int indicating function execution status
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_unsuback_packet(uint16_t *packet_id,
uint8_t *buf,
size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(packet_id, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
uint8_t type = 0, dup = 0;
rc = mqtt_common_deserialize_ack_packet(&type, &dup, packet_id, buf, buf_len);
if (rc != QCLOUD_ERR_SUCCESS || type != MQTT_PACKET_TYPE_UNSUBACK) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Serializes the connect options into the buffer.
* @param buf the buffer into which the packet will be serialized
* @param len the length in bytes of the supplied buffer
* @param options the options to be used to build the connect packet
* @param serialized length
* @return int indicating function execution status
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_connect_packet(uint8_t *buf,
size_t buf_len,
mqtt_connect_opt_t *connect_opt,
uint32_t *serialized_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(connect_opt, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL);
int packet_len = 0;
uint8_t *ptr = buf;
mqtt_header_t header = {0};
mqtt_connect_flag_t flags = {0};
packet_len = mqtt_common_serialize_connect_packet_length(connect_opt);
if (mqtt_common_packet_length_get(packet_len) > buf_len) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
header.byte = 0;
header.bits.type = MQTT_PACKET_TYPE_CONNECT;
// 报文固定头部第一个字节
mqtt_common_packet_write_byte(&ptr, header.byte); /* write header */
// 报文固定头部剩余长度字段
ptr += mqtt_common_packet_encode(ptr, packet_len); /* write remaining length */
// 报文可变头部协议名 + 协议版本号
if (connect_opt->mqtt_version == 4) {
mqtt_common_packet_write_string(&ptr, "MQTT");
mqtt_common_packet_write_byte(&ptr, (uint8_t)4);
} else {
mqtt_common_packet_write_string(&ptr, "MQIsdp");
mqtt_common_packet_write_byte(&ptr, (uint8_t)3);
}
// 报文可变头部连接标识位
flags.all = 0;
flags.bits.cleansession = connect_opt->clean_session;
if (connect_opt->username_len) {
flags.bits.username = 1;
}
if (connect_opt->password_len) {
flags.bits.password = 1;
}
mqtt_common_packet_write_byte(&ptr, flags.all);
// 报文可变头部心跳周期/保持连接, 一个以秒为单位的时间间隔, 表示为一个16位的字
mqtt_common_packet_write_dbyte(&ptr, connect_opt->keep_alive_interval);
// 有效负载部分: 客户端标识符
mqtt_common_packet_write_string(&ptr, connect_opt->client_id);
// 用户名
if (flags.bits.username) {
mqtt_common_packet_write_string(&ptr, connect_opt->username);
}
if (flags.bits.password) {
mqtt_common_packet_write_string(&ptr, connect_opt->password);
}
*serialized_len = ptr - buf;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Deserializes the supplied (wire) buffer into connack data - return code
* @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
* @param connack_rc returned integer value of the connack return code
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return int indicating function execution status
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_connack_packet(uint8_t *session_present,
uint8_t *connack_rc,
uint8_t *buf,
size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(session_present, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(connack_rc, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
mqtt_header_t header = {0};
mqtt_connack_flags_t flags = {0};
uint8_t *curdata = buf, *enddata = NULL;
uint32_t decoded_len = 0, read_bytes_len = 0;
// CONNACK 头部大小是固定的2字节长度, 可变头部也是两个字节的长度, 无有效负载
if (buf_len < 4) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
// 读取固定头部第一个字节
header.byte = mqtt_common_packet_read_byte(&curdata);
if (header.bits.type != MQTT_PACKET_TYPE_CONNACK) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
// 读取固定头部剩余长度字段
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc = mqtt_common_packet_decode_from_buf(curdata, &decoded_len, &read_bytes_len), QCLOUD_ERR_SUCCESS, rc);
curdata += read_bytes_len;
enddata = curdata + decoded_len;
if (enddata - curdata != 2) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
// 读取可变头部-连接确认标志 参考MQTT协议说明文档3.2.2.1小结
flags.all = mqtt_common_packet_read_byte(&curdata);
*session_present = flags.bits.sessionpresent;
// 读取可变头部-连接返回码 参考MQTT协议说明文档3.2.2.3小结
*connack_rc = mqtt_common_packet_read_byte(&curdata);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
* @param buf the buffer into which the packet will be serialized
* @param buf_len the length in bytes of the supplied buffer, to avoid overruns
* @param packettype the message type
* @param serialized length
* @return int indicating function execution status
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_zero_payload_packet(uint8_t *buf,
size_t buf_len,
mqtt_packet_t packet_type,
uint32_t *serialized_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL);
uint8_t *ptr = buf;
mqtt_header_t header = {0};
/* Buffer should have at least 2 bytes for the header */
if (buf_len < 2) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
header.byte = 0;
header.bits.type = packet_type;
/* write header */
mqtt_common_packet_write_byte(&ptr, header.byte);
/* write remaining length */
ptr += mqtt_common_packet_encode(ptr, 0);
*serialized_len = ptr - buf;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Deserializes the supplied (wire) buffer into publish data
* @param dup returned integer - the MQTT dup flag
* @param qos returned integer - the MQTT QoS value
* @param retained returned integer - the MQTT retained flag
* @param packet_id returned integer - the MQTT packet identifier
* @param topicName returned MQTTString - the MQTT topic in the publish
* @param payload returned byte buffer - the MQTT publish payload
* @param payload_len returned integer - the length of the MQTT payload
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buf_len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_deserialize_publish_packet(uint8_t *dup, int *qos,
uint8_t *retained, uint16_t *packet_id,
char **topic, uint16_t *topic_len,
uint8_t **payload, size_t *payload_len,
uint8_t *buf, size_t buf_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(dup, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(qos, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(retained, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(packet_id, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
uint32_t decoded_len = 0, read_bytes_len = 0;
mqtt_header_t header = {0};
uint8_t *curdata = buf, *enddata = NULL;
/* Publish header size is at least four bytes.
* Fixed header is two bytes.
* Variable header size depends on QoS And Topic Name.
* QoS level 0 doesn't have a message identifier (0 - 2 bytes)
* Topic Name length fields decide size of topic name field (at least 2 bytes)
* MQTT v3.1.1 Specification 3.3.1 */
if (buf_len < 4) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
header.byte = mqtt_common_packet_read_byte(&curdata);
if (header.bits.type != MQTT_PACKET_TYPE_PUBLISH) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
*dup = header.bits.dup;
*qos = header.bits.qos;
*retained = header.bits.retain;
/* read remaining length */
rc = mqtt_common_packet_decode_from_buf(curdata, &decoded_len, &read_bytes_len); /* read remaining length */
if (QCLOUD_ERR_SUCCESS != rc) {
QCLOUD_FUNC_EXIT_RC(rc);
}
curdata += read_bytes_len;
enddata = curdata + decoded_len;
/* do we have enough data to read the protocol version byte? */
if (mqtt_common_packet_read_string(topic, topic_len, &curdata, enddata) != QCLOUD_ERR_SUCCESS ||
enddata - curdata < 0) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
if (*qos > MQTT_QOS0) {
*packet_id = mqtt_common_packet_read_dbyte(&curdata);
}
*payload_len = enddata - curdata;
*payload = curdata;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Serializes a puback packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param packetid integer - the MQTT packet identifier
* @return serialized length, or error if 0
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_puback_packet(uint8_t *buf,
size_t buf_len,
uint16_t packet_id,
uint32_t *serialized_len)
{
return mqtt_common_serialize_ack_packet(buf, buf_len, MQTT_PACKET_TYPE_PUBACK, 0, packet_id, serialized_len);
}
/**
* Serializes a pubrel packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param dup integer - the MQTT dup flag
* @param packetid integer - the MQTT packet identifier
* @return serialized length, or error if 0
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_pubrel_packet(uint8_t *buf,
size_t buf_len,
uint8_t dup,
uint16_t packet_id,
uint32_t *serialized_len)
{
return mqtt_common_serialize_ack_packet(buf, buf_len, MQTT_PACKET_TYPE_PUBREL, dup, packet_id, serialized_len);
}
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_pubrec_packet(uint8_t *buf,
size_t buf_len,
uint16_t packet_id,
uint32_t *serialized_len)
{
return mqtt_common_serialize_ack_packet(buf, buf_len, MQTT_PACKET_TYPE_PUBREC, 0, packet_id, serialized_len);
}
/**
* Serializes the supplied publish data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buf_len the length in bytes of the supplied buffer
* @param dup integer - the MQTT dup flag
* @param qos integer - the MQTT QoS value
* @param retained integer - the MQTT retained flag
* @param packet_id integer - the MQTT packet identifier
* @param topicName MQTTString - the MQTT topic in the publish
* @param payload byte buffer - the MQTT publish payload
* @param payload_len integer - the length of the MQTT payload
* @return the length of the serialized data. <= 0 indicates error
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_publish_packet(uint8_t *buf,
size_t buf_len,
uint8_t dup,
int qos,
uint8_t retained,
uint16_t packet_id,
char *topic,
uint8_t *payload,
size_t payload_len,
uint32_t *serialized_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(payload, QCLOUD_ERR_INVAL);
uint8_t *ptr = buf;
mqtt_header_t header = {0};
int rem_len = 0;
rem_len = mqtt_common_serialize_publish_packet_length(qos, topic, payload_len);
if (mqtt_common_packet_length_get(rem_len) > buf_len) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
header.bits.type = MQTT_PACKET_TYPE_PUBLISH;
header.bits.dup = dup;
header.bits.qos = qos;
header.bits.retain = retained;
mqtt_common_packet_write_byte(&ptr, header.byte); /* write header */
ptr += mqtt_common_packet_encode(ptr, rem_len); /* write remaining length */;
mqtt_common_packet_write_string(&ptr, topic); /* Variable Header: Topic Name */
if (qos > MQTT_QOS0) {
mqtt_common_packet_write_dbyte(&ptr, packet_id); /* Variable Header: Topic Name */
}
memcpy(ptr, payload, payload_len);
ptr += payload_len;
*serialized_len = ptr - buf;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Serializes the supplied subscribe data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buf_len the length in bytes of the supplied bufferr
* @param dup integer - the MQTT dup flag
* @param packet_id integer - the MQTT packet identifier
* @param count - number of members in the topicFilters and reqQos arrays
* @param topicFilters - array of topic filter names
* @param requestedQoSs - array of requested QoS
* @return the length of the serialized data. <= 0 indicates error
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_subscribe_packet(uint8_t *buf,
size_t buf_len,
uint8_t dup,
uint16_t packet_id,
uint32_t count,
char *topic_filters[],
int requested_qoss[],
uint32_t *serialized_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL);
int i = 0;
uint8_t *ptr = buf;
mqtt_header_t header = {0};
uint32_t rem_len = 0;
// SUBSCRIBE报文的剩余长度 = 报文标识符(2 byte) + count * (长度字段(2 byte) + topicLen + qos(1 byte))
rem_len = mqtt_common_serialize_subscribe_packet_length(count, topic_filters);
if (mqtt_common_packet_length_get(rem_len) > buf_len) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
// 初始化报文头部
header.byte = 0;
header.bits.type = MQTT_PACKET_TYPE_SUBSCRIBE;
header.bits.dup = dup;
header.bits.qos = MQTT_QOS1;
// 写报文固定头部第一个字节
mqtt_common_packet_write_byte(&ptr, header.byte);
// 写报文固定头部剩余长度字段
ptr += mqtt_common_packet_encode(ptr, rem_len);
// 写可变头部: 报文标识符
mqtt_common_packet_write_dbyte(&ptr, packet_id);
// 写报文的负载部分数据
for (i = 0; i < count; ++i) {
mqtt_common_packet_write_string(&ptr, topic_filters[i]);
mqtt_common_packet_write_byte(&ptr, (uint8_t)requested_qoss[i]);
}
*serialized_len = ptr - buf;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buf_len the length in bytes of the data in the supplied buffer
* @param dup integer - the MQTT dup flag
* @param packet_id integer - the MQTT packet identifier
* @param count - number of members in the topicFilters array
* @param topicFilters - array of topic filter names
* @param serialized_len - the length of the serialized data
* @return int indicating function execution status
*/
__QCLOUD_INTERNAL__ qcloud_err_t mqtt_common_serialize_unsubscribe_packet(uint8_t *buf, size_t buf_len,
uint8_t dup, uint16_t packet_id,
uint32_t count, char *topic_filters[],
uint32_t *serialized_len)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL);
int i = 0;
uint8_t *ptr = buf;
mqtt_header_t header = {0};
uint32_t rem_len = 0;
rem_len = mqtt_common_serialize_unsubscribe_packet_length(count, topic_filters);
if (mqtt_common_packet_length_get(rem_len) > buf_len) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT);
}
header.byte = 0;
header.bits.type = MQTT_PACKET_TYPE_UNSUBSCRIBE;
header.bits.dup = dup;
header.bits.qos = MQTT_QOS1;
mqtt_common_packet_write_byte(&ptr, header.byte); /* write header */
ptr += mqtt_common_packet_encode(ptr, rem_len); /* write remaining length */
mqtt_common_packet_write_dbyte(&ptr, packet_id);
for (i = 0; i < count; ++i) {
mqtt_common_packet_write_string(&ptr, topic_filters[i]);
}
*serialized_len = ptr - buf;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}

View File

@@ -1,153 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_STATIC__ qcloud_err_t mqtt_connack2errno(uint8_t connack_rc)
{
switch (connack_rc) {
case MQTT_CONNACK_CONNECTION_ACCEPTED:
return QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED;
case MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR:
return QCLOUD_ERR_MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION;
case MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR:
return QCLOUD_ERR_MQTT_CONNACK_IDENTIFIER_REJECTED;
case MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR:
return QCLOUD_ERR_MQTT_CONNACK_SERVER_UNAVAILABLE;
case MQTT_CONNACK_BAD_USERDATA_ERROR:
return QCLOUD_ERR_MQTT_CONNACK_BAD_USERDATA;
case MQTT_CONNACK_NOT_AUTHORIZED_ERROR:
return QCLOUD_ERR_MQTT_CONNACK_NOT_AUTHORIZED;
default:
return QCLOUD_ERR_MQTT_CONNACK_UNKNOWN;
}
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_connect(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(connect_opt, QCLOUD_ERR_INVAL);
osal_timer_t timer;
uint32_t serialized_len = 0;
uint8_t connack_rc = 0, session_present = 0;
qcloud_err_t rc = QCLOUD_ERR_FAILURE;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, client->command_timeout);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc = client->network.connect(&(client->network)), QCLOUD_ERR_SUCCESS, rc);
osal_mutex_lock(client->tx_lock);
// 序列化CONNECT报文
rc = mqtt_common_serialize_connect_packet(client->tx_buffer, sizeof(client->tx_buffer), connect_opt, &serialized_len);
if (rc != QCLOUD_ERR_SUCCESS || serialized_len == 0) {
osal_mutex_unlock(client->tx_lock);
goto errout;
}
// 发送CONNECT报文
rc = mqtt_glue_packet_send(client, serialized_len, &timer);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
goto errout;
}
osal_mutex_unlock(client->tx_lock);
// 阻塞等待CONNACK的报文,
rc = mqtt_glue_spin4ack(client, &timer, (uint8_t)MQTT_PACKET_TYPE_CONNACK);
if (QCLOUD_ERR_SUCCESS != rc) {
goto errout;
}
// 反序列化CONNACK包, 检查返回码
rc = mqtt_common_deserialize_connack_packet(&session_present, &connack_rc, client->rx_buffer, sizeof(client->rx_buffer));
if (QCLOUD_ERR_SUCCESS != rc) {
goto errout;
}
rc = mqtt_connack2errno(connack_rc);
if (rc != QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED) {
goto errout;
}
mqtt_client_connection_state_set(client, QCLOUD_MQTT_CONNECTION_STATE_CONNECTED);
client->keep_alive_interval = connect_opt->keep_alive_interval;
osal_mutex_lock(client->global_lock);
client->is_manually_disconnected = QCLOUD_FALSE;
client->ping_outstanding = 0;
osal_timer_countdown(&client->ping_timer, client->keep_alive_interval);
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
errout:
client->network.disconnect(&client->network);
QCLOUD_FUNC_EXIT_RC(rc);
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_disconnect(qcloud_mqtt_client_t *client)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
osal_timer_t timer;
uint32_t serialized_len = 0;
if (!qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
mqtt_glue_msg_handler_list_destroy(client);
// 1. 组disconnect包
osal_mutex_lock(client->tx_lock);
rc = mqtt_common_serialize_zero_payload_packet(client->tx_buffer, sizeof(client->tx_buffer), MQTT_PACKET_TYPE_DISCONNECT, &serialized_len);
if (rc != QCLOUD_ERR_SUCCESS) {
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, client->command_timeout);
// 2. 发送disconnect包
if (serialized_len > 0) {
rc = mqtt_glue_packet_send(client, serialized_len, &timer);
if (rc != QCLOUD_ERR_SUCCESS) {
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
}
osal_mutex_unlock(client->tx_lock);
// 3. 断开底层TCP连接, 并修改相关标识位
client->network.disconnect(&(client->network));
mqtt_client_connection_state_set(client, QCLOUD_MQTT_CONNECTION_STATE_DISCONNECTED);
client->is_manually_disconnected = QCLOUD_TRUE;
QCLOUD_LOG_I("mqtt disconnect!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,65 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_publish(qcloud_mqtt_client_t *client, char *topic, mqtt_publish_opt_t *publish_opt)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(publish_opt, QCLOUD_ERR_INVAL);
QCLOUD_STRING_PTR_SANITY_CHECK(topic, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
osal_timer_t timer;
uint32_t len = 0;
size_t topic_len = 0;
topic_len = strlen(topic);
if (topic_len > QCLOUD_MQTT_TOPIC_SIZE_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH);
}
if (publish_opt->qos == MQTT_QOS2) {
QCLOUD_LOG_E("QoS2 isn't supported yet");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_QOS_NOT_SUPPORT);
}
if (!qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, client->command_timeout);
osal_mutex_lock(client->tx_lock);
if (publish_opt->qos == MQTT_QOS1) {
publish_opt->id = mqtt_glue_packet_id_generate(client);
}
QCLOUD_LOG_D("publish topic seq=%d|name=%s|payload=%s", publish_opt->id, topic, (char *)publish_opt->payload);
rc = mqtt_common_serialize_publish_packet(client->tx_buffer, sizeof(client->tx_buffer),
0, publish_opt->qos, publish_opt->retained, publish_opt->id,
topic, (uint8_t *) publish_opt->payload, publish_opt->payload_len, &len);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
rc = mqtt_glue_packet_send(client, len, &timer);
if (rc == QCLOUD_ERR_SUCCESS && publish_opt->qos > MQTT_QOS0) {
mqtt_glue_ack_list_record(client, QCLOUD_MQTT_ACK_TYPE_PUBACK, NULL, publish_opt->id, len);
}
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,89 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_subscribe(qcloud_mqtt_client_t *client, const char *topic_filter, mqtt_subscribe_opt_t *subscribe_opt)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(subscribe_opt, QCLOUD_ERR_INVAL);
QCLOUD_STRING_PTR_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
osal_timer_t timer;
size_t topic_len;
uint32_t len = 0;
uint16_t packet_id = 0;
char *topic_filter_mutable = NULL;
qcloud_mqtt_msg_handler_t *msg_handler = NULL;
topic_len = strlen(topic_filter);
if (topic_len > QCLOUD_MQTT_TOPIC_SIZE_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH);
}
if (subscribe_opt->qos == MQTT_QOS2) {
QCLOUD_LOG_E("QoS2 not supported yet");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_QOS_NOT_SUPPORT);
}
if (!qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN)
}
/* topic filter should be valid in the whole sub life */
topic_filter_mutable = mqtt_glue_string_const2mutable(topic_filter, topic_len);
if (!topic_filter_mutable) {
QCLOUD_LOG_E("malloc failed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, client->command_timeout);
osal_mutex_lock(client->tx_lock);
// 序列化SUBSCRIBE报文
packet_id = mqtt_glue_packet_id_generate(client);
QCLOUD_LOG_D("topic name=%s|packet id=%d|private data=%s", topic_filter_mutable, packet_id, (char *)subscribe_opt->private_data);
rc = mqtt_common_serialize_subscribe_packet(client->tx_buffer, sizeof(client->tx_buffer),
0, packet_id, 1, &topic_filter_mutable,
(int *)&subscribe_opt->qos, &len);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
mqtt_glue_string_mutable_free(topic_filter_mutable);
QCLOUD_FUNC_EXIT_RC(rc);
}
// 发送SUBSCRIBE报文
rc = mqtt_glue_packet_send(client, len, &timer);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
mqtt_glue_string_mutable_free(topic_filter_mutable);
QCLOUD_FUNC_EXIT_RC(rc);
}
msg_handler = mqtt_glue_msg_handler_create(topic_filter_mutable, subscribe_opt);
if (!msg_handler) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
rc = mqtt_glue_ack_list_record(client, QCLOUD_MQTT_ACK_TYPE_SUBACK, msg_handler, packet_id, len);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
mqtt_glue_msg_handler_destory(msg_handler);
QCLOUD_FUNC_EXIT_RC(rc);
}
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,83 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_unsubscribe(qcloud_mqtt_client_t *client, const char *topic_filter)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_STRING_PTR_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
osal_timer_t timer;
size_t topic_len = 0;
uint32_t len = 0;
uint16_t packet_id = 0;
int is_subscribed = QCLOUD_FALSE;
char *topic_filter_mutable = NULL;
topic_len = strlen(topic_filter);
if (topic_len > QCLOUD_MQTT_TOPIC_SIZE_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH);
}
mqtt_glue_msg_handler_uninstall(client, topic_filter, &is_subscribed);
if (!is_subscribed) {
QCLOUD_LOG_E("not subscribed: %s", topic_filter);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_UNSUB_FAIL);
}
if (!qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
/* topic filter should be valid in the whole sub life */
topic_filter_mutable = mqtt_glue_string_const2mutable(topic_filter, topic_len);
if (!topic_filter_mutable) {
QCLOUD_LOG_E("malloc failed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, client->command_timeout);
osal_mutex_lock(client->tx_lock);
packet_id = mqtt_glue_packet_id_generate(client);
rc = mqtt_common_serialize_unsubscribe_packet(client->tx_buffer, sizeof(client->tx_buffer),
0, packet_id, 1, &topic_filter_mutable, &len);
mqtt_glue_string_mutable_free(topic_filter_mutable);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
/* send the unsubscribe packet */
rc = mqtt_glue_packet_send(client, len, &timer);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
rc = mqtt_glue_ack_list_record(client, QCLOUD_MQTT_ACK_TYPE_UNSUBACK, NULL, packet_id, len);
if (QCLOUD_ERR_SUCCESS != rc) {
QCLOUD_LOG_E("push publish into to pubInfolist failed: %d", rc);
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,286 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_STATIC__ qcloud_err_t mqtt_yield_resubscribe(qcloud_mqtt_client_t *client)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
char *topic = NULL;
mqtt_subscribe_opt_t subscribe_opt;
qcloud_list_t *curr, *next;
qcloud_mqtt_msg_handler_t *msg_handler;
if (!qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
if (qcloud_list_empty(&client->msg_handler_list)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
osal_mutex_lock(client->msg_handler_list_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->msg_handler_list) {
msg_handler = QCLOUD_LIST_ENTRY(curr, qcloud_mqtt_msg_handler_t, list);
subscribe_opt.message_handler = msg_handler->handler;
subscribe_opt.qos = msg_handler->qos;
subscribe_opt.private_data = msg_handler->private_data;
rc = qcloud_mqtt_subscribe(client, msg_handler->topic_filter_mutable, &subscribe_opt);
if (rc != QCLOUD_ERR_SUCCESS) {
osal_mutex_unlock(client->msg_handler_list_lock);
QCLOUD_LOG_E("resubscribe failed %d, topic: %s", rc, topic);
QCLOUD_FUNC_EXIT_RC(rc);
}
}
osal_mutex_unlock(client->msg_handler_list_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ qcloud_err_t mqtt_yield_do_reconnect(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(connect_opt, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
QCLOUD_LOG_I("attempt to reconnect...");
if (qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_ALREADY_CONNECTED);
}
rc = qcloud_mqtt_connect(client, connect_opt);
if (!qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(rc);
}
rc = mqtt_yield_resubscribe(client);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_RECONNECTED);
}
/**
* @brief 处理非手动断开连接的情况
*
* @param client
* @return
*/
__QCLOUD_STATIC__ qcloud_err_t mqtt_yield_try_disconnect(qcloud_mqtt_client_t *client)
{
QCLOUD_FUNC_ENTRY;
qcloud_err_t rc;
if (!qcloud_mqtt_client_is_connected(client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
rc = qcloud_mqtt_disconnect(client);
// 若断开连接失败, 强制断开底层TLS层连接
if (rc != QCLOUD_ERR_SUCCESS) {
client->network.disconnect(&(client->network));
mqtt_client_connection_state_set(client, QCLOUD_MQTT_CONNECTION_STATE_DISCONNECTED);
}
mqtt_glue_callback_involve(client, MQTT_EVENT_DISCONNECT, NULL);
// 非手动断开连接
client->is_manually_disconnected = QCLOUD_FALSE;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
/**
* @brief 处理自动重连的相关逻辑
*
* @param client
* @return
*/
__QCLOUD_STATIC__ qcloud_err_t mqtt_yield_try_reconnect(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt)
{
QCLOUD_FUNC_ENTRY;
qcloud_err_t rc = QCLOUD_ERR_MQTT_RECONNECTED;
// 自动重连等待时间还未过期, 还未到重连的时候, 返回正在进行重连
if (!osal_timer_is_expired(&client->reconnect_timer)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT);
}
rc = mqtt_yield_do_reconnect(client, connect_opt);
if (rc == QCLOUD_ERR_MQTT_RECONNECTED) {
QCLOUD_LOG_E("reconnect success");
mqtt_glue_callback_involve(client, MQTT_EVENT_RECONNECT, NULL);
QCLOUD_FUNC_EXIT_RC(rc);
} else {
QCLOUD_LOG_E("attempt reconnect failed %d", rc);
rc = QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT;
}
client->reconnect_try_duration *= 2;
if (client->reconnect_try_duration > QCLOUD_MQTT_RECONNECT_TRY_THRESHOLD) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_RECONNECT_TIMEOUT);
}
osal_timer_countdown_ms(&client->reconnect_timer, client->reconnect_try_duration);
QCLOUD_FUNC_EXIT_RC(rc);
}
/**
* @brief 处理与服务器维持心跳的相关逻辑
*
* @param client
* @return
*/
__QCLOUD_STATIC__ qcloud_err_t mqtt_yield_keep_alive(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt)
{
#define MQTT_PING_RETRY_TIMES 2
QCLOUD_FUNC_ENTRY;
int try = 0;
qcloud_err_t rc;
osal_timer_t timer;
uint32_t serialized_len = 0;
if (!connect_opt->keep_alive_interval) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
if (!osal_timer_is_expired(&client->ping_timer)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
if (client->ping_outstanding >= MQTT_PING_RETRY_TIMES) {
// reaching here means we haven't received any MQTT packet for a long time(keep_alive_interval)
QCLOUD_LOG_E("fail to recv MQTT msg.");
QCLOUD_FUNC_EXIT_RC(mqtt_yield_try_disconnect(client));
}
/* there is no ping outstanding - send one */
osal_mutex_lock(client->tx_lock);
rc = mqtt_common_serialize_zero_payload_packet(client->tx_buffer, sizeof(client->tx_buffer), MQTT_PACKET_TYPE_PINGREQ, &serialized_len);
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
QCLOUD_FUNC_EXIT_RC(rc);
}
/* send the ping packet */
osal_timer_init(&timer);
do {
osal_timer_countdown_ms(&timer, client->command_timeout);
rc = mqtt_glue_packet_send(client, serialized_len, &timer);
} while (QCLOUD_ERR_SUCCESS != rc && (try++ < 3));
if (QCLOUD_ERR_SUCCESS != rc) {
osal_mutex_unlock(client->tx_lock);
// if send a PING fails, propably the connection is not OK and we decide to disconnect and begin reconnection attempts
QCLOUD_LOG_E("fail to send PING request.");
rc = mqtt_yield_try_disconnect(client);
QCLOUD_FUNC_EXIT_RC(rc);
}
osal_mutex_unlock(client->tx_lock);
osal_mutex_lock(client->global_lock);
++client->ping_outstanding;
/* start a timer to wait for PINGRESP from server */
osal_timer_countdown(&client->ping_timer, QCLOUD_MIN(5, connect_opt->keep_alive_interval / 2));
osal_mutex_unlock(client->global_lock);
QCLOUD_LOG_D("PING request %u sent.", client->ping_outstanding);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ qcloud_err_t qcloud_mqtt_yield(qcloud_mqtt_client_t *client, mqtt_connect_opt_t *connect_opt, uint32_t timeout_ms)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL);
qcloud_err_t rc = QCLOUD_ERR_SUCCESS;
osal_timer_t timer;
uint8_t packet_type;
// 1. 检查连接是否已经手动断开
if (!qcloud_mqtt_client_is_connected(client)) {
if (client->is_manually_disconnected) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED);
} else if (client->auto_connect_state != QCLOUD_AUTO_CONN_STATE_ENABLED) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
}
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, timeout_ms);
// 3. 循环读取消息以及心跳包管理
while (!osal_timer_is_expired(&timer)) {
if (!qcloud_mqtt_client_is_connected(client)) {
if (client->reconnect_try_duration > QCLOUD_MQTT_RECONNECT_TRY_THRESHOLD) {
rc = QCLOUD_ERR_MQTT_RECONNECT_TIMEOUT;
break;
}
rc = mqtt_yield_try_reconnect(client, connect_opt);
continue;
}
rc = mqtt_glue_spin(client, &timer, &packet_type);
if (rc == QCLOUD_ERR_SUCCESS) {
/* check list of ACK pend list to remove node that is timeout */
mqtt_glue_ack_list_scan(client);
rc = mqtt_yield_keep_alive(client, connect_opt);
} else if (rc == QCLOUD_ERR_SSL_READ_TIMEOUT ||
rc == QCLOUD_ERR_SSL_READ ||
rc == QCLOUD_ERR_TCP_PEER_SHUTDOWN ||
rc == QCLOUD_ERR_TCP_READ_FAIL) {
QCLOUD_LOG_E("network failed, MQTT disconnect %d", rc);
rc = mqtt_yield_try_disconnect(client);
}
if (rc == QCLOUD_ERR_MQTT_NO_CONN) {
++client->network_disconnect_counter;
if (client->auto_connect_state != QCLOUD_AUTO_CONN_STATE_ENABLED) {
break;
}
client->reconnect_try_duration = QCLOUD_MQTT_RECONNECT_TRY_INITIAL;
osal_timer_countdown_ms(&client->reconnect_timer, client->reconnect_try_duration);
// 如果超时时间到了,则会直接返回
rc = QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT;
} else if (rc != QCLOUD_ERR_SUCCESS) {
break;
}
}
QCLOUD_FUNC_EXIT_RC(rc);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,398 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"
#include "mbedtls/timing.h"
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/debug.h"
#define DEBUG_LEVEL 0
void mbedtls_dtls_net_init(mbedtls_net_context *ctx);
int mbedtls_dtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto);
void mbedtls_dtls_net_usleep(unsigned long usec);
int mbedtls_dtls_net_recv(void *ctx, unsigned char *buf, size_t len);
int mbedtls_dtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout);
int mbedtls_dtls_net_send(void *ctx, const unsigned char *buf, size_t len);
void mbedtls_dtls_net_free(mbedtls_net_context *ctx);
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_KEY)
static const int ciphersuites[] = { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0 };
#endif
typedef struct dtls_paramter_st {
mbedtls_net_context socket_fd; // socket文件描述符
mbedtls_entropy_context entropy; // 保存熵配置
mbedtls_ctr_drbg_context ctr_drbg; // 随机数生成器
mbedtls_ssl_context ssl; // 保存SSL基本数据
mbedtls_ssl_config ssl_conf; // TSL/TLS配置信息
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt ca_cert; // ca证书信息
mbedtls_x509_crt client_cert; // 客户端证书信息
#endif
mbedtls_pk_context private_key; // 客户端私钥信息
mbedtls_timing_delay_context timer;
mbedtls_ssl_cookie_ctx cookie_ctx;
} dtls_param_t;
/**
* @brief 释放mbedtls开辟的内存
*/
static void mbedtls_dtls_param_free(dtls_param_t *dtls_param)
{
mbedtls_dtls_net_free(&dtls_param->socket_fd);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt_free(&dtls_param->client_cert);
mbedtls_x509_crt_free(&dtls_param->ca_cert);
mbedtls_pk_free(&dtls_param->private_key);
#endif
mbedtls_ssl_free(&dtls_param->ssl);
mbedtls_ssl_config_free(&dtls_param->ssl_conf);
mbedtls_ctr_drbg_free(&dtls_param->ctr_drbg);
mbedtls_entropy_free(&dtls_param->entropy);
#if 0
mbedtls_ssl_cookie_free(&(dtls_param->cookie_ctx));
#endif
osal_free(dtls_param);
}
static void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str)
{
QCLOUD_LOG_I("[mbedTLS]:[%s]:[%d]: %s\r\n", file, line, str);
}
static int mbedtls_client_init(dtls_param_t *dtls_param, qcloud_tls_opt_t *tls_opt)
{
int ret = 0;
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif
mbedtls_dtls_net_init(&dtls_param->socket_fd);
mbedtls_ssl_init(&dtls_param->ssl);
mbedtls_ssl_config_init(&dtls_param->ssl_conf);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt_init(&dtls_param->ca_cert);
mbedtls_x509_crt_init(&dtls_param->client_cert);
mbedtls_pk_init(&dtls_param->private_key);
#endif
mbedtls_ctr_drbg_init(&dtls_param->ctr_drbg);
mbedtls_entropy_init(&dtls_param->entropy);
if((ret = mbedtls_ctr_drbg_seed(&dtls_param->ctr_drbg, mbedtls_entropy_func,
&dtls_param->entropy, NULL,0)) != 0) {
QCLOUD_LOG_E("mbedtls_ctr_drbg_seed failed returned -0x%x", -ret);
return QCLOUD_ERR_SSL_INIT;
}
mbedtls_ssl_conf_authmode(&dtls_param->ssl_conf, MBEDTLS_SSL_VERIFY_NONE );
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if (tls_opt->ca_cert != NULL) {
if ((ret = mbedtls_x509_crt_parse(&dtls_param->ca_cert, (const unsigned char *)tls_opt->ca_cert,
(tls_opt->ca_cert_len + 1)))) {
QCLOUD_LOG_E("parse ca crt failed returned -0x%04x", -ret);
return QCLOUD_ERR_SSL_CERT;
}
}
#endif
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
if (tls_opt->cert_path != NULL && tls_opt->priv_key_path != NULL) {
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if ((ret = mbedtls_x509_crt_parse_file(&dtls_param->client_cert, tls_opt->cert_path)) != 0) {
QCLOUD_LOG_E("load client cert file failed returned -0x%x", ret);
return QCLOUD_ERR_SSL_CERT;
}
#endif
if ((ret = mbedtls_pk_parse_keyfile(&dtls_param->private_key, tls_opt->priv_key_path, "")) != 0) {
QCLOUD_LOG_E("load client key file failed returned -0x%x", ret);
return QCLOUD_ERR_SSL_CERT;
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if (0 == ret) {
mbedtls_ssl_conf_ca_chain(&dtls_param->ssl_conf, &dtls_param->ca_cert, NULL);
if ((ret = mbedtls_ssl_conf_own_cert(&dtls_param->ssl_conf, &dtls_param->client_cert, &dtls_param->private_key)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_conf_own_cert failed returned -0x%x", -ret);
return QCLOUD_ERR_SSL_CERT;
}
}
#endif
} else {
QCLOUD_LOG_D("cert_file/key_file is empty!|cert_file=%s|key_file=%s", tls_opt->cert_path, tls_opt->priv_key_path);
}
#else
if (tls_opt->psk != NULL && tls_opt->psk_id !=NULL) {
const char *psk_id = tls_opt->psk_id;
ret = mbedtls_ssl_conf_psk(&dtls_param->ssl_conf, (unsigned char *)tls_opt->psk, tls_opt->psk_len,
(const unsigned char *)psk_id, strlen(psk_id));
} else {
QCLOUD_LOG_D("psk/pskid is empty!|psk=%s|psd_id=%s", tls_opt->psk, tls_opt->psk_id);
}
if (0 != ret) {
QCLOUD_LOG_E("mbedtls_ssl_conf_psk fail: -0x%x", -ret);
return ret;
}
#endif
return ret;
}
/**
* @brief 建立UDP连接
*
* @param socket_fd Socket描述符
* @param host 服务器主机名
* @param port 服务器端口地址
* @return 返回QCLOUD_ERR_SUCCESS, 表示成功
*/
int mbedtls_udp_connect(mbedtls_net_context *socket_fd, const char *host, int port)
{
int ret = 0;
char port_str[6];
osal_snprintf(port_str, 6, "%d", port);
if ((ret = mbedtls_dtls_net_connect(socket_fd, host, port_str, MBEDTLS_NET_PROTO_UDP)) != 0) {
QCLOUD_LOG_E("mbedtls_dtls_net_connect host:%s port:%s returned -0x%04x", host, port_str, -ret);
switch (ret) {
case MBEDTLS_ERR_NET_SOCKET_FAILED:
return QCLOUD_ERR_TCP_SOCKET_FAILED;
case MBEDTLS_ERR_NET_UNKNOWN_HOST:
return QCLOUD_ERR_TCP_UNKNOWN_HOST;
default:
return QCLOUD_ERR_TCP_CONNECT;
}
}
#if 0
if ((ret = mbedtls_net_set_block(socket_fd)) != 0) {
QCLOUD_LOG_E("set block faliled returned -0x%04x", -ret);
return QCLOUD_ERR_TCP_CONNECT;
}
#endif
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_OSAL__ void *osal_dtls_connect(qcloud_tls_opt_t *tls_opt, const char *host, int port)
{
QCLOUD_FUNC_ENTRY;
int ret = QCLOUD_ERR_SUCCESS;
dtls_param_t *dtls_param = NULL;
if (!tls_opt) {
return NULL;
}
dtls_param = (dtls_param_t *)osal_malloc(sizeof(dtls_param_t));
if (!dtls_param) {
return NULL;
}
if ((ret = mbedtls_client_init(dtls_param, tls_opt)) != QCLOUD_ERR_SUCCESS) {
goto error;
}
QCLOUD_LOG_D(" Connecting to /%s/%d...", host, port);
if ((ret = mbedtls_udp_connect(&dtls_param->socket_fd, host, port)) != QCLOUD_ERR_SUCCESS) {
goto error;
}
QCLOUD_LOG_D(" Setting up the SSL/TLS structure...");
if ((ret = mbedtls_ssl_config_defaults(&dtls_param->ssl_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_config_defaults result 0x%04x", ret);
goto error;
}
mbedtls_ssl_conf_authmode(&dtls_param->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_rng(&dtls_param->ssl_conf, mbedtls_ctr_drbg_random, &dtls_param->ctr_drbg);
mbedtls_ssl_conf_dbg(&dtls_param->ssl_conf, mbedtls_debug, NULL);
#if 0
if ((ret = mbedtls_ssl_cookie_setup(&pDataParams->cookie_ctx, mbedtls_ctr_drbg_random, &pDataParams->ctr_drbg)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_cookie_setup result 0x%04x", ret);
goto error;
}
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
mbedtls_ssl_conf_dtls_cookies(&dtls_param->ssl_conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &dtls_param->cookie_ctx);
#endif
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_KEY)
mbedtls_ssl_conf_ciphersuites(&dtls_param->ssl_conf, ciphersuites);
#endif
#ifdef MBEDTLS_SSL_PROTO_DTLS
if (dtls_param->ssl_conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
mbedtls_ssl_conf_min_version(&dtls_param->ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_max_version(&dtls_param->ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_handshake_timeout(&dtls_param->ssl_conf, (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2),
(MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4));
}
#endif
if ((ret = mbedtls_ssl_setup(&dtls_param->ssl, &dtls_param->ssl_conf)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_setup failed returned -0x%x", -ret);
goto error;
}
if (dtls_param->ssl_conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
mbedtls_ssl_set_timer_cb(&dtls_param->ssl, (void *)&dtls_param->timer, mbedtls_timing_set_delay,
mbedtls_timing_get_delay);
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if ((ret = mbedtls_ssl_set_hostname(&dtls_param->ssl, host)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_set_hostname failed returned -0x%x", -ret);
goto error;
}
#endif
mbedtls_ssl_set_bio(&dtls_param->ssl, (void *)&dtls_param->socket_fd, mbedtls_dtls_net_send, mbedtls_dtls_net_recv,
mbedtls_dtls_net_recv_timeout);
QCLOUD_LOG_D("Performing the SSL/TLS handshake...");
while ((ret = mbedtls_ssl_handshake(&dtls_param->ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
QCLOUD_LOG_E("mbedtls_ssl_handshake failed returned -0x%x", -ret);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
QCLOUD_LOG_E("Unable to verify the server's certificate");
}
#endif
goto error;
}
}
if ((ret = mbedtls_ssl_get_verify_result(&dtls_param->ssl)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_get_verify_result failed returned -0x%x", -ret);
goto error;
}
return dtls_param;
error:
mbedtls_dtls_param_free(dtls_param);
return NULL;
}
__QCLOUD_OSAL__ void osal_dtls_disconnect(void *handle)
{
int rc = 0;
dtls_param_t *dtls_param = NULL;
if (!handle) {
return;
}
dtls_param = (dtls_param_t *)handle;
do {
rc = mbedtls_ssl_close_notify(&dtls_param->ssl);
} while (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE);
mbedtls_dtls_param_free(dtls_param);
}
__QCLOUD_OSAL__ qcloud_err_t osal_dtls_write(void *handle, const void *buf, size_t len, size_t *write_len)
{
QCLOUD_POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(write_len, QCLOUD_ERR_INVAL);
int rc;
dtls_param_t *data_params = NULL;
data_params = (dtls_param_t *)handle;
rc = mbedtls_ssl_write(&data_params->ssl, buf, len);
if (rc < 0) {
QCLOUD_LOG_E("ssl_write failed %d", rc);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SSL_WRITE);
}
*write_len = rc;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_OSAL__ qcloud_err_t osal_dtls_read(void *handle, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
QCLOUD_POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(read_len, QCLOUD_ERR_INVAL);
int rc = 0;
dtls_param_t *data_params = NULL;
data_params = (dtls_param_t *)handle;
mbedtls_ssl_conf_read_timeout(&data_params->ssl_conf, timeout);
do {
rc = mbedtls_ssl_read(&data_params->ssl, buf, len);
} while (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE);
if (rc > 0) {
*read_len = rc;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
switch (rc) {
case MBEDTLS_ERR_SSL_TIMEOUT:
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SSL_READ_TIMEOUT);
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
QCLOUD_LOG_E("connection closed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_DTLS_PEER_CLOSE_NOTIFY);
default:
QCLOUD_LOG_E("ssl_read returned -0x%x", -rc);
break;
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,116 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 <stdarg.h>
#include <string.h>
#include "tos_k.h"
#include "qcloud.h"
__QCLOUD_OSAL__ void osal_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
__QCLOUD_OSAL__ int osal_snprintf(char *str, const int len, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(str, len, fmt, args);
va_end(args);
return rc;
}
__QCLOUD_OSAL__ int osal_vsnprintf(char *str, const int len, const char *format, va_list ap)
{
return vsnprintf(str, len, format, ap);
}
__QCLOUD_OSAL__ void *osal_mutex_create(void)
{
k_mutex_t *mutex;
mutex = (k_mutex_t *)osal_malloc(sizeof(k_mutex_t));
if (!mutex) {
return K_NULL;
}
tos_mutex_create(mutex);
return (void *)mutex;
}
__QCLOUD_OSAL__ void osal_mutex_destroy(void *mutex)
{
k_err_t ret;
if (K_ERR_NONE != (ret = tos_mutex_destroy((k_mutex_t *)mutex))) {
osal_printf("osal_mutex_destroy err, err:%d\n\r", ret);
} else {
osal_free((void *)mutex);
}
}
__QCLOUD_OSAL__ void osal_mutex_lock(void *mutex)
{
k_err_t ret;
if (K_ERR_NONE != (ret = tos_mutex_pend((k_mutex_t *)mutex))) {
osal_printf("osal_mutex_lock err, err:%d\n\r", ret);
}
}
__QCLOUD_OSAL__ int osal_mutex_trylock(void *mutex)
{
k_err_t ret;
if (K_ERR_NONE != (ret = tos_mutex_pend_timed((k_mutex_t *)mutex, 0))) {
osal_printf("osal_mutex_lock err, err:%d\n\r", ret);
return (int)ret;
}
return 0;
}
__QCLOUD_OSAL__ void osal_mutex_unlock(void *mutex)
{
k_err_t ret;
if (K_ERR_NONE != (ret = tos_mutex_post((k_mutex_t *)mutex))) {
osal_printf("osal_mutex_unlock err, err:%d\n\r", ret);
}
}
__QCLOUD_OSAL__ void *osal_malloc(uint32_t size)
{
return tos_mmheap_alloc(size);
}
__QCLOUD_OSAL__ void osal_free(void *ptr)
{
tos_mmheap_free(ptr);
}
__QCLOUD_OSAL__ void osal_sleep_ms(uint32_t ms)
{
(void)tos_sleep_hmsm(0,0,0, ms);
}

View File

@@ -1,91 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 <stdio.h>
#include <string.h>
#include "tos_k.h"
#include "sal_module_wrapper.h"
#include "qcloud.h"
#define PORT_BUFF_LEN 16
__QCLOUD_OSAL__ int osal_tcp_connect(const char *host, uint16_t port)
{
int fd;
char port_str[PORT_BUFF_LEN];
memset(port_str, 0, PORT_BUFF_LEN);
snprintf(port_str, PORT_BUFF_LEN, "%u", port);
QCLOUD_LOG_I("osal_tcp_connect entry, host=%s port=%d(%s)", host , port, port_str);
fd = tos_sal_module_connect(host, port_str, TOS_SAL_PROTO_TCP);
if (fd < 0) {
QCLOUD_LOG_I("net connect fail\n\r");
if (QCLOUD_ERR_SUCCESS == tos_sal_module_init()) {
QCLOUD_LOG_I("net reinit success\n\r");
fd = tos_sal_module_connect(host, port_str, TOS_SAL_PROTO_TCP);
if (fd < 0) {
QCLOUD_LOG_I("net connect fail\n\r");
return NULL;
} else {
QCLOUD_LOG_I("net connect success, fd=%d\n\r", fd);
}
} else {
QCLOUD_LOG_I("net reinit fail\n\r");
return NULL;
}
}
return fd;
}
__QCLOUD_OSAL__ int osal_tcp_disconnect(int fd)
{
(void)tos_sal_module_close(fd);
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_OSAL__ qcloud_err_t osal_tcp_write(int fd, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
int ret;
ret = tos_sal_module_send(fd, buf, len);
if (ret < 0) {
return QCLOUD_ERR_TCP_WRITE_FAIL;
}
(*(int *)write_len) = ret;
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_OSAL__ qcloud_err_t osal_tcp_read(int fd, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
int ret;
ret = tos_sal_module_recv_timeout(fd, buf, len, timeout);
if (ret < 0) {
return QCLOUD_ERR_TCP_READ_FAIL;
}
if (ret == 0) {
return QCLOUD_ERR_TCP_NOTHING_TO_READ;
}
(*(int *)read_len) = ret;
return QCLOUD_ERR_SUCCESS;
}

View File

@@ -1,234 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 <stdio.h>
#include <string.h>
#include "tos_k.h"
#include "qcloud.h"
#include "lwip/api.h"
#include "lwip/sockets.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
__QCLOUD_OSAL__ int osal_tcp_connect(const char *host, uint16_t port)
{
int ret;
int fd = 0;
char port_str[6];
struct addrinfo hints, *addr_list, *cur;
osal_snprintf(port_str, 6, "%d", port);
memset(&hints, 0x00, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
ret = getaddrinfo(host, port_str, &hints, &addr_list);
if (ret) {
QCLOUD_LOG_E("getaddrinfo(%s:%s) error: %s", host, port_str, strerror(errno));
return -1;
}
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (fd < 0) {
ret = -1;
continue;
}
if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
ret = fd;
break;
}
close(fd);
ret = -1;
}
if (ret == -1) {
QCLOUD_LOG_E("fail to connect: %s:%s", host, port_str);
}
freeaddrinfo(addr_list);
return ret;
}
__QCLOUD_OSAL__ int osal_tcp_disconnect(int fd)
{
int rc;
/* Shutdown both send and receive operations. */
rc = shutdown(fd, 2);
if (rc != 0) {
QCLOUD_LOG_E("shutdown error: %s", strerror(errno));
return -1;
}
rc = close(fd);
if (rc != 0) {
QCLOUD_LOG_E("closesocket error: %s", strerror(errno));
return -1;
}
return 0;
}
__QCLOUD_OSAL__ qcloud_err_t osal_tcp_write(int fd, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
int ret;
qcloud_err_t rc = QCLOUD_ERR_SUCCESS;
uint32_t len_sent = 0;
fd_set sets;
uint32_t time_remain;
osal_timer_t timer;
struct timeval tv;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, timeout);
do {
if (osal_timer_is_expired(&timer)) {
rc = QCLOUD_ERR_TCP_WRITE_TIMEOUT;
break;
}
time_remain = osal_timer_remain(&timer);
tv.tv_sec = time_remain / 1000;
tv.tv_usec = (time_remain % 1000) * 1000;
FD_ZERO(&sets);
FD_SET(fd, &sets);
ret = select(fd + 1, NULL, &sets, NULL, &tv);
if (ret > 0) {
if (FD_ISSET(fd, &sets) == 0) {
QCLOUD_LOG_E("Should NOT arrive");
/* If timeout in next loop, it will not sent any data */
rc = QCLOUD_ERR_TCP_NOTHING_TO_READ;
continue;
}
} else if (ret == 0) {
rc = QCLOUD_ERR_TCP_WRITE_TIMEOUT;
QCLOUD_LOG_E("select-write timeout %d", fd);
break;
} else {
if (errno == EINTR) {
QCLOUD_LOG_E("EINTR be caught");
continue;
}
rc = QCLOUD_ERR_TCP_WRITE_FAIL;
QCLOUD_LOG_E("select-write fail: %s", strerror(errno));
break;
}
ret = send(fd, (uint8_t *)buf + len_sent, len - len_sent, 0);
if (ret > 0) {
len_sent += ret;
} else if (ret == 0) {
QCLOUD_LOG_E("No data be sent. Should NOT arrive");
} else {
if (errno == EINTR) {
QCLOUD_LOG_E("EINTR be caught");
continue;
}
ret = QCLOUD_ERR_TCP_WRITE_FAIL;
QCLOUD_LOG_E("send fail: %s", strerror(errno));
break;
}
} while (len_sent < len);
*write_len = (size_t)len_sent;
return len_sent > 0 ? QCLOUD_ERR_SUCCESS : rc;
}
__QCLOUD_OSAL__ qcloud_err_t osal_tcp_read(int fd, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
int ret;
qcloud_err_t rc = QCLOUD_ERR_SUCCESS;
uint32_t len_recv = 0;
uint32_t time_remain;
fd_set sets;
struct timeval tv;
osal_timer_t timer;
struct sockaddr_in peer;
socklen_t sLen = sizeof(peer);
int peer_port = 0;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, timeout);
do {
if (osal_timer_is_expired(&timer)) {
rc = QCLOUD_ERR_TCP_READ_TIMEOUT;
break;
}
time_remain = osal_timer_remain(&timer);
tv.tv_sec = time_remain / 1000;
tv.tv_usec = (time_remain % 1000) * 1000;
FD_ZERO(&sets);
FD_SET(fd, &sets);
ret = select(fd + 1, &sets, NULL, NULL, &tv);
if (ret > 0) {
ret = recv(fd, (uint8_t *)buf + len_recv, len - len_recv, 0);
if (ret > 0) {
len_recv += ret;
} else if (ret == 0) {
getpeername(fd, (struct sockaddr*)&peer, &sLen);
peer_port = ntohs(peer.sin_port);
QCLOUD_LOG_E("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port);
rc = QCLOUD_ERR_TCP_PEER_SHUTDOWN;
break;
} else {
if (EINTR == errno) {
QCLOUD_LOG_E("EINTR be caught");
continue;
}
QCLOUD_LOG_E("recv error: %s", strerror(errno));
rc = QCLOUD_ERR_TCP_READ_FAIL;
break;
}
} else if (ret == 0) {
rc = QCLOUD_ERR_TCP_READ_TIMEOUT;
break;
} else {
QCLOUD_LOG_E("select-recv error: %s", strerror(errno));
rc = QCLOUD_ERR_TCP_READ_FAIL;
break;
}
} while ((len_recv < len));
*read_len = (size_t)len_recv;
if (rc == QCLOUD_ERR_TCP_READ_TIMEOUT && len_recv == 0) {
rc = QCLOUD_ERR_TCP_NOTHING_TO_READ;
}
return (len == len_recv) ? QCLOUD_ERR_SUCCESS : rc;
}

View File

@@ -1,93 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <tos_k.h>
#include <string.h>
#include "tos_k.h"
#include "qcloud.h"
static char now_time_str[20] = {0};
__QCLOUD_OSAL__ uint32_t osal_uptime_ms(void)
{
#if (TOS_CFG_CPU_TICK_PER_SECOND == 1000)
return (uint32_t)tos_systick_get();
#else
k_tick_t tick = 0u;
tick = tos_systick_get() * 1000;
return (uint32_t)((tick + TOS_CFG_CPU_TICK_PER_SECOND - 1) / TOS_CFG_CPU_TICK_PER_SECOND);
#endif
}
__QCLOUD_OSAL__ long osal_timer_current_sec(void)
{
return osal_uptime_ms() / 1000 + 50 * 365 * 24 * 3600; // 100 years
}
__QCLOUD_OSAL__ char *osal_timer_current(void)
{
long time_sec;
time_sec = osal_timer_current_sec();
memset(now_time_str, 0, 20);
snprintf(now_time_str, 20, "%d",time_sec);
return now_time_str;
}
__QCLOUD_OSAL__ int osal_timer_is_expired(osal_timer_t *timer)
{
return osal_uptime_ms() > timer->end_time ? 1 : 0;
}
__QCLOUD_OSAL__ void osal_timer_countdown_ms(osal_timer_t *timer, uint32_t timeout)
{
timer->end_time = osal_uptime_ms();
timer->end_time += timeout;
}
__QCLOUD_OSAL__ void osal_timer_countdown(osal_timer_t *timer, uint32_t timeout)
{
timer->end_time = osal_uptime_ms();
timer->end_time += timeout * 1000;
}
__QCLOUD_OSAL__ uint32_t osal_timer_remain(osal_timer_t *timer)
{
uint32_t now;
now = osal_uptime_ms();
if (timer->end_time <= now) {
return 0;
}
return timer->end_time - now;
}
__QCLOUD_OSAL__ void osal_timer_init(osal_timer_t *timer)
{
timer->end_time = 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,438 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 <stdint.h>
#include <string.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "tos_k.h"
#include "qcloud.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#define DEBUG_LEVEL 0
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_KEY)
static const int ciphersuites[] = {MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0};
#endif
/**
* @brief 用于保存SSL连接相关数据结构
*/
typedef struct tls_paramter_st {
mbedtls_net_context socket_fd; // socket文件描述符
mbedtls_entropy_context entropy; // 保存熵配置
mbedtls_ctr_drbg_context ctr_drbg; // 随机数生成器
mbedtls_ssl_context ssl; // 保存SSL基本数据
mbedtls_ssl_config ssl_conf; // TSL/TLS配置信息
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt ca_cert; // ca证书信息
mbedtls_x509_crt client_cert; // 客户端证书信息
#endif
mbedtls_pk_context private_key; // 客户端私钥信息
} tls_param_t;
/**
* @brief 释放mbedtls开辟的内存
*/
static void mbedtls_tls_param_free(tls_param_t *tls_paramter)
{
mbedtls_net_free(&tls_paramter->socket_fd);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt_free(&tls_paramter->client_cert);
mbedtls_x509_crt_free(&tls_paramter->ca_cert);
mbedtls_pk_free(&tls_paramter->private_key);
#endif
mbedtls_ssl_free(&tls_paramter->ssl);
mbedtls_ssl_config_free(&tls_paramter->ssl_conf);
mbedtls_ctr_drbg_free(&tls_paramter->ctr_drbg);
mbedtls_entropy_free(&tls_paramter->entropy);
osal_free(tls_paramter);
}
/**
* @brief mbedtls库初始化
*
* 1. 执行mbedtls库相关初始化函数
* 2. 随机数生成器
* 3. 加载CA证书, 客户端证书及私钥文件/设置psk
*
* @param pDataParams TLS连接相关数据结构
* @param pConnectParams TLS证书密钥相关
* @return 返回QCLOUD_ERR_SUCCESS, 表示成功
*/
static void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str)
{
QCLOUD_LOG_I("[mbedTLS]:[%s]:[%d]: %s\r\n", file, line, str);
}
static int mbedtls_client_init(tls_param_t *tls_param, qcloud_tls_opt_t *tls_opt)
{
int ret = QCLOUD_ERR_SUCCESS;
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif
mbedtls_net_init(&tls_param->socket_fd);
mbedtls_ssl_init(&tls_param->ssl);
mbedtls_ssl_config_init(&tls_param->ssl_conf);
mbedtls_ctr_drbg_init(&tls_param->ctr_drbg);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt_init(&tls_param->ca_cert);
mbedtls_x509_crt_init(&tls_param->client_cert);
mbedtls_pk_init(&tls_param->private_key);
#endif
mbedtls_entropy_init(&tls_param->entropy);
mbedtls_ssl_conf_dbg(&tls_param->ssl_conf, mbedtls_debug, NULL);
// 随机数, 增加custom参数, 目前为NULL
if ((ret = mbedtls_ctr_drbg_seed(&tls_param->ctr_drbg, mbedtls_entropy_func,
&tls_param->entropy, NULL, 0)) != 0) {
QCLOUD_LOG_E("mbedtls_ctr_drbg_seed failed returned -0x%04x", -ret);
return QCLOUD_ERR_SSL_INIT;
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if (tls_opt->ca_cert != NULL) {
if ((ret = mbedtls_x509_crt_parse(&tls_param->ca_cert, (const unsigned char *)tls_opt->ca_cert,
(tls_opt->ca_cert_len + 1)))) {
QCLOUD_LOG_E("parse ca crt failed returned -0x%04x", -ret);
return QCLOUD_ERR_SSL_CERT;
}
}
#endif
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
if (tls_opt->cert_path != NULL && tls_opt->priv_key_path != NULL) {
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if ((ret = mbedtls_x509_crt_parse_file(&tls_param->client_cert, tls_opt->cert_path)) != 0) {
QCLOUD_LOG_E("load client cert file failed returned 0x%x", ret<0?-ret:ret);
return QCLOUD_ERR_SSL_CERT;
}
#endif
if ((ret = mbedtls_pk_parse_keyfile(&tls_param->private_key, tls_opt->priv_key_path, "")) != 0) {
QCLOUD_LOG_E("load client key file failed returned 0x%x", ret < 0 ? -ret : ret);
return QCLOUD_ERR_SSL_CERT;
}
} else {
QCLOUD_LOG_E("cert_file/key_file is empty!|cert_file=%s|key_file=%s", tls_opt->cert_path, tls_opt->priv_key_path);
}
#else
if (tls_opt->psk != NULL && tls_opt->psk_id != NULL) {
const char *psk_id = tls_opt->psk_id;
ret = mbedtls_ssl_conf_psk(&tls_param->ssl_conf, (unsigned char *)tls_opt->psk, tls_opt->psk_len,
(const unsigned char *)psk_id, strlen(psk_id));
} else {
QCLOUD_LOG_D("psk/pskid is empty!|psk=%s|psd_id=%s", tls_opt->psk, tls_opt->psk_id);
}
if (0 != ret) {
QCLOUD_LOG_E("mbedtls_ssl_conf_psk fail: -0x%x", -ret);
return ret;
}
#endif
return QCLOUD_ERR_SUCCESS;
}
/**
* @brief 建立TCP连接
*
* @param socket_fd Socket描述符
* @param host 服务器主机名
* @param port 服务器端口地址
* @return 返回QCLOUD_ERR_SUCCESS, 表示成功
*/
int mbedtls_tcp_connect(mbedtls_net_context *socket_fd, const char *host, int port)
{
int ret = 0;
char port_str[6];
osal_snprintf(port_str, 6, "%d", port);
if ((ret = mbedtls_net_connect(socket_fd, host, port_str, MBEDTLS_NET_PROTO_TCP)) != 0) {
QCLOUD_LOG_E("tcp connect failed returned -0x%04x", -ret);
switch (ret) {
case MBEDTLS_ERR_NET_SOCKET_FAILED:
return QCLOUD_ERR_TCP_SOCKET_FAILED;
case MBEDTLS_ERR_NET_UNKNOWN_HOST:
return QCLOUD_ERR_TCP_UNKNOWN_HOST;
default:
return QCLOUD_ERR_TCP_CONNECT;
}
}
#if 0
if ((ret = mbedtls_net_set_block(socket_fd)) != 0) {
QCLOUD_LOG_E("set block faliled returned -0x%04x", -ret);
return QCLOUD_ERR_TCP_CONNECT;
}
#endif
return QCLOUD_ERR_SUCCESS;
}
/**
* @brief 在该函数中可对服务端证书进行自定义的校验
*
* 这种行为发生在握手过程中, 一般是校验连接服务器的主机名与服务器证书中的CN或SAN的域名信息是否一致
* 不过, mbedtls库已经实现该功能, 可以参考函数 `mbedtls_x509_crt_verify_with_profile`
*
* @param hostname 连接服务器的主机名
* @param crt x509格式的证书
* @param depth
* @param flags
* @return
*/
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static int qcloud_server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
{
return *flags;
}
#endif
__QCLOUD_OSAL__ void *osal_tls_connect(qcloud_tls_opt_t *tls_opt, const char *host, int port)
{
int ret = 0;
tls_param_t *tls_param = NULL;
if (!tls_opt) {
return NULL;
}
tls_param = (tls_param_t *)osal_malloc(sizeof(tls_param_t));
if (!tls_param) {
return NULL;
}
if ((ret = mbedtls_client_init(tls_param, tls_opt)) != QCLOUD_ERR_SUCCESS) {
goto error;
}
QCLOUD_LOG_D(" Connecting to /%s/%d...", host, port);
if ((ret = mbedtls_tcp_connect(&tls_param->socket_fd, host, port)) != QCLOUD_ERR_SUCCESS) {
goto error;
}
QCLOUD_LOG_D(" Setting up the SSL/TLS structure...");
if ((ret = mbedtls_ssl_config_defaults(&tls_param->ssl_conf, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_config_defaults failed returned -0x%04x", -ret);
goto error;
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_ssl_conf_verify(&tls_param->ssl_conf, qcloud_server_certificate_verify, (void *)host);
mbedtls_ssl_conf_authmode(&tls_param->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
#endif
mbedtls_ssl_conf_rng(&tls_param->ssl_conf, mbedtls_ctr_drbg_random, &tls_param->ctr_drbg);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_ssl_conf_ca_chain(&tls_param->ssl_conf, &tls_param->ca_cert, NULL);
if ((ret = mbedtls_ssl_conf_own_cert(&tls_param->ssl_conf,
&tls_param->client_cert, &tls_param->private_key)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_conf_own_cert failed returned 0x%04x", -ret);
goto error;
}
#endif
mbedtls_ssl_conf_read_timeout(&tls_param->ssl_conf, tls_opt->timeout);
if ((ret = mbedtls_ssl_setup(&tls_param->ssl, &tls_param->ssl_conf)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_setup failed returned 0x%04x", -ret);
goto error;
}
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_KEY)
// 选择加密套件代码,以后不通加密方式合并端口的时候可以用到
if(tls_opt->psk != NULL) {
mbedtls_ssl_conf_ciphersuites(&tls_param->ssl_conf, ciphersuites);
}
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
// Set the hostname to check against the received server certificate and sni
if ((ret = mbedtls_ssl_set_hostname(&tls_param->ssl, host)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_set_hostname failed returned 0x%04x", -ret);
goto error;
}
#endif
mbedtls_ssl_set_bio(&tls_param->ssl, &tls_param->socket_fd, mbedtls_net_send, mbedtls_net_recv,
mbedtls_net_recv_timeout);
QCLOUD_LOG_D("Performing the SSL/TLS handshake...");
while ((ret = mbedtls_ssl_handshake(&tls_param->ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
QCLOUD_LOG_E("mbedtls_ssl_handshake failed returned 0x%04x", -ret);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
QCLOUD_LOG_E("Unable to verify the server's certificate");
}
#endif
goto error;
}
}
if ((ret = mbedtls_ssl_get_verify_result(&tls_param->ssl)) != 0) {
QCLOUD_LOG_E("mbedtls_ssl_get_verify_result failed returned 0x%04x", -ret);
goto error;
}
mbedtls_ssl_conf_read_timeout(&tls_param->ssl_conf, 100);
return tls_param;
error:
mbedtls_tls_param_free(tls_param);
return NULL;
}
__QCLOUD_OSAL__ void osal_tls_disconnect(void *handle)
{
int ret = 0;
tls_param_t *tls_param;
if (!handle) {
QCLOUD_LOG_D("handle is NULL");
return;
}
tls_param = (tls_param_t *)handle;
do {
ret = mbedtls_ssl_close_notify(&tls_param->ssl);
} while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE);
mbedtls_tls_param_free(tls_param);
}
__QCLOUD_OSAL__ qcloud_err_t osal_tls_write(void *handle, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
QCLOUD_POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(write_len, QCLOUD_ERR_INVAL);
osal_timer_t timer;
tls_param_t *tls_param;
int error = QCLOUD_FALSE;
int write_rc = 0;
size_t written_so_far;
tls_param = (tls_param_t *)handle;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, timeout);
for (written_so_far = 0; written_so_far < len && !osal_timer_is_expired(&timer); written_so_far += write_rc) {
while (!osal_timer_is_expired(&timer) &&
(write_rc = mbedtls_ssl_write(&tls_param->ssl, (uint8_t *)buf + written_so_far, len - written_so_far)) <= 0) {
if (write_rc != MBEDTLS_ERR_SSL_WANT_READ && write_rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
QCLOUD_LOG_E("tls_write failed 0x%04x", -write_rc);
error = QCLOUD_TRUE;
break;
}
}
if (error) {
break;
}
}
*write_len = written_so_far;
if (error) {
return QCLOUD_ERR_SSL_WRITE;
} else if (osal_timer_is_expired(&timer) && written_so_far != len) {
return QCLOUD_ERR_SSL_WRITE_TIMEOUT;
}
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_OSAL__ qcloud_err_t osal_tls_read(void *handle, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
//mbedtls_ssl_conf_read_timeout(&(pParams->ssl_conf), timeout_ms); TODO:每次调用这个方法会导致read阻塞, 超时也不返回
// 这里使用非阻塞的方式, 具体的超时操作由上层做
QCLOUD_POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(read_len, QCLOUD_ERR_INVAL);
osal_timer_t timer;
tls_param_t *tls_param = NULL;
*read_len = 0;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, timeout);
tls_param = (tls_param_t *)handle;
do {
int read_rc = 0;
read_rc = mbedtls_ssl_read(&tls_param->ssl, (uint8_t *)buf + *read_len, len - *read_len);
if (read_rc > 0) {
*read_len += read_rc;
} else if (read_rc == 0 ||
(read_rc != MBEDTLS_ERR_SSL_WANT_WRITE &&
read_rc != MBEDTLS_ERR_SSL_WANT_READ &&
read_rc != MBEDTLS_ERR_SSL_TIMEOUT)) {
QCLOUD_LOG_E("tls_read failed: 0x%04x", -read_rc);
return QCLOUD_ERR_SSL_READ;
}
if (osal_timer_is_expired(&timer)) {
break;
}
} while (*read_len < len);
if (len == *read_len) {
return QCLOUD_ERR_SUCCESS;
}
if (*read_len == 0) {
return QCLOUD_ERR_SSL_NOTHING_TO_READ;
} else {
return QCLOUD_ERR_SSL_READ_TIMEOUT;
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,92 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 <stdio.h>
#include <string.h>
#include "tos_k.h"
#include "sal_module_wrapper.h"
#include "qcloud.h"
#define PORT_BUFF_LEN 16
__QCLOUD_OSAL__ int osal_udp_connect(const char *host, uint16_t port)
{
int fd;
char port_str[PORT_BUFF_LEN];
memset(port_str, 0, PORT_BUFF_LEN);
snprintf(port_str, PORT_BUFF_LEN, "%u", port);
QCLOUD_LOG_I("osal_udp_connect entry, host=%s port=%d(%s)", host , port, port_str);
fd = tos_sal_module_connect("111.230.127.136", "5684", TOS_SAL_PROTO_UDP);
if (fd < 0) {
QCLOUD_LOG_I("net connect fail\n\r");
if (QCLOUD_ERR_SUCCESS == tos_sal_module_init()) { /* ÖØÐ³õʼ»¯Ä£×é */
QCLOUD_LOG_I("net reinit success\n\r");
fd = tos_sal_module_connect(host, port_str, TOS_SAL_PROTO_UDP);
if (fd < 0) {
QCLOUD_LOG_I("net connect fail\n\r");
return NULL;
} else {
QCLOUD_LOG_I("net connect success, fd=%d\n\r", fd);
}
} else {
QCLOUD_LOG_I("net reinit fail\n\r");
return NULL;
}
}
return fd;
}
__QCLOUD_OSAL__ void osal_udp_disconnect(int sockfd)
{
(void)tos_sal_module_close(sockfd);
}
__QCLOUD_OSAL__ qcloud_err_t osal_udp_write(int sockfd, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
int ret;
ret = tos_sal_module_sendto(sockfd, NULL, NULL, buf, len);
if (ret < 0) {
return QCLOUD_ERR_UDP_WRITE_FAIL;
}
(*(int *)write_len) = ret;
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_OSAL__ qcloud_err_t osal_udp_read(int sockfd, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
int ret;
QCLOUD_LOG_I("osal_udp_read len %d timeout %d\r\n", len, timeout);
ret = tos_sal_module_recvfrom_timeout(sockfd, buf, len, timeout);
if (ret < 0) {
return QCLOUD_ERR_UDP_READ_FAIL;
}
if (ret == 0) {
return QCLOUD_ERR_UDP_NOTHING_TO_READ;
}
*(int *)read_len = ret;
return QCLOUD_ERR_SUCCESS;
}

View File

@@ -1,130 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 <stdio.h>
#include <string.h>
#include "tos_k.h"
#include "qcloud.h"
#include "lwip/api.h"
#include "lwip/sockets.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
__QCLOUD_OSAL__ int osal_udp_connect(const char *host, uint16_t port)
{
#define NETWORK_ADDR_LEN (16)
int ret;
int fd = 0;
char port_str[6] = {0};
struct addrinfo hints, *addr_list, *cur;
osal_snprintf(port_str, 6, "%d", port);
memset((char *)&hints, 0x00, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_UDP;
QCLOUD_LOG_D("establish udp connection with server(host=%s port=%s)", host, port_str);
if (getaddrinfo(host, port_str, &hints, &addr_list) != 0) {
QCLOUD_LOG_E("getaddrinfo error,errno:%s", strerror(errno));
return 0;
}
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (fd < 0) {
ret = 0;
continue;
}
if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
ret = fd;
break;
}
close(fd);
ret = 0;
}
if (ret == 0) {
QCLOUD_LOG_E("fail to establish udp");
} else {
QCLOUD_LOG_D("success to establish udp, fd=%d", ret);
}
freeaddrinfo(addr_list);
return fd;
}
__QCLOUD_OSAL__ void osal_udp_disconnect(int sockfd)
{
close(sockfd);
}
__QCLOUD_OSAL__ qcloud_err_t osal_udp_write(int sockfd, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
int ret;
ret = send(sockfd, (char *)buf, (int)len, 0);
if (ret < 0) {
return QCLOUD_ERR_UDP_WRITE_FAIL;
}
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_OSAL__ qcloud_err_t osal_udp_read(int sockfd, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
int ret;
struct timeval tv;
fd_set read_fds;
if (sockfd < 0) {
return QCLOUD_ERR_UDP_READ_FAIL;
}
FD_ZERO(&read_fds);
FD_SET(sockfd, &read_fds);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ret = select(sockfd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
/* Zero fds ready means we timed out */
if (ret == 0) {
return QCLOUD_ERR_UDP_READ_TIMEOUT; /* receive timeout */
} else if (ret < 0) {
if (errno == EINTR) {
return QCLOUD_ERR_UDP_READ_FAIL; /* want read */
}
return QCLOUD_ERR_UDP_READ_TIMEOUT; /* receive failed */
}
ret = read(sockfd, buf, len);
if (ret > 0) {
return QCLOUD_ERR_SUCCESS;
} else {
return QCLOUD_ERR_UDP_READ_FAIL;
}
}

View File

@@ -1,62 +0,0 @@
#include "qcloud.h"
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
__QCLOUD_API__ qcloud_err_t qcloud_device_create(qcloud_device_t *device,
const char *product_id,
const char *device_name,
const char *cert_path,
const char *priv_key_path)
{
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_DEV_INFO);
QCLOUD_POINTER_SANITY_CHECK(product_id, QCLOUD_ERR_DEV_INFO);
QCLOUD_POINTER_SANITY_CHECK(device_name, QCLOUD_ERR_DEV_INFO);
QCLOUD_POINTER_SANITY_CHECK(cert_path, QCLOUD_ERR_DEV_INFO);
QCLOUD_POINTER_SANITY_CHECK(priv_key_path, QCLOUD_ERR_DEV_INFO);
if (strlen(product_id) > QCLOUD_DEVICE_PRODUCT_ID_MAX ||
strlen(device_name) > QCLOUD_DEVICE_DEVICE_NAME_MAX ||
strlen(cert_path) > QCLOUD_PATH_MAX ||
strlen(priv_key_path) > QCLOUD_PATH_MAX) {
return QCLOUD_ERR_DEV_INFO;
}
device->product_id = product_id;
device->device_name = device_name;
device->cert_path = cert_path;
device->priv_key_path = priv_key_path;
QCLOUD_LOG_I("SDK version: %s, product ID: %s, device name: %s", QCLOUD_SDK_VERSION, product_id, device_name);
return QCLOUD_ERR_SUCCESS;
}
#else
__QCLOUD_API__ qcloud_err_t qcloud_device_create(qcloud_device_t *device,
const char *product_id,
const char *device_name,
const char *key)
{
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_DEV_INFO);
QCLOUD_POINTER_SANITY_CHECK(product_id, QCLOUD_ERR_DEV_INFO);
QCLOUD_POINTER_SANITY_CHECK(device_name, QCLOUD_ERR_DEV_INFO);
QCLOUD_POINTER_SANITY_CHECK(key, QCLOUD_ERR_DEV_INFO);
if (strlen(product_id) > QCLOUD_DEVICE_PRODUCT_ID_MAX ||
strlen(device_name) > QCLOUD_DEVICE_DEVICE_NAME_MAX ||
strlen(key) > QCLOUD_DEVICE_KEY_MAX) {
return QCLOUD_ERR_DEV_INFO;
}
device->product_id = product_id;
device->device_name = device_name;
device->key = key;
QCLOUD_LOG_I("SDK version: %s, product ID: %s, device name: %s", QCLOUD_SDK_VERSION, product_id, device_name);
return QCLOUD_ERR_SUCCESS;
}
#endif

View File

@@ -1,55 +0,0 @@
#include "qcloud.h"
static const char *level_str[] = {
"DIS", "ERR", "WRN", "INF", "DBG"
};
static qcloud_log_handler_t sg_log_message_handler= NULL;
__QCLOUD_STATIC__ const char *file_path2name(const char *file_path)
{
const char *suffix = NULL;
suffix = strrchr(file_path, '\\');
if (!suffix) {
return file_path;
}
return ++suffix;
}
void qcloud_log_handler_set(qcloud_log_handler_t handler)
{
sg_log_message_handler = handler;
}
void qcloud_log_write(const char *file, const char *func, const int line, const int level, const char *fmt, ...)
{
/* format log content */
const char *file_name = file_path2name(file);
char sg_text_buf[QCLOUD_LOG_LEN_MAX + 1];
char *tmp_buf = sg_text_buf;
char *o = tmp_buf;
memset(tmp_buf, 0, sizeof(sg_text_buf));
o += osal_snprintf(o, sizeof(sg_text_buf), "%s|%s|%s|%s(%d): ", level_str[level], osal_timer_current(), file_name, func, line);
va_list ap;
va_start(ap, fmt);
o += vsnprintf(o, QCLOUD_LOG_LEN_MAX - 2 - strlen(tmp_buf), fmt, ap);
va_end(ap);
strcat(tmp_buf, "\r\n");
/* customer defined log print handler */
if (sg_log_message_handler != NULL && sg_log_message_handler(tmp_buf)) {
return;
}
/* default log handler: print to console */
osal_printf("%s", tmp_buf);
return;
}

View File

@@ -1,135 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 "qcloud.h"
__QCLOUD_STATIC__ int qcloud_network_tcp_is_connected(qcloud_network_t *network)
{
return network->fd >= 0;
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_network_tcp_read(qcloud_network_t *network, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(read_len, QCLOUD_ERR_INVAL);
return osal_tcp_read(network->fd, buf, len, timeout, read_len);
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_network_tcp_write(qcloud_network_t *network, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(write_len, QCLOUD_ERR_INVAL);
return osal_tcp_write(network->fd, buf, len, timeout, write_len);
}
__QCLOUD_STATIC__ void qcloud_network_tcp_disconnect(qcloud_network_t *network)
{
if (!network || network->fd < 0) {
return;
}
osal_tcp_disconnect(network->fd);
network->fd = -1;
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_network_tcp_connect(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->fd = osal_tcp_connect(network->host, network->port);
if (network->fd >= 0) {
return QCLOUD_ERR_SUCCESS;
}
return QCLOUD_ERR_FAILURE;
}
__QCLOUD_API__ qcloud_err_t qcloud_network_tcp_init(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->connect = qcloud_network_tcp_connect;
network->read = qcloud_network_tcp_read;
network->write = qcloud_network_tcp_write;
network->disconnect = qcloud_network_tcp_disconnect;
network->is_connected = qcloud_network_tcp_is_connected;
network->fd = -1;
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_STATIC__ int qcloud_network_udp_is_connected(qcloud_network_t *network)
{
return network->fd >= 0;
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_network_udp_read(qcloud_network_t *network, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(read_len, QCLOUD_ERR_INVAL);
return osal_udp_read(network->fd, buf, len, timeout, read_len);
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_network_udp_write(qcloud_network_t *network, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(write_len, QCLOUD_ERR_INVAL);
return osal_udp_write(network->fd, buf, len, timeout, write_len);
}
__QCLOUD_STATIC__ void qcloud_network_udp_disconnect(qcloud_network_t *network)
{
if (!network || network->fd < 0) {
return;
}
osal_udp_disconnect(network->fd);
network->fd = -1;
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_network_udp_connect(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->fd = osal_udp_connect(network->host, network->port);
if (network->fd >= 0) {
return QCLOUD_ERR_SUCCESS;
}
return QCLOUD_ERR_FAILURE;
}
__QCLOUD_API__ qcloud_err_t qcloud_network_udp_init(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->connect = qcloud_network_udp_connect;
network->read = qcloud_network_udp_read;
network->write = qcloud_network_udp_write;
network->disconnect = qcloud_network_udp_disconnect;
network->is_connected = qcloud_network_udp_is_connected;
network->fd = -1;
return QCLOUD_ERR_SUCCESS;
}

View File

@@ -1,198 +0,0 @@
#include "qcloud.h"
#if (QCLOUD_CFG_TLS_EN > 0u)
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
__QCLOUD_STATIC__ qcloud_err_t qcloud_tls_init_with_cert(qcloud_tls_opt_t *tls_opt, qcloud_device_t *device)
{
if (!device->cert_path || !device->priv_key_path) {
QCLOUD_LOG_E("cert file or key file is empty!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
QCLOUD_LOG_D("cert path: %s", device->cert_path);
QCLOUD_LOG_D("priv key path: %s", device->priv_key_path);
tls_opt->cert_path = device->cert_path;
tls_opt->priv_key_path = device->priv_key_path;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
#else
__QCLOUD_STATIC__ qcloud_err_t qcloud_tls_psk_id_generate(qcloud_tls_opt_t *tls_opt, qcloud_device_t *device)
{
int psk_id_len = 0;
memset(tls_opt->psk_id, 0, sizeof(tls_opt->psk_id));
psk_id_len = osal_snprintf(tls_opt->psk_id, QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX, "%s%s", device->product_id, device->device_name);
if (psk_id_len < 0 || psk_id_len >= QCLOUD_MQTT_DEVICE_CLIENT_ID_MAX) {
QCLOUD_LOG_E("psk id generate failed");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_DEV_INFO);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_tls_psk_generate(qcloud_tls_opt_t *tls_opt, qcloud_device_t *device)
{
size_t key_len = 0, decoded_psk_len;
if (!device->key) {
QCLOUD_LOG_E("device key NULL!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
memset(tls_opt->psk, 0, sizeof(tls_opt->psk));
key_len = strlen(device->key);
if (qcloud_utils_base64_decode(tls_opt->psk, sizeof(tls_opt->psk), &decoded_psk_len,
(const unsigned char *)device->key, key_len) != 0) {
QCLOUD_LOG_E("psk decode failed!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
tls_opt->psk_len = decoded_psk_len;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_tls_init_with_key(qcloud_tls_opt_t *tls_opt, qcloud_device_t *device)
{
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_tls_psk_generate(tls_opt, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_tls_psk_id_generate(tls_opt, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
#endif
__QCLOUD_INTERNAL__ qcloud_err_t qcloud_tls_init(qcloud_tls_opt_t *tls_opt, qcloud_device_t *device)
{
#if (QCLOUD_CFG_AUTH_MODE == QCLOUD_AUTH_MODE_CERT)
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_tls_init_with_cert(tls_opt, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#else
QCLOUD_FUNC_EXIT_RC_IF_NOT(qcloud_tls_init_with_key(tls_opt, device), QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
#endif
tls_opt->ca_cert = qcloud_ca_cert;
tls_opt->ca_cert_len = strlen(tls_opt->ca_cert);
tls_opt->handle = NULL;
tls_opt->timeout = QCLOUD_TLS_HANDSHAKE_TIMEOUT;
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_tls_connect(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->tls_opt.handle = osal_tls_connect(&(network->tls_opt), network->host, network->port);
if (network->tls_opt.handle) {
return QCLOUD_ERR_SUCCESS;
}
return QCLOUD_ERR_FAILURE;
}
__QCLOUD_STATIC__ void qcloud_tls_disconnect(qcloud_network_t *network)
{
if (!network || !network->tls_opt.handle) {
return;
}
osal_tls_disconnect(network->tls_opt.handle);
network->tls_opt.handle = NULL;
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_tls_read(qcloud_network_t *network, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
return osal_tls_read(network->tls_opt.handle, buf, len, timeout, read_len);
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_tls_write(qcloud_network_t *network, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
return osal_tls_write(network->tls_opt.handle, buf, len, timeout, write_len);
}
__QCLOUD_STATIC__ int qcloud_tls_is_connected(qcloud_network_t *network)
{
return network->tls_opt.handle != NULL;
}
__QCLOUD_INTERNAL__ qcloud_err_t qcloud_network_tls_init(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->connect = qcloud_tls_connect;
network->read = qcloud_tls_read;
network->write = qcloud_tls_write;
network->disconnect = qcloud_tls_disconnect;
network->is_connected = qcloud_tls_is_connected;
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_INTERNAL__ qcloud_err_t qcloud_dtls_connect(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->tls_opt.handle = osal_dtls_connect(&(network->tls_opt), network->host, network->port);
if (network->tls_opt.handle != 0) {
return QCLOUD_ERR_SUCCESS;
}
return QCLOUD_ERR_FAILURE;
}
__QCLOUD_STATIC__ void qcloud_dtls_disconnect(qcloud_network_t *network)
{
if (!network || !network->tls_opt.handle) {
return;
}
osal_dtls_disconnect(network->tls_opt.handle);
network->tls_opt.handle = NULL;
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_dtls_read(qcloud_network_t *network, void *buf, size_t len, uint32_t timeout, size_t *read_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
return osal_dtls_read(network->tls_opt.handle, buf, len, timeout, read_len);
}
__QCLOUD_STATIC__ qcloud_err_t qcloud_dtls_write(qcloud_network_t *network, const void *buf, size_t len, uint32_t timeout, size_t *write_len)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
return osal_dtls_write(network->tls_opt.handle, buf, len, write_len);
}
__QCLOUD_STATIC__ int qcloud_dtls_is_connected(qcloud_network_t *network)
{
return network->tls_opt.handle != NULL;
}
__QCLOUD_INTERNAL__ qcloud_err_t qcloud_network_dtls_init(qcloud_network_t *network)
{
QCLOUD_POINTER_SANITY_CHECK(network, QCLOUD_ERR_INVAL);
network->connect = qcloud_dtls_connect;
network->read = qcloud_dtls_read;
network->write = qcloud_dtls_write;
network->disconnect = qcloud_dtls_disconnect;
network->is_connected = qcloud_dtls_is_connected;
return QCLOUD_ERR_SUCCESS;
}
#endif

View File

@@ -1,936 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
__QCLOUD_STATIC__ qcloud_err_t shadow_client_construct(qcloud_shadow_client_t *client,
mqtt_event_handler_fn_t handler,
shadow_type_t shadow_type,
qcloud_device_t *device)
{
int topic_len = 0;
client->shadow_type = shadow_type;
client->event_handler.handler = handler;
client->version = 0;
client->token_num = 0;
client->sync_state = QCLOUD_SHADOW_SYNC_STATE_NONE;
client->request_list_counter = 0;
qcloud_list_init(&client->request_list);
qcloud_list_init(&client->property_list);
memset(client->request_topic_subscribe, 0, sizeof(client->request_topic_subscribe));
if (shadow_type == SHADOW_TYPE_TEMPLATE) {
topic_len = osal_snprintf(client->request_topic_subscribe, QCLOUD_MQTT_TOPIC_SIZE_MAX,
"$template/operation/result/%s/%s",
device->product_id, device->device_name);
} else {
topic_len = osal_snprintf(client->request_topic_subscribe, QCLOUD_MQTT_TOPIC_SIZE_MAX,
"$shadow/operation/result/%s/%s",
device->product_id, device->device_name);
}
if (topic_len < 0 || topic_len >= QCLOUD_MQTT_TOPIC_SIZE_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
memset(client->request_topic_publish, 0, sizeof(client->request_topic_publish));
if (shadow_type == SHADOW_TYPE_TEMPLATE) {
topic_len = osal_snprintf(client->request_topic_publish, QCLOUD_MQTT_TOPIC_SIZE_MAX,
"$template/operation/%s/%s",
device->product_id, device->device_name);
} else {
topic_len = osal_snprintf(client->request_topic_publish, QCLOUD_MQTT_TOPIC_SIZE_MAX,
"$shadow/operation/%s/%s",
device->product_id, device->device_name);
}
if (topic_len < 0 || topic_len >= QCLOUD_MQTT_TOPIC_SIZE_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
strncpy(client->device_product_id, device->product_id, sizeof(client->device_product_id));
client->device_product_id[QCLOUD_DEVICE_PRODUCT_ID_MAX] = '\0';
client->global_lock = osal_mutex_create();
if (!client->global_lock) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ void shadow_incoming_msg_handler(void *client, void *context, mqtt_event_t *event)
{
uint16_t packet_id;
mqtt_incoming_msg_t *mqtt_msg;
qcloud_shadow_client_t *shadow_client = NULL;
shadow_client = (qcloud_shadow_client_t *)context;
switch (event->type) {
case MQTT_EVENT_SUBCRIBE_SUCCESS:
packet_id = *(uint16_t *)event->message;
QCLOUD_LOG_D("subscribe success, packet id=%u", (uint32_t)packet_id);
shadow_client->sync_state = QCLOUD_SHADOW_SYNC_STATE_SUCCESS;
break;
case MQTT_EVENT_SUBCRIBE_TIMEOUT:
packet_id = *(uint16_t *)event->message;
QCLOUD_LOG_D("subscribe wait ack timeout, packet id=%u", (uint32_t)packet_id);
shadow_client->sync_state = QCLOUD_SHADOW_SYNC_STATE_TIMEOUT;
break;
case MQTT_EVENT_SUBCRIBE_NACK:
packet_id = *(uint16_t *)event->message;
QCLOUD_LOG_D("subscribe nack, packet id=%u", (uint32_t)packet_id);
shadow_client->sync_state = QCLOUD_SHADOW_SYNC_STATE_NACK;
break;
case MQTT_EVENT_PUBLISH_RECVEIVED:
mqtt_msg = (mqtt_incoming_msg_t *)event->message;
QCLOUD_LOG_D("topic arrived without handler: topic=%.*s, payload=%.*s",
mqtt_msg->topic_len,
mqtt_msg->topic,
mqtt_msg->payload_len,
mqtt_msg->payload);
break;
default:
break;
}
if (shadow_client->event_handler.handler) {
shadow_client->event_handler.handler(shadow_client, shadow_client->event_handler.context, event);
}
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_create(qcloud_shadow_client_t *client,
qcloud_device_t *device,
mqtt_event_handler_fn_t handler,
shadow_type_t shadow_type)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(device, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
memset(client, 0, sizeof(qcloud_shadow_client_t));
rc = qcloud_mqtt_client_create(&client->mqtt_client, device, shadow_incoming_msg_handler, (void *)client, QCLOUD_AUTO_CONN_STATE_ENABLED);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
rc = qcloud_mqtt_connect_opt_create(&client->mqtt_connect_opt, device, MQTT_VERSION_3_1_1, 240, MQTT_CLEAN_SESSION_STATE_ENABLED);
if (rc != QCLOUD_ERR_SUCCESS) {
goto errout;
}
rc = shadow_client_construct(client, handler, shadow_type, device);
if (rc != QCLOUD_ERR_SUCCESS) {
goto errout;
}
rc = qcloud_mqtt_client_connect(&client->mqtt_client, &client->mqtt_connect_opt);
if (rc != QCLOUD_ERR_SUCCESS) {
goto errout;
}
rc = shadow_glue_operation_request_subscribe(client);
if (rc != QCLOUD_ERR_SUCCESS) {
goto errout;
}
client->sync_state = QCLOUD_SHADOW_SYNC_STATE_PENDACK;
while (client->sync_state == QCLOUD_SHADOW_SYNC_STATE_PENDACK) {
qcloud_shadow_client_yield(client, 100);
}
if (client->sync_state != QCLOUD_SHADOW_SYNC_STATE_SUCCESS) {
goto errout;
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
errout:
qcloud_mqtt_client_destroy(&client->mqtt_client);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_yield(qcloud_shadow_client_t *client, uint32_t timeout)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_NUMBERIC_SANITY_CHECK(timeout, QCLOUD_ERR_INVAL);
shadow_glue_request_list_scan(client);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_client_yield(&client->mqtt_client, &client->mqtt_connect_opt, timeout));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_publish(qcloud_shadow_client_t *client, char *topic, mqtt_publish_opt_t *publish_opt)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(topic, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(publish_opt, QCLOUD_ERR_INVAL);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_publish(&client->mqtt_client, topic, publish_opt));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_subscribe(qcloud_shadow_client_t *client, const char *topic_filter, mqtt_subscribe_opt_t *subscribe_opt)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(subscribe_opt, QCLOUD_ERR_INVAL);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_subscribe(&client->mqtt_client, topic_filter, subscribe_opt));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_unsubscribe(qcloud_shadow_client_t *client, const char *topic_filter)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_unsubscribe(&client->mqtt_client, topic_filter));
}
__QCLOUD_API__ int qcloud_shadow_client_is_connected(qcloud_shadow_client_t *client)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
return qcloud_mqtt_client_is_connected(&client->mqtt_client);
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_destroy(qcloud_shadow_client_t *client)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
shadow_glue_operation_request_unsubscribe(client);
shadow_glue_property_list_destroy(client);
shadow_glue_request_list_destroy(client);
qcloud_mqtt_client_destroy(&client->mqtt_client);
if (client->global_lock) {
osal_mutex_destroy(client->global_lock);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS)
}
__QCLOUD_STATIC__ int shadow_device_property_is_exist(qcloud_shadow_client_t *client, shadow_dev_property_t *that_dev_property)
{
QCLOUD_FUNC_ENTRY;
qcloud_list_t *curr, *next;
qcloud_shadow_prop_info_t *property_info = NULL;
shadow_dev_property_t *this_dev_property = NULL;
if (qcloud_list_empty(&client->property_list)) {
return QCLOUD_FALSE;
}
osal_mutex_lock(client->global_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->property_list) {
property_info = QCLOUD_LIST_ENTRY(curr, qcloud_shadow_prop_info_t, list);
this_dev_property = property_info->dev_property;
if (strcmp(this_dev_property->key, that_dev_property->key) != 0 ||
this_dev_property->type != that_dev_property->type) {
continue;
}
osal_mutex_unlock(client->global_lock);
return QCLOUD_TRUE;
}
osal_mutex_unlock(client->global_lock);
return QCLOUD_FALSE;
}
__QCLOUD_STATIC__ qcloud_err_t shadow_device_property_do_register(qcloud_shadow_client_t *client,
shadow_dev_property_t *dev_property,
shadow_property_delta_handler_fn_t handler)
{
qcloud_shadow_prop_info_t *property_info = NULL;
property_info = (qcloud_shadow_prop_info_t *)osal_malloc(sizeof(qcloud_shadow_prop_info_t));
if (!property_info) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
qcloud_list_init(&property_info->list);
property_info->dev_property = dev_property;
property_info->handler = handler;
qcloud_list_add(&property_info->list, &client->property_list);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_device_property_register(qcloud_shadow_client_t *client,
shadow_dev_property_t *dev_property,
shadow_property_delta_handler_fn_t handler)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(dev_property, QCLOUD_ERR_INVAL);
if (!qcloud_mqtt_client_is_connected(&client->mqtt_client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
if (shadow_device_property_is_exist(client, dev_property)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SHADOW_PROPERTY_EXIST);
}
QCLOUD_FUNC_EXIT_RC(shadow_device_property_do_register(client, dev_property, handler));
}
__QCLOUD_STATIC__ qcloud_err_t shadow_device_property_do_unregister(qcloud_shadow_client_t *client, shadow_dev_property_t *that_dev_property)
{
QCLOUD_FUNC_ENTRY;
qcloud_list_t *curr, *next;
qcloud_shadow_prop_info_t *property_info = NULL;
shadow_dev_property_t *this_dev_property = NULL;
if (qcloud_list_empty(&client->property_list)) {
return QCLOUD_ERR_FAILURE;
}
osal_mutex_lock(client->global_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->property_list) {
property_info = QCLOUD_LIST_ENTRY(curr, qcloud_shadow_prop_info_t, list);
this_dev_property = property_info->dev_property;
if (strcmp(this_dev_property->key, that_dev_property->key) != 0 ||
this_dev_property->type != that_dev_property->type) {
continue;
}
qcloud_list_del(&property_info->list);
osal_free(property_info);
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_device_property_unregister(qcloud_shadow_client_t *client, shadow_dev_property_t *dev_property)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(dev_property, QCLOUD_ERR_INVAL);
if (!qcloud_mqtt_client_is_connected(&client->mqtt_client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
if (!shadow_device_property_is_exist(client, dev_property)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SHADOW_NOT_PROPERTY_EXIST);
}
QCLOUD_FUNC_EXIT_RC(shadow_device_property_do_unregister(client, dev_property));
}
__QCLOUD_STATIC__ void shadow_req_state_update_handler(void *client, qcloud_shadow_req_method_t method, qcloud_shadow_req_state_t req_state, const char *json_doc, void *context)
{
QCLOUD_LOG_D("request state=%d", req_state);
if (json_doc) {
QCLOUD_LOG_D("json doc=%s", json_doc);
} else {
QCLOUD_LOG_D("json doc NULL");
}
*((qcloud_shadow_req_state_t *)context) = req_state;
}
__QCLOUD_STATIC__ qcloud_err_t shadow_request_state2errno(qcloud_shadow_req_state_t state)
{
switch (state) {
case QCLOUD_SHADOW_REQUEST_STATE_ACCEPTED:
return QCLOUD_ERR_SUCCESS;
case QCLOUD_SHADOW_REQUEST_STATE_TIMEOUT:
return QCLOUD_ERR_SHADOW_UPDATE_TIMEOUT;
case QCLOUD_SHADOW_REQUEST_STATE_REJECTED:
return QCLOUD_ERR_SHADOW_UPDATE_REJECTED;
}
return QCLOUD_ERR_INVAL;
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_update_async(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
shadow_requset_handler_fn_t handler,
void *context,
uint32_t timeout)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
QCLOUD_NUMBERIC_SANITY_CHECK(timeout, QCLOUD_ERR_INVAL);
qcloud_shadow_req_opt_t request_opt;
if (!qcloud_mqtt_client_is_connected(&client->mqtt_client)) {
QCLOUD_LOG_E("mqtt disconnected");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
// 如果没有之前没有订阅$shadow/operation/result成功再一次订阅
if (client->sync_state != QCLOUD_SHADOW_SYNC_STATE_SUCCESS) {
shadow_glue_operation_request_subscribe(client);
}
QCLOUD_LOG_D("update request docment: %s", json_doc);
request_opt.method = QCLOUD_SHADOW_REQUEST_METHOD_UPDATE;
request_opt.handler = handler;
request_opt.context = context;
request_opt.timeout = timeout; // in seconds
QCLOUD_FUNC_EXIT_RC(shadow_glue_request_post(client, &request_opt, json_doc, json_doc_size));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_update_sync(qcloud_shadow_client_t *client, char *json_doc, size_t json_doc_size, uint32_t timeout)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
QCLOUD_NUMBERIC_SANITY_CHECK(timeout, QCLOUD_ERR_INVAL);
qcloud_err_t rc = QCLOUD_ERR_SUCCESS;
qcloud_shadow_req_state_t req_state = QCLOUD_SHADOW_REQUEST_STATE_NONE;
if (!qcloud_mqtt_client_is_connected(&client->mqtt_client)) {
QCLOUD_LOG_E("shadow disconnected");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
rc = qcloud_shadow_client_update_async(client, json_doc, json_doc_size, shadow_req_state_update_handler, &req_state, timeout);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
while (req_state == QCLOUD_SHADOW_REQUEST_STATE_NONE) {
qcloud_shadow_client_yield(client, 200);
}
return shadow_request_state2errno(req_state);
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_get_async(qcloud_shadow_client_t *client,
shadow_requset_handler_fn_t handler,
void *context,
uint32_t timeout)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(handler, QCLOUD_ERR_INVAL);
QCLOUD_NUMBERIC_SANITY_CHECK(timeout, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
qcloud_shadow_req_opt_t request_opt;
char request_json_buffer[QCLOUD_SHADOW_JSON_WITH_CLIENT_TOKEN_MAX];
if (!qcloud_mqtt_client_is_connected(&client->mqtt_client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
// 如果没有之前没有订阅$shadow/operation/result成功再一次订阅
if (client->sync_state != QCLOUD_SHADOW_SYNC_STATE_SUCCESS) {
shadow_glue_operation_request_subscribe(client);
}
++client->token_num;
rc = shadow_json_empty_doc_build(request_json_buffer, client->token_num, client->device_product_id);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
QCLOUD_LOG_D("get request document: %s", request_json_buffer);
request_opt.method = QCLOUD_SHADOW_REQUEST_METHOD_GET;
request_opt.handler = handler;
request_opt.context = context;
request_opt.timeout = timeout; // in seconds
QCLOUD_FUNC_EXIT_RC(shadow_glue_request_post(client, &request_opt, request_json_buffer, sizeof(request_json_buffer)));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_get_sync(qcloud_shadow_client_t *client, uint32_t timeout)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_NUMBERIC_SANITY_CHECK(timeout, QCLOUD_ERR_INVAL);
qcloud_err_t rc = QCLOUD_ERR_SUCCESS;
qcloud_shadow_req_state_t req_state = QCLOUD_SHADOW_REQUEST_STATE_NONE;
if (!qcloud_mqtt_client_is_connected(&client->mqtt_client)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN);
}
rc = qcloud_shadow_client_get_async(client, shadow_req_state_update_handler, &req_state, timeout);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, QCLOUD_ERR_FAILURE);
while (req_state == QCLOUD_SHADOW_REQUEST_STATE_NONE) {
qcloud_shadow_client_yield(client, 200);
}
QCLOUD_FUNC_EXIT_RC(shadow_request_state2errno(req_state));
}
/**
* @brief 初始化一个JSON文档
*
* 本函数主要是为JSON文档添加state字段, 即 "{\"state\":{", 所以在生成JSON文档时, 请先调用该方法
*
* @param jsonBuffer 为存储JSON文档准备的字符串缓冲区
* @param sizeOfBuffer 缓冲区大小
* @return 返回QCLOUD_ERR_SUCCESS, 表示初始化成功
*/
__QCLOUD_STATIC__ qcloud_err_t shadow_jsondoc_init(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int is_overwrite)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
int rc = 0;
if (is_overwrite) {
rc = osal_snprintf(json_doc, json_doc_size, "{\"version\":%d, \"overwriteUpdate\":true, \"state\":{", client->version);
} else {
rc = osal_snprintf(json_doc, json_doc_size, "{\"version\":%d, \"state\":{", client->version);
}
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc, json_doc_size));
}
/**
* @brief 在JSON文档中添加结尾部分的内容, 包括clientToken字段、version字段
*
* @param jsonBuffer 为存储JSON文档准备的字符串缓冲区
* @param sizeOfBuffer 缓冲区大小
* @return 返回QCLOUD_ERR_SUCCESS, 表示成功
*/
__QCLOUD_STATIC__ qcloud_err_t shadow_jsondoc_finalize(qcloud_shadow_client_t *client, char *json_doc, size_t json_doc_size)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
int rc_snprintf;
qcloud_err_t rc;
size_t remain_size = 0;
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "}, \"%s\":\"", SHADOW_FIELD_CLIENT_TOKEN);
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
++client->token_num;
rc = shadow_json_client_token_generate(json_doc + strlen(json_doc), remain_size, client->token_num, client->device_product_id);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
return QCLOUD_ERR_JSON_BUFFER_TOO_SHORT;
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"}");
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, remain_size));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_report_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
va_list args;
size_t remain_size = 0;
int i = 0, rc_snprintf = 0;
shadow_dev_property_t *dev_property;
rc = shadow_jsondoc_init(client, json_doc, json_doc_size, QCLOUD_FALSE);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"reported\":{");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
va_start(args, count);
for (i = 0; i < count; ++i) {
dev_property = va_arg(args, shadow_dev_property_t *);
if (!dev_property || !dev_property->key) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = shadow_json_node_add(json_doc, remain_size, dev_property->key, dev_property->data, dev_property->type);
if (rc != QCLOUD_ERR_SUCCESS) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(rc);
}
}
va_end(args);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
return QCLOUD_ERR_JSON_BUFFER_TOO_SHORT;
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "},");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json add report failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
rc = shadow_jsondoc_finalize(client, json_doc, json_doc_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json finalize failed: %d", rc);
}
QCLOUD_FUNC_EXIT_RC(rc);
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_report_construct_array(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count,
shadow_dev_property_t *dev_propertys[])
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(dev_propertys, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
int8_t i = 0, rc_snprintf = 0;
size_t remain_size = 0;
shadow_dev_property_t *dev_property;
rc = shadow_jsondoc_init(client, json_doc, json_doc_size, QCLOUD_FALSE);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"reported\":{");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
for (i = 0; i < count; ++i) {
dev_property = dev_propertys[i];
if (!dev_property || !dev_property->key) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = shadow_json_node_add(json_doc, remain_size, dev_property->key, dev_property->data, dev_property->type);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
return QCLOUD_ERR_JSON_BUFFER_TOO_SHORT;
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "},");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json add report failed: %d", rc);
return rc;
}
rc = shadow_jsondoc_finalize(client, json_doc, json_doc_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json finalize failed: %d", rc);
}
return rc;
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_overwrite_report_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
va_list args;
size_t remain_size = 0;
int rc_snprintf = 0, i = 0;
shadow_dev_property_t *dev_property;
rc = shadow_jsondoc_init(client, json_doc, json_doc_size, QCLOUD_TRUE);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"reported\":{");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
va_start(args, count);
for (i = 0; i < count; ++i) {
dev_property = va_arg(args, shadow_dev_property_t *);
if (!dev_property || !dev_property->key) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = shadow_json_node_add(json_doc, remain_size, dev_property->key, dev_property->data, dev_property->type);
if (rc != QCLOUD_ERR_SUCCESS) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(rc);
}
}
va_end(args);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
return QCLOUD_ERR_JSON_BUFFER_TOO_SHORT;
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "},");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("shadow json add report failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
rc = shadow_jsondoc_finalize(client, json_doc, json_doc_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("shadow json finalize failed: %d", rc);
}
QCLOUD_FUNC_EXIT_RC(rc);
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_report_with_desire_null_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
va_list args;
size_t remain_size = 0;
int rc_snprintf = 0, i = 0;
shadow_dev_property_t *dev_property;
rc = shadow_jsondoc_init(client, json_doc, json_doc_size, QCLOUD_FALSE);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"reported\":{");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
va_start(args, count);
for (i = 0; i < count; ++i) {
dev_property = va_arg(args, shadow_dev_property_t *);
if (!dev_property || !dev_property->key) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = shadow_json_node_add(json_doc, remain_size, dev_property->key, dev_property->data, dev_property->type);
if (rc != QCLOUD_ERR_SUCCESS) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(rc);
}
}
va_end(args);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
return QCLOUD_ERR_JSON_BUFFER_TOO_SHORT;
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "},");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("shadow json add report failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"desired\": null ");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
QCLOUD_FUNC_EXIT_RC(shadow_jsondoc_finalize(client, json_doc, json_doc_size));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_desire_null_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
size_t remain_size = 0;
int rc_snprintf = 0;
rc = shadow_jsondoc_init(client, json_doc, json_doc_size, QCLOUD_FALSE);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"desired\": null ");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
QCLOUD_FUNC_EXIT_RC(shadow_jsondoc_finalize(client, json_doc, json_doc_size));
}
__QCLOUD_API__ qcloud_err_t qcloud_shadow_client_desire_construct(qcloud_shadow_client_t *client,
char *json_doc,
size_t json_doc_size,
int count, ...)
{
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
qcloud_err_t rc;
va_list args;
int i = 0, rc_snprintf = 0;
size_t remain_size = 0;
shadow_dev_property_t *dev_property;
rc = shadow_jsondoc_init(client, json_doc, json_doc_size, QCLOUD_FALSE);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("shadow json init failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"desired\":{");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
va_start(args, count);
for (i = 0; i < count; ++i) {
dev_property = va_arg(args, shadow_dev_property_t *);
if (!dev_property || !dev_property->key) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = shadow_json_node_add(json_doc, remain_size, dev_property->key, dev_property->data, dev_property->type);
if (rc != QCLOUD_ERR_SUCCESS) {
va_end(args);
QCLOUD_FUNC_EXIT_RC(rc);
}
}
va_end(args);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc) - 1, remain_size, "},");
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("json add desired failed: %d", rc);
QCLOUD_FUNC_EXIT_RC(rc);
}
QCLOUD_FUNC_EXIT_RC(shadow_jsondoc_finalize(client, json_doc, json_doc_size));
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,466 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
static char incoming_msg_from_cloud[QCLOUD_SHADOW_JSON_BUF_MAX];
__QCLOUD_STATIC__ void shadow_glue_json_node_insert(char *json_doc, char *json_node, int pos)
{
int i, n;
int len = strlen(json_doc);
int nlen = strlen(json_node);
for (i = len - 1; i >= pos; --i) {
*(json_doc + i + nlen) = *(json_doc + i);
}
for (n = 0; n < nlen; n++) {
*(json_doc + pos + n) = *json_node++;
}
*(json_doc + len + nlen) = 0;
}
/**
* @brief 根据RequestParams、Method来给json填入type字段的值
*/
__QCLOUD_STATIC__ qcloud_err_t shadow_glue_json_request_method_set(char *json_doc, size_t json_doc_size, qcloud_shadow_req_method_t requst_method)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
char *type = NULL;
char json_node[64] = {0};
size_t json_len, size_remaining, json_node_len;
switch (requst_method) {
case QCLOUD_SHADOW_REQUEST_METHOD_GET:
type = SHADOW_OPERATION_GET;
break;
case QCLOUD_SHADOW_REQUEST_METHOD_UPDATE:
type = SHADOW_OPERATION_UPDATE;
break;
}
json_len = strlen(json_doc);
size_remaining = json_doc_size - json_len;
osal_snprintf(json_node, 64, "\"type\":\"%s\", ", type);
json_node_len = strlen(json_node);
if (json_node_len >= size_remaining - 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
shadow_glue_json_node_insert(json_doc, json_node, 1);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_STATIC__ void shadow_glue_request_destroy(qcloud_shadow_request_t *request)
{
qcloud_list_del(&request->list);
osal_free(request);
}
/**
* @brief 执行设备影子操作的回调函数
*/
__QCLOUD_STATIC__ void shadow_glue_operation_request_do_handle(qcloud_shadow_client_t *client, const char *client_token, const char *method_type)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK_RTN(client);
QCLOUD_POINTER_SANITY_CHECK_RTN(client_token);
QCLOUD_POINTER_SANITY_CHECK_RTN(method_type);
char *delta = NULL;
int16_t result_code;
qcloud_list_t *curr, *next;
qcloud_shadow_request_t *request = NULL;
qcloud_shadow_req_state_t req_state = QCLOUD_SHADOW_REQUEST_STATE_NONE;
if (qcloud_list_empty(&client->request_list)) {
return;
}
osal_mutex_lock(client->global_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->request_list) {
request = QCLOUD_LIST_ENTRY(curr, qcloud_shadow_request_t, list);
if (strcmp(request->client_token, client_token) != 0) {
continue;
}
// ͨ<><CDA8> payload <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> result <20><>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>Ӧ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ɹ<EFBFBD>
// <20><>result = 0ʱ<30><CAB1>payload<61><64>Ϊ<EFBFBD>գ<EFBFBD>result<6C><74><30><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>updateʧ<65><CAA7>
if (!shadow_json_operation_result_code_parse(incoming_msg_from_cloud, &result_code)) {
QCLOUD_LOG_E("parse result code failed.");
shadow_glue_request_destroy(request);
continue;
}
req_state = (result_code == 0 ? QCLOUD_SHADOW_REQUEST_STATE_ACCEPTED : QCLOUD_SHADOW_REQUEST_STATE_REJECTED);
if ((strcmp(method_type, SHADOW_OPERATION_GET) == 0 && req_state == QCLOUD_SHADOW_REQUEST_STATE_ACCEPTED) ||
(strcmp(method_type, SHADOW_OPERATION_UPDATE) == 0 && req_state == QCLOUD_SHADOW_REQUEST_STATE_REJECTED)) {
if (shadow_json_operation_delta_get(incoming_msg_from_cloud, &delta)) {
shadow_glue_delta_handle(client, delta);
osal_free(delta);
}
}
if (request->handler) {
request->handler(client, request->method, req_state, incoming_msg_from_cloud, request->context);
}
shadow_glue_request_destroy(request);
--client->request_list_counter;
}
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT;
}
/**
* @brief 文档操作请求结果的回调函数
* 客户端先订阅 $shadow/operation/result/{ProductId}/{DeviceName}, 收到该topic的消息则会调用该回调函数
* 在这个回调函数中, 解析出各个设备影子文档操作的结果
*/
__QCLOUD_STATIC__ void shadow_glue_operation_result_handler(void *client, mqtt_incoming_msg_t *message, void *private_data)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK_RTN(client);
QCLOUD_POINTER_SANITY_CHECK_RTN(message);
int cloud_rcv_len;
uint32_t version = 0;
char *client_token = NULL, *method_type = NULL, *delta = NULL;
qcloud_mqtt_client_t *mqtt_client = NULL;
qcloud_shadow_client_t *shadow_client = NULL;
mqtt_client = (qcloud_mqtt_client_t *)client;
shadow_client = (qcloud_shadow_client_t*)mqtt_client->event_handler.context;
if (!message->topic || message->topic_len <= 0) {
return;
}
if (message->payload_len > QCLOUD_SHADOW_JSON_BUF_MAX) {
QCLOUD_LOG_E("received len exceeds limit");
goto out;
}
cloud_rcv_len = QCLOUD_MIN(QCLOUD_SHADOW_JSON_BUF_MAX - 1, message->payload_len);
memcpy(incoming_msg_from_cloud, message->payload, cloud_rcv_len + 1);
incoming_msg_from_cloud[cloud_rcv_len] = '\0'; // json_parse relies on a string
// 解析shadow result topic消息类型
if (!shadow_json_operation_type_parse(incoming_msg_from_cloud, &method_type)) {
QCLOUD_LOG_E("fail to parse type!");
goto out;
}
// 非delta消息的push一定由设备端触发找到设备段对应的client_token
if (strcmp(method_type, SHADOW_OPERATION_DELTA) != 0 &&
!shadow_json_client_token_parse(incoming_msg_from_cloud, &client_token)) {
QCLOUD_LOG_E("fail to parse client token! json=%s", incoming_msg_from_cloud);
goto out;
}
// 获取shadow push消息version如果比本地的version则修改本地version比本地可能是由于服务器回滚或出错
if (shadow_json_version_parse(incoming_msg_from_cloud, &version) &&
version > shadow_client->version) {
shadow_client->version = version;
}
if (strcmp(method_type, SHADOW_OPERATION_DELTA) == 0) {
if (shadow_json_delta_parse(incoming_msg_from_cloud, &delta)) {
QCLOUD_LOG_D("delta: %s", delta);
shadow_glue_delta_handle(shadow_client, delta);
}
goto out;
}
if (shadow_client) {
shadow_glue_operation_request_do_handle(shadow_client, client_token, method_type);
}
out:
if (!method_type) {
osal_free(method_type);
}
if (!client_token) {
osal_free(client_token);
}
if (!delta) {
osal_free(delta);
}
}
/**
* @brief 发布文档请求到物联云
*
* @param client Qcloud_IoT_Client对象
* @param method 文档操作方式
* @param pJsonDoc 等待发送的文档
* @return 返回QCLOUD_ERR_SUCCESS, 表示发布文档请求成功
*/
__QCLOUD_STATIC__ qcloud_err_t shadow_glue_operation_request_publish(qcloud_shadow_client_t *client,
char *json_doc)
{
QCLOUD_FUNC_ENTRY;
mqtt_publish_opt_t publish_opt;
memset(&publish_opt, 0, sizeof(mqtt_publish_opt_t));
publish_opt.qos = MQTT_QOS0;
publish_opt.payload = (void *)json_doc;
publish_opt.payload_len = strlen(json_doc);
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_client_publish(&client->mqtt_client, client->request_topic_publish, &publish_opt));
}
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_operation_request_subscribe(qcloud_shadow_client_t *client)
{
mqtt_subscribe_opt_t subscribe_opt;
subscribe_opt.message_handler = shadow_glue_operation_result_handler;
subscribe_opt.private_data = NULL;
subscribe_opt.qos = MQTT_QOS0;
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_client_subscribe(&client->mqtt_client, client->request_topic_subscribe, &subscribe_opt));
}
/**
* @brief 取消订阅topic: $shadow/operation/result/{ProductId}/{DeviceName}
*/
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_operation_request_unsubscribe(qcloud_shadow_client_t *client)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_FUNC_EXIT_RC(qcloud_mqtt_client_unsubscribe(&client->mqtt_client, client->request_topic_subscribe));
}
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_request_list_scan(qcloud_shadow_client_t *client)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
qcloud_list_t *curr, *next;
qcloud_shadow_request_t *request;
if (qcloud_list_empty(&client->request_list)) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
osal_mutex_lock(client->global_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->request_list) {
request = QCLOUD_LIST_ENTRY(curr, qcloud_shadow_request_t, list);
// check whether the ack is timeout
if (!osal_timer_is_expired(&request->timer)) {
continue;
}
if (request->handler) {
request->handler(client, request->method, QCLOUD_SHADOW_REQUEST_STATE_TIMEOUT, incoming_msg_from_cloud, request->context);
}
shadow_glue_request_destroy(request);
--client->request_list_counter;
}
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* @brief 将设备影子文档的操作请求保存在列表中
*/
__QCLOUD_STATIC__ qcloud_err_t shadow_glue_request_record(qcloud_shadow_client_t *client,
const char *client_token,
qcloud_shadow_req_opt_t *request_opt)
{
QCLOUD_FUNC_ENTRY;
qcloud_shadow_request_t *request = NULL;
if (client->request_list_counter >= QCLOUD_SHADOW_REQUEST_PENDING_MAX) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_MAX_APPENDING_REQUEST);
}
request = (qcloud_shadow_request_t *)osal_malloc(sizeof(qcloud_shadow_request_t));
if (!request) {
QCLOUD_LOG_E("malloc failed!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
request->handler = request_opt->handler;
request->context = request_opt->context;
request->method = request_opt->method;
strncpy(request->client_token, client_token, QCLOUD_SHADOW_CLIENT_TOKEN_MAX);
osal_timer_init(&request->timer);
osal_timer_countdown(&request->timer, request_opt->timeout);
qcloud_list_init(&request->list);
osal_mutex_lock(client->global_lock);
qcloud_list_add(&request->list, &client->request_list);
++client->request_list_counter;
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
__QCLOUD_INTERNAL__ qcloud_err_t shadow_glue_request_post(qcloud_shadow_client_t *client,
qcloud_shadow_req_opt_t *request_opt,
char *json_doc,
size_t json_doc_size)
{
QCLOUD_FUNC_ENTRY;
QCLOUD_POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(request_opt, QCLOUD_ERR_INVAL);
QCLOUD_POINTER_SANITY_CHECK(json_doc, QCLOUD_ERR_INVAL);
qcloud_err_t rc = QCLOUD_ERR_SUCCESS;
char *client_token = NULL;
// 解析文档中的clientToken, 如果解析失败, 直接返回错误
if (!shadow_json_client_token_parse(json_doc, &client_token)) {
QCLOUD_LOG_E("fail to parse client token!");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
}
rc = shadow_glue_json_request_method_set(json_doc, json_doc_size, request_opt->method);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
// 相应的 operation topic 订阅成功或已经订阅
rc = shadow_glue_operation_request_publish(client, json_doc);
if (rc == QCLOUD_ERR_SUCCESS) {
rc = shadow_glue_request_record(client, client_token, request_opt);
}
osal_free(client_token);
QCLOUD_FUNC_EXIT_RC(rc);
}
/**
* @brief 处理注册属性的回调函数
* 当订阅的$shadow/operation/result/{ProductId}/{DeviceName}返回消息时,
* 若对应的type为delta, 则执行该函数
*
*/
__QCLOUD_INTERNAL__ void shadow_glue_delta_handle(qcloud_shadow_client_t *client, char *delta)
{
QCLOUD_FUNC_ENTRY;
qcloud_list_t *curr, *next;
qcloud_shadow_prop_info_t *property_info = NULL;
shadow_dev_property_t *dev_property = NULL;
if (qcloud_list_empty(&client->property_list)) {
return;
}
osal_mutex_lock(client->global_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->property_list) {
property_info = QCLOUD_LIST_ENTRY(curr, qcloud_shadow_prop_info_t, list);
dev_property = property_info->dev_property;
if (shadow_json_value_update(delta, dev_property)) {
property_info->handler(client, delta, strlen(delta), dev_property);
}
}
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT;
}
__QCLOUD_INTERNAL__ void shadow_glue_property_list_destroy(qcloud_shadow_client_t *client)
{
QCLOUD_FUNC_ENTRY;
qcloud_list_t *curr, *next;
qcloud_shadow_prop_info_t *property_info = NULL;
if (qcloud_list_empty(&client->property_list)) {
return;
}
osal_mutex_lock(client->global_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->property_list) {
property_info = QCLOUD_LIST_ENTRY(curr, qcloud_shadow_prop_info_t, list);
qcloud_list_del(&property_info->list);
osal_free(property_info);
}
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT;
}
__QCLOUD_INTERNAL__ void shadow_glue_request_list_destroy(qcloud_shadow_client_t *client)
{
QCLOUD_FUNC_ENTRY;
qcloud_list_t *curr, *next;
qcloud_shadow_request_t *request = NULL;
if (qcloud_list_empty(&client->request_list)) {
return;
}
osal_mutex_lock(client->global_lock);
QCLOUD_LIST_FOR_EACH_SAFE(curr, next, &client->request_list) {
request = QCLOUD_LIST_ENTRY(curr, qcloud_shadow_request_t, list);
qcloud_list_del(&request->list);
osal_free(request);
}
osal_mutex_unlock(client->global_lock);
QCLOUD_FUNC_EXIT;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,285 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
#define PRIi32 "i"
#define PRIi16 "i"
#define PRIi8 "i"
#define PRIu32 "u"
#define PRIu16 "u"
#define PRIu8 "u"
#define SCNi8 "hhi"
#define SCNu8 "hhu"
#define SCNi16 "hi"
#define SCNu16 "hu"
#define SCNi32 "i"
#define SCNu32 "u"
__QCLOUD_STATIC__ qcloud_err_t shadow_json_value_do_update(char *value, shadow_dev_property_t *dev_property)
{
switch (dev_property->type) {
case JSON_DATA_TYPE_BOOL:
return LITE_get_boolean(dev_property->data, value);
case JSON_DATA_TYPE_INT32:
return LITE_get_int32(dev_property->data, value);
case JSON_DATA_TYPE_INT16:
return LITE_get_int16(dev_property->data, value);
case JSON_DATA_TYPE_INT8:
return LITE_get_int8(dev_property->data, value);
case JSON_DATA_TYPE_UINT32:
return LITE_get_uint32(dev_property->data, value);
case JSON_DATA_TYPE_UINT16:
return LITE_get_uint16(dev_property->data, value);
case JSON_DATA_TYPE_UINT8:
return LITE_get_uint8(dev_property->data, value);
case JSON_DATA_TYPE_FLOAT:
return LITE_get_float(dev_property->data, value);
case JSON_DATA_TYPE_DOUBLE:
return LITE_get_double(dev_property->data, value);
case JSON_DATA_TYPE_STRING:
case JSON_DATA_TYPE_OBJECT:
QCLOUD_LOG_D("string/object to be deal, %d %s", dev_property->type, value);
return QCLOUD_ERR_SUCCESS;
default:
QCLOUD_LOG_E("unknow type, %d",dev_property->type);
return QCLOUD_ERR_FAILURE;
}
}
/**
* @brief 检查函数snprintf的返回值
*
* @param returnCode 函数snprintf的返回值
* @param maxSizeOfWrite 可写最大字节数
* @return 返回QCLOUD_ERR_JSON, 表示出错; 返回QCLOUD_ERR_JSON_BUFFER_TRUNCATED, 表示截断
*/
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_snprintf_rc2errno(int rc, size_t write_max)
{
if (rc < 0) {
return QCLOUD_ERR_JSON;
}
if (rc >= write_max) {
return QCLOUD_ERR_JSON_BUFFER_TRUNCATED;
}
return QCLOUD_ERR_SUCCESS;
}
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_client_token_generate(char *json_doc, size_t json_doc_size, uint32_t token_num, char *device_product_id)
{
int rc_snprintf;
rc_snprintf = osal_snprintf(json_doc, json_doc_size, "%s-%u", device_product_id, token_num);
return shadow_json_snprintf_rc2errno(rc_snprintf, json_doc_size);
}
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_node_add(char *json_doc, size_t json_doc_size, const char *key, void *data, json_data_type_t type)
{
qcloud_err_t rc;
int32_t rc_snprintf = 0;
size_t remain_size = 0;
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
return QCLOUD_ERR_JSON_BUFFER_TOO_SHORT;
}
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"%s\":", key);
rc = shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
QCLOUD_FUNC_EXIT_RC_IF_NOT(rc, QCLOUD_ERR_SUCCESS, rc);
if ((remain_size = json_doc_size - strlen(json_doc)) <= 1) {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_JSON_BUFFER_TOO_SHORT);
}
if (!data) {
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "null,");
QCLOUD_FUNC_EXIT_RC(shadow_json_snprintf_rc2errno(rc_snprintf, remain_size));
}
switch (type) {
case JSON_DATA_TYPE_INT32:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIi32
",", *(int32_t *)(data));
break;
case JSON_DATA_TYPE_INT16:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIi16
",", *(int16_t *)(data));
break;
case JSON_DATA_TYPE_INT8:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIi8
",", *(int8_t *)(data));
break;
case JSON_DATA_TYPE_UINT32:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIu32
",", *(uint32_t *)(data));
break;
case JSON_DATA_TYPE_UINT16:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIu16
",", *(uint16_t *)(data));
break;
case JSON_DATA_TYPE_UINT8:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%"
PRIu8
",", *(uint8_t *)(data));
break;
case JSON_DATA_TYPE_DOUBLE:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%f,", *(double *)(data));
break;
case JSON_DATA_TYPE_FLOAT:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%f,", *(float *)(data));
break;
case JSON_DATA_TYPE_BOOL:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%s,", *(bool *)(data) ? "true" : "false");
break;
case JSON_DATA_TYPE_STRING:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "\"%s\",", (char *)(data));
break;
case JSON_DATA_TYPE_OBJECT:
rc_snprintf = osal_snprintf(json_doc + strlen(json_doc), remain_size, "%s,", (char *)(data));
break;
}
return shadow_json_snprintf_rc2errno(rc_snprintf, remain_size);
}
__QCLOUD_INTERNAL__ qcloud_err_t shadow_json_empty_doc_build(char *json_doc, uint32_t token_num, char *device_product_id)
{
int rc_snprintf;
rc_snprintf = osal_snprintf(json_doc, QCLOUD_SHADOW_JSON_WITH_CLIENT_TOKEN_MAX, "{\"clientToken\":\"%s-%u\"}", device_product_id, token_num);
return shadow_json_snprintf_rc2errno(rc_snprintf, QCLOUD_SHADOW_JSON_WITH_CLIENT_TOKEN_MAX);
}
__QCLOUD_INTERNAL__ int shadow_json_client_token_parse(char *json_doc, char **client_token)
{
*client_token = LITE_json_value_of(SHADOW_FIELD_CLIENT_TOKEN, json_doc);
return *client_token != NULL;
}
__QCLOUD_INTERNAL__ int shadow_json_version_parse(char *json_doc, uint32_t *version)
{
int rc = QCLOUD_TRUE;
char *version_str;
version_str = LITE_json_value_of(SHADOW_PAYLOAD_VERSION, json_doc);
if (!version_str) {
return QCLOUD_FALSE;
}
if (sscanf(version_str, "%" SCNu32, version) != 1) {
QCLOUD_LOG_E("parse shadow version failed, rc: %d", QCLOUD_ERR_JSON_PARSE);
rc = QCLOUD_FALSE;
}
osal_free(version_str);
return rc;
}
__QCLOUD_INTERNAL__ int shadow_json_operation_type_parse(char *json_doc, char **type)
{
*type = LITE_json_value_of(SHADOW_FIELD_TYPE, json_doc);
return *type != NULL;
}
__QCLOUD_INTERNAL__ int shadow_json_operation_result_code_parse(char *json_doc, int16_t *result_code)
{
int rc = QCLOUD_TRUE;
char *result_code_str;
result_code_str = LITE_json_value_of(SHADOW_FIELD_RESULT, json_doc);
if (!result_code_str) {
return QCLOUD_FALSE;
}
if (sscanf(result_code_str, "%" SCNi16, result_code) != 1) {
QCLOUD_LOG_E("parse result code failed, %d", QCLOUD_ERR_JSON_PARSE);
rc = QCLOUD_FALSE;
}
osal_free(result_code_str);
return rc;
}
__QCLOUD_INTERNAL__ int shadow_json_delta_parse(char *json_doc, char **delta)
{
*delta = LITE_json_value_of(SHADOW_PAYLOAD_STATE, json_doc);
return *delta != NULL;
}
__QCLOUD_INTERNAL__ int shadow_json_operation_delta_get(char *json_doc, char **delta)
{
*delta = LITE_json_value_of(SHADOW_PAYLOAD_STATE_DELTA, json_doc);
return *delta != NULL;
}
__QCLOUD_INTERNAL__ int shadow_state_parse(char *json_doc, char **state)
{
*state = LITE_json_value_of(SHADOW_PAYLOAD_VERSION, json_doc);
return *state != NULL;
}
__QCLOUD_INTERNAL__ int shadow_json_value_update(char *json, shadow_dev_property_t *dev_property)
{
char *data;
data = LITE_json_value_of((char *)dev_property->key, json);
if (!data || strncmp(data, "null", 4) == 0 || strncmp(data, "NULL", 4) == 0) {
return QCLOUD_FALSE;
}
shadow_json_value_do_update(data, dev_property);
osal_free(data);
return QCLOUD_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,204 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdlib.h>
#include "qcloud_utils/qcloud_base64.h"
static const unsigned char base64_enc_map[64] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
static const unsigned char base64_dec_map[128] =
{
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 127, 127, 127, 127, 127
};
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
int qcloud_utils_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen )
{
size_t i, n;
unsigned char *p;
if( slen == 0 )
{
*olen = 0;
return( 0 );
}
n = slen / 3 + ( slen % 3 != 0 );
if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
{
*olen = BASE64_SIZE_T_MAX;
return( QCLOUD_ERR_FAILURE );
}
n *= 4;
if( ( dlen < n + 1 ) || ( NULL == dst ) )
{
*olen = n + 1;
return( QCLOUD_ERR_FAILURE );
}
n = ( slen / 3 ) * 3;
int C1, C2, C3;
for( i = 0, p = dst; i < n; i += 3 )
{
C1 = *src++;
C2 = *src++;
C3 = *src++;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
*p++ = base64_enc_map[C3 & 0x3F];
}
if( i < slen )
{
C1 = *src++;
C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
if( ( i + 1 ) < slen )
*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
else *p++ = '=';
*p++ = '=';
}
*olen = p - dst;
*p = 0;
return( 0 );
}
int qcloud_utils_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen )
{
size_t i, n;
uint32_t j, x;
unsigned char *p;
/* First pass: check for validity and get output length */
for( i = n = j = 0; i < slen; i++ )
{
/* Skip spaces before checking for EOL */
x = 0;
while( i < slen && src[i] == ' ' )
{
++i;
++x;
}
/* Spaces at end of buffer are OK */
if( i == slen )
break;
if( ( slen - i ) >= 2 &&
src[i] == '\r' && src[i + 1] == '\n' )
continue;
if( src[i] == '\n' )
continue;
/* Space inside a line is an error */
if( x != 0 )
return( QCLOUD_ERR_FAILURE );
if( src[i] == '=' && ++j > 2 )
return( QCLOUD_ERR_FAILURE );
if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
return( QCLOUD_ERR_FAILURE );
if( base64_dec_map[src[i]] < 64 && j != 0 )
return( QCLOUD_ERR_FAILURE );
n++;
}
if( n == 0 )
{
*olen = 0;
return( 0 );
}
n = ( ( n * 6 ) + 7 ) >> 3;
n -= j;
if( dst == NULL || dlen < n )
{
*olen = n;
return( QCLOUD_ERR_FAILURE );
}
for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
{
if( *src == '\r' || *src == '\n' || *src == ' ' )
continue;
j -= ( base64_dec_map[*src] == 64 );
x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
if( ++n == 4 )
{
n = 0;
if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
if( j > 2 ) *p++ = (unsigned char)( x );
}
}
*olen = p - dst;
return( 0 );
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,121 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 "qcloud.h"
#define KEY_IOPAD_SIZE 64
#define MD5_DIGEST_SIZE 16
#define SHA1_DIGEST_SIZE 20
void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len)
{
if((NULL == msg) || (NULL == digest) || (NULL == key)) {
QCLOUD_LOG_E("parameter is Null,failed!");
return;
}
if(key_len > KEY_IOPAD_SIZE) {
QCLOUD_LOG_E("key_len > size(%d) of array",KEY_IOPAD_SIZE);
return;
}
iot_md5_context context;
unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
unsigned char out[MD5_DIGEST_SIZE];
int i;
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < KEY_IOPAD_SIZE; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner MD5 */
utils_md5_init(&context); /* init context for 1st pass */
utils_md5_starts(&context); /* setup context for 1st pass */
utils_md5_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */
utils_md5_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
utils_md5_finish(&context, out); /* finish up 1st pass */
/* perform outer MD5 */
utils_md5_init(&context); /* init context for 2nd pass */
utils_md5_starts(&context); /* setup context for 2nd pass */
utils_md5_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */
utils_md5_update(&context, out, MD5_DIGEST_SIZE); /* then results of 1st hash */
utils_md5_finish(&context, out); /* finish up 2nd pass */
for (i = 0; i < MD5_DIGEST_SIZE; ++i) {
digest[i * 2] = utils_hb2hex(out[i] >> 4);
digest[i * 2 + 1] = utils_hb2hex(out[i]);
}
}
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len)
{
if((NULL == msg) || (NULL == digest) || (NULL == key)) {
QCLOUD_LOG_E("parameter is Null,failed!");
return;
}
if(key_len > KEY_IOPAD_SIZE) {
QCLOUD_LOG_E("key_len > size(%d) of array",KEY_IOPAD_SIZE);
return;
}
iot_sha1_context context;
unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
unsigned char out[SHA1_DIGEST_SIZE];
int i;
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < KEY_IOPAD_SIZE; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner SHA */
utils_sha1_init(&context); /* init context for 1st pass */
utils_sha1_starts(&context); /* setup context for 1st pass */
utils_sha1_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */
utils_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
utils_sha1_finish(&context, out); /* finish up 1st pass */
/* perform outer SHA */
utils_sha1_init(&context); /* init context for 2nd pass */
utils_sha1_starts(&context); /* setup context for 2nd pass */
utils_sha1_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */
utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
utils_sha1_finish(&context, out); /* finish up 2nd pass */
for (i = 0; i < SHA1_DIGEST_SIZE; ++i) {
digest[i * 2] = utils_hb2hex(out[i] >> 4);
digest[i * 2 + 1] = utils_hb2hex(out[i]);
}
}

View File

@@ -1,829 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "qcloud.h"
#define HTTP_CLIENT_MIN(x,y) (((x)<(y))?(x):(y))
#define HTTP_CLIENT_MAX(x,y) (((x)>(y))?(x):(y))
#define HTTP_CLIENT_AUTHB_SIZE 128
#define HTTP_CLIENT_CHUNK_SIZE 1024
#define HTTP_CLIENT_SEND_BUF_SIZE 1024
#define HTTP_CLIENT_MAX_HOST_LEN 64
#define HTTP_CLIENT_MAX_URL_LEN 1024
#define HTTP_RETRIEVE_MORE_DATA (1)
#if defined(MBEDTLS_DEBUG_C)
#define DEBUG_LEVEL 2
#endif
static void _http_client_base64enc(char *out, const char *in)
{
const char code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
int i = 0, x = 0, l = 0;
for (; *in; in++) {
x = x << 8 | *in;
for (l += 8; l >= 6; l -= 6) {
out[i++] = code[(x >> (l - 6)) & 0x3f];
}
}
if (l > 0) {
x <<= 6 - l;
out[i++] = code[x & 0x3f];
}
for (; i % 4;) {
out[i++] = '=';
}
out[i] = '\0';
}
static int _http_client_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host, uint32_t maxhost_len,
int *port, char *path, uint32_t max_path_len)
{
char *scheme_ptr = (char *) url;
char *host_ptr = (char *) strstr(url, "://");
uint32_t host_len = 0;
uint32_t path_len;
char *path_ptr;
char *fragment_ptr;
if (host_ptr == NULL) {
QCLOUD_LOG_E("Could not find host");
return QCLOUD_ERR_HTTP_PARSE;
}
if (max_scheme_len < host_ptr - scheme_ptr + 1) {
QCLOUD_LOG_E("Scheme str is too small (%u >= %u)", max_scheme_len, (uint32_t)(host_ptr - scheme_ptr + 1));
return QCLOUD_ERR_HTTP_PARSE;
}
memcpy(scheme, scheme_ptr, host_ptr - scheme_ptr);
scheme[host_ptr - scheme_ptr] = '\0';
host_ptr += 3;
*port = 0;
path_ptr = strchr(host_ptr, '/');
if (NULL == path_ptr) {
path_ptr = scheme_ptr + (int)strlen(url);
host_len = path_ptr - host_ptr;
memcpy(host, host_ptr, host_len);
host[host_len] = '\0';
memcpy(path, "/", 1);
path[1] = '\0';
return QCLOUD_ERR_SUCCESS;
}
if (host_len == 0) {
host_len = path_ptr - host_ptr;
}
if (maxhost_len < host_len + 1) {
QCLOUD_LOG_E("Host str is too long (host_len(%d) >= max_len(%d))", host_len + 1, maxhost_len);
return QCLOUD_ERR_HTTP_PARSE;
}
memcpy(host, host_ptr, host_len);
host[host_len] = '\0';
fragment_ptr = strchr(host_ptr, '#');
if (fragment_ptr != NULL) {
path_len = fragment_ptr - path_ptr;
} else {
path_len = strlen(path_ptr);
}
if (max_path_len < path_len + 1) {
QCLOUD_LOG_E("Path str is too small (%d >= %d)", max_path_len, path_len + 1);
return QCLOUD_ERR_HTTP_PARSE;
}
memcpy(path, path_ptr, path_len);
path[path_len] = '\0';
return QCLOUD_ERR_SUCCESS;
}
static int _http_client_parse_host(const char *url, char *host, uint32_t host_max_len)
{
const char *host_ptr = (const char *) strstr(url, "://");
uint32_t host_len = 0;
char *path_ptr;
if (host_ptr == NULL) {
QCLOUD_LOG_E("Could not find host");
return QCLOUD_ERR_HTTP_PARSE;
}
host_ptr += 3;
uint32_t pro_len = 0;
pro_len = host_ptr - url;
path_ptr = strchr(host_ptr, '/');
if (path_ptr != NULL)
host_len = path_ptr - host_ptr;
else
host_len = strlen(url) - pro_len;
if (host_max_len < host_len + 1) {
QCLOUD_LOG_E("Host str is too small (%d >= %d)", host_max_len, host_len + 1);
return QCLOUD_ERR_HTTP_PARSE;
}
memcpy(host, host_ptr, host_len);
host[host_len] = '\0';
return QCLOUD_ERR_SUCCESS;
}
/**
* @brief 拼接发送的数据
*
* @param client http client
* @param send_buf 发送数据buffer
* @param send_idx 标志send_buf数据结束的位置
* @param buf 需要被发送的数据拼接到send_buf中
* @param len buf的长度
* @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功
*/
static int _http_client_get_info(HTTPClient *client, unsigned char *send_buf, int *send_idx, char *buf, uint32_t len)
{
int rc = QCLOUD_ERR_SUCCESS;
int cp_len;
int idx = *send_idx;
if (len == 0) {
len = strlen(buf);
}
do {
if ((HTTP_CLIENT_SEND_BUF_SIZE - idx) >= len) {
cp_len = len;
} else {
cp_len = HTTP_CLIENT_SEND_BUF_SIZE - idx;
}
memcpy(send_buf + idx, buf, cp_len);
idx += cp_len;
len -= cp_len;
if (idx == HTTP_CLIENT_SEND_BUF_SIZE) {
size_t byte_written_len = 0;
rc = client->network.write(&(client->network), send_buf, HTTP_CLIENT_SEND_BUF_SIZE, 5000, &byte_written_len);
if (byte_written_len) {
return (byte_written_len);
}
}
} while (len);
*send_idx = idx;
return rc;
}
static int _http_client_send_auth(HTTPClient *client, unsigned char *send_buf, int *send_idx)
{
char b_auth[(int)((HTTP_CLIENT_AUTHB_SIZE + 3) * 4 / 3 + 1)];
char base64buff[HTTP_CLIENT_AUTHB_SIZE + 3];
_http_client_get_info(client, send_buf, send_idx, "Authorization: Basic ", 0);
osal_snprintf(base64buff, sizeof(base64buff), "%s:%s", client->auth_user, client->auth_password);
_http_client_base64enc(b_auth, base64buff);
b_auth[strlen(b_auth) + 1] = '\0';
b_auth[strlen(b_auth)] = '\n';
_http_client_get_info(client, send_buf, send_idx, b_auth, 0);
return QCLOUD_ERR_SUCCESS;
}
/**
* @brief 根据请求url和method拼接请求头
*
* @param client http client
* @param url 请求url
* @param method 请求方法
* @param client_data http数据负载
* @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功
*/
static int _http_client_send_header(HTTPClient *client, const char *url, HttpMethod method, HTTPClientData *client_data)
{
char scheme[8] = { 0 };
char host[HTTP_CLIENT_MAX_HOST_LEN] = { 0 };
char path[HTTP_CLIENT_MAX_URL_LEN] = { 0 };
int len;
unsigned char send_buf[HTTP_CLIENT_SEND_BUF_SIZE] = { 0 };
char buf[HTTP_CLIENT_SEND_BUF_SIZE] = { 0 };
char *meth = (method == HTTP_GET) ? "GET" : (method == HTTP_POST) ? "POST" :
(method == HTTP_PUT) ? "PUT" : (method == HTTP_DELETE) ? "DELETE" :
(method == HTTP_HEAD) ? "HEAD" : "";
int rc;
int port;
int res = _http_client_parse_url(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
if (res != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("httpclient_parse_url returned %d", res);
return res;
}
if (strcmp(scheme, "http") == 0) {
} else if (strcmp(scheme, "https") == 0) {
}
memset(send_buf, 0, HTTP_CLIENT_SEND_BUF_SIZE);
len = 0;
osal_snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host);
rc = _http_client_get_info(client, send_buf, &len, buf, strlen(buf));
if (rc) {
QCLOUD_LOG_E("Could not write request");
return QCLOUD_ERR_HTTP_CONN;
}
if (client->auth_user) {
_http_client_send_auth(client, send_buf, &len);
}
if (client->header) {
_http_client_get_info(client, send_buf, &len, (char *) client->header, strlen(client->header));
}
if (client_data->post_buf != NULL) {
osal_snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", client_data->post_buf_len);
_http_client_get_info(client, send_buf, &len, buf, strlen(buf));
if (client_data->post_content_type != NULL) {
osal_snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", client_data->post_content_type);
_http_client_get_info(client, send_buf, &len, buf, strlen(buf));
}
}
_http_client_get_info(client, send_buf, &len, "\r\n", 0);
//QCLOUD_LOG_D("REQUEST:\n%s", send_buf);
size_t written_len = 0;
rc = client->network.write(&client->network, send_buf, len, 5000, &written_len);
if (written_len > 0) {
//QCLOUD_LOG_D("Written %lu bytes", written_len);
} else if (written_len == 0) {
QCLOUD_LOG_E("written_len == 0,Connection was closed by server");
return QCLOUD_ERR_HTTP_CLOSED; /* Connection was closed by server */
} else {
QCLOUD_LOG_E("Connection error (send returned %d)", rc);
return QCLOUD_ERR_HTTP_CONN;
}
return QCLOUD_ERR_SUCCESS;
}
/**
* @brief 发送post的请求体数据
*
* @param client http client
* @param client_data http数据负载
* @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功
*/
static int _http_client_send_userdata(HTTPClient *client, HTTPClientData *client_data)
{
if (client_data->post_buf && client_data->post_buf_len) {
//QCLOUD_LOG_D("client_data->post_buf: %s", client_data->post_buf);
{
size_t written_len = 0;
int rc = client->network.write(&client->network, (unsigned char *)client_data->post_buf, client_data->post_buf_len, 5000, &written_len);
if (written_len > 0) {
//QCLOUD_LOG_D("Written %d bytes", written_len);
} else if (written_len == 0) {
QCLOUD_LOG_E("written_len == 0,Connection was closed by server");
return QCLOUD_ERR_HTTP_CLOSED;
} else {
QCLOUD_LOG_E("Connection error (send returned %d)", rc);
return QCLOUD_ERR_HTTP_CONN;
}
}
}
return QCLOUD_ERR_SUCCESS;
}
/**
* @brief 读取http数据
*
* @param client http client
* @param buf 数据buffer
* @param min_len 读取数据的最小长度
* @param max_len 读取数据的最大长度
* @param p_read_len 成功读取到的数据的长度
* @param timeout_ms 超时时间
* @param client_data http数据负载
* @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功
*/
static int _http_client_recv(HTTPClient *client, char *buf, int min_len, int max_len, int *p_read_len, uint32_t timeout_ms, HTTPClientData *client_data)
{
QCLOUD_FUNC_ENTRY;
int rc = 0;
osal_timer_t timer;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, (unsigned int)timeout_ms);
*p_read_len = 0;
rc = client->network.read(&client->network, (unsigned char *)buf, max_len, (uint32_t)osal_timer_remain(&timer), (size_t *)p_read_len);
if (rc == QCLOUD_ERR_SSL_NOTHING_TO_READ || rc == QCLOUD_ERR_TCP_NOTHING_TO_READ) {
QCLOUD_LOG_D("HTTP read nothing and timeout");
rc = QCLOUD_ERR_SUCCESS;
}
else if (rc == QCLOUD_ERR_SSL_READ_TIMEOUT || rc == QCLOUD_ERR_TCP_READ_TIMEOUT) {
if (*p_read_len == client_data->retrieve_len || client_data->retrieve_len == 0)
rc = QCLOUD_ERR_SUCCESS;
}
else if (rc == QCLOUD_ERR_TCP_PEER_SHUTDOWN && *p_read_len > 0) {
/* HTTP server give response and close this connection */
client->network.disconnect(&client->network);
rc = QCLOUD_ERR_SUCCESS;
}
else if (rc != QCLOUD_ERR_SUCCESS) { // 其他错误
QCLOUD_LOG_E("Connection error rc = %d (recv returned %d)", rc, *p_read_len);
QCLOUD_FUNC_EXIT_RC(rc);
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
static int _http_client_retrieve_content(HTTPClient *client, char *data, int len, uint32_t timeout_ms,
HTTPClientData *client_data)
{
QCLOUD_FUNC_ENTRY;
int count = 0;
int templen = 0;
int crlf_pos;
osal_timer_t timer;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, (unsigned int)timeout_ms);
client_data->is_more = QCLOUD_TRUE;
if (client_data->response_content_len == -1 && client_data->is_chunked == QCLOUD_FALSE) {
while (1) {
int rc, max_len;
if (count + len < client_data->response_buf_len - 1) {
memcpy(client_data->response_buf + count, data, len);
count += len;
client_data->response_buf[count] = '\0';
} else {
memcpy(client_data->response_buf + count, data, client_data->response_buf_len - 1 - count);
client_data->response_buf[client_data->response_buf_len - 1] = '\0';
return HTTP_RETRIEVE_MORE_DATA;
}
max_len = HTTP_CLIENT_MIN(HTTP_CLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count);
rc = _http_client_recv(client, data, 1, max_len, &len, (uint32_t)osal_timer_remain(&timer), client_data);
/* Receive data */
//QCLOUD_LOG_D("data len: %d %d", len, count);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
}
if (len == 0) {
/* read no more data */
QCLOUD_LOG_D("no more data, len == 0");
client_data->is_more = QCLOUD_FALSE;
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
}
}
while (1) {
uint32_t readLen = 0;
if (client_data->is_chunked && client_data->retrieve_len <= 0) {
/* Read chunk header */
bool foundCrlf;
int n;
do {
foundCrlf = QCLOUD_FALSE;
crlf_pos = 0;
data[len] = 0;
if (len >= 2) {
for (; crlf_pos < len - 2; crlf_pos++) {
if (data[crlf_pos] == '\r' && data[crlf_pos + 1] == '\n') {
foundCrlf = QCLOUD_TRUE;
break;
}
}
}
if (!foundCrlf) {
/* Try to read more */
if (len < HTTP_CLIENT_CHUNK_SIZE) {
int new_trf_len, rc;
rc = _http_client_recv(client,
data + len,
0,
HTTP_CLIENT_CHUNK_SIZE - len - 1,
&new_trf_len,
osal_timer_remain(&timer),
client_data);
len += new_trf_len;
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
} else {
continue;
}
} else {
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_HTTP);
}
}
} while (!foundCrlf);
data[crlf_pos] = '\0';
// n = sscanf(data, "%x", &readLen);/* chunk length */
readLen = strtoul(data, NULL, 16);
n = (0 == readLen) ? 0 : 1;
client_data->retrieve_len = readLen;
client_data->response_content_len += client_data->retrieve_len;
if (readLen == 0) {
client_data->is_more = QCLOUD_FALSE;
QCLOUD_LOG_D("no more (last chunk)");
}
if (n != 1) {
QCLOUD_LOG_E("Could not read chunk length");
return QCLOUD_ERR_HTTP_UNRESOLVED_DNS;
}
memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2));
len -= (crlf_pos + 2);
} else {
readLen = client_data->retrieve_len;
}
do {
templen = HTTP_CLIENT_MIN(len, readLen);
if (count + templen < client_data->response_buf_len - 1) {
memcpy(client_data->response_buf + count, data, templen);
count += templen;
client_data->response_buf[count] = '\0';
client_data->retrieve_len -= templen;
} else {
memcpy(client_data->response_buf + count, data, client_data->response_buf_len - 1 - count);
client_data->response_buf[client_data->response_buf_len - 1] = '\0';
client_data->retrieve_len -= (client_data->response_buf_len - 1 - count);
QCLOUD_FUNC_EXIT_RC(HTTP_RETRIEVE_MORE_DATA);
}
if (len > readLen) {
QCLOUD_LOG_D("memmove %d %d %d\n", readLen, len, client_data->retrieve_len);
memmove(data, &data[readLen], len - readLen); /* chunk case, read between two chunks */
len -= readLen;
readLen = 0;
client_data->retrieve_len = 0;
} else {
readLen -= len;
}
if (readLen) {
int rc;
int max_len = HTTP_CLIENT_MIN(HTTP_CLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count);
max_len = HTTP_CLIENT_MIN(max_len, readLen);
rc = _http_client_recv(client, data, 1, max_len, &len, osal_timer_remain(&timer), client_data);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
}
}
} while (readLen);
if (client_data->is_chunked) {
if (len < 2) {
int new_trf_len, rc;
/* Read missing chars to find end of chunk */
rc = _http_client_recv(client, data + len, 2 - len, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len,
osal_timer_remain(&timer), client_data);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
}
len += new_trf_len;
}
if ((data[0] != '\r') || (data[1] != '\n')) {
QCLOUD_LOG_E("Format error, %s", data); /* after memmove, the beginning of next chunk */
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_UNRESOLVED_DNS);
}
memmove(data, &data[2], len - 2); /* remove the \r\n */
len -= 2;
} else {
//QCLOUD_LOG_D("no more (content-length)");
client_data->is_more = QCLOUD_FALSE;
break;
}
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
/**
* @brief 解析response body数据
*
* @param client HTTPClient数据
* @param data 读取到的数据
* @param len 读取到的数据的长度
* @param timeout_ms 读取数据的超时时间
* @param client_data http数据负载
* @return 返回QCLOUD_ERR_SUCCESS, 表示成功
*/
static int _http_client_response_parse(HTTPClient *client, char *data, int len, uint32_t timeout_ms,
HTTPClientData *client_data)
{
QCLOUD_FUNC_ENTRY;
int crlf_pos;
osal_timer_t timer;
char *tmp_ptr, *ptr_body_end;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, timeout_ms);
client_data->response_content_len = -1;
char *crlf_ptr = strstr(data, "\r\n");
if (crlf_ptr == NULL) {
QCLOUD_LOG_E("\\r\\n not found");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_UNRESOLVED_DNS);
}
crlf_pos = crlf_ptr - data;
data[crlf_pos] = '\0';
#if 0
if (sscanf(data, "HTTP/%*d.%*d %d %*[^\r\n]", &(client->response_code)) != 1) {
QCLOUD_LOG_E("Not a correct HTTP answer : %s\n", data);
return QCLOUD_ERR_HTTP_UNRESOLVED_DNS;
}
#endif
client->response_code = atoi(data + 9);
if ((client->response_code < 200) || (client->response_code >= 400)) {
QCLOUD_LOG_W("Response code %d", client->response_code);
if (client->response_code == 403)
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_AUTH);
if (client->response_code == 404)
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_NOT_FOUND);
}
//QCLOUD_LOG_D("Reading headers : %s", data);
// 移除null终止字符
memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2) + 1);
len -= (crlf_pos + 2);
client_data->is_chunked = QCLOUD_FALSE;
if (NULL == (ptr_body_end = strstr(data, "\r\n\r\n"))) {
int new_trf_len, rc;
rc = _http_client_recv(client, data + len, 1, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len, osal_timer_remain(&timer), client_data);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
}
len += new_trf_len;
data[len] = '\0';
if (NULL == (ptr_body_end = strstr(data, "\r\n\r\n"))) {
QCLOUD_LOG_E("parse error: no end of the request body");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
}
}
if (NULL != (tmp_ptr = strstr(data, "Content-Length"))) {
client_data->response_content_len = atoi(tmp_ptr + strlen("Content-Length: "));
client_data->retrieve_len = client_data->response_content_len;
} else if (NULL != (tmp_ptr = strstr(data, "Transfer-Encoding"))) {
int len_chunk = strlen("Chunked");
char *chunk_value = data + strlen("Transfer-Encoding: ");
if ((! memcmp(chunk_value, "Chunked", len_chunk))
|| (! memcmp(chunk_value, "chunked", len_chunk))) {
client_data->is_chunked = QCLOUD_TRUE;
client_data->response_content_len = 0;
client_data->retrieve_len = 0;
}
} else {
QCLOUD_LOG_E("Could not parse header");
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_HTTP);
}
len = len - (ptr_body_end + 4 - data);
memmove(data, ptr_body_end + 4, len + 1);
int rc = _http_client_retrieve_content(client, data, len, osal_timer_remain(&timer), client_data);
QCLOUD_FUNC_EXIT_RC(rc);
}
static int _http_client_connect(HTTPClient *client)
{
if (QCLOUD_ERR_SUCCESS != client->network.connect(&client->network)) {
return QCLOUD_ERR_HTTP_CONN;
}
return QCLOUD_ERR_SUCCESS;
}
static int _http_client_send_request(HTTPClient *client, const char *url, HttpMethod method, HTTPClientData *client_data)
{
int rc;
rc = _http_client_send_header(client, url, method, client_data);
if (rc != 0) {
QCLOUD_LOG_E("httpclient_send_header is error, rc = %d", rc);
return rc;
}
if (method == HTTP_POST || method == HTTP_PUT) {
rc = _http_client_send_userdata(client, client_data);
}
return rc;
}
/**
* @brief 接收http返回的数据
*
* @param client http client
* @param timeout_ms 读取数据的超时时间
* @param client_data http数据负载
* @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功
*/
static int _http_client_recv_response(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data)
{
QCLOUD_FUNC_ENTRY;
int reclen = 0, rc = QCLOUD_ERR_HTTP_CONN;
char buf[HTTP_CLIENT_CHUNK_SIZE] = { 0 };
osal_timer_t timer;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, timeout_ms);
if (!client->network.is_connected(&client->network)) {
QCLOUD_LOG_E("Connection has not been established");
QCLOUD_FUNC_EXIT_RC(rc);
}
if (client_data->is_more) {
client_data->response_buf[0] = '\0';
rc = _http_client_retrieve_content(client, buf, reclen, osal_timer_remain(&timer), client_data);
} else {
client_data->is_more = QCLOUD_TRUE;
rc = _http_client_recv(client, buf, 1, HTTP_CLIENT_CHUNK_SIZE - 1, &reclen, osal_timer_remain(&timer), client_data);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_FUNC_EXIT_RC(rc);
}
buf[reclen] = '\0';
if (reclen) {
//osal_printf("RESPONSE:\n%s", buf);
rc = _http_client_response_parse(client, buf, reclen, osal_timer_remain(&timer), client_data);
}
}
QCLOUD_FUNC_EXIT_RC(rc);
}
static int _http_network_init(qcloud_network_t *network, const char *host, int port, const char *ca_crt_dir)
{
int rc = QCLOUD_ERR_SUCCESS;
if (network == NULL) {
return QCLOUD_ERR_INVAL;
}
#if (QCLOUD_CFG_TLS_EN > 0u)
if (ca_crt_dir != NULL) {
network->tls_opt.ca_cert = ca_crt_dir;
network->tls_opt.ca_cert_len = strlen(network->tls_opt.ca_cert);
network->tls_opt.timeout = 10000;
}
#endif
memset(network->host, 0, sizeof(network->host));
strncpy(network->host, host, sizeof(network->host) - 1);
network->port = port;
rc = qcloud_network_tcp_init(network);
return rc;
}
int qcloud_http_client_connect(HTTPClient *client, const char *url, int port, const char *ca_crt)
{
if (!client->network.is_connected(&client->network)) {
QCLOUD_LOG_E("http client has connected to host!");
return QCLOUD_ERR_HTTP_CONN;
}
int rc;
char host[HTTP_CLIENT_MAX_HOST_LEN] = {0};
rc = _http_client_parse_host(url, host, sizeof(host));
if (rc != QCLOUD_ERR_SUCCESS) return rc;
rc = _http_network_init(&client->network, host, port, ca_crt);
if (rc != QCLOUD_ERR_SUCCESS)
return rc;
rc = _http_client_connect(client);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("http_client_connect is error,rc = %d", rc);
qcloud_http_client_close(client);
} else {
/* reduce log print due to frequent log server connect/disconnect */
QCLOUD_LOG_D("http client connect success");
}
return rc;
}
void qcloud_http_client_close(HTTPClient *client)
{
if (client->network.is_connected(&client->network)) {
client->network.disconnect(&client->network);
}
}
int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method, HTTPClientData *client_data)
{
int rc;
if (!client->network.is_connected(&client->network)) {
rc = qcloud_http_client_connect(client, url, port, ca_crt);
if (rc != QCLOUD_ERR_SUCCESS) return rc;
}
rc = _http_client_send_request(client, url, method, client_data);
if (rc != QCLOUD_ERR_SUCCESS) {
QCLOUD_LOG_E("http_client_send_request is error,rc = %d", rc);
qcloud_http_client_close(client);
return rc;
}
return QCLOUD_ERR_SUCCESS;
}
int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data)
{
QCLOUD_FUNC_ENTRY;
int rc = QCLOUD_ERR_SUCCESS;
osal_timer_t timer;
osal_timer_init(&timer);
osal_timer_countdown_ms(&timer, (unsigned int) timeout_ms);
if ((NULL != client_data->response_buf)
&& (0 != client_data->response_buf_len)) {
rc = _http_client_recv_response(client, osal_timer_remain(&timer), client_data);
if (rc < 0) {
QCLOUD_LOG_E("http_client_recv_response is error,rc = %d", rc);
qcloud_http_client_close(client);
QCLOUD_FUNC_EXIT_RC(rc);
}
}
QCLOUD_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,250 +0,0 @@
/*
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
* License-Identifier: Apache-2.0
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "qcloud.h"
#define json_debug QCLOUD_LOG_D
typedef struct JSON_NV {
int nLen;
int vLen;
int vType;
char *pN;
char *pV;
} JSON_NV;
char *json_get_object(int type, char *str)
{
char *pos = 0;
char ch = (type == JSOBJECT) ? '{' : '[';
while (str != 0 && *str != 0) {
if (*str == ' ') {
str++;
continue;
}
pos = (*str == ch) ? str : 0;
break;
}
return pos;
}
char *json_get_next_object(int type, char *str, char **key, int *key_len,
char **val, int *val_len, int *val_type)
{
char JsonMark[JSTYPEMAX][2] = { { '\"', '\"' }, { '{', '}' }, { '[', ']' }, { '0', ' ' } };
int iMarkDepth = 0, iValueType = JSNONE, iNameLen = 0, iValueLen = 0;
char *p_cName = 0, *p_cValue = 0, *p_cPos = str;
if (type == JSOBJECT) {
/* Get Key */
p_cPos = strchr(p_cPos, '"');
if (!p_cPos) {
return 0;
}
p_cName = ++p_cPos;
p_cPos = strchr(p_cPos, '"');
if (!p_cPos) {
return 0;
}
iNameLen = p_cPos - p_cName;
/* Get Value */
p_cPos = strchr(p_cPos, ':');
}
while (p_cPos && *p_cPos) {
if (*p_cPos == '"') {
iValueType = JSSTRING;
p_cValue = ++p_cPos;
break;
} else if (*p_cPos == '{') {
iValueType = JSOBJECT;
p_cValue = p_cPos++;
break;
} else if (*p_cPos == '[') {
iValueType = JSARRAY;
p_cValue = p_cPos++;
break;
} else if ((*p_cPos == '-') || (*p_cPos >= '0' && *p_cPos <= '9')) {
iValueType = JSNUMBER;
p_cValue = p_cPos++;
break;
} else if (*p_cPos == 't' || *p_cPos == 'T' || *p_cPos == 'f' || *p_cPos == 'F') {
iValueType = JSBOOLEAN;
p_cValue = p_cPos;
break;
}else if (*p_cPos == 'n' || *p_cPos == 'N') {
iValueType = JSNULL;
p_cValue = p_cPos;
break;
}
p_cPos++;
}
while (p_cPos && *p_cPos && iValueType > JSNONE) {
if (iValueType == JSBOOLEAN) {
int len = strlen(p_cValue);
if ((*p_cValue == 't' || *p_cValue == 'T') && len >= 4
&& (!strncmp(p_cValue, "true", 4)
|| !strncmp(p_cValue, "TRUE", 4))) {
iValueLen = 4;
p_cPos = p_cValue + iValueLen;
break;
} else if ((*p_cValue == 'f' || *p_cValue == 'F') && len >= 5
&& (!strncmp(p_cValue, "false", 5)
|| !strncmp(p_cValue, "FALSE", 5))) {
iValueLen = 5;
p_cPos = p_cValue + iValueLen;
break;
}
} else if (iValueType == JSNULL) { //support null/NULL
int nlen = strlen(p_cValue);
if ((*p_cValue == 'n' || *p_cValue == 'N') && nlen >= 4
&& (!strncmp(p_cValue, "null", 4)
|| !strncmp(p_cValue, "NULL", 4))) {
iValueLen = 4;
p_cPos = p_cValue + iValueLen;
break;
}
}
else if (iValueType == JSNUMBER) {
//if (*p_cPos < '0' || *p_cPos > '9') {
if ((*p_cPos < '0' || *p_cPos > '9')&&(*p_cPos != '.')) { //support float
iValueLen = p_cPos - p_cValue;
break;
}
} else if (*p_cPos == JsonMark[iValueType][1]) {
if (iMarkDepth == 0) {
iValueLen = p_cPos - p_cValue + (iValueType == JSSTRING ? 0 : 1);
p_cPos++;
break;
} else {
iMarkDepth--;
}
} else if (*p_cPos == JsonMark[iValueType][0]) {
iMarkDepth++;
}
p_cPos++;
}
if (type == JSOBJECT) {
*key = p_cName;
*key_len = iNameLen;
}
*val = p_cValue;
*val_len = iValueLen;
*val_type = iValueType;
if (iValueType == JSSTRING) {
return p_cValue + iValueLen + 1;
} else {
return p_cValue + iValueLen;
}
}
int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData)
{
char *pos = 0, *key = 0, *val = 0;
int klen = 0, vlen = 0, vtype = 0;
char last_char = 0;
int ret = JSON_RESULT_ERR;
if (p_cJsonStr == NULL || iStrLen == 0 || pfnCB == NULL) {
return ret;
}
if (iStrLen != strlen(p_cJsonStr)) {
QCLOUD_LOG_W("Backup last_char since %d != %d", iStrLen, (int)strlen(p_cJsonStr));
backup_json_str_last_char(p_cJsonStr, iStrLen, last_char);
}
json_object_for_each_kv(p_cJsonStr, pos, key, klen, val, vlen, vtype) {
if (key && klen && val && vlen) {
ret = JSON_RESULT_OK;
if (JSON_PARSE_FINISH == pfnCB(key, klen, val, vlen, vtype, p_CBData)) {
break;
}
}
}
if (iStrLen != strlen(p_cJsonStr)) {
restore_json_str_last_char(p_cJsonStr, iStrLen, last_char);
}
return ret;
}
int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
void *p_CBData)
{
JSON_NV *p_stNameValue = (JSON_NV *)p_CBData;
#if (JSON_DEBUG == 1)
int i;
if (p_cName) {
json_debug("Name:");
for (i = 0; i < iNameLen; i++) {
json_debug("%c", *(p_cName + i));
}
}
if (p_cValue) {
json_debug("Value:");
for (i = 0; i < iValueLen; i++) {
json_debug("%c", *(p_cValue + i));
}
}
#endif
if (!strncmp(p_cName, p_stNameValue->pN, p_stNameValue->nLen)) {
p_stNameValue->pV = p_cValue;
p_stNameValue->vLen = iValueLen;
p_stNameValue->vType = iValueType;
return JSON_PARSE_FINISH;
} else {
return JSON_PARSE_OK;
}
}
char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType)
{
JSON_NV stNV;
memset(&stNV, 0, sizeof(stNV));
stNV.pN = p_cName;
stNV.nLen = strlen(p_cName);
if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) {
if (p_iValueLen) {
*p_iValueLen = stNV.vLen;
}
if (p_iValueType) {
*p_iValueType = stNV.vType;
if(JSNULL == stNV.vType){
stNV.pV = NULL;
}
}
}
return stNV.pV;
}

View File

@@ -1,200 +0,0 @@
/*
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
* License-Identifier: Apache-2.0
*
* 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 "qcloud.h"
#ifndef SCNi8
#define SCNi8 "hhi"
#endif
#ifndef SCNu8
#define SCNu8 "hhu"
#endif
#ifndef SCNi16
#define SCNi16 "hi"
#endif
#ifndef SCNu16
#define SCNu16 "hu"
#endif
#ifndef SCNi32
#define SCNi32 "i"
#endif
#ifndef SCNu32
#define SCNu32 "u"
#endif
char *LITE_json_value_of(char *key, char *src)
{
char *value = NULL;
int value_len = -1;
char *ret = NULL;
char *delim = NULL;
char *key_iter;
char *key_next;
int key_len;
char *src_iter;
src_iter = src;
key_iter = key;
do {
if ((delim = strchr(key_iter, '.')) != NULL) {
key_len = delim - key_iter;
key_next = osal_malloc(key_len + 1);
strncpy(key_next, key_iter, key_len);
key_next[key_len] = '\0';
value = json_get_value_by_name(src_iter, strlen(src_iter), key_next, &value_len, 0);
if (value == NULL) {
osal_free(key_next);
return NULL;
}
src_iter = value;
key_iter = delim + 1;
osal_free(key_next);
}
} while (delim);
value = json_get_value_by_name(src_iter, strlen(src_iter), key_iter, &value_len, 0);
if (NULL == value) {
return NULL;
}
ret = osal_malloc((value_len + 1) * sizeof(char));
if (NULL == ret) {
return NULL;
}
osal_snprintf(ret, value_len + 1, "%s", value);
return ret;
}
list_head_t *LITE_json_keys_of(char *src, char *prefix)
{
static LIST_HEAD(keylist);
char *pos = 0, *key = 0, *val = 0;
int klen = 0, vlen = 0, vtype = 0;
if (src == NULL || prefix == NULL) {
return NULL;
}
if (!strcmp("", prefix)) {
INIT_LIST_HEAD(&keylist);
}
json_object_for_each_kv(src, pos, key, klen, val, vlen, vtype) {
if (key && klen && val && vlen) {
json_key_t *entry = NULL;
entry = osal_malloc(sizeof(json_key_t));
if (NULL == entry) {
return NULL;
}
memset(entry, 0, sizeof(json_key_t));
entry->key = LITE_format_string("%s%.*s", prefix, klen, key);
list_add_tail(&entry->list, &keylist);
if (JSOBJECT == vtype) {
char *iter_val = LITE_format_string("%.*s", vlen, val);
char *iter_pre = LITE_format_string("%s%.*s.", prefix, klen, key);
LITE_json_keys_of(iter_val, iter_pre);
osal_free(iter_val);
osal_free(iter_pre);
}
}
}
if (!strcmp("", prefix)) {
json_key_t *entry = NULL;
entry = osal_malloc(sizeof(json_key_t));
if (NULL == entry) {
return NULL;
}
memset(entry, 0, sizeof(json_key_t));
list_add_tail(&entry->list, &keylist);
return &keylist;
}
return NULL;
}
void LITE_json_keys_release(list_head_t *keylist)
{
json_key_t *pos, *tmp;
list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) {
if (pos->key) {
osal_free(pos->key);
}
list_del(&pos->list);
osal_free(pos);
}
}
qcloud_err_t LITE_get_int32(int32_t *value, char *src) {
return (sscanf(src, "%" SCNi32, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_int16(int16_t *value, char *src) {
return (sscanf(src, "%" SCNi16, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_int8(int8_t *value, char *src) {
return (sscanf(src, "%" SCNi8, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_uint32(uint32_t *value, char *src) {
return (sscanf(src, "%" SCNu32, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_uint16(uint16_t *value, char *src) {
return (sscanf(src, "%" SCNu16, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_uint8(uint8_t *value, char *src) {
return (sscanf(src, "%" SCNu8, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_float(float *value, char *src) {
return (sscanf(src, "%f", value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_double(double *value, char *src) {
return (sscanf(src, "%lf", value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE;
}
qcloud_err_t LITE_get_boolean(bool *value, char *src) {
if (!strcmp(src, "false")) {
*value = false;
}
else {
*value = true;
}
return QCLOUD_ERR_SUCCESS;
}

View File

@@ -1,315 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <string.h>
#include "qcloud.h"
#define MD5_DIGEST_SIZE 16
/* Implementation that should never be optimized out by the compiler */
static void _utils_md5_zeroize(void *v, size_t n)
{
volatile unsigned char *p = v;
while (n--) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef IOT_MD5_GET_UINT32_LE
#define IOT_MD5_GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef IOT_MD5_PUT_UINT32_LE
#define IOT_MD5_PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
}
#endif
void utils_md5_init(iot_md5_context *ctx)
{
memset(ctx, 0, sizeof(iot_md5_context));
}
void utils_md5_free(iot_md5_context *ctx)
{
if (ctx == NULL) {
return;
}
_utils_md5_zeroize(ctx, sizeof(iot_md5_context));
}
void utils_md5_clone(iot_md5_context *dst,
const iot_md5_context *src)
{
*dst = *src;
}
/*
* MD5 context setup
*/
void utils_md5_starts(iot_md5_context *ctx)
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
}
void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64])
{
uint32_t X[16], A, B, C, D;
IOT_MD5_GET_UINT32_LE(X[ 0], data, 0);
IOT_MD5_GET_UINT32_LE(X[ 1], data, 4);
IOT_MD5_GET_UINT32_LE(X[ 2], data, 8);
IOT_MD5_GET_UINT32_LE(X[ 3], data, 12);
IOT_MD5_GET_UINT32_LE(X[ 4], data, 16);
IOT_MD5_GET_UINT32_LE(X[ 5], data, 20);
IOT_MD5_GET_UINT32_LE(X[ 6], data, 24);
IOT_MD5_GET_UINT32_LE(X[ 7], data, 28);
IOT_MD5_GET_UINT32_LE(X[ 8], data, 32);
IOT_MD5_GET_UINT32_LE(X[ 9], data, 36);
IOT_MD5_GET_UINT32_LE(X[10], data, 40);
IOT_MD5_GET_UINT32_LE(X[11], data, 44);
IOT_MD5_GET_UINT32_LE(X[12], data, 48);
IOT_MD5_GET_UINT32_LE(X[13], data, 52);
IOT_MD5_GET_UINT32_LE(X[14], data, 56);
IOT_MD5_GET_UINT32_LE(X[15], data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define P(a,b,c,d,k,s,t) \
{ \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x,y,z) (z ^ (x & (y ^ z)))
P(A, B, C, D, 0, 7, 0xD76AA478);
P(D, A, B, C, 1, 12, 0xE8C7B756);
P(C, D, A, B, 2, 17, 0x242070DB);
P(B, C, D, A, 3, 22, 0xC1BDCEEE);
P(A, B, C, D, 4, 7, 0xF57C0FAF);
P(D, A, B, C, 5, 12, 0x4787C62A);
P(C, D, A, B, 6, 17, 0xA8304613);
P(B, C, D, A, 7, 22, 0xFD469501);
P(A, B, C, D, 8, 7, 0x698098D8);
P(D, A, B, C, 9, 12, 0x8B44F7AF);
P(C, D, A, B, 10, 17, 0xFFFF5BB1);
P(B, C, D, A, 11, 22, 0x895CD7BE);
P(A, B, C, D, 12, 7, 0x6B901122);
P(D, A, B, C, 13, 12, 0xFD987193);
P(C, D, A, B, 14, 17, 0xA679438E);
P(B, C, D, A, 15, 22, 0x49B40821);
#undef F
#define F(x,y,z) (y ^ (z & (x ^ y)))
P(A, B, C, D, 1, 5, 0xF61E2562);
P(D, A, B, C, 6, 9, 0xC040B340);
P(C, D, A, B, 11, 14, 0x265E5A51);
P(B, C, D, A, 0, 20, 0xE9B6C7AA);
P(A, B, C, D, 5, 5, 0xD62F105D);
P(D, A, B, C, 10, 9, 0x02441453);
P(C, D, A, B, 15, 14, 0xD8A1E681);
P(B, C, D, A, 4, 20, 0xE7D3FBC8);
P(A, B, C, D, 9, 5, 0x21E1CDE6);
P(D, A, B, C, 14, 9, 0xC33707D6);
P(C, D, A, B, 3, 14, 0xF4D50D87);
P(B, C, D, A, 8, 20, 0x455A14ED);
P(A, B, C, D, 13, 5, 0xA9E3E905);
P(D, A, B, C, 2, 9, 0xFCEFA3F8);
P(C, D, A, B, 7, 14, 0x676F02D9);
P(B, C, D, A, 12, 20, 0x8D2A4C8A);
#undef F
#define F(x,y,z) (x ^ y ^ z)
P(A, B, C, D, 5, 4, 0xFFFA3942);
P(D, A, B, C, 8, 11, 0x8771F681);
P(C, D, A, B, 11, 16, 0x6D9D6122);
P(B, C, D, A, 14, 23, 0xFDE5380C);
P(A, B, C, D, 1, 4, 0xA4BEEA44);
P(D, A, B, C, 4, 11, 0x4BDECFA9);
P(C, D, A, B, 7, 16, 0xF6BB4B60);
P(B, C, D, A, 10, 23, 0xBEBFBC70);
P(A, B, C, D, 13, 4, 0x289B7EC6);
P(D, A, B, C, 0, 11, 0xEAA127FA);
P(C, D, A, B, 3, 16, 0xD4EF3085);
P(B, C, D, A, 6, 23, 0x04881D05);
P(A, B, C, D, 9, 4, 0xD9D4D039);
P(D, A, B, C, 12, 11, 0xE6DB99E5);
P(C, D, A, B, 15, 16, 0x1FA27CF8);
P(B, C, D, A, 2, 23, 0xC4AC5665);
#undef F
#define F(x,y,z) (y ^ (x | ~z))
P(A, B, C, D, 0, 6, 0xF4292244);
P(D, A, B, C, 7, 10, 0x432AFF97);
P(C, D, A, B, 14, 15, 0xAB9423A7);
P(B, C, D, A, 5, 21, 0xFC93A039);
P(A, B, C, D, 12, 6, 0x655B59C3);
P(D, A, B, C, 3, 10, 0x8F0CCC92);
P(C, D, A, B, 10, 15, 0xFFEFF47D);
P(B, C, D, A, 1, 21, 0x85845DD1);
P(A, B, C, D, 8, 6, 0x6FA87E4F);
P(D, A, B, C, 15, 10, 0xFE2CE6E0);
P(C, D, A, B, 6, 15, 0xA3014314);
P(B, C, D, A, 13, 21, 0x4E0811A1);
P(A, B, C, D, 4, 6, 0xF7537E82);
P(D, A, B, C, 11, 10, 0xBD3AF235);
P(C, D, A, B, 2, 15, 0x2AD7D2BB);
P(B, C, D, A, 9, 21, 0xEB86D391);
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
/*
* MD5 process buffer
*/
void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t ilen)
{
size_t fill;
uint32_t left;
if (ilen == 0) {
return;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if (ctx->total[0] < (uint32_t) ilen) {
ctx->total[1]++;
}
if (left && ilen >= fill) {
memcpy((void *)(ctx->buffer + left), input, fill);
utils_md5_process(ctx, ctx->buffer);
input += fill;
ilen -= fill;
left = 0;
}
while (ilen >= 64) {
utils_md5_process(ctx, input);
input += 64;
ilen -= 64;
}
if (ilen > 0) {
memcpy((void *)(ctx->buffer + left), input, ilen);
}
}
static const unsigned char iot_md5_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD5 final digest
*/
void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16])
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = (ctx->total[0] >> 29)
| (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
IOT_MD5_PUT_UINT32_LE(low, msglen, 0);
IOT_MD5_PUT_UINT32_LE(high, msglen, 4);
last = ctx->total[0] & 0x3F;
padn = (last < 56) ? (56 - last) : (120 - last);
utils_md5_update(ctx, iot_md5_padding, padn);
utils_md5_update(ctx, msglen, 8);
IOT_MD5_PUT_UINT32_LE(ctx->state[0], output, 0);
IOT_MD5_PUT_UINT32_LE(ctx->state[1], output, 4);
IOT_MD5_PUT_UINT32_LE(ctx->state[2], output, 8);
IOT_MD5_PUT_UINT32_LE(ctx->state[3], output, 12);
}
/*
* output = MD5( input buffer )
*/
void utils_md5(const unsigned char *input, size_t ilen, unsigned char output[16])
{
iot_md5_context ctx;
utils_md5_init(&ctx);
utils_md5_starts(&ctx);
utils_md5_update(&ctx, input, ilen);
utils_md5_finish(&ctx, output);
utils_md5_free(&ctx);
}
int8_t utils_hb2hex(uint8_t hb)
{
hb = hb & 0xF;
return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,335 +0,0 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* 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 <stdlib.h>
#include <string.h>
#include "qcloud.h"
/* Implementation that should never be optimized out by the compiler */
static void utils_sha1_zeroize(void *v, size_t n)
{
volatile unsigned char *p = v;
while (n--) {
*p++ = 0;
}
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef IOT_SHA1_GET_UINT32_BE
#define IOT_SHA1_GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef IOT_SHA1_PUT_UINT32_BE
#define IOT_SHA1_PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
void utils_sha1_init(iot_sha1_context *ctx)
{
memset(ctx, 0, sizeof(iot_sha1_context));
}
void utils_sha1_free(iot_sha1_context *ctx)
{
if (ctx == NULL) {
return;
}
utils_sha1_zeroize(ctx, sizeof(iot_sha1_context));
}
void utils_sha1_clone(iot_sha1_context *dst,
const iot_sha1_context *src)
{
*dst = *src;
}
/*
* SHA-1 context setup
*/
void utils_sha1_starts(iot_sha1_context *ctx)
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
{
uint32_t temp, W[16], A, B, C, D, E;
IOT_SHA1_GET_UINT32_BE(W[ 0], data, 0);
IOT_SHA1_GET_UINT32_BE(W[ 1], data, 4);
IOT_SHA1_GET_UINT32_BE(W[ 2], data, 8);
IOT_SHA1_GET_UINT32_BE(W[ 3], data, 12);
IOT_SHA1_GET_UINT32_BE(W[ 4], data, 16);
IOT_SHA1_GET_UINT32_BE(W[ 5], data, 20);
IOT_SHA1_GET_UINT32_BE(W[ 6], data, 24);
IOT_SHA1_GET_UINT32_BE(W[ 7], data, 28);
IOT_SHA1_GET_UINT32_BE(W[ 8], data, 32);
IOT_SHA1_GET_UINT32_BE(W[ 9], data, 36);
IOT_SHA1_GET_UINT32_BE(W[10], data, 40);
IOT_SHA1_GET_UINT32_BE(W[11], data, 44);
IOT_SHA1_GET_UINT32_BE(W[12], data, 48);
IOT_SHA1_GET_UINT32_BE(W[13], data, 52);
IOT_SHA1_GET_UINT32_BE(W[14], data, 56);
IOT_SHA1_GET_UINT32_BE(W[15], data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P(A, B, C, D, E, W[0]);
P(E, A, B, C, D, W[1]);
P(D, E, A, B, C, W[2]);
P(C, D, E, A, B, W[3]);
P(B, C, D, E, A, W[4]);
P(A, B, C, D, E, W[5]);
P(E, A, B, C, D, W[6]);
P(D, E, A, B, C, W[7]);
P(C, D, E, A, B, W[8]);
P(B, C, D, E, A, W[9]);
P(A, B, C, D, E, W[10]);
P(E, A, B, C, D, W[11]);
P(D, E, A, B, C, W[12]);
P(C, D, E, A, B, W[13]);
P(B, C, D, E, A, W[14]);
P(A, B, C, D, E, W[15]);
P(E, A, B, C, D, R(16));
P(D, E, A, B, C, R(17));
P(C, D, E, A, B, R(18));
P(B, C, D, E, A, R(19));
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P(A, B, C, D, E, R(20));
P(E, A, B, C, D, R(21));
P(D, E, A, B, C, R(22));
P(C, D, E, A, B, R(23));
P(B, C, D, E, A, R(24));
P(A, B, C, D, E, R(25));
P(E, A, B, C, D, R(26));
P(D, E, A, B, C, R(27));
P(C, D, E, A, B, R(28));
P(B, C, D, E, A, R(29));
P(A, B, C, D, E, R(30));
P(E, A, B, C, D, R(31));
P(D, E, A, B, C, R(32));
P(C, D, E, A, B, R(33));
P(B, C, D, E, A, R(34));
P(A, B, C, D, E, R(35));
P(E, A, B, C, D, R(36));
P(D, E, A, B, C, R(37));
P(C, D, E, A, B, R(38));
P(B, C, D, E, A, R(39));
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P(A, B, C, D, E, R(40));
P(E, A, B, C, D, R(41));
P(D, E, A, B, C, R(42));
P(C, D, E, A, B, R(43));
P(B, C, D, E, A, R(44));
P(A, B, C, D, E, R(45));
P(E, A, B, C, D, R(46));
P(D, E, A, B, C, R(47));
P(C, D, E, A, B, R(48));
P(B, C, D, E, A, R(49));
P(A, B, C, D, E, R(50));
P(E, A, B, C, D, R(51));
P(D, E, A, B, C, R(52));
P(C, D, E, A, B, R(53));
P(B, C, D, E, A, R(54));
P(A, B, C, D, E, R(55));
P(E, A, B, C, D, R(56));
P(D, E, A, B, C, R(57));
P(C, D, E, A, B, R(58));
P(B, C, D, E, A, R(59));
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P(A, B, C, D, E, R(60));
P(E, A, B, C, D, R(61));
P(D, E, A, B, C, R(62));
P(C, D, E, A, B, R(63));
P(B, C, D, E, A, R(64));
P(A, B, C, D, E, R(65));
P(E, A, B, C, D, R(66));
P(D, E, A, B, C, R(67));
P(C, D, E, A, B, R(68));
P(B, C, D, E, A, R(69));
P(A, B, C, D, E, R(70));
P(E, A, B, C, D, R(71));
P(D, E, A, B, C, R(72));
P(C, D, E, A, B, R(73));
P(B, C, D, E, A, R(74));
P(A, B, C, D, E, R(75));
P(E, A, B, C, D, R(76));
P(D, E, A, B, C, R(77));
P(C, D, E, A, B, R(78));
P(B, C, D, E, A, R(79));
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen)
{
size_t fill;
uint32_t left;
if (ilen == 0) {
return;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if (ctx->total[0] < (uint32_t) ilen) {
ctx->total[1]++;
}
if (left && ilen >= fill) {
memcpy((void *)(ctx->buffer + left), input, fill);
utils_sha1_process(ctx, ctx->buffer);
input += fill;
ilen -= fill;
left = 0;
}
while (ilen >= 64) {
utils_sha1_process(ctx, input);
input += 64;
ilen -= 64;
}
if (ilen > 0) {
memcpy((void *)(ctx->buffer + left), input, ilen);
}
}
static const unsigned char iot_sha1_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = (ctx->total[0] >> 29)
| (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
IOT_SHA1_PUT_UINT32_BE(high, msglen, 0);
IOT_SHA1_PUT_UINT32_BE(low, msglen, 4);
last = ctx->total[0] & 0x3F;
padn = (last < 56) ? (56 - last) : (120 - last);
utils_sha1_update(ctx, iot_sha1_padding, padn);
utils_sha1_update(ctx, msglen, 8);
IOT_SHA1_PUT_UINT32_BE(ctx->state[0], output, 0);
IOT_SHA1_PUT_UINT32_BE(ctx->state[1], output, 4);
IOT_SHA1_PUT_UINT32_BE(ctx->state[2], output, 8);
IOT_SHA1_PUT_UINT32_BE(ctx->state[3], output, 12);
IOT_SHA1_PUT_UINT32_BE(ctx->state[4], output, 16);
}
/*
* output = SHA-1( input buffer )
*/
void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20])
{
iot_sha1_context ctx;
utils_sha1_init(&ctx);
utils_sha1_starts(&ctx);
utils_sha1_update(&ctx, input, ilen);
utils_sha1_finish(&ctx, output);
utils_sha1_free(&ctx);
}

View File

@@ -1,174 +0,0 @@
/*
* Copyright (c) 2017-2019 Tencent Group. All rights reserved.
* License-Identifier: Apache-2.0
*
* 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 "qcloud.h"
char *LITE_format_string(const char *fmt, ...)
{
#define TEMP_STRING_MAXLEN (512)
va_list ap;
char *tmp = NULL;
char *dst;
int rc = -1;
va_start(ap, fmt);
tmp = osal_malloc(TEMP_STRING_MAXLEN);
if(NULL == tmp)
{
return NULL;
}
memset(tmp, 0, TEMP_STRING_MAXLEN);
rc = osal_vsnprintf(tmp, TEMP_STRING_MAXLEN, fmt, ap);
va_end(ap);
LITE_ASSERT(tmp);
LITE_ASSERT(rc < 1024);
dst = LITE_strdup(tmp);
osal_free(tmp);
return dst;
#undef TEMP_STRING_MAXLEN
}
char *LITE_format_nstring(const int len, const char *fmt, ...)
{
va_list ap;
char *tmp = NULL;
char *dst;
int rc = -1;
va_start(ap, fmt);
tmp = osal_malloc(len+2);
if(NULL == tmp)
{
return NULL;
}
memset(tmp, 0, len+2);
rc = osal_vsnprintf(tmp, len+1, fmt, ap);
va_end(ap);
LITE_ASSERT(tmp);
LITE_ASSERT(rc < 1024);
dst = osal_malloc(len + 1);
osal_snprintf(dst, (len + 1), "%s", tmp);
osal_free(tmp);
return dst;
}
char *LITE_strdup(const char *src)
{
int len = 0;
char *dst = NULL;
if (!src) {
return NULL;
}
len = strlen(src) + 1;
if (len > 1024) {
QCLOUD_LOG_E("Too long string to duplicate, abort! len = %d", len);
return NULL;
}
dst = (char *)osal_malloc(sizeof(char) * len);
if (!dst) {
return NULL;
}
strncpy(dst, src, len);
return dst;
}
void LITE_hexbuf_convert(unsigned char *digest, char *out, int in_len, int uppercase)
{
static char *zEncode[] = {"0123456789abcdef", "0123456789ABCDEF"};
int j = 0;
int i = 0;
int idx = uppercase ? 1 : 0;
for (i = 0; i < in_len; i ++) {
int a = digest[i];
out[j++] = zEncode[idx][(a >> 4) & 0xf];
out[j++] = zEncode[idx][a & 0xf];
}
}
static uint8_t _hexval_of_char(char hex)
{
if (LITE_isdigit(hex)) {
return (hex - '0');
}
if (hex >= 'a' && hex <= 'f') {
return (hex - 'a' + 10);
}
if (hex >= 'A' && hex <= 'F') {
return (hex - 'A' + 10);
}
return 0;
}
void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int in_len)
{
int i = 0;
uint8_t ch0, ch1;
if (in_len % 2 != 0) {
QCLOUD_LOG_E("hexstr length (%d) is not even", in_len);
return;
}
while (i < in_len) {
ch0 = _hexval_of_char((char)hexstr[2 * i]);
ch1 = _hexval_of_char((char)hexstr[2 * i + 1]);
out_buf[i] = (ch0 << 4 | ch1);
i++;
}
}
void LITE_replace_substr(char originalString[], char key[], char swap[])
{
int lengthOfOriginalString, lengthOfKey, lengthOfSwap, i, j, flag;
char tmp[512];
lengthOfOriginalString = strlen(originalString);
lengthOfKey = strlen(key);
lengthOfSwap = strlen(swap);
for (i = 0; i <= lengthOfOriginalString - lengthOfKey; i++) {
flag = 1;
for (j = 0; j < lengthOfKey; j++) {
if (originalString[i + j] != key[j]) {
flag = 0;
break;
}
}
if (flag) {
strcpy(tmp, originalString);
strcpy(&tmp[i], swap);
strcpy(&tmp[i + lengthOfSwap], &originalString[i + lengthOfKey]);
strcpy(originalString, tmp);
i += lengthOfSwap - 1;
lengthOfOriginalString = strlen(originalString);
}
}
}

View File

@@ -1,352 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import sys
import os
import argparse
import glob
#import cStringIO
reload(sys)
sys.setdefaultencoding("utf-8")
try: import simplejson as json
except: import json
# {"version":"1.0","properties":[{"id":"light_switch","name":"电灯开关","desc":"控制电灯开灭","required":true,"mode":"rw","define":{"type":"bool","mapping":{"0":"关","1":"开"}}},{"id":"color","name":"颜色","desc":"灯光颜色","mode":"rw","define":{"type":"enum","mapping":{"0":"Red","1":"Green","2":"Blue"}}},{"id":"brightness","name":"颜色","desc":"灯光颜色","mode":"rw","define":{"type":"int","unit":"%","unitDesc":"亮度百分比","min":"0","max":"100"}},{"id":"name","name":"灯位置名称","desc":"灯位置名称:书房、客厅等","mode":"rw","required":true,"define":{"type":"string","min":"0","max":"64"}}]}
class TEMPLATE_CONSTANTS:
VERSION = "version"
TYPE = "type"
NAME = "name"
ID = "id"
MIN = "min"
MAX = "max"
DEFINE = "define"
PROPERTIES = "properties"
EVENTS = "events"
MAPPING = "mapping"
UNIT = "unit"
UNITDESC = "unitDesc"
REQUIRED = "required"
MODE = "mode"
class iot_enum:
def __init__(self, parent, name, index):
self.parent = parent
self.id = name
self.index = index
def get_c_macro_name(self):
return "e_{}_{}".format(self.parent.upper(), self.id.upper())
def get_define_str(self):
return "#define {} {}".format(self.get_c_macro_name(), self.index)
class iot_field:
def __init__(self,id, name, index, field_obj):
self.default_value = ""
self.enums = []
self.index = index
self.id = id
self.name = name
self.type_name = field_obj["define"]["type"]
if self.type_name == "bool":
self.type_define = "TYPE_DEF_TEMPLATE_BOOL"
self.type_id = "TYPE_TEMPLATE_BOOL"
self.default_value = "0"
elif self.type_name == "enum":
self.type_define = "TYPE_DEF_TEMPLATE_NUM"
self.type_id = "TYPE_TEMPLATE_NUM"
if TEMPLATE_CONSTANTS.DEFINE not in field_obj:
raise ValueError("错误:{} 字段定义中未找到枚举定义{} 字段".format(name, TEMPLATE_CONSTANTS.DEFINE))
enum_defs = field_obj["define"]["mapping"]
for enum_id in enum_defs:
enum_name = enum_defs[enum_id]
current_enum = iot_enum(self.id, enum_name, enum_id)
self.enums.append(current_enum)
if self.default_value == "":
self.default_value = enum_id
if self.default_value == "":
raise ValueError("错误:{} 字段默认值 {} 非法".format(name, field_obj["default"]))
elif self.type_name == "float":
self.type_define = "TYPE_DEF_TEMPLATE_FLOAT"
self.type_id = "TYPE_TEMPLATE_FLOAT"
self.min_value = field_obj["define"]["min"]
self.max_value = field_obj["define"]["max"]
self.default_value = field_obj["define"]["start"]
if float(self.default_value) < float(self.min_value) or float(self.default_value) > float(self.max_value):
raise ValueError("错误:{} 字段 default 指定的默认值超出 min~max 取值范围".format(name))
elif self.type_name == "int":
self.type_define = "TYPE_DEF_TEMPLATE_INT"
self.type_id = "TYPE_TEMPLATE_INT"
self.min_value = field_obj["define"]["min"]
self.max_value = field_obj["define"]["max"]
self.default_value = field_obj["define"]["start"]
if int(self.default_value) < int(self.min_value) or int(self.default_value) > int(self.max_value):
raise ValueError("错误:{} 字段 default 指定的默认值超出 min~max 取值范围".format(name))
elif self.type_name == "string":
self.type_define = "TYPE_DEF_TEMPLATE_STRING"
self.type_id = "TYPE_TEMPLATE_STRING"
self.min_value = field_obj["define"]["min"]
self.max_value = field_obj["define"]["max"]
self.default_value = "{'\\0'}"
elif self.type_name == "timestamp":
self.type_define = "TYPE_DEF_TEMPLATE_TIME"
self.type_id = "TYPE_TEMPLATE_TIME"
self.default_value = 0
else:
raise ValueError('{} 字段 数据类型 type={} 取值非法有效值应为bool,enum,int,float,string'.format(name, field_obj["type"]))
def get_id_c_macro_name(self):
return "TC_IOT_PROP_{}".format(self.id)
def get_id_c_member_name(self):
return "m_{}".format(self.id)
def get_id_default_value(self):
return "{}".format(self.default_value)
def get_id_define_str(self):
return "#define {} {}".format(self.get_id_c_macro_name(), self.index)
def get_struct_field_declare(self):
if self.type_id == "TYPE_TEMPLATE_STRING":
return "TYPE_DEF_TEMPLATE_STRING m_{}[{}+1];".format(self.id, str(self.max_value))
else:
return "{} m_{};".format(self.type_define, self.id)
def get_global_field_declare(self):
if self.type_id == "TYPE_TEMPLATE_STRING":
return "TYPE_DEF_TEMPLATE_STRING sg_{}[{}+1]={};".format(self.id, str(self.max_value),"{0}")
else:
return "{} sg_{} = {};".format(self.type_define, self.id, self.default_value)
def get_meta_define_str(self, var_name):
return '{{ "{}", &{}.{}, {} }},' \
.format(self.id, var_name, self.get_id_c_member_name(), self.type_id)
class iot_event:
def __init__(self,id, name, index, event):
self.index = index
self.id = id
self.name = name
self.event_type = event["type"]
self.desc = event["desc"]
self.event_properties = []
self.event_property_count = 0
for property in event["params"]:
self.event_properties.append(iot_field(property["id"], property["name"], self.event_property_count, property))
self.event_property_count += 1
def get_sigle_event_info(self):
event_info = ""
event_info += "\n id:{} name:\"{}\" type:\"{}\"\n".format(self.id, self.name, self.event_type)
event_info += " property_count:{} \n params:[".format(self.event_property_count)
for field in self.event_properties:
event_info += "\n para:{} type:{}".format(field.id, field.type_id)
event_info += "\n ]"
return event_info
def gen_sigle_event_info(self):
resault = ""
event_para_info = ""
event_property_info = ""
event_var_info = ""
for field in self.event_properties:
event_para_info += "static {}\n".format(field.get_global_field_declare())
event_property_info += "\n {"
if field.type_id == "TYPE_TEMPLATE_STRING":
event_property_info += ".key = \"{}\", .data = sg_{}, .type = {}".format(field.id, field.id, field.type_id)
else:
event_property_info += ".key = \"{}\", .data = &sg_{}, .type = {}".format(field.id, field.id, field.type_id)
event_property_info += "},"
event_var_info += "static DeviceProperty g_propertyEvent_{}[] = ".format(self.id)
resault += event_para_info + event_var_info + "{\n"+event_property_info + "\n};\n"
return resault
class iot_struct:
def __init__(self, model):
self.version = model["version"]
self.fields = []
self.field_id = 0
self.events = []
self.event_id = 0
for field_define in model["properties"]:
if TEMPLATE_CONSTANTS.NAME not in field_define:
raise ValueError("错误:字段定义中未找到 Name 字段")
self.fields.append(iot_field(field_define["id"], field_define["name"], self.field_id, field_define))
self.field_id += 1
for event in model["events"]:
if TEMPLATE_CONSTANTS.NAME not in event:
raise ValueError("错误:字段定义中未找到 Name 字段")
self.events.append(iot_event(event["id"], event["name"], self.event_id, event))
self.event_id += 1
def dump_data_info(self):
print("dump iot struct,counts:{}".format(self.field_id))
for temp_field in self.fields:
if temp_field.type_name == "enum":
print("{} {} {} {} ".format(temp_field.id, temp_field.type_name, temp_field.default_value, temp_field.type_define))
print("enums:{")
for enum in temp_field.enums:
print("{} ".format(enum.get_c_macro_name()))
print("}")
else:
print("{} {} {} {}\n".format(temp_field.id, temp_field.type_name, temp_field.default_value,
temp_field.type_define))
def dump_event_info(self):
count = 0
event_str = ""
event_str += ("#define EVENT_COUNTS ({})\n").format(self.event_id)
for event_d in self.events:
event_str += "{}\n".format(event_d.gen_sigle_event_info())
count += 1
return event_str
def data_config_macro_define(self, struct_Template="sDataPoint",var_gTemplate="sg_DataTemplate"):
define_str = ""
define_str += "/*-----------------data config start -------------------*/ \n\n"
define_str += "#define TOTAL_PROPERTY_COUNT {}\n\n".format(self.field_id)
define_str += "static {} {}[TOTAL_PROPERTY_COUNT];\n\n".format(struct_Template, var_gTemplate)
return define_str
def declare_product_data_struct(self, struct_name="ProductDataDefine", var_gname="sg_ProductData"):
result = ""
result += "typedef struct _" + struct_name + " {\n"
for field in self.fields:
result += " {}\n".format(field.get_struct_field_declare())
result += "} " + struct_name + ";\n\n"
result += "static " + struct_name + " "+var_gname + ";\n\n"
return result
def property_data_initializer(self, struct_name="ProductDataDefine", var_gProduct="sg_ProductData", var_gTemplate="sg_DataTemplate"):
count = 0
init_str = ""
init_str += "static void _init_data_template(void)\n{\n"
#init_str += " memset((void *) & {}, 0, sizeof({}));\n".format(var_gProduct, struct_name)
for field in self.fields:
if field.type_define == "TYPE_DEF_TEMPLATE_STRING":
init_str += " {}.{}[0] = {};\n".format(var_gProduct, field.get_id_c_member_name(), "'\\0'")
init_str += " {}[{}].data_property.data = {}.{};\n".format(var_gTemplate, count, var_gProduct, field.get_id_c_member_name())
else:
init_str += " {}.{} = {};\n".format(var_gProduct, field.get_id_c_member_name(),field.get_id_default_value())
init_str += " {}[{}].data_property.data = &{}.{};\n".format(var_gTemplate, count, var_gProduct, field.get_id_c_member_name())
init_str += " {}[{}].data_property.key = \"{}\";\n".format(var_gTemplate, count, field.id)
init_str += " {}[{}].data_property.type = {};\n\n".format(var_gTemplate, count, field.type_id)
count += 1
init_str += "};\n"
return init_str;
def gen_data_config(self):
data_config = ""
data_config +="{}".format(self.data_config_macro_define())
data_config +="{}".format(self.declare_product_data_struct())
data_config += "{}".format(self.property_data_initializer())
return data_config
def gen_event_config(self):
resault = ""
event_config = ""
events_var = ""
event_str = ""
event_config += ("\n#define EVENT_COUNTS ({})\n\n").format(self.event_id)
events_var += "\nstatic sEvent g_events[]={\n"
for event_d in self.events:
event_config += "{}\n".format(event_d.gen_sigle_event_info())
event_str += "\n {"
event_str += "\n .event_name = \"{}\",".format(event_d.id)
event_str += "\n .type = \"{}\",".format(event_d.event_type)
event_str += "\n .timestamp = 0,"
event_str += "\n .eventDataNum = sizeof(g_propertyEvent_{})/sizeof(g_propertyEvent_{}[0]),".format(event_d.id, event_d.id)
event_str += "\n .pEventData = g_propertyEvent_{},".format(event_d.id)
event_str +="\n },"
resault += event_config + events_var + event_str + "\n};\n"
return resault
def main():
parser = argparse.ArgumentParser(description='Iothub datatemplate and events config code generator.', usage='use "./codegen.py -c xx/config.json" gen config code')
parser.add_argument('-c','--config', dest='config',metavar='xxx.json', required=False,default='xxx.json',
help='copy the generated file (data_config.c and events_config.c) to datatemplate_sample dir '
'or your own code dir with datatemplate. '
'\nconfig file can be download from tencent iot-hub platfrom. https://console.cloud.tencent.com/iotcloud')
parser.add_argument('-d','--dest', dest='dest', required=False,default='.',
help='Dest directory for generated code files, no / at the end.')
args = parser.parse_args()
config_path = args.config
if not os.path.exists(config_path):
print(u"错误:配置文件不存在,请重新指定数据模板配置文件路径,请参考用法 ./codegen.py -c xx/data_template.json".format(config_path))
return 1
config_dir = os.path.dirname(config_path)
if config_dir:
config_dir += "/"
f = open(config_path, "r")
try:
thingmodel = json.load(f)
if 'properties' not in thingmodel:
thingmodel.properties = []
if 'events' not in thingmodel:
thingmodel.events = []
print(u"加载 {} 文件成功".format(config_path))
except ValueError as e:
print(u"错误:文件格式非法,请检查 {} 文件是否是 JSON 格式。".format(config_path))
return 1
if TEMPLATE_CONSTANTS.PROPERTIES not in thingmodel:
print(u"错误:{} 文件中未发现 DataTemplate 属性字段,请检查文件格式是否合法。".format(config_path))
return 1
try:
snippet = iot_struct(thingmodel)
output_data_config_file_name = args.dest + "/data_config.c"
output_file = open(output_data_config_file_name, "w")
output_file.write("{}".format(snippet.gen_data_config()))
output_file.close()
output_event_config_file_name = args.dest + "/events_config.c"
output_file = open(output_event_config_file_name, "w")
output_file.write("#if (QCLOUD_CFG_EVENT_EN > 0u)\n{}\n#endif\n".format(snippet.gen_event_config()))
output_file.close()
print(u"文件 {} 生成成功".format(output_data_config_file_name))
print(u"文件 {} 生成成功".format(output_event_config_file_name))
return 0
except ValueError as e:
print(e)
return 1
if __name__ == '__main__':
sys.exit(main())

View File

@@ -1,230 +0,0 @@
{
"version":"1.0",
"properties":[
{
"id":"time",
"name":"time",
"required":false,
"desc":"",
"mode":"rw",
"define":{
"type":"timestamp"
}
},
{
"id":"float",
"name":"float",
"required":false,
"desc":"",
"mode":"r",
"define":{
"type":"float",
"min":"-10",
"max":"10",
"start":"-5",
"step":"0.5",
"unit":"cm"
}
},
{
"id":"light_switch",
"name":"电灯开关",
"required":true,
"desc":"控制电灯开灭",
"mode":"rw",
"define":{
"type":"bool",
"mapping":{
"0":"关",
"1":"开"
}
}
},
{
"id":"color",
"name":"颜色",
"desc":"灯光颜色",
"mode":"rw",
"define":{
"type":"enum",
"mapping":{
"0":"Red",
"1":"Green",
"2":"Blue"
}
}
},
{
"id":"brightness",
"name":"颜色",
"required":false,
"desc":"灯光颜色",
"mode":"rw",
"define":{
"type":"int",
"min":"-9",
"max":"100",
"start":"-1",
"step":"5",
"unit":"cm"
}
},
{
"id":"name",
"name":"灯位置名称",
"desc":"灯位置名称:书房、客厅等",
"mode":"rw",
"required":true,
"define":{
"type":"string",
"min":"1",
"max":"64"
}
}
],
"events":[
{
"id":"all_function",
"name":"ALL_FUNCTION",
"required":false,
"desc":"",
"params":[
{
"id":"bool",
"name":"bool",
"desc":"",
"define":{
"type":"bool",
"mapping":{
"0":"关",
"1":"开"
}
}
},
{
"id":"int",
"name":"int",
"desc":"",
"define":{
"type":"int",
"min":"1",
"max":"100",
"start":"1",
"step":"1",
"unit":"cm"
}
},
{
"id":"str",
"name":"str",
"desc":"",
"define":{
"type":"string",
"min":"1",
"max":"64"
}
},
{
"id":"float",
"name":"float",
"desc":"",
"define":{
"type":"float",
"min":"0",
"max":"100",
"start":"0",
"step":"1.5",
"unit":"cm"
}
},
{
"id":"enum1",
"name":"enum1",
"desc":"",
"define":{
"type":"enum",
"mapping":{
"0":"color",
"1":"door"
}
}
},
{
"id":"time",
"name":"time",
"desc":"",
"define":{
"type":"timestamp"
}
}
],
"type":"alert"
},
{
"id":"status_report",
"name":"DeviceStatus",
"desc":"Report the device status我是中文",
"type":"info",
"required":true,
"params":[
{
"id":"status",
"name":"running_state",
"desc":"Report current device running state",
"define":{
"type":"bool",
"mapping":{
"0":"normal",
"1":"fault"
}
}
},
{
"id":"message",
"name":"Message",
"desc":"Some extra message",
"define":{
"type":"string",
"min":"1",
"max":"64"
}
}
]
},
{
"id":"hardware_fault",
"name":"Hardware_fault",
"required":false,
"desc":"Report hardware fault",
"params":[
{
"id":"name",
"name":"Name",
"desc":"Name like: memory,tf card, censors ...",
"define":{
"type":"string",
"min":"1",
"max":"64"
}
},
{
"id":"error_code",
"name":"Error_Code",
"desc":"Error code for fault",
"define":{
"type":"int",
"unit":"",
"step":"1",
"min":"0",
"max":"2000",
"start":"0"
}
}
],
"type":"fault"
}
],
"profile":{
"productID":"C0NEMO9UO0"
}
}