update qcloud sdk

1. iot-hub sdk update to 3.2.0
2. iot-explorer update to 3.1.1
This commit is contained in:
daishengdong
2020-05-07 11:11:04 +08:00
parent c8e39739d3
commit 3e631cd96a
594 changed files with 47287 additions and 44165 deletions

View File

@@ -0,0 +1,872 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "at_client.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "at_utils.h"
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "utils_param_check.h"
#include "utils_timer.h"
#define AT_RESP_END_OK "OK"
#define AT_RESP_END_ERROR "ERROR"
#define AT_RESP_END_FAIL "FAIL"
#define AT_END_CR_LF "\r\n"
sRingbuff g_ring_buff;
static at_client sg_at_client = {0};
static uint32_t sg_flags = 0;
/*this function can be called only by at_uart_isr, just push the data to the at_client ringbuffer.*/
void at_client_uart_rx_isr_cb(uint8_t *pdata, uint8_t len)
{
(void)ring_buff_push_data(&g_ring_buff, pdata, len);
}
/**
* Create response object.
*
* @param buf_size the maximum response buffer size
* @param line_num the number of setting response lines
* = 0: the response data will auto return when received 'OK' or 'ERROR'
* != 0: the response data will return when received setting lines number data
* @param timeout the maximum response time
*
* @return != NULL: response object
* = NULL: no memory
*/
at_response_t at_create_resp(uint32_t buf_size, uint32_t line_num, uint32_t timeout)
{
at_response_t resp = NULL;
resp = (at_response_t)HAL_Malloc(sizeof(at_response));
if (resp == NULL) {
Log_e("AT create response object failed! No memory for response object!");
return NULL;
}
resp->buf = (char *)HAL_Malloc(buf_size);
if (resp->buf == NULL) {
Log_e("AT create response object failed! No memory for response buffer!");
HAL_Free(resp);
return NULL;
}
resp->buf_size = buf_size;
resp->line_num = line_num;
resp->line_counts = 0;
resp->timeout = timeout;
return resp;
}
/**
* Delete and free response object.
*
* @param resp response object
*/
void at_delete_resp(at_response_t resp)
{
if (resp && resp->buf) {
HAL_Free(resp->buf);
}
if (resp) {
HAL_Free(resp);
resp = NULL;
}
}
void at_delayms(uint32_t delayms)
{
#ifdef AT_OS_USED
HAL_SleepMs(delayms);
#else
HAL_DelayMs(delayms);
#endif
}
void at_setFlag(uint32_t flag)
{
sg_flags |= flag & 0xffffffff;
}
void at_clearFlag(uint32_t flag)
{
sg_flags &= (~flag) & 0xffffffff;
}
uint32_t at_getFlag(void)
{
return sg_flags;
}
bool at_waitFlag(uint32_t flag, uint32_t timeout)
{
Timer timer;
bool Ret = false;
countdown_ms(&timer, timeout);
do {
if (flag == (at_getFlag() & flag)) {
Ret = true;
break;
}
at_delayms(1);
} while (!expired(&timer));
return Ret;
}
/**
* Get one line AT response buffer by line number.
*
* @param resp response object
* @param resp_line line number, start from '1'
*
* @return != NULL: response line buffer
* = NULL: input response line error
*/
const char *at_resp_get_line(at_response_t resp, uint32_t resp_line)
{
char *resp_buf = resp->buf;
char *resp_line_buf = NULL;
int line_num = 1;
POINTER_SANITY_CHECK(resp, NULL);
if (resp_line > resp->line_counts || resp_line == 0) {
Log_e("AT response get line failed! Input response line(%d) error!", resp_line);
return NULL;
}
for (line_num = 1; line_num <= resp->line_counts; line_num++) {
if (resp_line == line_num) {
resp_line_buf = resp_buf;
return resp_line_buf;
}
resp_buf += strlen(resp_buf) + 1;
}
return NULL;
}
/**
* Get one line AT response buffer by keyword
*
* @param resp response object
* @param keyword query keyword
*
* @return != NULL: response line buffer
* = NULL: no matching data
*/
const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword)
{
char *resp_buf = resp->buf;
char *resp_line_buf = NULL;
int line_num = 1;
POINTER_SANITY_CHECK(resp, NULL);
POINTER_SANITY_CHECK(keyword, NULL);
for (line_num = 1; line_num <= resp->line_counts; line_num++) {
if (strstr(resp_buf, keyword)) {
resp_line_buf = resp_buf;
return resp_line_buf;
}
resp_buf += strlen(resp_buf) + 1;
}
return NULL;
}
/**
* Get and parse AT response buffer arguments by line number.
*
* @param resp response object
* @param resp_line line number, start from '1'
* @param resp_expr response buffer expression
*
* @return -1 : input response line number error or get line buffer error
* 0 : parsed without match
* >0 : the number of arguments successfully parsed
*/
int at_resp_parse_line_args(at_response_t resp, uint32_t resp_line, const char *resp_expr, ...)
{
va_list args;
int resp_args_num = 0;
const char *resp_line_buf = NULL;
POINTER_SANITY_CHECK(resp, -1);
POINTER_SANITY_CHECK(resp_expr, -1);
if ((resp_line_buf = at_resp_get_line(resp, resp_line)) == NULL) {
return -1;
}
va_start(args, resp_expr);
resp_args_num = vsscanf(resp_line_buf, resp_expr, args);
va_end(args);
return resp_args_num;
}
/**
* Get and parse AT response buffer arguments by keyword.
*
* @param resp response object
* @param keyword query keyword
* @param resp_expr response buffer expression
*
* @return -1 : input keyword error or get line buffer error
* 0 : parsed without match
* >0 : the number of arguments successfully parsed
*/
int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const char *resp_expr, ...)
{
va_list args;
int resp_args_num = 0;
const char *resp_line_buf = NULL;
POINTER_SANITY_CHECK(resp, -1);
POINTER_SANITY_CHECK(resp_expr, -1);
if ((resp_line_buf = at_resp_get_line_by_kw(resp, keyword)) == NULL) {
return -1;
}
va_start(args, resp_expr);
resp_args_num = vsscanf(resp_line_buf, resp_expr, args);
va_end(args);
return resp_args_num;
}
/**
* Send commands to AT server and wait response.
*
* @param client current AT client object
* @param resp AT response object, using NULL when you don't care response
* @param cmd_expr AT commands expression
*
* @return 0 : success
* -1 : response status error
* -2 : wait timeout
*/
int at_obj_exec_cmd(at_response_t resp, const char *cmd_expr, ...)
{
POINTER_SANITY_CHECK(cmd_expr, QCLOUD_ERR_INVAL);
va_list args;
int cmd_size = 0;
int result = QCLOUD_RET_SUCCESS;
const char *cmd = NULL;
at_client_t client = at_client_get();
if (client == NULL) {
Log_e("input AT Client object is NULL, please create or get AT Client object!");
return QCLOUD_ERR_FAILURE;
}
HAL_MutexLock(client->lock);
resp->line_counts = 0;
client->resp_status = AT_RESP_OK;
client->resp = resp;
va_start(args, cmd_expr);
at_vprintfln(cmd_expr, args);
va_end(args);
if (resp != NULL) {
#ifndef AT_OS_USED
client->resp_status = AT_RESP_TIMEOUT;
at_client_yeild(NULL, resp->timeout);
if (client->resp_status != AT_RESP_OK) {
cmd = at_get_last_cmd(&cmd_size);
Log_e("execute command (%.*s) failed!", cmd_size, cmd);
result = QCLOUD_ERR_FAILURE;
goto __exit;
}
#else
if (HAL_SemaphoreWait(client->resp_sem, resp->timeout) < 0) {
cmd = at_get_last_cmd(&cmd_size);
Log_e("execute command (%.*s) failed!", cmd_size, cmd);
result = QCLOUD_ERR_FAILURE;
goto __exit;
}
if (client->resp_status != AT_RESP_OK) {
cmd = at_get_last_cmd(&cmd_size);
Log_e("execute command (%.*s) failed!", cmd_size, cmd);
result = QCLOUD_ERR_FAILURE;
goto __exit;
}
#endif
}
__exit:
client->resp = NULL;
HAL_MutexUnlock(client->lock);
return result;
}
/**
* Send data to AT server, send data don't have end sign(eg: \r\n).
*
* @param client current AT client object
* @param buf send data buffer
* @param size send fixed data size
* @param timeout timeout for send
*
* @return >0: send data size
* =0: send failed
*/
int at_client_send(at_client_t client, const char *buf, int size, uint32_t timeout)
{
POINTER_SANITY_CHECK(buf, 0);
if (client == NULL) {
Log_e("input AT Client object is NULL, please create or get AT Client object!");
return 0;
}
#ifdef AT_DEBUG
at_print_raw_cmd("send", buf, size);
#endif
return HAL_AT_Uart_Send((void *)buf, size);
}
static int at_client_getchar(at_client_t client, char *pch, uint32_t timeout)
{
int ret = QCLOUD_RET_SUCCESS;
Timer timer;
countdown_ms(&timer, timeout);
do {
#ifndef AT_UART_RECV_IRQ
if (0 == HAL_AT_Uart_Recv((void *)pch, 1, NULL, timeout)) {
continue;
}
#else
if (0 ==
ring_buff_pop_data(client->pRingBuff, (uint8_t *)pch, 1)) { // push data to ringbuff @ AT_UART_IRQHandler
continue;
}
#endif
else {
break;
}
} while (!expired(&timer));
if (expired(&timer)) {
ret = QCLOUD_ERR_FAILURE;
}
return ret;
}
/**
* AT client receive fixed-length data.
*
* @param client current AT client object
* @param buf receive data buffer
* @param size receive fixed data size
* @param timeout receive data timeout (ms)
*
* @note this function can only be used in execution function of URC data
*
* @return >0: receive data size
* =0: receive failed
*/
int at_client_obj_recv(char *buf, int size, int timeout)
{
int read_idx = 0;
int result = QCLOUD_RET_SUCCESS;
char ch;
POINTER_SANITY_CHECK(buf, 0);
at_client_t client = at_client_get();
if (client == NULL) {
Log_e("input AT Client object is NULL, please create or get AT Client object!");
return 0;
}
while (1) {
if (read_idx < size) {
result = at_client_getchar(client, &ch, timeout);
if (result != QCLOUD_RET_SUCCESS) {
Log_e("AT Client receive failed, uart device get data error(%d)", result);
return 0;
}
buf[read_idx++] = ch;
} else {
break;
}
}
#ifdef AT_DEBUG
at_print_raw_cmd("urc_recv", buf, size);
#endif
return read_idx;
}
/**
* AT client set end sign.
*
* @param client current AT client object
* @param ch the end sign, can not be used when it is '\0'
*/
void at_set_end_sign(char ch)
{
at_client_t client = at_client_get();
if (client == NULL) {
Log_e("input AT Client object is NULL, please create or get AT Client object!");
return;
}
client->end_sign = ch;
}
/**
* set URC(Unsolicited Result Code) table
*
* @param client current AT client object
* @param table URC table
* @param size table size
*/
void at_set_urc_table(at_client_t client, const at_urc_t urc_table, uint32_t table_sz)
{
int idx;
if (client == NULL) {
Log_e("input AT Client object is NULL, please create or get AT Client object!");
return;
}
for (idx = 0; idx < table_sz; idx++) {
POINTER_SANITY_CHECK_RTN(urc_table[idx].cmd_prefix);
POINTER_SANITY_CHECK_RTN(urc_table[idx].cmd_suffix);
}
client->urc_table = urc_table;
client->urc_table_size = table_sz;
}
at_client_t at_client_get(void)
{
return &sg_at_client;
}
static const at_urc *get_urc_obj(at_client_t client)
{
int i, prefix_len, suffix_len;
int buf_sz;
char *buffer = NULL;
if (client->urc_table == NULL) {
return NULL;
}
buffer = client->recv_buffer;
buf_sz = client->cur_recv_len;
for (i = 0; i < client->urc_table_size; i++) {
prefix_len = strlen(client->urc_table[i].cmd_prefix);
suffix_len = strlen(client->urc_table[i].cmd_suffix);
if (buf_sz < prefix_len + suffix_len) {
continue;
}
if ((prefix_len ? !strncmp(buffer, client->urc_table[i].cmd_prefix, prefix_len) : 1) &&
(suffix_len ? !strncmp(buffer + buf_sz - suffix_len, client->urc_table[i].cmd_suffix, suffix_len) : 1)) {
// Log_d("matched:%s", client->urc_table[i].cmd_prefix);
return &client->urc_table[i];
}
}
return NULL;
}
static int at_recv_readline(at_client_t client)
{
int read_len = 0;
char ch = 0, last_ch = 0;
bool is_full = false;
int ret;
memset(client->recv_buffer, 0x00, client->recv_bufsz);
client->cur_recv_len = 0;
while (1) {
ret = at_client_getchar(client, &ch, GET_CHAR_TIMEOUT_MS);
if (QCLOUD_RET_SUCCESS != ret) {
return -1;
}
if (read_len < client->recv_bufsz) {
client->recv_buffer[read_len++] = ch;
client->cur_recv_len = read_len;
} else {
is_full = true;
}
/* is newline or URC data */
if ((ch == '\n' && last_ch == '\r') || (client->end_sign != 0 && ch == client->end_sign) ||
get_urc_obj(client)) {
if (is_full) {
Log_e("read line failed. The line data length is out of buffer size(%d)!", client->recv_bufsz);
memset(client->recv_buffer, 0x00, client->recv_bufsz);
client->cur_recv_len = 0;
ring_buff_flush(client->pRingBuff);
return -1;
}
break;
}
last_ch = ch;
}
#ifdef AT_DEBUG
at_print_raw_cmd("recvline", client->recv_buffer, read_len);
#endif
return read_len;
}
#ifdef AT_OS_USED
static void client_parser(void *userContex)
{
int resp_buf_len = 0;
const at_urc *urc;
int line_counts = 0;
at_client_t client = at_client_get();
Log_d("client_parser start...");
while (1) {
if (at_recv_readline(client) > 0) {
#ifdef AT_DEBUG
const char *cmd = NULL;
int cmdsize = 0;
cmd = at_get_last_cmd(&cmdsize);
Log_d("last_cmd:(%.*s), readline:%s", cmdsize, cmd, client->recv_buffer);
#endif
if ((urc = get_urc_obj(client)) != NULL) {
/* current receive is request, try to execute related operations */
if (urc->func != NULL) {
urc->func(client->recv_buffer, client->cur_recv_len);
}
} else if (client->resp != NULL) {
if (client->end_sign != 0) { // handle endsign
if (client->recv_buffer[client->cur_recv_len - 1] != client->end_sign) {
continue;
} else {
goto exit;
}
}
/* current receive is response */
client->recv_buffer[client->cur_recv_len - 1] = '\0';
if (resp_buf_len + client->cur_recv_len < client->resp->buf_size) {
/* copy response lines, separated by '\0' */
memcpy(client->resp->buf + resp_buf_len, client->recv_buffer, client->cur_recv_len);
resp_buf_len += client->cur_recv_len;
line_counts++;
} else {
client->resp_status = AT_RESP_BUFF_FULL;
Log_e("Read response buffer failed. The Response buffer size is out of buffer size(%d)!",
client->resp->buf_size);
}
/* check response result */
if (memcmp(client->recv_buffer, AT_RESP_END_OK, strlen(AT_RESP_END_OK)) == 0 &&
client->resp->line_num == 0) {
/* get the end data by response result, return response state END_OK. */
client->resp_status = AT_RESP_OK;
} else if (strstr(client->recv_buffer, AT_RESP_END_ERROR) ||
(memcmp(client->recv_buffer, AT_RESP_END_FAIL, strlen(AT_RESP_END_FAIL)) == 0)) {
client->resp_status = AT_RESP_ERROR;
} else if (line_counts == client->resp->line_num && client->resp->line_num) {
/* get the end data by response line, return response state END_OK.*/
client->resp_status = AT_RESP_OK;
} else {
continue;
}
exit:
client->resp->line_counts = line_counts;
client->resp = NULL;
resp_buf_len = 0;
line_counts = 0;
HAL_SemaphorePost(client->resp_sem);
} else {
// Log_d("unrecognized line: %.*s", client->cur_recv_len, client->recv_buffer);
}
} else {
// Log_d("read no new line");
}
}
}
#else
void at_client_yeild(at_urc *expect_urc, uint32_t timeout)
{
int resp_buf_len = 0;
const at_urc *urc;
int line_counts = 0;
int prefix_len;
int suffix_len;
Timer timer;
at_client_t client = at_client_get();
Log_d("Entry...");
countdown_ms(&timer, timeout);
do {
if (at_recv_readline(client) > 0) {
#ifdef AT_DEBUG
const char *cmd = NULL;
int cmdsize = 0;
cmd = at_get_last_cmd(&cmdsize);
Log_d("last_cmd:(%.*s), readline:%s", cmdsize, cmd, client->recv_buffer);
#endif
if ((urc = get_urc_obj(client)) != NULL) {
/* current receive is request, try to execute related operations */
if (urc->func != NULL) {
urc->func(client->recv_buffer, client->cur_recv_len);
}
/*expect urc matched then break*/
if (expect_urc != NULL) {
prefix_len = strlen(expect_urc->cmd_prefix);
suffix_len = strlen(expect_urc->cmd_suffix);
if ((prefix_len ? !strncmp(urc->cmd_prefix, expect_urc->cmd_prefix, prefix_len) : 1) &&
(suffix_len ? !strncmp(urc->cmd_suffix, expect_urc->cmd_suffix, suffix_len) : 1)) {
client->resp_status = AT_RESP_OK;
break;
}
}
} else if (client->resp != NULL) {
if (client->end_sign != 0) { // handle endsign
if (client->recv_buffer[client->cur_recv_len - 1] != client->end_sign) {
continue;
} else {
client->resp_status = AT_RESP_OK;
client->resp->line_counts = line_counts;
client->resp = NULL;
// client->resp_notice = true;
resp_buf_len = 0;
line_counts = 0;
break;
}
}
/* current receive is response */
client->recv_buffer[client->cur_recv_len - 1] = '\0';
if (resp_buf_len + client->cur_recv_len < client->resp->buf_size) {
/* copy response lines, separated by '\0' */
memcpy(client->resp->buf + resp_buf_len, client->recv_buffer, client->cur_recv_len);
resp_buf_len += client->cur_recv_len;
line_counts++;
} else {
client->resp_status = AT_RESP_BUFF_FULL;
Log_e("Read response buffer failed. The Response buffer size is out of buffer size(%d)!",
client->resp->buf_size);
}
/* check response result */
if (memcmp(client->recv_buffer, AT_RESP_END_OK, strlen(AT_RESP_END_OK)) == 0 &&
client->resp->line_num == 0) {
/* get the end data by response result, return response state END_OK. */
client->resp_status = AT_RESP_OK;
} else if (strstr(client->recv_buffer, AT_RESP_END_ERROR) ||
(memcmp(client->recv_buffer, AT_RESP_END_FAIL, strlen(AT_RESP_END_FAIL)) == 0)) {
client->resp_status = AT_RESP_ERROR;
} else if (line_counts == client->resp->line_num && client->resp->line_num) {
/* get the end data by response line, return response state END_OK.*/
client->resp_status = AT_RESP_OK;
} else {
if (!expired(&timer)) {
continue;
} else {
break;
}
}
client->resp->line_counts = line_counts;
client->resp = NULL;
// client->resp_notice = true;
resp_buf_len = 0;
line_counts = 0;
break;
} else {
// Log_d("unrecognized line: %.*s", client->cur_recv_len, client->recv_buffer);
}
} else {
// Log_d("read no new line");
}
} while (!expired(&timer));
}
#endif
/* initialize the client parameters */
int at_client_para_init(at_client_t client)
{
char *ringBuff = NULL;
char *recvBuff = NULL;
client->lock = HAL_MutexCreate();
if (NULL == client->lock) {
Log_e("create lock err");
return QCLOUD_ERR_FAILURE;
}
#ifdef AT_OS_USED
client->resp_sem = HAL_SemaphoreCreate();
if (NULL == client->resp_sem) {
Log_e("create sem err");
goto err_exit;
}
client->parser = client_parser;
#endif
ringBuff = HAL_Malloc(RING_BUFF_LEN);
if (NULL == ringBuff) {
Log_e("malloc ringbuff err");
goto err_exit;
}
ring_buff_init(&g_ring_buff, ringBuff, RING_BUFF_LEN);
recvBuff = HAL_Malloc(CLINET_BUFF_LEN);
if (NULL == recvBuff) {
Log_e("malloc recvbuff err");
goto err_exit;
}
client->recv_buffer = recvBuff;
client->pRingBuff = &g_ring_buff;
client->recv_bufsz = CLINET_BUFF_LEN;
client->cur_recv_len = 0;
client->resp = NULL;
client->urc_table = NULL;
client->urc_table_size = 0;
client->end_sign = 0;
return QCLOUD_RET_SUCCESS;
err_exit:
if (client->lock) {
HAL_MutexDestroy(client->lock);
client->lock = NULL;
}
if (client->resp_sem) {
HAL_SemaphoreDestroy(client->resp_sem);
client->resp_sem = NULL;
}
HAL_Free(ringBuff);
HAL_Free(recvBuff);
return QCLOUD_ERR_FAILURE;
}
/**
* AT client initialize.
*
* @param pClient pinter of at client which to be inited
* @return @see eTidResault
*/
int at_client_init(at_client_t *pClient)
{
POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL);
at_client_t client;
int result;
client = at_client_get();
if (NULL == client) {
Log_e("no at client get");
result = QCLOUD_ERR_FAILURE;
goto exit;
}
if (AT_STATUS_INITIALIZED == client->status) {
Log_e("at client has been initialized");
result = QCLOUD_ERR_FAILURE;
goto exit;
}
result = at_client_para_init(client);
if (result == QCLOUD_RET_SUCCESS) {
Log_d("AT client(V%s) initialize success.", AT_FRAME_VERSION);
client->status = AT_STATUS_INITIALIZED;
*pClient = client;
#if defined(AT_OS_USED) && defined(MULTITHREAD_ENABLED)
// create thread for at parser
if (NULL != client->parser) {
#define AT_PARSER_THREAD_STACK 6144
#define AT_PARSER_THREAD_PRIORITY 0
ThreadParams thread_params = {0};
thread_params.thread_func = client->parser;
thread_params.thread_name = "at_client_parser";
thread_params.user_arg = client;
thread_params.stack_size = AT_PARSER_THREAD_STACK;
thread_params.priority = AT_PARSER_THREAD_PRIORITY;
result = HAL_ThreadCreate(&thread_params);
if (QCLOUD_RET_SUCCESS == result) {
Log_d("create at_parser thread success!");
} else {
Log_e("create at_parser thread fail!");
}
#undef AT_PARSER_THREAD_STACK
#undef AT_PARSER_THREAD_PRIORITY
}
#endif
} else {
*pClient = NULL;
client->status = AT_STATUS_UNINITIALIZED;
Log_e("AT client(V%s) initialize failed(%d).", AT_FRAME_VERSION, result);
}
exit:
return result;
}
int at_client_deinit(at_client_t pClient)
{
// TO DO:
return QCLOUD_RET_SUCCESS;
}

View File

@@ -0,0 +1,413 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "at_socket_inf.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#include "utils_param_check.h"
/** The global array of available at */
static at_socket_ctx_t at_socket_ctxs[MAX_AT_SOCKET_NUM];
/**at socket operation mutex */
static void *sg_at_socket_mutex;
/**at device driver ops*/
static at_device_op_t *sg_at_device_ops = NULL;
#define MAX_RECV_PKT_PER_CHAIN (10)
static at_device_op_t *_at_device_op_get(void)
{
return sg_at_device_ops;
}
static int _at_socket_ctx_free(at_socket_ctx_t *pCtx)
{
POINTER_SANITY_CHECK(pCtx, QCLOUD_ERR_INVAL);
pCtx->fd = UNUSED_SOCKET;
pCtx->net_type = eNET_DEFAULT;
if (pCtx->recvpkt_list) {
list_destroy(pCtx->recvpkt_list);
pCtx->recvpkt_list = NULL;
}
if (pCtx->recv_lock) {
HAL_MutexDestroy(pCtx->recv_lock);
pCtx->recv_lock = NULL;
}
return QCLOUD_RET_SUCCESS;
}
static at_socket_ctx_t *_at_socket_ctx_alloc(void)
{
int i;
for (i = 0; i < MAX_AT_SOCKET_NUM; i++) {
if (at_socket_ctxs[i].state == eSOCKET_CLOSED) {
at_socket_ctxs[i].net_type = eNET_DEFAULT;
at_socket_ctxs[i].send_timeout_ms = AT_SOCKET_SEND_TIMEOUT_MS;
at_socket_ctxs[i].recv_timeout_ms = AT_SOCKET_RECV_TIMEOUT_MS;
at_socket_ctxs[i].dev_op = _at_device_op_get();
at_socket_ctxs[i].recv_lock = HAL_MutexCreate();
if (NULL == at_socket_ctxs[i].recv_lock) {
Log_e("create recv lock fail");
goto exit;
}
at_socket_ctxs[i].recvpkt_list = list_new();
if (NULL != at_socket_ctxs[i].recvpkt_list) {
at_socket_ctxs[i].recvpkt_list->free = HAL_Free;
} else {
Log_e("no memory to allocate recvpkt_list");
goto exit;
}
at_socket_ctxs[i].state = eSOCKET_ALLOCED;
return &at_socket_ctxs[i];
}
}
exit:
if (i < MAX_AT_SOCKET_NUM) {
_at_socket_ctx_free(&at_socket_ctxs[i]);
}
return NULL;
}
static at_socket_ctx_t *_at_socket_find(int fd)
{
int i;
for (i = 0; i < MAX_AT_SOCKET_NUM; i++) {
if (at_socket_ctxs[i].fd == fd) {
return &at_socket_ctxs[i];
}
}
return NULL;
}
/* get a block to the AT socket receive list*/
static int _at_recvpkt_put(List *rlist, const char *ptr, size_t length)
{
at_recv_pkt *pkt = NULL;
if (rlist->len > MAX_RECV_PKT_PER_CHAIN) {
Log_e("Too many recv packets wait for read");
HAL_Free(pkt);
return QCLOUD_ERR_FAILURE;
}
pkt = (at_recv_pkt *)HAL_Malloc(sizeof(struct at_recv_pkt));
if (pkt == NULL) {
Log_e("No memory for receive packet table!");
return QCLOUD_ERR_FAILURE;
}
pkt->bfsz_totle = length;
pkt->bfsz_index = 0;
pkt->buff = (char *)ptr;
ListNode *node = list_node_new(pkt);
if (NULL == node) {
Log_e("run list_node_new is error!");
HAL_Free(pkt);
return QCLOUD_ERR_FAILURE;
}
list_rpush(rlist, node);
return length;
}
/* get a block from AT socket receive list */
static int _at_recvpkt_get(List *pkt_list, char *buff, size_t len)
{
ListIterator *iter;
ListNode * node = NULL;
at_recv_pkt * pkt;
size_t readlen = 0, page_len = 0;
POINTER_SANITY_CHECK(buff, QCLOUD_ERR_INVAL);
if (pkt_list->len) {
iter = list_iterator_new(pkt_list, LIST_HEAD);
if (NULL == iter) {
Log_e("new listiterator fail");
return QCLOUD_ERR_TCP_READ_FAIL;
}
/*traverse recv pktlist*/
do {
node = list_iterator_next(iter);
if (!node) {
break;
}
/*get recv packet*/
pkt = (at_recv_pkt *)(node->val);
if (!pkt) {
Log_e("pkt is invalid!");
list_remove(pkt_list, node);
continue;
}
page_len = pkt->bfsz_totle - pkt->bfsz_index;
if (page_len >= (len - readlen)) {
memcpy(buff + readlen, pkt->buff + pkt->bfsz_index, (len - readlen));
pkt->bfsz_index += len - readlen;
readlen = len;
break;
} else {
memcpy(buff + readlen, pkt->buff + pkt->bfsz_index, page_len);
readlen += page_len;
/*delete pkt after read*/
HAL_Free(pkt->buff);
list_remove(pkt_list, node);
}
} while (1);
list_iterator_destroy(iter);
}
return readlen;
}
static void _at_socket_recv_cb(int fd, at_socket_evt_t event, char *buff, size_t bfsz)
{
POINTER_SANITY_CHECK_RTN(buff);
at_socket_ctx_t *pAtSocket;
if (event == AT_SOCKET_EVT_RECV) {
HAL_MutexLock(sg_at_socket_mutex);
pAtSocket = _at_socket_find(fd + MAX_AT_SOCKET_NUM);
if (_at_recvpkt_put(pAtSocket->recvpkt_list, buff, bfsz) < 0) {
Log_e("put recv package to list fail");
HAL_Free(buff);
}
HAL_MutexUnlock(sg_at_socket_mutex);
}
}
static void _at_socket_closed_cb(int fd, at_socket_evt_t event, char *buff, size_t bfsz)
{
// fancyxu
at_socket_ctx_t *pAtSocket;
pAtSocket = _at_socket_find(fd + MAX_AT_SOCKET_NUM);
if (event == AT_SOCKET_EVT_CLOSED) {
HAL_MutexLock(sg_at_socket_mutex);
pAtSocket->state = eSOCKET_CLOSED;
_at_socket_ctx_free(pAtSocket);
HAL_MutexUnlock(sg_at_socket_mutex);
}
}
int at_device_op_register(at_device_op_t *device_op)
{
int rc;
if (NULL == sg_at_device_ops) {
sg_at_device_ops = device_op;
rc = QCLOUD_RET_SUCCESS;
} else {
Log_e("pre device op already register");
rc = QCLOUD_ERR_FAILURE;
}
return rc;
}
int at_socket_init(void)
{
int i;
int rc = QCLOUD_RET_SUCCESS;
for (i = 0; i < MAX_AT_SOCKET_NUM; i++) {
at_socket_ctxs[i].fd = UNUSED_SOCKET;
at_socket_ctxs[i].state = eSOCKET_CLOSED;
at_socket_ctxs[i].dev_op = NULL;
at_socket_ctxs[i].recvpkt_list = NULL;
}
sg_at_socket_mutex = HAL_MutexCreate();
if (sg_at_socket_mutex == NULL) {
Log_e("create sg_at_socket_mutex fail \n");
rc = QCLOUD_ERR_FAILURE;
}
if (NULL != sg_at_device_ops) {
if (QCLOUD_RET_SUCCESS == sg_at_device_ops->init()) {
Log_d("at device %s init success",
(NULL == sg_at_device_ops->deviceName) ? "noname" : sg_at_device_ops->deviceName);
sg_at_device_ops->set_event_cb(AT_SOCKET_EVT_RECV, _at_socket_recv_cb);
sg_at_device_ops->set_event_cb(AT_SOCKET_EVT_CLOSED, _at_socket_closed_cb);
} else {
Log_e("at device %s init fail",
(NULL == sg_at_device_ops->deviceName) ? "noname" : sg_at_device_ops->deviceName);
}
}
return rc;
}
int at_socket_parse_domain(const char *host_name, char *host_ip, size_t host_ip_len)
{
at_device_op_t *at_op = _at_device_op_get();
POINTER_SANITY_CHECK(at_op, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(at_op->parse_domain, QCLOUD_ERR_INVAL);
return at_op->parse_domain(host_name, host_ip, host_ip_len);
}
int at_socket_get_local_mac(char *macbuff, size_t bufflen)
{
at_device_op_t *at_op = _at_device_op_get();
POINTER_SANITY_CHECK(at_op, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(at_op->get_local_mac, QCLOUD_ERR_INVAL);
return at_op->get_local_mac(macbuff, bufflen);
}
int at_socket_get_local_ip(char *ip, size_t iplen, char *gw, size_t gwlen, char *mask, size_t masklen)
{
at_device_op_t *at_op = _at_device_op_get();
POINTER_SANITY_CHECK(at_op, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(at_op->get_local_ip, QCLOUD_ERR_INVAL);
return at_op->get_local_ip(ip, iplen, gw, gwlen, mask, masklen);
}
int at_socket_connect(const char *host, uint16_t port, eNetProto eProto)
{
at_socket_ctx_t *pAtSocket;
int fd;
HAL_MutexLock(sg_at_socket_mutex);
pAtSocket = _at_socket_ctx_alloc();
HAL_MutexUnlock(sg_at_socket_mutex);
if ((NULL == pAtSocket) || (NULL == pAtSocket->dev_op) || (NULL == pAtSocket->dev_op->connect)) {
Log_e("alloc socket fail");
return QCLOUD_ERR_FAILURE;
}
fd = pAtSocket->dev_op->connect(host, port, eProto);
if (fd < 0) {
Log_e("dev_op connect fail,pls check at device driver!");
_at_socket_ctx_free(pAtSocket);
} else {
pAtSocket->fd = fd + MAX_AT_SOCKET_NUM;
pAtSocket->state = eSOCKET_CONNECTED;
}
return pAtSocket->fd;
}
int at_socket_close(int fd)
{
at_socket_ctx_t *pAtSocket;
pAtSocket = _at_socket_find(fd);
if (NULL == pAtSocket) { // server close the connection
Log_e("socket was closed");
return QCLOUD_ERR_TCP_PEER_SHUTDOWN;
}
int rc;
if ((eSOCKET_CONNECTED == pAtSocket->state) && (NULL != pAtSocket->dev_op) && (NULL != pAtSocket->dev_op->close)) {
rc = pAtSocket->dev_op->close(pAtSocket->fd - MAX_AT_SOCKET_NUM);
} else {
rc = QCLOUD_ERR_FAILURE;
}
return rc;
}
int at_socket_send(int fd, const void *buf, size_t len)
{
at_socket_ctx_t *pAtSocket;
pAtSocket = _at_socket_find(fd);
POINTER_SANITY_CHECK(pAtSocket, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(pAtSocket->dev_op, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(pAtSocket->dev_op->send, QCLOUD_ERR_INVAL);
if (pAtSocket->state != eSOCKET_CONNECTED) {
Log_e("socket was closed");
return QCLOUD_ERR_TCP_PEER_SHUTDOWN;
} else {
return pAtSocket->dev_op->send(fd - MAX_AT_SOCKET_NUM, buf, len);
}
}
int at_socket_recv(int fd, void *buf, size_t len)
{
at_socket_ctx_t *pAtSocket;
size_t recv_len;
pAtSocket = _at_socket_find(fd);
POINTER_SANITY_CHECK(pAtSocket, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(pAtSocket->dev_op, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(pAtSocket->dev_op->recv_timeout, QCLOUD_ERR_INVAL);
if (pAtSocket->state != eSOCKET_CONNECTED) {
Log_e("socket was closed");
return QCLOUD_ERR_TCP_READ_FAIL;
} else {
HAL_MutexLock(pAtSocket->recv_lock);
// call at device recv driver for os and nonos
if (pAtSocket->recvpkt_list->len == 0) {
if (pAtSocket->dev_op->recv_timeout(fd - MAX_AT_SOCKET_NUM, buf, len, pAtSocket->recv_timeout_ms) !=
QCLOUD_RET_SUCCESS) {
Log_e("at device recv err"); // do not return yet
}
}
/* receive packet list last transmission of remaining data */
recv_len = _at_recvpkt_get(pAtSocket->recvpkt_list, (char *)buf, len);
HAL_MutexUnlock(pAtSocket->recv_lock);
}
return recv_len;
}
int at_socket_recv_timeout(int fd, void *buf, size_t len, uint32_t timeout)
{
at_socket_ctx_t *pAtSocket;
pAtSocket = _at_socket_find(fd);
POINTER_SANITY_CHECK(pAtSocket, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(pAtSocket->dev_op, QCLOUD_ERR_INVAL);
POINTER_SANITY_CHECK(pAtSocket->dev_op->recv_timeout, QCLOUD_ERR_INVAL);
if (pAtSocket->state != eSOCKET_CONNECTED) {
Log_e("socket was closed");
return QCLOUD_ERR_TCP_PEER_SHUTDOWN;
} else {
return pAtSocket->dev_op->recv_timeout(fd - MAX_AT_SOCKET_NUM, buf, len, timeout);
}
}

View File

@@ -0,0 +1,345 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "at_utils.h"
#include <ctype.h>
#include <string.h>
#include "at_client.h"
#include "qcloud_iot_import.h"
#include "utils_param_check.h"
static char send_buf[CLINET_BUFF_LEN];
static int last_cmd_len = 0;
/**
* dump hex format data to console device
*
* @param name name for hex object, it will show on log header
* @param buf hex buffer
* @param size buffer size
*/
void at_print_raw_cmd(const char *name, const char *buf, int size)
{
int i, j;
for (i = 0; i < size; i += WIDTH_SIZE) {
HAL_Printf("%s: %04X-%04X: ", name, i, i + WIDTH_SIZE);
for (j = 0; j < WIDTH_SIZE; j++) {
if (i + j < size) {
HAL_Printf("%02X ", buf[i + j]);
} else {
HAL_Printf(" ");
}
if ((j + 1) % 8 == 0) {
HAL_Printf(" ");
}
}
HAL_Printf(" ");
for (j = 0; j < WIDTH_SIZE; j++) {
if (i + j < size) {
HAL_Printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
}
}
HAL_Printf("\n\r");
}
}
const char *at_get_last_cmd(int *cmd_size)
{
*cmd_size = last_cmd_len;
return send_buf;
}
int at_vprintf(const char *format, va_list args)
{
last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args);
#ifdef AT_DEBUG
at_print_raw_cmd("send", send_buf, last_cmd_len);
#endif
return HAL_AT_Uart_Send((uint8_t *)send_buf, last_cmd_len);
}
int at_vprintfln(const char *format, va_list args)
{
int len;
len = at_vprintf(format, args);
HAL_AT_Uart_Send("\r\n", 2);
return len + 2;
}
/**
* at_sscanf - Unformat a buffer into a list of arguments, rewrite sscanf
* @buf: input buffer
* @fmt: format of buffer
* @args: arguments
*/
int at_sscanf(const char *buf, const char *fmt, va_list args)
{
const char *str = buf;
char * next;
int num = 0;
int qualifier;
int base;
int field_width = -1;
int is_sign = 0;
while (*fmt && *str) {
/* skip any white space in format */
/* white space in format matchs any amount of
* white space, including none, in the input.
*/
if (isspace(*fmt)) {
while (isspace(*fmt)) ++fmt;
while (isspace(*str)) ++str;
}
/* anything that is not a conversion must match exactly */
if (*fmt != '%' && *fmt) {
if (*fmt++ != *str++)
break;
continue;
}
if (!*fmt)
break;
++fmt;
/* skip this conversion.
* advance both strings to next white space
*/
if (*fmt == '*') {
while (!isspace(*fmt) && *fmt) fmt++;
while (!isspace(*str) && *str) str++;
continue;
}
/* get field width */
if (isdigit(*fmt))
field_width = atoi(fmt);
/* get conversion qualifier */
qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') {
qualifier = *fmt;
fmt++;
}
base = 10;
is_sign = 0;
if (!*fmt || !*str)
break;
switch (*fmt++) {
case 'c': {
char *s = (char *)va_arg(args, char *);
if (field_width == -1)
field_width = 1;
do {
*s++ = *str++;
} while (field_width-- > 0 && *str);
num++;
}
continue;
case 's': {
char *s = (char *)va_arg(args, char *);
if (field_width == -1)
field_width = INT_MAX;
/* first, skip leading white space in buffer */
while (isspace(*str)) str++;
/* now copy until next white space */
while (*str && ((*str) != ',')) {
if (isspace(*str)) {
str++;
} else {
*s++ = *str++;
}
}
*s = '\0';
num++;
}
continue;
/* S for special handling for MQTTPUB JSON content */
case 'S': {
char *s = (char *)va_arg(args, char *);
if (field_width == -1)
field_width = INT_MAX;
/* first, skip leading white space in buffer */
while (isspace(*str)) str++;
/* now copy until next white space */
while (*str) {
if (isspace(*str)) {
str++;
} else {
*s++ = *str++;
}
}
*s = '\0';
num++;
}
continue;
case 'n':
/* return number of characters read so far */
{
int *i = (int *)va_arg(args, int *);
*i = str - buf;
}
continue;
case 'o':
base = 8;
break;
case 'x':
case 'X':
base = 16;
break;
case 'd':
case 'i':
is_sign = 1;
case 'u':
break;
case '%':
/* looking for '%' in str */
if (*str++ != '%')
return num;
continue;
default:
/* invalid format; stop here */
return num;
}
/* have some sort of integer conversion.
* first, skip white space in buffer.
*/
while (isspace(*str)) str++;
if (!*str || !isdigit(*str))
break;
switch (qualifier) {
case 'h':
if (is_sign) {
short *s = (short *)va_arg(args, short *);
*s = (short)strtol(str, &next, base);
} else {
unsigned short *s = (unsigned short *)va_arg(args, unsigned short *);
*s = (unsigned short)strtoul(str, &next, base);
}
break;
case 'l':
if (is_sign) {
long *l = (long *)va_arg(args, long *);
*l = strtol(str, &next, base);
} else {
unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
*l = strtoul(str, &next, base);
}
break;
case 'L':
if (is_sign) {
long long *l = (long long *)va_arg(args, long long *);
*l = strtoll(str, &next, base);
} else {
unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *);
*l = strtoull(str, &next, base);
}
break;
case 'Z': {
unsigned long *s = (unsigned long *)va_arg(args, unsigned long *);
*s = (unsigned long)strtoul(str, &next, base);
} break;
default:
if (is_sign) {
int *i = (int *)va_arg(args, int *);
*i = (int)strtol(str, &next, base);
} else {
unsigned int *i = (unsigned int *)va_arg(args, unsigned int *);
*i = (unsigned int)strtoul(str, &next, base);
}
break;
}
num++;
if (!next)
break;
str = next;
}
return num;
}
/**
* AT server request arguments parse arguments
*
* @param req_args request arguments
* @param req_expr request expression
*
* @return -1 : parse arguments failed
* 0 : parse without match
* >0 : The number of arguments successfully parsed
*/
int at_req_parse_args(const char *req_args, const char *req_expr, ...)
{
va_list args;
int req_args_num = 0;
POINTER_SANITY_CHECK(req_args, 0);
POINTER_SANITY_CHECK(req_expr, 0);
va_start(args, req_expr);
// req_args_num = vsscanf(req_args, req_expr, args);
req_args_num = at_sscanf(req_args, req_expr, args);
va_end(args);
return req_args_num;
}
void at_strip(char *str, const char patten)
{
char *start, *end;
start = str;
end = str + strlen(str) - 1;
if (*str == patten) {
start++;
}
if (*end == patten) {
*end-- = '\0';
}
strcpy(str, start);
}
void chr_strip(char *str, const char patten)
{
char *end = str + strlen(str);
while (*str != '\0') {
if (*str == patten) {
memmove(str, str + 1, end - str);
}
str++;
}
}

View File

@@ -0,0 +1,153 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "qcloud_iot_export.h"
#include "qcloud_iot_import.h"
#ifdef AT_TCP_ENABLED
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "at_socket_inf.h"
#include "network_interface.h"
#include "utils_param_check.h"
#include "utils_timer.h"
int network_at_tcp_init(Network *pNetwork)
{
int rc;
/*at device init entry: at_client init, device driver register to at_socket*/
rc = at_device_init();
if (QCLOUD_RET_SUCCESS != rc) {
Log_e("at device init fail,rc:%d", rc);
return rc;
}
/*do after at device init*/
rc = at_socket_init();
if (QCLOUD_RET_SUCCESS != rc) {
Log_e("at socket init fail,rc:%d", rc);
}
return rc;
}
int network_at_tcp_connect(Network *pNetwork)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int fd = at_socket_connect(pNetwork->host, pNetwork->port, eNET_TCP);
if (fd < 0) {
Log_e("fail to connect with TCP server: %s:%u", pNetwork->host, pNetwork->port);
pNetwork->handle = AT_NO_CONNECTED_FD;
return -1;
} else {
Log_d("connected with TCP server: %s:%u", pNetwork->host, pNetwork->port);
pNetwork->handle = fd;
return 0;
}
}
int network_at_tcp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len)
{
int ret, err_code;
uint32_t len_recv;
Timer timer;
InitTimer(&timer);
countdown_ms(&timer, timeout_ms);
len_recv = 0;
err_code = 0;
do {
if (expired(&timer)) {
err_code = QCLOUD_ERR_TCP_READ_TIMEOUT;
break;
}
ret = at_socket_recv(pNetwork->handle, data + len_recv, datalen - len_recv);
if (ret > 0) {
len_recv += ret;
} else if (ret == 0) {
err_code = QCLOUD_ERR_TCP_NOTHING_TO_READ;
} else { // ret < 0
Log_e("recv fail\n");
err_code = QCLOUD_ERR_TCP_READ_FAIL;
break;
}
} while ((len_recv < datalen));
if (err_code == QCLOUD_ERR_TCP_READ_TIMEOUT && len_recv == 0) {
err_code = QCLOUD_ERR_TCP_NOTHING_TO_READ;
}
*read_len = len_recv;
return (datalen == len_recv) ? QCLOUD_RET_SUCCESS : err_code;
}
int network_at_tcp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms,
size_t *written_len)
{
int ret;
uint32_t len_sent;
Timer timer;
int net_err = 0;
InitTimer(&timer);
countdown_ms(&timer, timeout_ms);
len_sent = 0;
ret = 1; /* send one time if timeout_ms is value 0 */
do {
ret = at_socket_send(pNetwork->handle, data + len_sent, datalen - len_sent);
if (ret > 0) {
len_sent += ret;
} else if (0 == ret) {
Log_e("No data be sent\n");
} else {
Log_e("send fail, ret:%d\n", ret);
net_err = 1;
break;
}
} while (!net_err && (len_sent < datalen) && (!expired(&timer)));
*written_len = (size_t)len_sent;
return (len_sent > 0 && net_err == 0) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_TCP_WRITE_FAIL;
}
void network_at_tcp_disconnect(Network *pNetwork)
{
int rc;
rc = at_socket_close((int)pNetwork->handle);
if (QCLOUD_RET_SUCCESS != rc) {
Log_e("socket close error\n");
}
return;
}
#endif

View File

@@ -0,0 +1,111 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "network_interface.h"
#include "qcloud_iot_export_error.h"
#include "utils_param_check.h"
int is_network_connected(Network *pNetwork)
{
return pNetwork->handle;
}
#ifdef AT_TCP_ENABLED
int is_network_at_connected(Network *pNetwork)
{
return pNetwork->handle == AT_NO_CONNECTED_FD ? 0 : pNetwork->handle == AT_NO_CONNECTED_FD;
}
#endif
int network_init(Network *pNetwork)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
// to avoid process crash when writing to a broken socket
#if defined(__linux__)
signal(SIGPIPE, SIG_IGN);
#endif
switch (pNetwork->type) {
case NETWORK_TCP:
#ifdef AT_TCP_ENABLED
pNetwork->init = network_at_tcp_init;
pNetwork->connect = network_at_tcp_connect;
pNetwork->read = network_at_tcp_read;
pNetwork->write = network_at_tcp_write;
pNetwork->disconnect = network_at_tcp_disconnect;
pNetwork->is_connected = is_network_at_connected;
pNetwork->handle = AT_NO_CONNECTED_FD;
#else
pNetwork->init = network_tcp_init;
pNetwork->connect = network_tcp_connect;
pNetwork->read = network_tcp_read;
pNetwork->write = network_tcp_write;
pNetwork->disconnect = network_tcp_disconnect;
pNetwork->is_connected = is_network_connected;
pNetwork->handle = 0;
#endif
break;
#ifndef AUTH_WITH_NOTLS
case NETWORK_TLS:
pNetwork->init = network_tls_init;
pNetwork->connect = network_tls_connect;
pNetwork->read = network_tls_read;
pNetwork->write = network_tls_write;
pNetwork->disconnect = network_tls_disconnect;
pNetwork->is_connected = is_network_connected;
pNetwork->handle = 0;
break;
#endif
#ifdef COAP_COMM_ENABLED
#ifdef AUTH_WITH_NOTLS
case NETWORK_UDP:
pNetwork->init = network_udp_init;
pNetwork->connect = network_udp_connect;
pNetwork->read = network_udp_read;
pNetwork->write = network_udp_write;
pNetwork->disconnect = network_udp_disconnect;
pNetwork->is_connected = is_network_connected;
pNetwork->handle = 0;
break;
#else
case NETWORK_DTLS:
pNetwork->init = network_dtls_init;
pNetwork->connect = network_dtls_connect;
pNetwork->read = network_dtls_read;
pNetwork->write = network_dtls_write;
pNetwork->disconnect = network_dtls_disconnect;
pNetwork->is_connected = is_network_connected;
pNetwork->handle = 0;
break;
#endif
#endif
default:
Log_e("unknown network type: %d", pNetwork->type);
return QCLOUD_ERR_INVAL;
}
return pNetwork->init(pNetwork);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,131 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "network_interface.h"
#include "qcloud_iot_export_error.h"
#include "qcloud_iot_import.h"
#include "utils_param_check.h"
/*
* TCP/UDP socket API
*/
int network_tcp_init(Network *pNetwork)
{
return QCLOUD_RET_SUCCESS;
}
int network_tcp_connect(Network *pNetwork)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
pNetwork->handle = HAL_TCP_Connect(pNetwork->host, pNetwork->port);
if (0 == pNetwork->handle) {
return -1;
}
return 0;
}
int network_tcp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int rc = 0;
rc = HAL_TCP_Read(pNetwork->handle, data, (uint32_t)datalen, timeout_ms, read_len);
return rc;
}
int network_tcp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int rc = 0;
rc = HAL_TCP_Write(pNetwork->handle, data, datalen, timeout_ms, written_len);
return rc;
}
void network_tcp_disconnect(Network *pNetwork)
{
POINTER_SANITY_CHECK_RTN(pNetwork);
if (0 == pNetwork->handle) {
return;
}
HAL_TCP_Disconnect(pNetwork->handle);
pNetwork->handle = 0;
return;
}
#if (defined COAP_COMM_ENABLED) && (defined AUTH_WITH_NOTLS)
int network_udp_init(Network *pNetwork)
{
return QCLOUD_RET_SUCCESS;
}
int network_udp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int ret = HAL_UDP_ReadTimeout(pNetwork->handle, data, datalen, timeout_ms);
if (ret > 0) {
*read_len = ret;
ret = 0;
}
return ret;
}
int network_udp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int ret = HAL_UDP_Write(pNetwork->handle, data, datalen);
if (ret > 0) {
*written_len = ret;
ret = 0;
}
return ret;
}
void network_udp_disconnect(Network *pNetwork)
{
POINTER_SANITY_CHECK_RTN(pNetwork);
HAL_UDP_Disconnect(pNetwork->handle);
pNetwork->handle = 0;
return;
}
int network_udp_connect(Network *pNetwork)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
pNetwork->handle = HAL_UDP_Connect(pNetwork->host, pNetwork->port);
if (0 == pNetwork->handle) {
return -1;
}
return 0;
}
#endif

View File

@@ -0,0 +1,117 @@
/*
* Tencent is pleased to support the open source community by making IoT Hub available.
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "network_interface.h"
#include "qcloud_iot_export_error.h"
#include "qcloud_iot_import.h"
#include "utils_param_check.h"
/*
* TLS/DTLS network API
*/
#ifndef AUTH_WITH_NOTLS
int network_tls_init(Network *pNetwork)
{
return QCLOUD_RET_SUCCESS;
}
int network_tls_connect(Network *pNetwork)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int ret = QCLOUD_ERR_FAILURE;
pNetwork->handle = (uintptr_t)HAL_TLS_Connect(&(pNetwork->ssl_connect_params), pNetwork->host, pNetwork->port);
if (pNetwork->handle != 0) {
ret = QCLOUD_RET_SUCCESS;
}
return ret;
}
int network_tls_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int rc = HAL_TLS_Read(pNetwork->handle, data, datalen, timeout_ms, read_len);
return rc;
}
int network_tls_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int rc = HAL_TLS_Write(pNetwork->handle, data, datalen, timeout_ms, written_len);
return rc;
}
void network_tls_disconnect(Network *pNetwork)
{
POINTER_SANITY_CHECK_RTN(pNetwork);
HAL_TLS_Disconnect(pNetwork->handle);
pNetwork->handle = 0;
}
#ifdef COAP_COMM_ENABLED
int network_dtls_init(Network *pNetwork)
{
return QCLOUD_RET_SUCCESS;
}
int network_dtls_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
return HAL_DTLS_Read(pNetwork->handle, data, datalen, timeout_ms, read_len);
}
int network_dtls_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
return HAL_DTLS_Write(pNetwork->handle, data, datalen, written_len);
}
void network_dtls_disconnect(Network *pNetwork)
{
POINTER_SANITY_CHECK_RTN(pNetwork);
HAL_DTLS_Disconnect(pNetwork->handle);
pNetwork->handle = 0;
return;
}
int network_dtls_connect(Network *pNetwork)
{
POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL);
int ret = QCLOUD_ERR_FAILURE;
pNetwork->handle = (uintptr_t)HAL_DTLS_Connect(&(pNetwork->ssl_connect_params), pNetwork->host, pNetwork->port);
if (pNetwork->handle != 0) {
ret = QCLOUD_RET_SUCCESS;
}
return ret;
}
#endif
#endif