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:
872
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/at_client.c
vendored
Normal file
872
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/at_client.c
vendored
Normal 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;
|
||||
}
|
413
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/at_socket_inf.c
vendored
Normal file
413
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/at_socket_inf.c
vendored
Normal 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);
|
||||
}
|
||||
}
|
345
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/at_utils.c
vendored
Normal file
345
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/at_utils.c
vendored
Normal 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++;
|
||||
}
|
||||
}
|
153
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/network_at_tcp.c
vendored
Normal file
153
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/at_socket/network_at_tcp.c
vendored
Normal 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
|
111
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/network_interface.c
vendored
Normal file
111
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/network_interface.c
vendored
Normal 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
|
131
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/socket/network_socket.c
vendored
Normal file
131
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/socket/network_socket.c
vendored
Normal 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
|
117
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/tls/network_tls.c
vendored
Normal file
117
components/connectivity/qcloud-iot-hub-sdk/3rdparty/sdk_src/network/tls/network_tls.c
vendored
Normal 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
|
Reference in New Issue
Block a user