first commit for opensource

first commit for opensource
This commit is contained in:
supowang
2019-09-16 13:19:50 +08:00
parent 08ab013b8e
commit edb2879617
6303 changed files with 5472815 additions and 23 deletions

View File

@@ -0,0 +1,51 @@
#ifndef _QCLOUD_
#define _QCLOUD_
#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

View File

@@ -0,0 +1,323 @@
/*
* 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

@@ -0,0 +1,75 @@
/*
* 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

@@ -0,0 +1,27 @@
#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

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

View File

@@ -0,0 +1,28 @@
#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

@@ -0,0 +1,45 @@
#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

@@ -0,0 +1,32 @@
#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

@@ -0,0 +1,19 @@
#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

@@ -0,0 +1,112 @@
#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, // 表示TCP连接建立套接字失败
QCLOUD_ERR_UDP_UNKNOWN_HOST = -602, // 表示无法通过主机名获取IP地址
QCLOUD_ERR_UDP_CONNECT = -603, // 表示建立TCP连接失败
QCLOUD_ERR_UDP_READ_TIMEOUT = -604, // 表示TCP读超时
QCLOUD_ERR_UDP_WRITE_TIMEOUT = -605, // 表示TCP写超时
QCLOUD_ERR_UDP_READ_FAIL = -606, // 表示TCP读错误
QCLOUD_ERR_UDP_WRITE_FAIL = -607, // 表示TCP写错误
QCLOUD_ERR_UDP_NOTHING_TO_READ = -609, // 表示底层没有数据可以读取
} qcloud_err_t;
#endif

View File

@@ -0,0 +1,129 @@
#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

@@ -0,0 +1,150 @@
/*
* 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

@@ -0,0 +1,57 @@
#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

@@ -0,0 +1,173 @@
#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

@@ -0,0 +1,310 @@
#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

@@ -0,0 +1,34 @@
#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

@@ -0,0 +1,36 @@
#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

@@ -0,0 +1,13 @@
#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

@@ -0,0 +1,29 @@
#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

@@ -0,0 +1,13 @@
#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

@@ -0,0 +1,23 @@
#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

@@ -0,0 +1,13 @@
#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

@@ -0,0 +1,13 @@
#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

@@ -0,0 +1,273 @@
#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 设备属性处理回调函数
*
* @param pJsonValueBuffer 设备属性值
* @param valueLength 设备属性值长度
* @param DeviceProperty 设备属性结构体
*/
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 每次文档请求响应的回调函数
*
* @param method 文档操作方式
* @param requestAck 请求响应类型
* @param pJsonDocument 云端响应返回的文档
* @param userContext 用户数据
*
*/
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

@@ -0,0 +1,15 @@
#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

@@ -0,0 +1,104 @@
#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

@@ -0,0 +1,16 @@
#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

@@ -0,0 +1,317 @@
/*
* 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

@@ -0,0 +1,36 @@
/*
* 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

@@ -0,0 +1,26 @@
/*
* 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

@@ -0,0 +1,80 @@
/*
* 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

@@ -0,0 +1,157 @@
/*
* 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

@@ -0,0 +1,109 @@
#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

@@ -0,0 +1,92 @@
/*
* 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

@@ -0,0 +1,495 @@
/*
* 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

@@ -0,0 +1,92 @@
/*
* 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

@@ -0,0 +1,87 @@
/*
* 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