first commit for opensource
first commit for opensource
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -0,0 +1,5 @@
|
||||
#ifndef _QCLOUD_CONFIG_CHECK_
|
||||
#define _QCLOUD_CONFIG_CHECK_
|
||||
|
||||
#endif
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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_ */
|
@@ -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
|
||||
|
@@ -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_ */
|
@@ -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__ */
|
@@ -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_ */
|
||||
|
@@ -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__ */
|
||||
|
@@ -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
|
@@ -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
|
||||
|
@@ -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
|
Reference in New Issue
Block a user