support aliyun sdk on TencentOS tiny

sample: examples\aliyun_iotkit_csdk_mqtt
project: board\TencentOS_tiny_EVB_MX_Plus\KEIL\aliyun_iotkit_csdk_mqtt
This commit is contained in:
dcxajichu
2019-10-31 16:36:28 +08:00
parent 30ea36a7ab
commit 8c24d921b0
692 changed files with 199829 additions and 0 deletions

View File

@@ -0,0 +1,945 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "infra_config.h"
#include "mqtt_api.h"
#include "at_wrapper.h"
#include "at_parser.h"
#include "at_api.h"
#include "at_mqtt.h"
#define AT_ICA_MQTT_MQTTMODE "AT+IMQTTMODE"
#define AT_ICA_MQTT_MQTTOPEN "AT+IMQTTOPEN"
#define AT_ICA_MQTT_MQTTAUTH "AT+IMQTTAUTH"
#define AT_ICA_MQTT_MQTTPARA "AT+IMQTTPARA"
#define AT_ICA_MQTT_MQTTCONN "AT+IMQTTCONN"
#define AT_ICA_MQTT_MQTTPUB "AT+IMQTTPUB"
#define AT_ICA_MQTT_MQTTPUBIN "AT+IMQTTPUBIN"
#define AT_ICA_MQTT_MQTTSUB "AT+IMQTTSUB"
#define AT_ICA_MQTT_MQTTUNSUB "AT+IMQTTUNSUB"
#define AT_ICA_MQTT_MQTTSTATE "AT+IMQTTSTATE"
#define AT_ICA_MQTT_MQTTDISCONN "AT+IMQTTDISCONN"
#define AT_ICA_MQTT_MQTTDBG "AT+IMQTTDBG"
#define AT_ICA_MQTT_MQTTRCV "+IMQTT"
#define AT_ICA_MQTT_MQTTERROR "+CME"
#define AT_ICA_MQTT_MQTTOK "OK"
#define AT_ICA_MQTT_MQTTRCVPUB "+IMQTTRCVPUB"
#define AT_ICA_MQTT_MQTTRCVPUBIN "+IMQTTRCVPUBIN"
#define AT_ICA_MQTT_MQTTPINGRSP "+IMQTTPINGRSP"
#define AT_ICA_MQTT_MQTTAUTHRSP "+IMQTTAUTH"
#define AT_ICA_MQTT_MQTTPUBRSP "+IMQTTPUB"
#define AT_ICA_MQTT_MQTTSUBRSP "+IMQTTSUB"
#define AT_ICA_MQTT_MQTTUNSUBRSP "+IMQTTUNSUB"
#define AT_ICA_MQTT_MQTTSTATERSP "+IMQTTSTATE"
#define AT_ICA_MQTT_POSTFIX "\r\n"
#define AT_MQTT_WAIT_FOREVER 0xffffffffu
#define AT_MQTT_CMD_MAX_LEN 400
#define AT_MQTT_CMD_SUCCESS_RSP "OK"
#define AT_MQTT_CMD_FAIL_RSP "FAIL"
#define AT_MQTT_CMD_ERROR_RSP "ERROR"
#define AT_MQTT_SUBSCRIBE_FAIL 128
#define AT_MQTT_RSP_MAX_LEN (CONFIG_MQTT_MESSAGE_MAXLEN + CONFIG_MQTT_TOPIC_MAXLEN + 20)
#define AT_MQTT_WAIT_TIMEOUT 10*1000
#define mal_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#ifdef INFRA_MEM_STATS
#include "infra_mem_stats.h"
#define AT_MQTT_ICA_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "mal.ica")
#define AT_MQTT_ICA_FREE(ptr) LITE_free(ptr)
#else
#define AT_MQTT_ICA_MALLOC(size) HAL_Malloc(size)
#define AT_MQTT_ICA_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
#endif
char at_recv_rsp_buf[AT_MQTT_CMD_MAX_LEN];
typedef enum {
AT_MQTT_IDLE = 0,
AT_MQTT_SEND_TYPE_SIMPLE,
AT_MQTT_AUTH,
AT_MQTT_SUB,
AT_MQTT_UNSUB,
AT_MQTT_PUB,
} at_mqtt_send_type_t;
int at_ica_mqtt_atsend(char *at_cmd, int timeout_ms);
int at_ica_mqtt_client_deinit(void);
int at_ica_mqtt_client_init(void);
int at_ica_mqtt_client_state(void);
int at_ica_mqtt_client_publish(const char *topic, int qos, const char *message);
int at_ica_mqtt_client_unsubscribe(const char *topic,
unsigned int *mqtt_packet_id,
int *mqtt_status);
int at_ica_mqtt_client_subscribe(const char *topic,
int qos,
unsigned int *mqtt_packet_id,
int *mqtt_status,
int timeout_ms);
int at_ica_mqtt_client_conn(char *proKey, char *devName, char *devSecret, int tlsEnable);
int at_ica_mqtt_client_auth(char *proKey, char *devName, char *devSecret, int tlsEnable);
int at_ica_mqtt_client_disconn(void);
int HAL_AT_MQTT_Init(iotx_mqtt_param_t *pInitParams)
{
return at_ica_mqtt_client_init();
}
int HAL_AT_MQTT_Deinit()
{
return at_ica_mqtt_client_deinit();
}
int HAL_AT_MQTT_Connect(char *proKey, char *devName, char *devSecret)
{
return at_ica_mqtt_client_conn(proKey, devName, devSecret, 0);
}
int HAL_AT_MQTT_Disconnect(void)
{
return at_ica_mqtt_client_disconn();
}
int HAL_AT_MQTT_Subscribe(const char *topic, int qos, unsigned int *mqtt_packet_id, int *mqtt_status, int timeout_ms)
{
return at_ica_mqtt_client_subscribe(topic, qos, mqtt_packet_id, mqtt_status, timeout_ms);
}
int HAL_AT_MQTT_Unsubscribe(const char *topic, unsigned int *mqtt_packet_id, int *mqtt_status)
{
return at_ica_mqtt_client_unsubscribe(topic, mqtt_packet_id, mqtt_status);
}
int HAL_AT_MQTT_Publish(const char *topic, int qos, const char *message, unsigned int msg_len)
{
return at_ica_mqtt_client_publish(topic, qos, message);
}
int HAL_AT_MQTT_State(void)
{
return at_ica_mqtt_client_state();
}
int HAL_AT_MQTT_Connectwifi(char *at_conn_wifi)
{
#ifdef MAL_ICA_ENABLED
char at_cmd[64];
/* disconnect before connect to the network */
if (at_ica_mqtt_client_disconn() != 0) {
return -1;
}
memcpy(at_cmd, at_conn_wifi, 64);
/* connect to the network */
if (at_ica_mqtt_atsend(at_cmd, AT_MQTT_WAIT_FOREVER) != 0) {
return -1;
}
return 0;
#endif
return -1;
}
#ifndef PLATFORM_HAS_OS
char g_ica_rsp_buff[AT_MQTT_RSP_MAX_LEN];
#else
static char *g_ica_rsp_buff = NULL;
#endif
static volatile int g_mqtt_connect_state = IOTX_MC_STATE_INVALID;
static volatile at_mqtt_send_type_t g_ica_at_response = AT_MQTT_IDLE;
static volatile int g_at_response_result = 0;
#ifdef PLATFORM_HAS_OS
static void *g_sem_response;
#else
int g_at_response = 0;
#endif
static volatile int g_response_msg_number = 0;
static int g_response_packetid = 0;
static int g_response_status = 0;
static int g_public_qos = 0;
int at_ica_mqtt_atsend(char *at_cmd, int timeout_ms);
static void at_err_callback(char *at_rsp)
{
char *temp;
int data;
temp = strtok(at_rsp, ":");
temp = strtok(NULL, ":");
if ((data = strtol(temp, NULL, 0)) == 3) {
g_at_response_result = 0;
} else {
g_at_response_result = -1;
}
#ifdef PLATFORM_HAS_OS
/* notify the sender error; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
}
static void at_succ_callback(void)
{
g_at_response_result = 0;
#ifdef PLATFORM_HAS_OS
/* notify the sender ok; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
}
static void sub_callback(char *at_rsp)
{
char *temp;
if (strstr(at_rsp, AT_MQTT_CMD_ERROR_RSP)) {
g_at_response_result = -1;
#ifdef PLATFORM_HAS_OS
/* notify the sender fail; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
} else if (NULL != strstr(at_rsp, AT_ICA_MQTT_MQTTSUBRSP)) {
/* get status/packet_id */
if (NULL != strstr(at_rsp, ",")) {
g_at_response_result = 0;
temp = strtok(at_rsp, ":");
if (temp != NULL) {
temp = strtok(NULL, ",");
} else {
mal_err("subscribe rsp param invalid 1");
g_at_response_result = -1;
#ifdef PLATFORM_HAS_OS
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
}
if (temp != NULL) {
g_response_packetid = strtol(temp, NULL, 0);
temp = strtok(NULL, "\r\n");
} else {
mal_err("subscribe rsp param invalid 2");
g_at_response_result = -1;
#ifdef PLATFORM_HAS_OS
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
}
if (temp != NULL) {
g_response_status = strtol(temp, NULL, 0);
} else {
mal_err("subscribe rsp param invalid 3");
g_at_response_result = -1;
#ifdef PLATFORM_HAS_OS
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
}
#ifdef PLATFORM_HAS_OS
/* notify the sender ok; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
}
}
return;
}
static void unsub_callback(char *at_rsp)
{
char *temp;
if (strstr(at_rsp, AT_MQTT_CMD_ERROR_RSP)) {
g_at_response_result = -1;
#ifdef PLATFORM_HAS_OS
/* notify the sender fail; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
} else if (NULL != strstr(at_rsp, AT_ICA_MQTT_MQTTUNSUBRSP)) {
/* get status/packet_id */
if (NULL != strstr(at_rsp, ",")) {
g_at_response_result = 0;
temp = strtok(at_rsp, ":");
if (temp != NULL) {
temp = strtok(NULL, ",");
} else {
mal_err("subscribe rsp param invalid 1");
return;
}
if (temp != NULL) {
g_response_packetid = strtol(temp, NULL, 0);
temp = strtok(NULL, "\r\n");
} else {
mal_err("subscribe rsp param invalid 2");
return;
}
if (temp != NULL) {
g_response_status = strtol(temp, NULL, 0);
} else {
mal_err("subscribe rsp param invalid 3");
return;
}
mal_err("unsub: %s", g_ica_rsp_buff);
mal_err("unsub packetid: %d, sta: %d", g_response_packetid, g_response_status);
#ifdef PLATFORM_HAS_OS
/* notify the sender ok; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
}
}
return;
}
static void pub_callback(char *at_rsp)
{
char *temp;
if (strstr(at_rsp, AT_MQTT_CMD_ERROR_RSP)) {
g_at_response_result = -1;
#ifdef PLATFORM_HAS_OS
/* notify the sender fail; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
return;
} else if (NULL != strstr(at_rsp, AT_ICA_MQTT_MQTTPUBRSP)) {
/* get status/packet_id */
if ((NULL != strstr(at_rsp, ","))
|| (0 == g_public_qos)) {
temp = strtok(at_rsp, ":");
if (temp != NULL) {
if (0 == g_public_qos) {
temp = strtok(NULL, "\r\n");
} else {
temp = strtok(NULL, ",");
}
} else {
mal_err("public get packetid error");
return;
}
if (temp != NULL) {
g_response_packetid = strtol(temp, NULL, 0);
} else {
mal_err("public parse packetid error");
return;
}
if (0 != g_public_qos) {
temp = strtok(NULL, "\r\n");
if (temp != NULL) {
g_response_status = strtol(temp, NULL, 0);
} else {
mal_err("public parse status error");
return;
}
}
g_at_response_result = 0;
#ifdef PLATFORM_HAS_OS
/* notify the sender ok; */
HAL_SemaphorePost(g_sem_response);
#else
g_at_response ++;
#endif
}
}
return;
}
static void state_change_callback(char *at_rsp)
{
char *temp;
if (NULL == at_rsp) {
return;
}
temp = strtok(at_rsp, ":");
if (temp != NULL) {
temp = strtok(NULL, "\r\n");
if (temp != NULL) {
g_mqtt_connect_state = strtol(temp, NULL, 0);
}
}
return;
}
static void recv_data_callback(char *at_rsp)
{
char *temp = NULL;
char *topic_ptr = NULL;
char *msg_ptr = NULL;
unsigned int msg_len = 0;
struct at_mqtt_input param;
if (NULL == at_rsp) {
return;
}
/* try to get msg id */
temp = strtok(g_ica_rsp_buff, ":");
if (temp != NULL) {
temp = strtok(NULL, ",");
if (temp != NULL) {
/* packet_id = strtol(temp, NULL, 0); */
} else {
mal_err("packet id error");
return;
}
} else {
mal_err("packet id not found");
return;
}
/* try to get topic string */
temp = strtok(NULL, "\"");
if (temp != NULL) {
temp[strlen(temp)] = '\0';
topic_ptr = temp;
} else {
mal_err("publish topic not found");
return;
}
/* try to get payload string */
temp = strtok(NULL, ",");
if (temp != NULL) {
msg_len = strtol(temp, NULL, 0);
while (*temp++ != '\"');
msg_ptr = temp;
msg_ptr[msg_len] = '\0';
param.topic = topic_ptr;
param.topic_len = strlen(topic_ptr);
param.message = msg_ptr;
param.msg_len = strlen(msg_ptr);
if (IOT_ATM_Input(&param) != 0) {
mal_err("hand data to uplayer fail!\n");
}
return;
} else {
mal_err("publish data not found");
return;
}
}
static void at_ica_mqtt_client_rsp_callback(void *arg, char *rspinfo, int rsplen)
{
if (NULL == rspinfo || rsplen == 0) {
mal_err("invalid input of rsp callback");
return;
}
if (NULL == g_ica_rsp_buff) {
mal_err("g_ica_rsp_buff rsp is NULL");
return;
}
if (rsplen > AT_MQTT_RSP_MAX_LEN) {
mal_err("rsp len(%d) exceed max len", rsplen);
return;
}
memcpy(g_ica_rsp_buff, rspinfo, rsplen);
g_ica_rsp_buff[rsplen] = '\0';
if (0 == memcmp(g_ica_rsp_buff,
AT_ICA_MQTT_MQTTERROR,
strlen(AT_ICA_MQTT_MQTTERROR))) {
at_err_callback(g_ica_rsp_buff);
} else if (0 == memcmp(g_ica_rsp_buff,
AT_ICA_MQTT_MQTTRCVPUB,
strlen(AT_ICA_MQTT_MQTTRCVPUB))) { /* Receive Publish Data */
recv_data_callback(g_ica_rsp_buff);
} else if (0 == memcmp(g_ica_rsp_buff,
AT_ICA_MQTT_MQTTSTATERSP,
strlen(AT_ICA_MQTT_MQTTSTATERSP))) { /* Receive Mqtt Status Change */
state_change_callback(g_ica_rsp_buff);
} else {
switch (g_ica_at_response) { /* nothing to process */
case AT_MQTT_IDLE:
break;
case AT_MQTT_SEND_TYPE_SIMPLE:
if (0 == memcmp(g_ica_rsp_buff,
AT_MQTT_CMD_SUCCESS_RSP,
strlen(AT_MQTT_CMD_SUCCESS_RSP))) {
at_succ_callback();
} else {
mal_err("invalid success type %s", g_ica_rsp_buff);
}
break;
case AT_MQTT_AUTH:
if (0 == memcmp(g_ica_rsp_buff,
AT_ICA_MQTT_MQTTAUTHRSP,
strlen(AT_ICA_MQTT_MQTTAUTHRSP))) {
if (NULL != strstr(g_ica_rsp_buff, AT_MQTT_CMD_SUCCESS_RSP)) {
at_succ_callback();
}
}
break;
case AT_MQTT_SUB:
sub_callback(g_ica_rsp_buff);
break;
case AT_MQTT_UNSUB:
unsub_callback(g_ica_rsp_buff);
break;
case AT_MQTT_PUB:
pub_callback(g_ica_rsp_buff);
break;
default:
break;
}
}
return;
}
int at_ica_mqtt_client_disconn(void)
{
char at_cmd[64];
memset(at_cmd, 0, 64);
/* connect to the network */
HAL_Snprintf(at_cmd,
64,
"%s\r\n",
AT_ICA_MQTT_MQTTDISCONN);
/* disconnect from server */
if (0 != at_ica_mqtt_atsend(at_cmd, AT_MQTT_WAIT_TIMEOUT)) {
mal_err("disconnect at command fail");
return -1;
}
return 0;
}
int at_ica_mqtt_client_auth(char *proKey, char *devName, char *devSecret, int tlsEnable)
{
char at_cmd[AT_MQTT_CMD_MAX_LEN];
if ((proKey == NULL) || (devName == NULL) || (devSecret == NULL)) {
mal_err("auth param should not be NULL");
return -1;
}
/* set tls mode before auth */
if (tlsEnable) {
memset(at_cmd, 0, AT_MQTT_CMD_MAX_LEN);
HAL_Snprintf(at_cmd,
AT_MQTT_CMD_MAX_LEN - 1,
"%s=%d\r\n",
AT_ICA_MQTT_MQTTMODE,
1);
if (0 != at_ica_mqtt_atsend(at_cmd, AT_MQTT_WAIT_TIMEOUT)) {
mal_err("tls at command fail");
return -1;
}
}
/* submit auth */
memset(at_cmd, 0, AT_MQTT_CMD_MAX_LEN);
HAL_Snprintf(at_cmd,
AT_MQTT_CMD_MAX_LEN - 1,
"%s=\"%s\",\"%s\",\"%s\"\r\n",
AT_ICA_MQTT_MQTTAUTH,
proKey, devName, devSecret);
if (0 != at_ica_mqtt_atsend(at_cmd, AT_MQTT_WAIT_TIMEOUT)) {
mal_err("auth at command fail");
return -1;
}
return 0;
}
int at_ica_mqtt_client_conn(char *proKey, char *devName, char *devSecret, int tlsEnable)
{
char at_cmd[64];
if ((proKey == NULL) || (devName == NULL) || (devSecret == NULL)) {
mal_err("conn param should not be NULL");
return -1;
}
if (0 != at_ica_mqtt_client_auth(proKey, devName, devSecret, tlsEnable)) {
mal_err("authen fail");
return -1;
}
/* connect to mqtt server */
memset(at_cmd, 0, 64);
HAL_Snprintf(at_cmd,
64,
"%s\r\n",
AT_ICA_MQTT_MQTTCONN);
if (0 != at_ica_mqtt_atsend(at_cmd, AT_MQTT_WAIT_TIMEOUT)) {
mal_err("conn at command fail");
return -1;
}
return 0;
}
int at_ica_mqtt_client_subscribe(const char *topic,
int qos,
unsigned int *mqtt_packet_id,
int *mqtt_status,
int timeout_ms)
{
char at_cmd[AT_MQTT_CMD_MAX_LEN];
if ((topic == NULL) || (mqtt_packet_id == NULL) || (mqtt_status == NULL)) {
mal_err("subscribe param should not be NULL");
return -1;
}
memset(at_cmd, 0, AT_MQTT_CMD_MAX_LEN);
HAL_Snprintf(at_cmd,
AT_MQTT_CMD_MAX_LEN - 1,
"%s=\"%s\",%d\r\n",
AT_ICA_MQTT_MQTTSUB,
topic,
qos);
if (0 != at_ica_mqtt_atsend(at_cmd, timeout_ms)) {
mal_err("sub at command fail");
return -1;
}
return 0;
}
int at_ica_mqtt_client_unsubscribe(const char *topic,
unsigned int *mqtt_packet_id,
int *mqtt_status)
{
char at_cmd[AT_MQTT_CMD_MAX_LEN];
if ((topic == NULL) || (mqtt_packet_id == NULL) || (mqtt_status == NULL)) {
mal_err("unsubscribe param should not be NULL");
return -1;
}
memset(at_cmd, 0, AT_MQTT_CMD_MAX_LEN);
HAL_Snprintf(at_cmd,
AT_MQTT_CMD_MAX_LEN - 1,
"%s=\"%s\"\r\n",
AT_ICA_MQTT_MQTTUNSUB,
topic);
if (0 != at_ica_mqtt_atsend(at_cmd, AT_MQTT_WAIT_TIMEOUT)) {
mal_err("unsub at command fail");
return -1;
}
return 0;
}
int at_ica_mqtt_client_publish(const char *topic, int qos, const char *message)
{
char at_cmd[AT_MQTT_CMD_MAX_LEN] = {0};
char msg_convert[AT_MQTT_CMD_MAX_LEN] = {0};
char *temp;
if ((topic == NULL) || (message == NULL)) {
mal_err("publish param should not be NULL");
return -1;
}
temp = msg_convert;
/* for the case of " appeared in the string */
while (*message) {
if (*message == '\"') {
*temp++ = '\\';
}
*temp++ = *message++;
}
HAL_Snprintf(at_cmd,
AT_MQTT_CMD_MAX_LEN - 1,
"%s=\"%s\",%d,\"%s\"\r\n",
AT_ICA_MQTT_MQTTPUB,
topic,
qos,
msg_convert);
g_public_qos = qos;
if (0 != at_ica_mqtt_atsend(at_cmd, AT_MQTT_WAIT_TIMEOUT)) {
mal_err("pub at command fail");
return -1;
}
return 0;
}
int at_ica_mqtt_client_state(void)
{
int state;
switch(g_mqtt_connect_state){
case 0:
state = IOTX_MC_STATE_DISCONNECTED;
break;
case 1:
state = IOTX_MC_STATE_CONNECTED;
break;
default:
state = IOTX_MC_STATE_INVALID;
break;
}
return state;
}
int at_ica_mqtt_client_init(void)
{
#ifdef PLATFORM_HAS_OS
g_ica_rsp_buff = AT_MQTT_ICA_MALLOC(AT_MQTT_RSP_MAX_LEN);
if (NULL == g_ica_rsp_buff) {
mal_err("at ica mqtt client malloc buff failed");
return -1;
}
if (NULL == (g_sem_response = HAL_SemaphoreCreate())) {
if (NULL != g_ica_rsp_buff) {
AT_MQTT_ICA_FREE(g_ica_rsp_buff);
g_ica_rsp_buff = NULL;
}
mal_err("at ica mqtt client create sem failed");
return -1;
}
#else
memset(g_ica_rsp_buff, 0, AT_MQTT_RSP_MAX_LEN);
g_at_response = 0;
#endif
g_mqtt_connect_state = IOTX_MC_STATE_INVALID;
at_register_callback(AT_ICA_MQTT_MQTTRCV,
AT_ICA_MQTT_POSTFIX,
at_recv_rsp_buf,
AT_MQTT_CMD_MAX_LEN,
at_ica_mqtt_client_rsp_callback,
NULL);
at_register_callback(AT_ICA_MQTT_MQTTERROR,
AT_ICA_MQTT_POSTFIX,
at_recv_rsp_buf,
AT_MQTT_CMD_MAX_LEN,
at_ica_mqtt_client_rsp_callback,
NULL);
at_register_callback(AT_ICA_MQTT_MQTTOK,
AT_ICA_MQTT_POSTFIX,
at_recv_rsp_buf,
AT_MQTT_CMD_MAX_LEN,
at_ica_mqtt_client_rsp_callback,
NULL);
return 0;
}
int at_ica_mqtt_client_deinit(void)
{
#ifdef PLATFORM_HAS_OS
if (NULL != g_ica_rsp_buff) {
AT_MQTT_ICA_FREE(g_ica_rsp_buff);
g_ica_rsp_buff = NULL;
}
HAL_SemaphoreDestroy(g_sem_response);
#else
memset(g_ica_rsp_buff, 0, AT_MQTT_RSP_MAX_LEN);
g_at_response = 0;
#endif
g_mqtt_connect_state = IOTX_MC_STATE_INVALID;
return 0;
}
int at_ica_mqtt_atsend(char *at_cmd, int timeout_ms)
{
if (at_cmd == NULL) {
return -1;
}
/* state error */
if (g_ica_at_response != AT_MQTT_IDLE) {
mal_err("at send state is not idle (%d)", g_ica_at_response);
return -1;
}
mal_err("send: %s", at_cmd);
if (NULL != strstr(at_cmd, AT_ICA_MQTT_MQTTAUTH)) {
g_ica_at_response = AT_MQTT_AUTH;
} else if (NULL != strstr(at_cmd, AT_ICA_MQTT_MQTTSUB)) {
g_ica_at_response = AT_MQTT_SUB;
} else if (NULL != strstr(at_cmd, AT_ICA_MQTT_MQTTUNSUB)) {
g_ica_at_response = AT_MQTT_UNSUB;
} else if (NULL != strstr(at_cmd, AT_ICA_MQTT_MQTTPUB)) {
g_ica_at_response = AT_MQTT_PUB;
} else {
g_ica_at_response = AT_MQTT_SEND_TYPE_SIMPLE;
}
if (0 != at_send_no_reply(at_cmd, strlen(at_cmd), false)) {
mal_err("at send raw api fail");
g_ica_at_response = AT_MQTT_IDLE;
return -1;
}
#ifdef PLATFORM_HAS_OS
HAL_SemaphoreWait(g_sem_response, timeout_ms);
#else
if(!g_at_response)
{
at_yield(NULL, 0, NULL, 500);
}
else
{
g_at_response --;
}
#endif
g_ica_at_response = AT_MQTT_IDLE;
return g_at_response_result;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,747 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include "infra_config.h"
#include "mqtt_api.h"
#include "at_wrapper.h"
#include "at_parser.h"
#include "at_api.h"
#define TAG "at_mk3060_wifi"
#define CMD_FAIL_RSP "ERROR"
#define MAX_DATA_LEN 4096
#define MAX_DOMAIN_LEN 256
#define DATA_LEN_MAX 10
#define LINK_ID_MAX 5
#define SEM_WAIT_DURATION 5000
#define AT_CMD_EHCO_OFF "AT+UARTE=OFF"
#define STOP_CMD "AT+CIPSTOP"
#define STOP_CMD_LEN (sizeof(STOP_CMD)+1+1+5+1)
#define STOP_AUTOCONN_CMD "AT+CIPAUTOCONN"
#define STOP_AUTOCONN_CMD_LEN (sizeof(STOP_AUTOCONN_CMD)+1+1+5+1)
#ifdef AT_DEBUG_MODE
#define at_conn_hal_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#else
#define at_conn_hal_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_warning(...)
#define at_conn_hal_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_debug(...)
#endif
void *HAL_SemaphoreCreate(void);
void HAL_SemaphoreDestroy(void *sem);
void HAL_SemaphorePost(void *sem);
int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
typedef int (*at_data_check_cb_t)(char data);
/* Change to include data slink for each link id respectively. <TODO> */
typedef struct link_s {
int fd;
void* sem_start;
void* sem_close;
} link_t;
static link_t g_link[LINK_ID_MAX];
static void* g_link_mutex;
static char localipaddr[16];
static int socket_data_info_get(char *buf, uint32_t buflen, at_data_check_cb_t valuecheck);
static int socket_data_len_check(char data);
#define WIFI_SSID "Yuemewifi-3766"
#define WIFI_PWD "aos12345"
#define WIFI_TIMEOUT 20000
static uint8_t gotip = 0;
#define MK3080_MAX_PAYLOAD_SIZE (CONFIG_MQTT_MESSAGE_MAXLEN + CONFIG_MQTT_TOPIC_MAXLEN + 20)
#ifndef PLATFORM_HAS_DYNMEM
static uint8_t payload[MK3080_MAX_PAYLOAD_SIZE] = {0};
#endif
static uint64_t _get_time_ms(void)
{
return HAL_UptimeMs();
}
static uint64_t _time_left(uint64_t t_end, uint64_t t_now)
{
uint64_t t_left;
if (t_end > t_now) {
t_left = t_end - t_now;
} else {
t_left = 0;
}
return t_left;
}
static int at_connect_wifi(char *ssid, char *pwd, uint32_t timeout_ms)
{
char conn_str[100]= {0};
char out[20] = {0};
uint64_t t_end, t_left;
t_end = _get_time_ms() + timeout_ms;
HAL_Snprintf(conn_str, 100, "AT+WJAP=%s,%s", ssid, pwd);
if (at_send_wait_reply(conn_str, strlen(conn_str), true, NULL,
0, out, sizeof(out), NULL) < 0){
return -1;
}
if (strstr(out, "ERROR") != NULL) {
return -1;
}
while(0 == gotip) {
HAL_SleepMs(50);
t_left = _time_left(t_end, _get_time_ms());
if (0 == t_left) {
at_conn_hal_err("wifi connect timeout!\n");
return -1;
}
#ifndef PLATFORM_HAS_OS
at_yield(NULL, 0, NULL, 100);
#endif
}
return 0;
}
static void handle_tcp_udp_client_conn_state(uint8_t link_id)
{
char s[32] = {0};
at_read(s, 6);
if (strstr(s, "CLOSED") != NULL) {
at_conn_hal_info("Server closed event.");
if (g_link[link_id].sem_close) {
at_conn_hal_debug(TAG, "sem is going to be waked up: 0x%x", &g_link[link_id].sem_close);
HAL_SemaphorePost(g_link[link_id].sem_close); /* wakeup send task */
}
at_conn_hal_info("Server conn (%d) closed.", link_id);
} else if (strstr(s, "CONNEC") != NULL) {
at_conn_hal_info("Server conn (%d) successful.", link_id);
at_read(s, 3);
if (g_link[link_id].sem_start) {
at_conn_hal_debug("sem is going to be waked up: 0x%x", &g_link[link_id].sem_start);
HAL_SemaphorePost(g_link[link_id].sem_start); /* wakeup send task */
}
} else if (strstr(s, "DISCON") != NULL) {
at_conn_hal_info("Server conn (%d) disconnected.", link_id);
at_read(s, 6);
} else {
at_conn_hal_warning("No one handle this unkown event!!!");
}
}
static int socket_data_len_check(char data)
{
if (data > '9' || data < '0') {
return -1;
}
return 0;
}
static int socket_data_info_get(char *buf, uint32_t buflen, at_data_check_cb_t valuecheck)
{
uint32_t i = 0;
if (NULL == buf || 0 == buflen) {
return -1;
}
do {
at_read(&buf[i], 1);
if (buf[i] == ',') {
buf[i] = 0;
break;
}
if (i >= buflen) {
at_conn_hal_err("Too long length of data.reader is %s \r\n", buf);
return -1;
}
if (NULL != valuecheck) {
if (valuecheck(buf[i])) {
at_conn_hal_err("Invalid string!!!, reader is %s \r\n", buf);
return -1;
}
}
i++;
} while (1);
return 0;
}
static void handle_socket_data()
{
int link_id = 0;
int ret = 0;
uint32_t len = 0;
char reader[16] = {0};
char *recvdata = NULL;
struct at_conn_input param;
/* Eat the "OCKET," */
at_read(reader, 6);
if (memcmp(reader, "OCKET,", strlen("OCKET,")) != 0) {
at_conn_hal_err("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x invalid event format!!!\r\n",
reader[0], reader[1], reader[2], reader[3], reader[4], reader[5]);
return;
}
memset(reader, 0, sizeof(reader));
ret = socket_data_info_get(reader, 1, &socket_data_len_check);
if (ret) {
at_conn_hal_err("Invalid link id 0x%02x !!!\r\n", reader[0]);
return;
}
link_id = reader[0] - '0';
memset(reader, 0, sizeof(reader));
/* len */
ret = socket_data_info_get(reader, sizeof(reader), &socket_data_len_check);
if (ret) {
at_conn_hal_err("Invalid datalen %s !!!\r\n", reader);
return;
}
len = atoi(reader);
if (len > MAX_DATA_LEN) {
at_conn_hal_err("invalid input socket data len %d \r\n", len);
return;
}
/* Prepare socket data */
#ifdef PLATFORM_HAS_DYNMEM
recvdata = (char *)HAL_Malloc(len);
#else
if (len <= MK3080_MAX_PAYLOAD_SIZE) {
recvdata = (char *)payload;
}
#endif
if (!recvdata) {
at_conn_hal_err("Error: %s %d out of memory, len is %d. \r\n", __func__, __LINE__, len);
return;
}
ret = at_read(recvdata, len);
if (ret != len) {
at_conn_hal_err("at read error recv %d want %d!\n", ret, len);
goto err;
}
memset(reader, 0, sizeof(reader));
at_read(reader, 2);
if (strncmp(reader, AT_RECV_PREFIX, 2) != 0) {
at_conn_hal_err("at fail to read delimiter %s after data %s!\n", AT_RECV_PREFIX, reader);
goto err;
}
if (g_link[link_id].fd >= 0) {
param.fd = g_link[link_id].fd;
param.data = recvdata;
param.datalen = len;
param.remote_ip = NULL;
param.remote_port = 0;
/* TODO get recv data src ip and port*/
if (IOT_ATM_Input(&param) != 0) {
at_conn_hal_err(" %s socket %d get data len %d fail to post to at_conn, drop it\n",
__func__, g_link[link_id].fd, len);
}
}
at_conn_hal_debug("%s socket data on link %d with length %d posted to at_conn\n",
__func__, link_id, len);
err:
#ifdef PLATFORM_HAS_DYNMEM
HAL_Free(recvdata);
#endif
return;
}
/*
* Wifi station event handler. include:
* +WEVENT:AP_UP
* +WEVENT:AP_DOWN
* +WEVENT:STATION_UP
* +WEVENT:STATION_DOWN
*/
static void mk3060wifi_event_handler(void *arg, char *buf, int buflen)
{
char eventhead[4] = {0};
char eventotal[16] = {0};
at_read(eventhead, 3);
if (strcmp(eventhead, "AP_") == 0) {
at_read(eventotal, 2);
if (strcmp(eventotal, "UP") == 0) {
} else if (strcmp(eventotal, "DO") == 0) {
/*eat WN*/
at_read(eventotal, 2);
} else {
at_conn_hal_err("!!!Error: wrong WEVENT AP string received. %s\r\n", eventotal);
return;
}
} else if (strcmp(eventhead, "STA") == 0) {
at_read(eventotal, 7);
if (strcmp(eventotal, "TION_UP") == 0) {
gotip = 1;
} else if (strcmp(eventotal, "TION_DO") == 0) {
/*eat WN*/
at_read(eventotal, 2);
memset(localipaddr, 0, sizeof(localipaddr));
gotip = 0;
} else {
at_conn_hal_err("!!!Error: wrong WEVENT STATION string received. %s\r\n", eventotal);
return;
}
} else {
at_conn_hal_err("!!!Error: wrong WEVENT string received. %s\r\n", eventhead);
return;
}
return;
}
/**
* Network connection state event handler. Events includes:
* 1. +CIPEVENT:id,SERVER,CONNECTED
* 2. +CIPEVENT:id,SERVER,CLOSED
* 3. +CIPEVENT:CLIENT,CONNECTED,ip,port
* 4. +CIPEVENT:CLIENT,CLOSED,ip,port
* 5. +CIPEVENT:id,UDP,CONNECTED
* 6. +CIPEVENT:id,UDP,CLOSED
* 7. +CIPEVENT:SOCKET,id,len,data
* 8. +CIPEVENT:UDP_BROADCAST,ip,port,id,len,data
*/
static void net_event_handler(void *arg, char *buf, int buflen)
{
char c;
char s[32] = {0};
at_read(&c, 1);
if (c >= '0' && c < ('0' + LINK_ID_MAX)) {
int link_id = c - '0';
at_read(&c, 1);
if (c != ',') {
at_conn_hal_err("!!!Error: wrong CIPEVENT string. 0x%02x\r\n", c);
return;
}
at_read(&c, 1);
if (c == 'S') {
at_conn_hal_debug("%s server conn state event, linkid: %d.", __func__, link_id);
/* Eat the "ERVER," */
at_read(s, 6);
if (memcmp(s, "ERVER,", strlen("ERVER,")) != 0) {
at_conn_hal_err("invalid event format 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
s[0], s[1], s[2], s[3], s[4], s[5]);
return;
}
handle_tcp_udp_client_conn_state(link_id);
} else if (c == 'U') {
at_conn_hal_debug("%s UDP conn state event.", __func__);
/* Eat the "DP," */
at_read(s, 3);
if (memcmp(s, "DP,", strlen("DP,")) != 0) {
at_conn_hal_err("%s invalid event format 0x%02x 0x%02x 0x%02x \r\n", __FUNCTION__, s[0], s[1], s[2]);
return;
}
handle_tcp_udp_client_conn_state(link_id);
} else {
at_conn_hal_err( "!!!Error: wrong CIPEVENT string 0x%02x at line %d\r\n", c, __LINE__);
return ;
}
} else if (c == 'S') {
at_conn_hal_debug("%s socket data event.", __func__);
handle_socket_data();
} else {
at_conn_hal_err("!!!Error: wrong CIPEVENT string received. 0x%02x\r\n", c);
return;
}
at_conn_hal_debug("%s exit.", __func__);
}
static void mk3060_uart_echo_off()
{
char *at_echo_str = AT_CMD_EHCO_OFF;
char out[64] = {0};
at_send_wait_reply(at_echo_str, strlen(AT_CMD_EHCO_OFF), true,
NULL, 0, out, sizeof(out), NULL);
at_conn_hal_debug("The AT response is: %s", out);
if (strstr(out, CMD_FAIL_RSP) != NULL) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
}
return;
}
static uint8_t inited = 0;
#define NET_OOB_PREFIX "+CIPEVENT:"
#define WIFIEVENT_OOB_PREFIX "+WEVENT:"
int HAL_AT_CONN_Init(void)
{
int link;
char cmd[STOP_AUTOCONN_CMD_LEN] = {0};
char out[64] = {0};
if (inited) {
at_conn_hal_warning("at_conn component is already initialized");
return 0;
}
if (NULL == (g_link_mutex = HAL_MutexCreate())) {
at_conn_hal_err("Creating link mutex failed (%s %d).", __func__, __LINE__);
return -1;
}
mk3060_uart_echo_off();
memset(g_link, 0, sizeof(g_link));
for (link = 0; link < LINK_ID_MAX; link++) {
g_link[link].fd = -1;
/*close all link */
HAL_Snprintf(cmd, STOP_CMD_LEN - 1, "%s=%d", STOP_CMD, link);
at_conn_hal_debug("%s %d - AT cmd to run: %s", __func__, __LINE__, cmd);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, out,
sizeof(out), NULL);
at_conn_hal_debug("The AT response is: %s", out);
if (strstr(out, CMD_FAIL_RSP) != NULL) {
at_conn_hal_debug("%s %d failed", __func__, __LINE__);
}
memset(cmd, 0, sizeof(cmd));
/*close all link auto reconnect */
HAL_Snprintf(cmd, STOP_AUTOCONN_CMD_LEN - 1, "%s=%d,0", STOP_AUTOCONN_CMD, link);
at_conn_hal_debug("%s %d - AT cmd to run: %s", __func__, __LINE__, cmd);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, out,
sizeof(out), NULL);
at_conn_hal_debug("The AT response is: %s", out);
if (strstr(out, CMD_FAIL_RSP) != NULL) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
}
memset(cmd, 0, sizeof(cmd));
}
at_register_callback(NET_OOB_PREFIX, NULL, NULL, 0, net_event_handler, NULL);
at_register_callback(WIFIEVENT_OOB_PREFIX, NULL, NULL, 0, mk3060wifi_event_handler, NULL);
if (at_connect_wifi(WIFI_SSID, WIFI_PWD, WIFI_TIMEOUT) < 0) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
return -1;
}
inited = 1;
return 0;
}
int HAL_AT_CONN_Deinit(void)
{
if (!inited) {
return 0;
}
HAL_MutexDestroy(g_link_mutex);
return 0;
}
#define START_CMD "AT+CIPSTART"
#define START_CMD_LEN (sizeof(START_CMD)+1+1+13+1+MAX_DOMAIN_LEN+1+5+1+5+1)
static char *start_cmd_type_str[] = {"tcp_server", "tcp_client", \
"ssl_client", "udp_broadcast", "udp_unicast"
};
int HAL_AT_CONN_Start(at_conn_t *c)
{
int link_id;
char cmd[START_CMD_LEN] = {0};
char out[256] = {0};
if (!c || !c->addr) {
at_conn_hal_err("%s %d - invalid argument", __func__, __LINE__);
return -1;
}
HAL_MutexLock(g_link_mutex);
for (link_id = 0; link_id < LINK_ID_MAX; link_id++) {
if (g_link[link_id].fd >= 0) {
continue;
} else {
g_link[link_id].fd = c->fd;
if (NULL == (g_link[link_id].sem_start = HAL_SemaphoreCreate())) {
at_conn_hal_err("failed to allocate semaphore %s", __func__);
g_link[link_id].fd = -1;
return -1;
}
if (NULL == (g_link[link_id].sem_close = HAL_SemaphoreCreate())) {
at_conn_hal_err("failed to allocate semaphore %s", __func__);
HAL_SemaphoreDestroy(g_link[link_id].sem_start);
g_link[link_id].fd = -1;
return -1;
}
break;
}
}
HAL_MutexUnlock(g_link_mutex);
/* The caller should deal with this failure */
if (link_id >= LINK_ID_MAX) {
at_conn_hal_info("No link available for now, %s failed.", __func__);
return -1;
}
at_conn_hal_debug("Creating %s connection ...", start_cmd_type_str[c->type]);
switch (c->type) {
case TCP_CLIENT:
HAL_Snprintf(cmd, START_CMD_LEN - 5 - 1, "%s=%d,%s,%s,%d",
START_CMD, link_id, start_cmd_type_str[c->type],
c->addr, c->r_port);
if (c->l_port >= 0) {
HAL_Snprintf(cmd + strlen(cmd), 7, ",%d", c->l_port);
}
break;
default:
at_conn_hal_err("Invalid connection type.");
goto err;
}
at_conn_hal_debug("\r\n%s %d - AT cmd to run: %s \r\n", __func__, __LINE__, cmd);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, out,
sizeof(out), NULL);
at_conn_hal_debug("The AT response is: %s", out);
if (strstr(out, CMD_FAIL_RSP) != NULL) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
goto err;
}
if (HAL_SemaphoreWait(g_link[link_id].sem_start, SEM_WAIT_DURATION) != 0) {
at_conn_hal_err("%s sem_wait failed", __func__);
goto err;
}
at_conn_hal_debug("%s sem_wait succeed.", __func__);
return 0;
err:
HAL_MutexLock(g_link_mutex);
if (g_link[link_id].sem_start) {
HAL_SemaphoreDestroy(g_link[link_id].sem_start);
}
if (g_link[link_id].sem_close) {
HAL_SemaphoreDestroy(g_link[link_id].sem_close);
}
g_link[link_id].fd = -1;
HAL_MutexUnlock(g_link_mutex);
return -1;
}
static int fd_to_linkid(int fd)
{
int link_id;
HAL_MutexLock(g_link_mutex);
for (link_id = 0; link_id < LINK_ID_MAX; link_id++) {
if (g_link[link_id].fd == fd) {
break;
}
}
HAL_MutexUnlock(g_link_mutex);
return link_id;
}
#define SEND_CMD "AT+CIPSEND"
#define SEND_CMD_LEN (sizeof(SEND_CMD)+1+1+5+1+DATA_LEN_MAX+1)
int HAL_AT_CONN_Send(int fd,
uint8_t *data,
uint32_t len,
char remote_ip[16],
int32_t remote_port,
int32_t timeout)
{
int link_id;
char cmd[SEND_CMD_LEN] = {0}, out[128] = {0};
if (!data) {
return -1;
}
at_conn_hal_debug("%s on fd %d", __func__, fd);
link_id = fd_to_linkid(fd);
if (link_id < 0 || link_id >= LINK_ID_MAX) {
at_conn_hal_err("No connection found for fd (%d) in %s", fd, __func__);
return -1;
}
/* AT+CIPSEND=id, */
HAL_Snprintf(cmd, SEND_CMD_LEN - 1, "%s=%d,", SEND_CMD, link_id);
/* [remote_port,] */
if (remote_port >= 0) {
HAL_Snprintf(cmd + strlen(cmd), 7, "%d,", remote_port);
}
/* data_length */
HAL_Snprintf(cmd + strlen(cmd), DATA_LEN_MAX + 1, "%d", len);
at_conn_hal_debug("\r\n%s %d - AT cmd to run: %s\r\n", __func__, __LINE__, cmd);
at_send_wait_reply((const char *)cmd, strlen(cmd), true, (const char *)data, len,
out, sizeof(out), NULL);
at_conn_hal_debug("\r\nThe AT response is: %s\r\n", out);
if (strstr(out, CMD_FAIL_RSP) != NULL) {
at_conn_hal_debug("%s %d failed", __func__, __LINE__);
return -1;
}
return 0;
}
#define DOMAIN_RSP "+CIPDOMAIN:"
#define DOMAIN_CMD "AT+CIPDOMAIN"
#define DOMAIN_CMD_LEN (sizeof(DOMAIN_CMD)+MAX_DOMAIN_LEN+1)
/* Return the first IP if multiple found. */
int HAL_AT_CONN_DomainToIp(char *domain,
char ip[16])
{
char cmd[DOMAIN_CMD_LEN] = {0}, out[256] = {0}, *head, *end;
HAL_Snprintf(cmd, DOMAIN_CMD_LEN - 1, "%s=%s", DOMAIN_CMD, domain);
at_conn_hal_debug("%s %d - AT cmd to run: %s", __func__, __LINE__, cmd);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, out,
sizeof(out), NULL);
at_conn_hal_debug("The AT response is: %s", out);
if (strstr(out, AT_RECV_SUCCESS_POSTFIX) == NULL) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
return -1;
}
/**
* +CIPDOMAIN:1\r\n
* 180.97.33.108\r\n
*
* OK\r\n
*/
if ((head = strstr(out, DOMAIN_RSP)) == NULL) {
at_conn_hal_err("No IP info found in result string %s \r\n.", out);
return -1;
}
/* Check the format */
head += strlen(DOMAIN_RSP);
if (head[0] < '0' && head[0] >= ('0' + LINK_ID_MAX)) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
goto err;
}
head++;
if (memcmp(head, AT_RECV_PREFIX, strlen(AT_RECV_PREFIX)) != 0) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
goto err;
}
/* We find the IP head */
head += strlen(AT_RECV_PREFIX);
end = head;
while (((end - head) < 15) && (*end != '\r')) {
end++;
}
if (((end - head) < 6) || ((end - head) > 15)) {
goto err;
}
/* We find a good IP, save it. */
memcpy(ip, head, end - head);
ip[end - head] = '\0';
at_conn_hal_debug("get domain %s ip %s \r\n", domain, ip);
return 0;
err:
at_conn_hal_err("Failed to get IP due to unexpected result string %s \r\n.", out);
return -1;
}
int HAL_AT_CONN_Close(int fd,
int32_t remote_port)
{
int link_id;
char cmd[STOP_CMD_LEN] = {0}, out[64];
link_id = fd_to_linkid(fd);
if (link_id < 0 || link_id >= LINK_ID_MAX) {
at_conn_hal_err("No connection found for fd (%d) in %s", fd, __func__);
return -1;
}
HAL_Snprintf(cmd, STOP_CMD_LEN - 1, "%s=%d", STOP_CMD, link_id);
at_conn_hal_debug("%s %d - AT cmd to run: %s", __func__, __LINE__, cmd);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, out,
sizeof(out), NULL);
at_conn_hal_debug("The AT response is: %s", out);
if (strstr(out, CMD_FAIL_RSP) != NULL) {
at_conn_hal_err("%s %d failed", __func__, __LINE__);
goto err;
}
if (HAL_SemaphoreWait(g_link[link_id].sem_close, SEM_WAIT_DURATION) != 0) {
at_conn_hal_err("%s sem_wait failed", __func__);
goto err;
}
at_conn_hal_debug("%s sem_wait succeed.", __func__);
err:
HAL_MutexLock(g_link_mutex);
if (g_link[link_id].sem_start) {
HAL_SemaphoreDestroy(g_link[link_id].sem_start);
}
if (g_link[link_id].sem_close) {
HAL_SemaphoreDestroy(g_link[link_id].sem_close);
}
g_link[link_id].fd = -1;
HAL_MutexUnlock(g_link_mutex);
return -1;
}

View File

@@ -0,0 +1,870 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include "infra_config.h"
#include "mqtt_api.h"
#include "at_wrapper.h"
#include "at_parser.h"
#include "at_api.h"
#define TAG "sim800_gprs_module"
#define SIM800_AT_CMD_SUCCESS_RSP "OK"
#define SIM800_AT_CMD_FAIL_RSP "ERROR"
#define AT_CMD_TEST "AT"
#define AT_CMD_TEST_RESULT "OK\r\n"
#define AT_CMD_ECHO_OFF "ATE0"
#define AT_CMD_BAUDRATE_SET "AT+IPR"
#define AT_CMD_FLOW_CONTROL "AT+IFC"
#define AT_CMD_SAVE_CONFIG "AT&W"
#define AT_CMD_SIM_PIN_CHECK "AT+CPIN?"
#define AT_CMD_SIGNAL_QUALITY_CHECK "AT+CSQ"
#define AT_CMD_NETWORK_REG_CHECK "AT+CREG?"
#define AT_CMD_GPRS_ATTACH_CHECK "AT+CGATT?"
#define AT_CMD_GPRS_PDP_DEACTIVE "AT+CIPSHUT"
#define AT_CMD_MULTI_IP_CONNECTION "AT+CIPMUX"
#define AT_CMD_SEND_DATA_PROMPT_SET "AT+CIPSPRT"
#define AT_CMD_RECV_DATA_FORMAT_SET "AT+CIPSRIP"
#define AT_CMD_DOMAIN_TO_IP "AT+CDNSGIP"
#define AT_CMD_DOMAIN_RSP "\r\n+CDNSGIP: "
#define AT_CMD_START_TASK "AT+CSTT"
#define AT_CMD_BRING_UP_GPRS_CONNECT "AT+CIICR"
#define AT_CMD_GOT_LOCAL_IP "AT+CIFSR"
#define AT_CMD_START_CLIENT_CONN "AT+CIPSTART"
#define AT_CMD_CLIENT_CONNECT_OK "CONNECT OK\r\n"
#define AT_CMD_CLIENT_CONNECT_FAIL "CONNECT FAIL\r\n"
#define AT_CMD_STOP_CONN "AT+CIPCLOSE"
#define AT_CMD_SEND_DATA "AT+CIPSEND"
#define AT_CMD_DATA_RECV "\r\n+RECEIVE,"
#define SIM800_DEFAULT_CMD_LEN 64
#define SIM800_DEFAULT_RSP_LEN 64
#define SIM800_MAX_LINK_NUM 6
#define SIM800_DOMAIN_MAX_LEN 64
#define SIM800_DOMAIN_RSP_MAX_LEN 128
#define SIM800_DOMAIN_CMD_LEN (sizeof(AT_CMD_DOMAIN_TO_IP) + SIM800_DOMAIN_MAX_LEN + 1)
#define SIM800_CONN_CMD_LEN (SIM800_DOMAIN_MAX_LEN + SIM800_DEFAULT_CMD_LEN)
#define SIM800_RETRY_MAX 50
#define SIM800_WAIT_MAX_MS 10000
#ifdef AT_DEBUG_MODE
#define at_conn_hal_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#else
#define at_conn_hal_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define at_conn_hal_debug(...)
#endif
#define SIM800_MAX_PAYLOAD_SIZE (CONFIG_MQTT_MESSAGE_MAXLEN + CONFIG_MQTT_TOPIC_MAXLEN + 20)
#ifndef PLATFORM_HAS_DYNMEM
static uint8_t payload[SIM800_MAX_PAYLOAD_SIZE] = {0};
#endif
/* Change to include data slink for each link id respectively. <TODO> */
typedef struct link_s {
int fd;
void* sem_start;
void* sem_close;
} link_t;
static uint8_t inited = 0;
static link_t g_link[SIM800_MAX_LINK_NUM];
static void *g_link_mutex;
static void *g_domain_mutex;
#ifdef PLATFORM_HAS_OS
static void *g_domain_sem;
#else
static int g_domain_mark = 0;
#endif
static char g_pcdomain_buf[SIM800_DOMAIN_RSP_MAX_LEN];
static char g_pcdomain_rsp[SIM800_DOMAIN_RSP_MAX_LEN];
static char g_pccmd[SIM800_CONN_CMD_LEN];
static char g_cmd[SIM800_DEFAULT_CMD_LEN];
static char g_rsp[SIM800_DEFAULT_RSP_LEN];
static int fd_to_linkid(int fd)
{
int link_id;
HAL_MutexLock(g_link_mutex);
for (link_id = 0; link_id < SIM800_MAX_LINK_NUM; link_id++) {
if (g_link[link_id].fd == fd) {
break;
}
}
HAL_MutexUnlock(g_link_mutex);
return link_id;
}
static void sim800_gprs_domain_rsp_callback(void *arg, char *rspinfo, int rsplen)
{
if (NULL == rspinfo || rsplen == 0) {
at_conn_hal_err( "invalid input at %s \r\n", __func__);
return;
}
memcpy(g_pcdomain_rsp, rspinfo, rsplen);
#ifdef PLATFORM_HAS_OS
HAL_SemaphorePost(g_domain_sem);
#else
g_domain_mark = 1;
#endif
return;
}
static void sim800_gprs_module_socket_data_handle(void *arg, char *rspinfo, int rsplen)
{
unsigned char uclinkid = 0;
unsigned char unusesymbol = 0;
unsigned char datalen[6] = {0};
unsigned char ipaddr[16] = {0};
unsigned char port[6] = {0};
int i = 0;
int j = 0;
int len = 0;
int remoteport = 0;
int linkid = 0;
char *recvdata = NULL;
struct at_conn_input param;
at_read((char *)&uclinkid, 1);
linkid = uclinkid - '0';
if (linkid < 0 || linkid >= SIM800_MAX_LINK_NUM) {
at_conn_hal_err( "Invalid link id 0x%02x !!!\r\n", linkid);
return;
}
/*eat , char*/
at_read((char *)&unusesymbol, 1);
/* get data len */
i = 0;
do {
at_read((char *)&datalen[i], 1);
if (datalen[i] == ',') {
break;
}
if (i >= sizeof(datalen)) {
at_conn_hal_err( "Too long length of data.datalen is %s \r\n", datalen);
return;
}
if (datalen[i] > '9' || datalen[i] < '0') {
at_conn_hal_err( "Invalid len string!!!, datalen is %s \r\n", datalen);
return;
}
i++;
} while (1);
/* len: string to number */
for (j = 0; j < i; j++) {
len = len * 10 + datalen[j] - '0';
}
/*get ip addr and port*/
i = 0;
do {
at_read((char *)&ipaddr[i], 1);
if (ipaddr[i] == ':') {
break;
}
if (i >= sizeof(ipaddr)) {
at_conn_hal_err( "Too long length of ipaddr.ipaddr is %s \r\n", ipaddr);
return;
}
if (!((ipaddr[i] <= '9' && ipaddr[i] >= '0') || ipaddr[i] == '.')) {
at_conn_hal_err( "Invalid ipaddr string!!!, ipaddr is %s \r\n", ipaddr);
return;
}
i++;
} while (1);
ipaddr[i] = 0;
i = 0;
do {
at_read((char *)&port[i], 1);
if (port[i] == '\r') {
break;
}
if (i >= sizeof(port)) {
at_conn_hal_err( "Too long length of remote port.port is %s \r\n", port);
return;
}
if (port[i] > '9' || port[i] < '0') {
at_conn_hal_err( "Invalid ipaddr string!!!, port is %s \r\n", port);
return;
}
i++;
} while (1);
port[i] = 0;
/*eat \n char*/
at_read((char *)&unusesymbol, 1);
for (j = 0; j < i; j++) {
remoteport = remoteport * 10 + port[j] - '0';
}
#ifdef PLATFORM_HAS_DYNMEM
/* Prepare socket data */
recvdata = (char *)HAL_Malloc(len);
#else
if (len <= SIM800_MAX_PAYLOAD_SIZE) {
recvdata = (char *)payload;
}
#endif
if (!recvdata) {
at_conn_hal_err( "Error: %s %d out of memory.", __func__, __LINE__);
return;
}
memset(recvdata, 0, len);
at_read(recvdata, len);
if (g_link[linkid].fd >= 0) {
param.fd = g_link[linkid].fd;
param.data = recvdata;
param.datalen = len;
param.remote_ip = (char *)ipaddr;
param.remote_port = remoteport;
/* TODO get recv data src ip and port*/
if (IOT_ATM_Input(&param) != 0) {
at_conn_hal_err( " %s socket %d get data len %d fail to post to at_conn, drop it\n",
__func__, g_link[linkid].fd, len);
}
}
at_conn_hal_debug( "%s socket data on link %d with length %d posted to at_conn\n",
__func__, linkid, len);
#ifdef PLATFORM_HAS_DYNMEM
HAL_Free(recvdata);
#endif
return;
}
static int sim800_send_with_retry(const char *cmd, int cmdlen, bool delimiter, const char *data,
int datalen, char *rspbuf, int buflen, const char *expectrsp)
{
int retry = 0;
if (NULL == cmd || 0 == cmdlen || NULL == rspbuf ||
0 == buflen || NULL == expectrsp) {
at_conn_hal_err("Invalid input %s %d\r\n", __func__, __LINE__);
return -1;
}
while(true) {
retry++;
memset(rspbuf, 0, buflen);
at_send_wait_reply(cmd, cmdlen, delimiter, data, datalen, rspbuf, buflen, NULL);
if (strstr(rspbuf, expectrsp) == NULL) {
if (retry > SIM800_RETRY_MAX) {
return -1;
}
at_conn_hal_err("%s %d cmd %s failed rsp %s retry count %d\r\n", __func__, __LINE__, cmd,rspbuf, retry);
HAL_SleepMs(50);
} else {
break;
}
}
return 0;
}
int sim800_uart_selfadaption(const char *command, const char *rsp, uint32_t rsplen)
{
char *buffer = g_rsp;
if (NULL == command || NULL == rsp || 0 == rsplen) {
at_conn_hal_err( "invalid input %s %d\r\n", __FILE__, __LINE__);
return -1;
}
if (sim800_send_with_retry(command, strlen(command), true, NULL, 0,
buffer, SIM800_DEFAULT_RSP_LEN, rsp) < 0) {
return -1;
}
return 0;
}
static int sim800_uart_init(void)
{
int ret = 0;
char *cmd = g_cmd;
char *rsp = g_rsp;
/* uart baudrate self adaption*/
ret = sim800_uart_selfadaption(AT_CMD_TEST, AT_CMD_TEST_RESULT, strlen(AT_CMD_TEST_RESULT));
if (ret) {
at_conn_hal_err( "sim800_uart_selfadaption fail \r\n");
return ret;
}
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
/*turn off echo*/
at_send_wait_reply(AT_CMD_ECHO_OFF, strlen(AT_CMD_ECHO_OFF), true, NULL, 0,
rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
memset(cmd, 0, SIM800_DEFAULT_CMD_LEN);
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
/*set baudrate 115200*/
HAL_Snprintf(cmd, SIM800_DEFAULT_CMD_LEN - 1, "%s=%d", AT_CMD_BAUDRATE_SET, AT_UART_BAUDRATE);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
memset(cmd, 0, SIM800_DEFAULT_CMD_LEN);
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
/*turn off flow control*/
HAL_Snprintf(cmd, SIM800_DEFAULT_CMD_LEN - 1, "%s=%d,%d", AT_CMD_FLOW_CONTROL, 0, 0);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
/*save configuration */
at_send_wait_reply(AT_CMD_SAVE_CONFIG, strlen(AT_CMD_SAVE_CONFIG), true, NULL, 0,
rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
return 0;
}
static int sim800_gprs_status_check(void)
{
char *rsp = g_rsp;
/*sim card status check*/
if (sim800_send_with_retry(AT_CMD_SIM_PIN_CHECK, strlen(AT_CMD_SIM_PIN_CHECK), true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, SIM800_AT_CMD_SUCCESS_RSP) < 0) {
at_conn_hal_err("sim card status check failed\n");
return -1;
}
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
/*Signal quaility check*/
at_send_wait_reply(AT_CMD_SIGNAL_QUALITY_CHECK, strlen(AT_CMD_SIGNAL_QUALITY_CHECK), true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
at_conn_hal_info( "signal quality is %s \r\n", rsp);
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
/*network registration check*/
at_send_wait_reply(AT_CMD_NETWORK_REG_CHECK, strlen(AT_CMD_NETWORK_REG_CHECK), true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
at_conn_hal_info( "network registration is %s \r\n", rsp);
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
/*GPRS attach check*/
at_send_wait_reply(AT_CMD_GPRS_ATTACH_CHECK, strlen(AT_CMD_GPRS_ATTACH_CHECK),true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
at_conn_hal_info( "gprs attach check %s \r\n", rsp);
return 0;
}
static int sim800_gprs_ip_init(void)
{
char *cmd = g_cmd;
char *rsp = g_rsp;
/*Deactivate GPRS PDP Context*/
if (sim800_send_with_retry(AT_CMD_GPRS_PDP_DEACTIVE, strlen(AT_CMD_GPRS_PDP_DEACTIVE), true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, SIM800_AT_CMD_SUCCESS_RSP) < 0) {
at_conn_hal_err("Deactivate GPRS PDP Context failed\n");
return -1;
}
/*set multi ip connection mode*/
memset(cmd, 0, SIM800_DEFAULT_CMD_LEN);
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
HAL_Snprintf(cmd, SIM800_DEFAULT_CMD_LEN - 1, "%s=%d", AT_CMD_MULTI_IP_CONNECTION, 1);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0,
rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
/*not prompt echo > when sending data*/
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
memset(cmd, 0, SIM800_DEFAULT_CMD_LEN);
HAL_Snprintf(cmd, SIM800_DEFAULT_CMD_LEN - 1, "%s=%d", AT_CMD_SEND_DATA_PROMPT_SET, 0);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0,
rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
/*Show Remote ip and port when receive data*/
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
memset(cmd, 0, SIM800_DEFAULT_CMD_LEN);
HAL_Snprintf(cmd, SIM800_DEFAULT_CMD_LEN - 1, "%s=%d", AT_CMD_RECV_DATA_FORMAT_SET, 1);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
return 0;
}
static int sim800_gprs_got_ip(void)
{
char *rsp = g_rsp;
atcmd_config_t atcmd_config = {NULL, AT_RECV_PREFIX, NULL};
/*start gprs stask*/
if (sim800_send_with_retry(AT_CMD_START_TASK, strlen(AT_CMD_START_TASK), true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, SIM800_AT_CMD_SUCCESS_RSP) < 0) {
at_conn_hal_err("%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
/*bring up wireless connectiong with gprs*/
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
at_send_wait_reply(AT_CMD_BRING_UP_GPRS_CONNECT, strlen(AT_CMD_BRING_UP_GPRS_CONNECT), true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
}
/*try to got ip*/
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
at_send_wait_reply(AT_CMD_GOT_LOCAL_IP, strlen(AT_CMD_GOT_LOCAL_IP), true, NULL, 0,
rsp, SIM800_DEFAULT_RSP_LEN, &atcmd_config);
if (strstr(rsp, SIM800_AT_CMD_FAIL_RSP) != NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
}
return 0;
}
static int sim800_gprs_get_ip_only()
{
char *rsp = g_rsp;
atcmd_config_t atcmd_config = {NULL, AT_RECV_PREFIX, NULL};
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
at_send_wait_reply(AT_CMD_GOT_LOCAL_IP, strlen(AT_CMD_GOT_LOCAL_IP), true,
NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN, &atcmd_config);
if (strstr(rsp, SIM800_AT_CMD_FAIL_RSP) != NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
return -1;
}
return 0;
}
int HAL_AT_CONN_Init(void)
{
int ret = 0;
uint32_t linknum = 0;
if (inited) {
at_conn_hal_info( "sim800 gprs module have already inited \r\n");
return 0;
}
memset(g_pcdomain_rsp , 0, SIM800_DOMAIN_RSP_MAX_LEN);
if (NULL == (g_link_mutex = HAL_MutexCreate())) {
at_conn_hal_err( "Creating link mutex failed (%s %d).", __func__, __LINE__);
goto err;
}
if (NULL == (g_domain_mutex = HAL_MutexCreate())) {
at_conn_hal_err( "Creating link mutex failed (%s %d).", __func__, __LINE__);
goto err;
}
#ifdef PLATFORM_HAS_OS
if (NULL == (g_domain_sem = HAL_SemaphoreCreate())) {
at_conn_hal_err( "Creating domain mutex failed (%s %d).", __func__, __LINE__);
goto err;
}
#endif
memset(g_link, 0, sizeof(g_link));
for (linknum = 0; linknum < SIM800_MAX_LINK_NUM; linknum++) {
g_link[linknum].fd = -1;
}
ret = sim800_uart_init();
if (ret) {
at_conn_hal_err( "%s %d failed \r\n", __func__, __LINE__);
goto err;
}
ret = sim800_gprs_status_check();
if (ret) {
at_conn_hal_err( "%s %d failed \r\n", __func__, __LINE__);
goto err;
}
ret = sim800_gprs_ip_init();
if (ret) {
at_conn_hal_err( "%s %d failed \r\n", __func__, __LINE__);
goto err;
}
/* reg oob for domain and packet input*/
at_register_callback(AT_CMD_DOMAIN_RSP, AT_RECV_PREFIX, g_pcdomain_buf, SIM800_DOMAIN_RSP_MAX_LEN,
sim800_gprs_domain_rsp_callback, NULL);
at_register_callback(AT_CMD_DATA_RECV, NULL, NULL, 0, sim800_gprs_module_socket_data_handle, NULL);
ret = sim800_gprs_got_ip();
if (ret) {
at_conn_hal_err( "%s %d failed \r\n", __func__, __LINE__);
goto err;
}
inited = 1;
return 0;
err:
if (g_link_mutex != NULL) {
HAL_MutexDestroy(g_link_mutex);
}
if (g_domain_mutex != NULL) {
HAL_MutexDestroy(g_domain_mutex);
}
#ifdef PLATFORM_HAS_OS
if (g_domain_sem != NULL) {
HAL_SemaphoreDestroy(g_domain_sem);
}
#endif
return -1;
}
int HAL_AT_CONN_Deinit()
{
if (!inited) {
return 0;
}
HAL_MutexDestroy(g_link_mutex);
inited = 0;
return 0;
}
#ifndef PLATFORM_HAS_OS
static uint64_t _get_time_ms(void)
{
return HAL_UptimeMs();
}
static uint64_t _time_left(uint64_t t_end, uint64_t t_now)
{
uint64_t t_left;
if (t_end > t_now) {
t_left = t_end - t_now;
} else {
t_left = 0;
}
return t_left;
}
#endif
int HAL_AT_CONN_DomainToIp(char *domain, char ip[16])
{
char *pccmd = NULL;
char *head = NULL;
char *end = NULL;
char *rsp = g_rsp;
int count = 0;
#ifndef PLATFORM_HAS_OS
uint64_t t_end, t_left;
#endif
if (!inited) {
at_conn_hal_err( "%s sim800 gprs module haven't init yet \r\n", __func__);
return -1;
}
if (NULL == domain || NULL == ip) {
at_conn_hal_err( "invalid input at %s \r\n", __func__);
return -1;
}
if (strlen(domain) > SIM800_DOMAIN_MAX_LEN) {
at_conn_hal_err( "domain length oversize at %s \r\n", __func__);
return -1;
}
pccmd = g_pccmd;
if (NULL == pccmd) {
at_conn_hal_err( "fail to malloc memory %d at %s \r\n", SIM800_DOMAIN_CMD_LEN, __func__);
return -1;
}
memset(pccmd, 0, SIM800_DOMAIN_CMD_LEN);
HAL_Snprintf(pccmd, SIM800_DOMAIN_CMD_LEN - 1, "%s=%s", AT_CMD_DOMAIN_TO_IP, domain);
HAL_MutexLock(g_domain_mutex);
restart:
count++;
if (count > SIM800_RETRY_MAX) {
at_conn_hal_err( "domain to ip retry failed!\r\n");
HAL_MutexUnlock(g_domain_mutex);
return -1;
}
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
at_send_wait_reply(pccmd, strlen(pccmd), true, NULL, 0, rsp,
SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "%s %d failed rsp %s\r\n", __func__, __LINE__, rsp);
goto err;
}
#ifdef PLATFORM_HAS_OS
HAL_SemaphoreWait(g_domain_sem, SIM800_WAIT_MAX_MS);
#else
t_end = _get_time_ms() + SIM800_WAIT_MAX_MS;
while(!g_domain_mark) {
at_yield(NULL, 0, NULL, 100);
t_left = _time_left(t_end, _get_time_ms());
if (0 == t_left) {
break;
}
}
g_domain_mark = 0;
#endif
/*
* formate is :
+CDNSGIP: 1,"www.baidu.com","183.232.231.173","183.232.231.172"
or :
+CDNSGIP: 0,8
*/
if ((head = strstr(g_pcdomain_rsp, domain)) == NULL) {
at_conn_hal_err( "invalid domain rsp %s at %d\r\n", g_pcdomain_rsp, __LINE__);
goto err;
}
head += (strlen(domain) + 3);
if ((end = strstr(head, "\"")) == NULL) {
at_conn_hal_err( "invalid domain rsp head is %s at %d\r\n", head, __LINE__);
goto err;
}
if ((end - head) > 15 || (end - head) < 7) {
at_conn_hal_err( "invalid domain rsp head is %s at %d\r\n", head, __LINE__);
goto err;
}
/* We find a good IP, save it. */
memcpy(ip, head, end - head);
ip[end - head] = '\0';
memset(g_pcdomain_rsp, 0, SIM800_DOMAIN_RSP_MAX_LEN);
HAL_MutexUnlock(g_domain_mutex);
return 0;
err:
if (sim800_gprs_get_ip_only() != 0) {
sim800_gprs_ip_init();
sim800_gprs_got_ip();
goto restart;
}
memset(g_pcdomain_rsp, 0, SIM800_DOMAIN_RSP_MAX_LEN);
HAL_MutexUnlock(g_domain_mutex);
return -1;
}
int HAL_AT_CONN_Start(at_conn_t *conn)
{
int linkid = 0;
char *pccmd = NULL;
char *rsp = g_rsp;
atcmd_config_t atcmd_config_client = { NULL, AT_CMD_CLIENT_CONNECT_OK, AT_CMD_CLIENT_CONNECT_FAIL};
if (!inited) {
at_conn_hal_err( "%s sim800 gprs module haven't init yet \r\n", __func__);
return -1;
}
if (!conn || !conn->addr) {
at_conn_hal_err( "%s %d - invalid input \r\n", __func__, __LINE__);
return -1;
}
HAL_MutexLock(g_link_mutex);
for (linkid = 0; linkid < SIM800_MAX_LINK_NUM; linkid++) {
if (g_link[linkid].fd >= 0) {
continue;
}
g_link[linkid].fd = conn->fd;
break;
}
HAL_MutexUnlock(g_link_mutex);
if (linkid >= SIM800_MAX_LINK_NUM) {
at_conn_hal_err( "No link available for now, %s failed. \r\n", __func__);
return -1;
}
pccmd = g_pccmd;
if (NULL == pccmd) {
at_conn_hal_err( "fail to malloc %d at %s \r\n", SIM800_CONN_CMD_LEN, __func__);
goto err;
}
memset(pccmd, 0, SIM800_CONN_CMD_LEN);
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
switch (conn->type) {
case TCP_CLIENT:
HAL_Snprintf(pccmd, SIM800_CONN_CMD_LEN - 1, "%s=%d,\"TCP\",\"%s\",%d", AT_CMD_START_CLIENT_CONN, linkid, conn->addr,
conn->r_port);
at_send_wait_reply(pccmd, strlen(pccmd), true, NULL, 0, rsp, SIM800_DEFAULT_RSP_LEN,
&atcmd_config_client);
if (strstr(rsp, AT_CMD_CLIENT_CONNECT_FAIL) != NULL) {
at_conn_hal_err( "pccmd %s fail, rsp %s \r\n", pccmd, rsp);
goto err;
}
break;
default:
at_conn_hal_err( "sim800 gprs module connect type %d not support \r\n", conn->type);
goto err;
}
return 0;
err:
HAL_MutexLock(g_link_mutex);
g_link[linkid].fd = -1;
HAL_MutexUnlock(g_link_mutex);
return -1;
}
int HAL_AT_CONN_Close(int fd, int32_t remote_port)
{
int linkid = 0;
int ret = 0;
char *cmd = g_cmd;
char *rsp = g_rsp;
if (!inited) {
at_conn_hal_err( "%s sim800 gprs module haven't init yet \r\n", __func__);
return -1;
}
linkid = fd_to_linkid(fd);
if (linkid < 0 || linkid >= SIM800_MAX_LINK_NUM) {
at_conn_hal_err( "No connection found for fd (%d) in %s \r\n", fd, __func__);
return -1;
}
memset(cmd, 0, SIM800_DEFAULT_CMD_LEN);
memset(rsp, 0, SIM800_DEFAULT_RSP_LEN);
HAL_Snprintf(cmd, SIM800_DEFAULT_CMD_LEN - 1, "%s=%d", AT_CMD_STOP_CONN, linkid);
at_send_wait_reply(cmd, strlen(cmd), true, NULL, 0,
rsp, SIM800_DEFAULT_RSP_LEN, NULL);
if (strstr(rsp, SIM800_AT_CMD_SUCCESS_RSP) == NULL) {
at_conn_hal_err( "cmd %s rsp is %s \r\n", cmd, rsp);
ret = -1;
}
HAL_MutexLock(g_link_mutex);
g_link[linkid].fd = -1;
HAL_MutexUnlock(g_link_mutex);
return ret;
}
int HAL_AT_CONN_Send(int fd,
uint8_t *data,
uint32_t len,
char remote_ip[16],
int32_t remote_port,
int32_t timeout)
{
int linkid;
char *cmd = g_cmd;
char *rsp = g_rsp;
if (!inited) {
at_conn_hal_err( "%s sim800 gprs module haven't init yet \r\n", __func__);
return -1;
}
linkid = fd_to_linkid(fd);
if (linkid < 0 || linkid >= SIM800_MAX_LINK_NUM) {
at_conn_hal_err( "No connection found for fd (%d) in %s \r\n", fd, __func__);
return -1;
}
memset(cmd, 0, SIM800_DEFAULT_CMD_LEN);
HAL_Snprintf(cmd, SIM800_DEFAULT_CMD_LEN - 1, "%s=%d,%d", AT_CMD_SEND_DATA, linkid, len);
if (sim800_send_with_retry((const char *)cmd, strlen(cmd), true, (const char *)data, len,
rsp, SIM800_DEFAULT_RSP_LEN, SIM800_AT_CMD_SUCCESS_RSP) < 0) {
at_conn_hal_err("cmd %s rsp %s at %s %d failed \r\n", cmd, rsp, __func__, __LINE__);
return -1;
}
return 0;
}

View File

@@ -0,0 +1,12 @@
LIBA_TARGET := libiot_hal.a
CFLAGS := $(filter-out -ansi,$(CFLAGS))
LIB_SRCS_PATTERN += os/$(CONFIG_VENDOR)/*.c
$(call Append_Conditional, LIB_SRCS_PATTERN, tls/*.c, _PLATFORM_IS_LINUX_ SUPPORT_TLS)
$(call Append_Conditional, LIB_SRCS_PATTERN, tls/*.c, _PLATFORM_IS_LINUX_ COAP_DTLS_SUPPORT)
$(call Append_Conditional, LIB_SRCS_PATTERN, atm/at_tcp/mk3060.c, AT_TCP_ENABLED AT_TCP_HAL_MK3060)
$(call Append_Conditional, LIB_SRCS_PATTERN, atm/at_tcp/sim800.c, AT_TCP_ENABLED AT_TCP_HAL_SIM800)
$(call Append_Conditional, LIB_SRCS_PATTERN, atm/at_mqtt/mqtt_ica.c, AT_MQTT_ENABLED AT_MQTT_HAL_ICA)
$(call Append_Conditional, LIB_SRCS_PATTERN, atm/at_mqtt/mqtt_sim800.c, AT_MQTT_ENABLED AT_MQTT_HAL_SIM800)
$(call Append_Conditional, LIB_SRCS_EXCLUDE, os/ubuntu/HAL_UART_linux.c, , AT_PARSER_ENABLED)

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __PLATFORM_DEBUG_H__
#define __PLATFORM_DEBUG_H__
#include "iotx_log.h"
#define hal_emerg(...) HAL_Printf("[prt] "), HAL_Printf(__VA_ARGS__), HAL_Printf("\r\n")
#define hal_crit(...) HAL_Printf("[prt] "), HAL_Printf(__VA_ARGS__), HAL_Printf("\r\n")
#define hal_err(...) HAL_Printf("[prt] "), HAL_Printf(__VA_ARGS__), HAL_Printf("\r\n")
#define hal_warning(...) HAL_Printf("[prt] "), HAL_Printf(__VA_ARGS__), HAL_Printf("\r\n")
#define hal_info(...) HAL_Printf("[prt] "), HAL_Printf(__VA_ARGS__), HAL_Printf("\r\n")
#define hal_debug(...) HAL_Printf("[prt] "), HAL_Printf(__VA_ARGS__), HAL_Printf("\r\n")
#endif /* __PLATFORM_DEBUG_H__ */

View File

@@ -0,0 +1,354 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
#define HAL_SEM_MAX_COUNT (10)
#define HAL_SEM_INIT_COUNT (0)
#define DEFAULT_THREAD_NAME "linkkit_task"
#define DEFAULT_THREAD_SIZE (256)
#define TASK_STACK_ALIGN_SIZE (4)
/**
* @brief Deallocate memory block
*
* @param[in] ptr @n Pointer to a memory block previously allocated with platform_malloc.
* @return None.
* @see None.
* @note None.
*/
void HAL_Free(void *ptr)
{
vPortFree(ptr);
}
/**
* @brief Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
*
* @param [in] size @n specify block size in bytes.
* @return A pointer to the beginning of the block.
* @see None.
* @note Block value is indeterminate.
*/
void *HAL_Malloc(uint32_t size)
{
return pvPortMalloc(size);
}
/**
* @brief Create a mutex.
*
* @retval NULL : Initialize mutex failed.
* @retval NOT_NULL : The mutex handle.
* @see None.
* @note None.
*/
void *HAL_MutexCreate(void)
{
QueueHandle_t sem;
sem = xSemaphoreCreateMutex();
if (0 == sem) {
return NULL;
}
return sem;
}
/**
* @brief Destroy the specified mutex object, it will release related resource.
*
* @param [in] mutex @n The specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexDestroy(void *mutex)
{
QueueHandle_t sem;
if (mutex == NULL) {
return;
}
sem = (QueueHandle_t)mutex;
vSemaphoreDelete(sem);
}
/**
* @brief Waits until the specified mutex is in the signaled state.
*
* @param [in] mutex @n the specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexLock(void *mutex)
{
BaseType_t ret;
QueueHandle_t sem;
if (mutex == NULL) {
return;
}
sem = (QueueHandle_t)mutex;
ret = xSemaphoreTake(sem, 0xffffffff);
while (pdPASS != ret) {
ret = xSemaphoreTake(sem, 0xffffffff);
}
}
/**
* @brief Releases ownership of the specified mutex object..
*
* @param [in] mutex @n the specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexUnlock(void *mutex)
{
QueueHandle_t sem;
if (mutex == NULL) {
return;
}
sem = (QueueHandle_t)mutex;
(void)xSemaphoreGive(sem);
}
/**
* @brief Writes formatted data to stream.
*
* @param [in] fmt: @n String that contains the text to be written, it can optionally contain embedded format specifiers
that specifies how subsequent arguments are converted for output.
* @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers.
* @return None.
* @see None.
* @note None.
*/
void HAL_Printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
/**
* @brief create a semaphore
*
* @return semaphore handle.
* @see None.
* @note The recommended value of maximum count of the semaphore is 255.
*/
void *HAL_SemaphoreCreate(void)
{
QueueHandle_t sem = 0;
sem = xSemaphoreCreateCounting(HAL_SEM_MAX_COUNT, HAL_SEM_INIT_COUNT);
if (0 == sem) {
return NULL;
}
return sem;
}
/**
* @brief destory a semaphore
*
* @param[in] sem @n the specified sem.
* @return None.
* @see None.
* @note None.
*/
void HAL_SemaphoreDestroy(void *sem)
{
QueueHandle_t queue;
if (sem == NULL) {
return;
}
queue = (QueueHandle_t)sem;
vSemaphoreDelete(queue);
}
/**
* @brief signal thread wait on a semaphore
*
* @param[in] sem @n the specified semaphore.
* @return None.
* @see None.
* @note None.
*/
void HAL_SemaphorePost(void *sem)
{
QueueHandle_t queue;
if (sem == NULL) {
return;
}
queue = (QueueHandle_t)sem;
(void)xSemaphoreGive(queue);
}
/**
* @brief wait on a semaphore
*
* @param[in] sem @n the specified semaphore.
* @param[in] timeout_ms @n timeout interval in millisecond.
If timeout_ms is PLATFORM_WAIT_INFINITE, the function will return only when the semaphore is signaled.
* @return
@verbatim
= 0: The state of the specified object is signaled.
= -1: The time-out interval elapsed, and the object's state is nonsignaled.
@endverbatim
* @see None.
* @note None.
*/
int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms)
{
BaseType_t ret = 0;
QueueHandle_t queue;
if (sem == NULL) {
return -1;
}
queue = (QueueHandle_t)sem;
ret = xSemaphoreTake(queue, timeout_ms);
if (pdPASS != ret) {
return -1;
}
return 0;
}
/**
* @brief Sleep thread itself.
*
* @param [in] ms @n the time interval for which execution is to be suspended, in milliseconds.
* @return None.
* @see None.
* @note None.
*/
void HAL_SleepMs(uint32_t ms)
{
osDelay(ms);
}
/**
* @brief Writes formatted data to string.
*
* @param [out] str: @n String that holds written text.
* @param [in] len: @n Maximum length of character will be written
* @param [in] fmt: @n Format that contains the text to be written, it can optionally contain embedded format specifiers
that specifies how subsequent arguments are converted for output.
* @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers.
* @return bytes of character successfully written into string.
* @see None.
* @note None.
*/
int HAL_Snprintf(char *str, const int len, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(str, len, fmt, args);
va_end(args);
return rc;
}
/**
* @brief create a thread
*
* @param[out] thread_handle @n The new thread handle, memory allocated before thread created and return it, free it after thread joined or exit.
* @param[in] start_routine @n A pointer to the application-defined function to be executed by the thread.
This pointer represents the starting address of the thread.
* @param[in] arg @n A pointer to a variable to be passed to the start_routine.
* @param[in] hal_os_thread_param @n A pointer to stack params.
* @param[out] stack_used @n if platform used stack buffer, set stack_used to 1, otherwise set it to 0.
* @return
@verbatim
= 0: on success.
= -1: error occur.
@endverbatim
* @see None.
* @note None.
*/
int HAL_ThreadCreate(
void **thread_handle,
void *(*work_routine)(void *),
void *arg,
hal_os_thread_param_t *hal_os_thread_param,
int *stack_used)
{
char *name;
size_t stacksize;
osThreadDef_t thread_def;
osThreadId handle;
if (thread_handle == NULL) {
return -1;
}
if (work_routine == NULL) {
return -1;
}
if (hal_os_thread_param == NULL) {
return -1;
}
if (stack_used == NULL) {
return -1;
}
if (stack_used != NULL) {
*stack_used = 0;
}
if (!hal_os_thread_param->name) {
name = DEFAULT_THREAD_NAME;
} else {
name = hal_os_thread_param->name;
}
if (hal_os_thread_param->stack_size == 0) {
stacksize = DEFAULT_THREAD_SIZE;
} else {
stacksize = hal_os_thread_param->stack_size;
}
thread_def.name = name;
thread_def.pthread = (os_pthread)work_routine;
thread_def.tpriority = (osPriority)hal_os_thread_param->priority;
thread_def.instances = 0;
thread_def.stacksize = (stacksize + TASK_STACK_ALIGN_SIZE - 1) / TASK_STACK_ALIGN_SIZE;
handle = osThreadCreate(&thread_def, arg);
if (NULL == handle) {
return -1;
}
*thread_handle = (void *)handle;
return 0;
}
/**
* @brief Retrieves the number of milliseconds that have elapsed since the system was boot.
*
* @return the number of milliseconds.
* @see None.
* @note None.
*/
uint64_t HAL_UptimeMs(void)
{
return (uint64_t)xTaskGetTickCount();
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
/**
* @brief Deallocate memory block
*
* @param[in] ptr @n Pointer to a memory block previously allocated with platform_malloc.
* @return None.
* @see None.
* @note None.
*/
void HAL_Free(void *ptr)
{
free(ptr);
}
/**
* @brief Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
*
* @param [in] size @n specify block size in bytes.
* @return A pointer to the beginning of the block.
* @see None.
* @note Block value is indeterminate.
*/
void *HAL_Malloc(uint32_t size)
{
return malloc(size);
}
/**
* @brief Create a mutex.
*
* @retval NULL : Initialize mutex failed.
* @retval NOT_NULL : The mutex handle.
* @see None.
* @note None.
*/
void *HAL_MutexCreate(void)
{
return (void *)1;
}
/**
* @brief Destroy the specified mutex object, it will release related resource.
*
* @param [in] mutex @n The specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexDestroy(void *mutex)
{
return;
}
/**
* @brief Waits until the specified mutex is in the signaled state.
*
* @param [in] mutex @n the specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexLock(void *mutex)
{
return;
}
/**
* @brief Releases ownership of the specified mutex object..
*
* @param [in] mutex @n the specified mutex.
* @return None.
* @see None.
* @note None.
*/
void HAL_MutexUnlock(void *mutex)
{
return;
}
/**
* @brief Writes formatted data to stream.
*
* @param [in] fmt: @n String that contains the text to be written, it can optionally contain embedded format specifiers
that specifies how subsequent arguments are converted for output.
* @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers.
* @return None.
* @see None.
* @note None.
*/
void HAL_Printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
/**
* @brief Writes formatted data to string.
*
* @param [out] str: @n String that holds written text.
* @param [in] len: @n Maximum length of character will be written
* @param [in] fmt: @n Format that contains the text to be written, it can optionally contain embedded format specifiers
that specifies how subsequent arguments are converted for output.
* @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers.
* @return bytes of character successfully written into string.
* @see None.
* @note None.
*/
int HAL_Snprintf(char *str, const int len, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(str, len, fmt, args);
va_end(args);
return rc;
}

View File

@@ -0,0 +1,92 @@
#include "infra_types.h"
#include "infra_defs.h"
#include "kal_public_defs.h"
#include "kal_public_api.h"
#include "kal_general_types.h"
#include "soc_api.h"
#define HAL_MEM_SIZE (30 * 1024)
static KAL_ADM_ID hal_heap_adm_id =NULL;
#if defined(WIN32)
static kal_uint8 my_heap[HAL_MEM_SIZE];
#else
static __align(32) kal_uint8 hal_heap[HAL_MEM_SIZE];
#endif
void hal_mem_init(void)
{
hal_heap_adm_id = kal_adm_create2(hal_heap, HAL_MEM_SIZE, NULL, KAL_FALSE, 0);
}
uint64_t HAL_UptimeMs(void)
{
unsigned int tick, cur_time;
kal_get_time(&tick);
cur_time = kal_ticks_to_milli_secs(tick);
return (uint64_t)cur_time;
}
int HAL_Snprintf(char *str, const int len, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(str, len, fmt, args);
va_end(args);
return rc;
}
void HAL_Printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
void *HAL_Malloc(uint32_t size)
{
if(hal_heap_adm_id == NULL)
{
hal_mem_init();
if(hal_heap_adm_id ==NULL){
return NULL;
}
}
return (void *)kal_adm_alloc(hal_heap_adm_id, size);
}
void HAL_Free(void *ptr)
{
if(hal_heap_adm_id ==NULL || ptr ==NULL){
return;
}
kal_adm_free(hal_heap_adm_id, ptr);
}
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN])
{
return (int)1;
}
int HAL_GetFirmwareVersion(char *version)
{
return (int)1;
}
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN])
{
return (int)1;
}
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN])
{
return (int)1;
}

View File

@@ -0,0 +1,219 @@
#include "infra_types.h"
#include "soc_api.h"
#include "kal_public_defs.h"
#include "kal_public_api.h"
#include "kal_general_types.h"
#include "soc_api.h"
extern kal_uint32 g_ali_nwk_account_id;
unsigned int get_cur_time(void)
{
unsigned int tick, cur_time;
kal_get_time(&tick);
cur_time = kal_ticks_to_milli_secs(tick);
return cur_time;
}
void InitTimer(OsTimer* timer)
{
timer->end_time = 0;
timer->over_flow = FALSE;
}
void countdown_ms(OsTimer* timer, unsigned int timeout)
{
unsigned int current_time = get_cur_time();
timer->end_time = current_time + timeout;
if(timer->end_time < current_time) {
timer->over_flow = TRUE;
}
}
char expired(OsTimer* timer)
{
int left = 0;
if (timer->over_flow) {
left = 0xFFFFFFFF - get_cur_time() + timer->end_time;
}
else {
left = timer->end_time - get_cur_time();
}
return (left < 0);
}
int HAL_TCP_Destroy(uintptr_t fd)
{
HAL_Printf("tcp destroy,sock: %d\n",fd);
if(-1 != fd)
soc_close(fd);
return 0;
}
uintptr_t HAL_TCP_Establish(const char *host, uint16_t port)
{
int rc = -1, sock = 0;
/*set the socket as no blocking*/
kal_bool option = KAL_TRUE;
kal_uint8 socket_opt = 1;
sockaddr_struct addr;
char * p;
kal_uint8 idx = 0;
kal_uint8 tmp = 0;
p = (char *)host;
/* parse ip addr string */
while(*p != '\0')
{
tmp = 0;
while((*p >= '0') && (*p <= '9'))
{
tmp = tmp*10 + *p - '0';
p++;
}
if((*p != '.') && (*p != '\0'))
{
ERROR_TRACE("init_socket.hostname error:%s", host);
return -1;
}
addr.addr[idx++] = tmp;
if((*p == '\0') || (idx > 3))
break;
p++;
}
addr.addr_len = 4;
addr.port = port;
addr.sock_type = SOC_SOCK_STREAM;
DEBUG_TRACE("[SOCKET]hostname:%s[%d.%d.%d.%d],port:%d,addr_len=%d", host, addr.addr[0], addr.addr[1], addr.addr[2], addr.addr[3], addr.port, addr.addr_len);
sock = soc_create(SOC_PF_INET, SOC_SOCK_STREAM, 0, MOD_MQTT, g_ali_nwk_account_id);
ERROR_TRACE("soc_create: %d\n",sock);
if (sock >= 0)
{
rc=soc_setsockopt(sock, SOC_NBIO, &option, sizeof(option));
ERROR_TRACE("soc_setsockopt1 return %d\n",rc);
socket_opt = SOC_READ | SOC_WRITE | SOC_ACCEPT | SOC_CONNECT | SOC_CLOSE;
rc = soc_setsockopt(sock, SOC_ASYNC, &socket_opt, sizeof(kal_uint8));
if (rc < 0)
{
ERROR_TRACE("soc_setsockopt async return %d\n",rc);
return -1;
}
ERROR_TRACE("soc_setsockopt2 return %d\n",rc);
rc = soc_connect(sock, &addr);
if (rc == SOC_SUCCESS) {
ERROR_TRACE("soc_connect succcess");
}else if (rc == SOC_WOULDBLOCK) {
ERROR_TRACE("soc_connect block");
}else{
ERROR_TRACE("soc_connect failed, rc: %d",rc);
return -1;
}
}
else{
ERROR_TRACE("cmns create sock failed %d\n",sock);
rc = -1;
}
return (uintptr_t)sock;
}
int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
{
soc_fd_set readfds;
OsTimer rtimer;
int bytes = 0;
int rc = 0;
soc_timeval_struct tv;
int slectrc=0;
kal_bool is_ready = 0;
if(0 == timeout_ms){
timeout_ms = 10;
}
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
InitTimer(&rtimer);
countdown_ms(&rtimer, timeout_ms);
do{
SOC_FD_ZERO(&readfds);
SOC_FD_SET(fd, &readfds);
slectrc = soc_select(fd+1, &readfds, NULL, NULL, &tv);
if(slectrc>=1 && SOC_FD_ISSET(fd, &readfds)){
do{
rc = soc_recv(fd, buf+bytes, len-bytes, 0);
if(rc > 0){
bytes += rc;
}
else if(rc < 0){
// SOC_WOULDBLOCK should be continue?
if(SOC_WOULDBLOCK != rc){
rc = -1;
}
else if(SOC_WOULDBLOCK == rc){
if(bytes>0 && bytes<len){
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
countdown_ms(&rtimer, timeout_ms);
}
}
break;
}
else {// FIN from the peer side
rc = -1;
break;
}
}while((bytes<len) && !expired(&rtimer));
}
else if(0 == slectrc){
if(bytes>0 && bytes<len){
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
countdown_ms(&rtimer, timeout_ms);
}
}
else{
//soc_select return value < 0, it means connect is broken
bytes = 0;
break;
}
//DEBUG_TRACE("linkit_read soc already read %d\n", bytes);
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
}while(!expired(&rtimer) && !(rc==-1) && (bytes<len));
return bytes;
}
int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms)
{
int rc = 0;
soc_timeval_struct tv;
soc_fd_set writefds;
tv.tv_sec = 0; /* 30 Secs Timeout */
tv.tv_usec = timeout_ms * 1000; // Not init'ing this can cause strange errors
SOC_FD_ZERO(&writefds);
SOC_FD_SET(fd, &writefds);
if(soc_select(fd+1, NULL, &writefds, NULL, &tv) >= 0){
if(SOC_FD_ISSET(fd, &writefds)){
rc = soc_send(fd, buf, len, 0);
}
}
return rc;
}

View File

@@ -0,0 +1,239 @@
#ifdef DEV_BIND_ENABLED
#include "infra_config.h"
#include <string.h>
#include "infra_defs.h"
#include "dev_bind_wrapper.h"
#endif
#if defined(WIFI_PROVISION_ENABLED)
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "iot_import_awss.h"
/**
* @brief 获取配网服务(`AWSS`)的超时时间长度, 单位是毫秒
*
* @return 超时时长, 单位是毫秒
* @note 推荐时长是60,0000毫秒
*/
int HAL_Awss_Get_Timeout_Interval_Ms(void)
{
return 30 * 60 * 1000;
}
/**
* @brief 获取在每个信道(`channel`)上扫描的时间长度, 单位是毫秒
*
* @return 时间长度, 单位是毫秒
* @note 推荐时长是200毫秒到400毫秒
*/
int HAL_Awss_Get_Channelscan_Interval_Ms(void)
{
return 250;
}
/**
* @brief 设置Wi-Fi网卡工作在监听(Monitor)模式, 并在收到802.11帧的时候调用被传入的回调函数
*
* @param[in] cb @n A function pointer, called back when wifi receive a frame.
*/
void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb)
{
}
/**
* @brief 设置Wi-Fi网卡离开监听(Monitor)模式, 并开始以站点(Station)模式工作
*/
void HAL_Awss_Close_Monitor(void)
{
}
/**
* @brief 设置Wi-Fi网卡切换到指定的信道(channel)上
*
* @param[in] primary_channel @n Primary channel.
* @param[in] secondary_channel @n Auxiliary channel if 40Mhz channel is supported, currently
* this param is always 0.
* @param[in] bssid @n A pointer to wifi BSSID on which awss lock the channel, most HAL
* may ignore it.
*/
void HAL_Awss_Switch_Channel(
_IN_ char primary_channel,
_IN_OPT_ char secondary_channel,
_IN_OPT_ uint8_t bssid[ETH_ALEN])
{
}
/**
* @brief 要求Wi-Fi网卡连接指定热点(Access Point)的函数
*
* @param[in] connection_timeout_ms @n AP connection timeout in ms or HAL_WAIT_INFINITE
* @param[in] ssid @n AP ssid
* @param[in] passwd @n AP passwd
* @param[in] auth @n optional(AWSS_AUTH_TYPE_INVALID), AP auth info
* @param[in] encry @n optional(AWSS_ENC_TYPE_INVALID), AP encry info
* @param[in] bssid @n optional(NULL or zero mac address), AP bssid info
* @param[in] channel @n optional, AP channel info
* @return
@verbatim
= 0: connect AP & DHCP success
= -1: connect AP or DHCP fail/timeout
@endverbatim
* @see None.
* @note
* If the STA connects the old AP, HAL should disconnect from the old AP firstly.
* If bssid specifies the dest AP, HAL should use bssid to connect dest AP.
*/
int HAL_Awss_Connect_Ap(
_IN_ uint32_t connection_timeout_ms,
_IN_ char ssid[HAL_MAX_SSID_LEN],
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
_IN_OPT_ enum AWSS_ENC_TYPE encry,
_IN_OPT_ uint8_t bssid[ETH_ALEN],
_IN_OPT_ uint8_t channel)
{
return 0;
}
/**
* @brief check system network is ready(get ip address) or not.
*
* @param None.
* @return 0, net is not ready; 1, net is ready.
* @see None.
* @note None.
*/
int HAL_Sys_Net_Is_Ready()
{
return 0;
}
/**
* @brief 在当前信道(channel)上以基本数据速率(1Mbps)发送裸的802.11帧(raw 802.11 frame)
*
* @param[in] type @n see enum HAL_Awss_frame_type, currently only FRAME_BEACON
* FRAME_PROBE_REQ is used
* @param[in] buffer @n 80211 raw frame, include complete mac header & FCS field
* @param[in] len @n 80211 raw frame length
* @return
@verbatim
= 0, send success.
= -1, send failure.
= -2, unsupported.
@endverbatim
* @see None.
* @note awss use this API send raw frame in wifi monitor mode & station mode
*/
int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type,
_IN_ uint8_t *buffer, _IN_ int len)
{
return 0;
}
/**
* @brief 在站点(Station)模式下使能或禁用对管理帧的过滤
*
* @param[in] filter_mask @n see mask macro in enum HAL_Awss_frame_type,
* currently only FRAME_PROBE_REQ_MASK & FRAME_BEACON_MASK is used
* @param[in] vendor_oui @n oui can be used for precise frame match, optional
* @param[in] callback @n see awss_wifi_mgmt_frame_cb_t, passing 80211
* frame or ie to callback. when callback is NULL
* disable sniffer feature, otherwise enable it.
* @return
@verbatim
= 0, success
= -1, fail
= -2, unsupported.
@endverbatim
* @see None.
* @note awss use this API to filter specific mgnt frame in wifi station mode
*/
int HAL_Wifi_Enable_Mgmt_Frame_Filter(
_IN_ uint32_t filter_mask,
_IN_OPT_ uint8_t vendor_oui[3],
_IN_ awss_wifi_mgmt_frame_cb_t callback)
{
return 0;
}
/**
* @brief 启动一次Wi-Fi的空中扫描(Scan)
*
* @param[in] cb @n pass ssid info(scan result) to this callback one by one
* @return 0 for wifi scan is done, otherwise return -1
* @see None.
* @note
* This API should NOT exit before the invoking for cb is finished.
* This rule is something like the following :
* HAL_Wifi_Scan() is invoked...
* ...
* for (ap = first_ap; ap <= last_ap; ap = next_ap){
* cb(ap)
* }
* ...
* HAL_Wifi_Scan() exit...
*/
int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb)
{
return 0;
}
/**
* @brief 获取所连接的热点(Access Point)的信息
*
* @param[out] ssid: array to store ap ssid. It will be null if ssid is not required.
* @param[out] passwd: array to store ap password. It will be null if ap password is not required.
* @param[out] bssid: array to store ap bssid. It will be null if bssid is not required.
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note
* If the STA dosen't connect AP successfully, HAL should return -1 and not touch the ssid/passwd/bssid buffer.
*/
int HAL_Wifi_Get_Ap_Info(
_OU_ char ssid[HAL_MAX_SSID_LEN],
_OU_ char passwd[HAL_MAX_PASSWD_LEN],
_OU_ uint8_t bssid[ETH_ALEN])
{
return 0;
}
/* @brief 打开当前设备热点并把设备由SoftAP模式切换到AP模式
*/
int HAL_Awss_Open_Ap(const char *ssid, const char *passwd, int beacon_interval, int hide)
{
return 0;
}
/* @brief 关闭当前设备热点并把设备由SoftAP模式切换到Station模式
*/
int HAL_Awss_Close_Ap()
{
return 0;
}
#endif /* #if defined(HAL_AWSS) */
#ifdef DEV_BIND_ENABLED
/**
* @brief 获取Wi-Fi网口的MAC地址, 格式应当是"XX:XX:XX:XX:XX:XX"
*
* @param mac_str : 用于存放MAC地址字符串的缓冲区数组
* @return 指向缓冲区数组起始位置的字符指针
*/
char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN])
{
strcpy(mac_str, "18:FE:34:12:33:44");
return mac_str;
}
#endif

View File

@@ -0,0 +1,149 @@
#include "infra_config.h"
#if defined(HAL_CRYPTO)
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <string.h>
#include <stdlib.h>
#include "infra_compat.h"
#include "mbedtls/aes.h"
#define AES_BLOCK_SIZE 16
typedef struct {
mbedtls_aes_context ctx;
uint8_t iv[16];
uint8_t key[16];
} platform_aes_t;
p_HAL_Aes128_t HAL_Aes128_Init(
const uint8_t *key,
const uint8_t *iv,
AES_DIR_t dir)
{
int ret = 0;
platform_aes_t *p_aes128 = NULL;
if (!key || !iv) return p_aes128;
p_aes128 = (platform_aes_t *)calloc(1, sizeof(platform_aes_t));
if (!p_aes128) return p_aes128;
mbedtls_aes_init(&p_aes128->ctx);
if (dir == HAL_AES_ENCRYPTION) {
ret = mbedtls_aes_setkey_enc(&p_aes128->ctx, key, 128);
} else {
ret = mbedtls_aes_setkey_dec(&p_aes128->ctx, key, 128);
}
if (ret == 0) {
memcpy(p_aes128->iv, iv, 16);
memcpy(p_aes128->key, key, 16);
} else {
free(p_aes128);
p_aes128 = NULL;
}
return (p_HAL_Aes128_t *)p_aes128;
}
int HAL_Aes128_Destroy(p_HAL_Aes128_t aes)
{
if (!aes) return -1;
mbedtls_aes_free(&((platform_aes_t *)aes)->ctx);
free(aes);
return 0;
}
int HAL_Aes128_Cbc_Encrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t blockNum,
void *dst)
{
int i = 0;
int ret = ret;
platform_aes_t *p_aes128 = (platform_aes_t *)aes;
if (!aes || !src || !dst) return -1;
for (i = 0; i < blockNum; ++i) {
ret = mbedtls_aes_crypt_cbc(&p_aes128->ctx, MBEDTLS_AES_ENCRYPT, AES_BLOCK_SIZE,
p_aes128->iv, src, dst);
src += 16;
dst += 16;
}
return ret;
}
int HAL_Aes128_Cbc_Decrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t blockNum,
void *dst)
{
int i = 0;
int ret = -1;
platform_aes_t *p_aes128 = (platform_aes_t *)aes;
if (!aes || !src || !dst) return ret;
for (i = 0; i < blockNum; ++i) {
ret = mbedtls_aes_crypt_cbc(&p_aes128->ctx, MBEDTLS_AES_DECRYPT, AES_BLOCK_SIZE,
p_aes128->iv, src, dst);
src += 16;
dst += 16;
}
return ret;
}
#if defined(MBEDTLS_CIPHER_MODE_CFB)
int HAL_Aes128_Cfb_Encrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t length,
void *dst)
{
size_t offset = 0;
int ret = -1;
platform_aes_t *p_aes128 = (platform_aes_t *)aes;
if (!aes || !src || !dst) return ret;
ret = mbedtls_aes_crypt_cfb128(&p_aes128->ctx, MBEDTLS_AES_ENCRYPT, length,
&offset, p_aes128->iv, src, dst);
return ret;
}
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
int HAL_Aes128_Cfb_Decrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t length,
void *dst)
{
size_t offset = 0;
int ret = -1;
platform_aes_t *p_aes128 = (platform_aes_t *)aes;
if (!aes || !src || !dst) return ret;
ret = mbedtls_aes_setkey_enc(&p_aes128->ctx, p_aes128->key, 128);
ret = mbedtls_aes_crypt_cfb128(&p_aes128->ctx, MBEDTLS_AES_DECRYPT, length,
&offset, p_aes128->iv, src, dst);
return ret;
}
#endif
#endif /* #if defined(HAL_CRYPTO) */

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef FS_ENABLED
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
void *HAL_Fopen(const char *path, const char *mode)
{
return (void *)fopen(path, mode);
}
uint32_t HAL_Fread(void *buff, uint32_t size, uint32_t count, void *stream)
{
return fread(buff, (size_t)size, (size_t)count, (FILE *)stream);
}
uint32_t HAL_Fwrite(const void *ptr, uint32_t size, uint32_t count, void *stream)
{
return (uint32_t)fwrite(ptr, (size_t)size, (size_t)count, (FILE *)stream);
}
int HAL_Fseek(void *stream, long offset, int framewhere)
{
return fseek((FILE *)stream, offset, framewhere);
}
int HAL_Fclose(void *stream)
{
return fclose((FILE *)stream);
}
long HAL_Ftell(void *stream)
{
return ftell((FILE *)stream);
}
#endif

View File

@@ -0,0 +1,471 @@
#include "infra_config.h"
#if defined(HAL_KV)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "stdint.h"
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <unistd.h>
#include "infra_defs.h"
#define TABLE_COL_SIZE (384)
#define TABLE_ROW_SIZE (2)
#define ITEM_MAX_KEY_LEN 128 /* The max key length for key-value item */
#define ITEM_MAX_VAL_LEN 512 /* The max value length for key-value item */
#define ITEM_MAX_LEN sizeof(kv_item_t)
#define KV_FILE_NAME "linkkit_kv.bin"
#define kv_err(...) do{printf(__VA_ARGS__);printf("\r\n");}while(0)
typedef struct kv {
char key[ITEM_MAX_KEY_LEN];
uint8_t value[ITEM_MAX_VAL_LEN];
int value_len;
} kv_item_t;
typedef struct kv_file_s {
const char *filename;
pthread_mutex_t lock;
} kv_file_t;
static int kv_get(const char *key, void *value, int *value_len);
static int kv_set(const char *key, void *value, int value_len);
static int kv_del(const char *key);
static unsigned int hash_gen(const char *key);
static int hash_table_put(kv_file_t *file, const char *key, void *value, int value_len);
static int hash_table_get(kv_file_t *file, const char *key, void *value, int *len);
static int hash_table_rm(kv_file_t *file, const char *key);
static kv_file_t *kv_open(const char *filename);
static int read_kv_item(const char *filename, void *buf, int location);
static int write_kv_item(const char *filename, void *data, int location);
static void free_kv(struct kv *kv)
{
if (kv) {
kv->value_len = 0;
free(kv);
}
}
static unsigned int hash_gen(const char *key)
{
unsigned int hash = 0;
while (*key) {
hash = (hash << 5) + hash + *key++;
}
return hash % TABLE_COL_SIZE;
}
/* insert or update a value indexed by key */
static int hash_table_put(kv_file_t *file, const char *key, void *value, int value_len)
{
int i;
int read_size;
kv_item_t *kv;
int j = 0;
kv_item_t *p;
if (!file || !file->filename || !key || !value || value_len <= 0) {
kv_err("paras err");
return -1;
}
value_len = value_len > ITEM_MAX_VAL_LEN ? ITEM_MAX_VAL_LEN : value_len;
i = hash_gen(key);
kv_err("hash i= %d", i);
read_size = ITEM_MAX_LEN * TABLE_ROW_SIZE;
kv = malloc(read_size);
if (kv == NULL) {
kv_err("malloc kv err");
return -1;
}
memset(kv, 0, read_size);
if (read_kv_item(file->filename, kv, i) != 0) {
kv_err("read kv err");
free_kv(kv);
return -1;
}
p = &kv[j];
while (p && p->value_len) { /* if key is already stroed, update its value */
if (strcmp(p->key, key) == 0) {
memset(p->value, 0, ITEM_MAX_VAL_LEN);
memcpy(p->value, value, value_len);
p->value_len = value_len;
break;
}
if (++j == TABLE_ROW_SIZE) {
kv_err("hash row full");
free(kv);
return -1;
}
p = &kv[j];
}
p = &kv[j];
if (p && !p->value_len) {/* if key has not been stored, then add it */
//p->next = NULL;
strncpy(p->key, key, ITEM_MAX_KEY_LEN - 1);
memcpy(p->value, value, value_len);
p->value_len = value_len;
}
if (write_kv_item(file->filename, kv, i) < 0) {
kv_err("write_kv_item err");
free(kv);
return -1;
}
free(kv);
return 0;
}
/* get a value indexed by key */
static int hash_table_get(kv_file_t *file, const char *key, void *value, int *len)
{
int i;
int read_size;
kv_item_t *kv;
int j = 0;
struct kv *p;
if (!file || !file->filename || !key || !value || !len || *len <= 0) {
kv_err("paras err");
return -1;
}
i = hash_gen(key);
read_size = sizeof(kv_item_t) * TABLE_ROW_SIZE;
kv = malloc(read_size);
if (kv == NULL) {
kv_err("malloc kv err");
return -1;
}
memset(kv, 0, read_size);
if (read_kv_item(file->filename, kv, i) != 0) {
kv_err("read kv err");
free_kv(kv);
return -1;
}
// struct kv *p = ht->table[i];
p = &kv[j];
while (p && p->value_len) {
if (strcmp(key, p->key) == 0) {
*len = p->value_len < *len ? p->value_len : *len;
memcpy(value, p->value, *len);
free_kv(kv);
return 0;
}
if (++j == TABLE_ROW_SIZE) {
break;
}
p = &kv[j];
}
free_kv(kv);
kv_err("not found");
return -1;
}
/* remove a value indexed by key */
static int hash_table_rm(kv_file_t *file, const char *key)
{
int i;
int read_size;
kv_item_t *kv;
int j = 0;
struct kv *p;
if (!file || !file->filename || !key) {
return -1;
}
i = hash_gen(key) % TABLE_COL_SIZE;
read_size = sizeof(kv_item_t) * TABLE_ROW_SIZE;
kv = malloc(read_size);
if (kv == NULL) {
return -1;
}
memset(kv, 0, read_size);
if (read_kv_item(file->filename, kv, i) != 0) {
free_kv(kv);
return -1;
}
p = &kv[j];
while (p && p->value_len) {
if (strcmp(key, p->key) == 0) {
memset(p, 0, ITEM_MAX_LEN);
}
if (++j == TABLE_ROW_SIZE) {
break;
}
p = &kv[j];
}
if (write_kv_item(file->filename, kv, i) < 0) {
free_kv(kv);
return -1;
}
free_kv(kv);
return 0;
}
static int read_kv_item(const char *filename, void *buf, int location)
{
struct stat st;
int ret = 0;
int offset;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
kv_err("open err");
return -1;
}
if (fstat(fd, &st) < 0) {
kv_err("fstat err");
close(fd);
return -1;
}
if (st.st_size < (location + 1) *ITEM_MAX_LEN * TABLE_ROW_SIZE) {
kv_err("read overstep");
close(fd);
return -1;
}
offset = location * ITEM_MAX_LEN * TABLE_ROW_SIZE;
ret = lseek(fd, offset, SEEK_SET);
if (ret < 0) {
kv_err("lseek err");
close(fd);
return -1;
}
if (read(fd, buf, ITEM_MAX_LEN * TABLE_ROW_SIZE) != ITEM_MAX_LEN * TABLE_ROW_SIZE) {
kv_err("read err");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int write_kv_item(const char *filename, void *data, int location)
{
struct stat st;
int offset;
int ret;
int fd = open(filename, O_WRONLY);
if (fd < 0) {
return -1;
}
if (fstat(fd, &st) < 0) {
kv_err("fstat err");
close(fd);
return -1;
}
if (st.st_size < (location + 1) *ITEM_MAX_LEN * TABLE_ROW_SIZE) {
kv_err("overstep st.st_size = %d location =%d cur loc=%d",
(int)st.st_size,
(int)location,
(int)((location + 1) *ITEM_MAX_LEN * TABLE_ROW_SIZE));
close(fd);
return -1;
}
offset = (location) * ITEM_MAX_LEN * TABLE_ROW_SIZE;
ret = lseek(fd, offset, SEEK_SET);
if (ret < 0) {
kv_err("lseek err");
close(fd);
return -1;
}
if (write(fd, data, ITEM_MAX_LEN * TABLE_ROW_SIZE) != ITEM_MAX_LEN * TABLE_ROW_SIZE) {
kv_err("kv write failed");
close(fd);
return -1;
}
fsync(fd);
close(fd);
return 0;
}
static int create_hash_file(kv_file_t *hash_kv)
{
int i;
int fd;
char init_data[ITEM_MAX_LEN * TABLE_ROW_SIZE] = {0};
if (hash_kv == NULL) {
return -1;
}
fd = open(hash_kv->filename, O_CREAT | O_RDWR, 0644);
if (fd < 0) {
return -1;
}
for (i = 0; i < TABLE_COL_SIZE ; i++) {
if (write(fd, init_data, ITEM_MAX_LEN * TABLE_ROW_SIZE) != ITEM_MAX_LEN *
TABLE_ROW_SIZE) { /* 3 = '{}' + null terminator */
kv_err("write err");
close(fd);
return -1;
}
}
if (fsync(fd) < 0) {
close(fd);
return -1;
}
close(fd);
return 0;
}
static kv_file_t *kv_open(const char *filename)
{
kv_file_t *file = malloc(sizeof(kv_file_t));
if (!file) {
return NULL;
}
memset(file, 0, sizeof(kv_file_t));
file->filename = filename;
pthread_mutex_init(&file->lock, NULL);
pthread_mutex_lock(&file->lock);
if (access(file->filename, F_OK) < 0) {
/* create KV file when not exist */
if (create_hash_file(file) < 0) {
goto fail;
}
}
pthread_mutex_unlock(&file->lock);
return file;
fail:
pthread_mutex_unlock(&file->lock);
free(file);
return NULL;
}
static int __kv_get(kv_file_t *file, const char *key, void *value, int *value_len)
{
int ret;
if (!file || !key || !value || !value_len || *value_len <= 0) {
return -1;
}
pthread_mutex_lock(&file->lock);
ret = hash_table_get(file, key, value, value_len);
pthread_mutex_unlock(&file->lock);
return ret;
}
static int __kv_set(kv_file_t *file, const char *key, void *value, int value_len)
{
int ret;
if (!file || !key || !value || value_len <= 0) {
return -1;
}
pthread_mutex_lock(&file->lock);
ret = hash_table_put(file, key, value, value_len);
pthread_mutex_unlock(&file->lock);
return ret;
}
int __kv_del(kv_file_t *file, const char *key)
{
int ret;
if (!file || !key) {
return -1;
}
/* remove old value if exist */
pthread_mutex_lock(&file->lock);
ret = hash_table_rm(file, key);
pthread_mutex_unlock(&file->lock);
return ret;
}
static kv_file_t *file = NULL;
static int kv_get(const char *key, void *value, int *value_len)
{
if (!file) {
file = kv_open(KV_FILE_NAME);
if (!file) {
kv_err("kv_open failed");
return -1;
}
}
return __kv_get(file, key, value, value_len);
}
static int kv_set(const char *key, void *value, int value_len)
{
if (!file) {
file = kv_open(KV_FILE_NAME);
if (!file) {
kv_err("kv_open failed");
return -1;
}
}
return __kv_set(file, key, value, value_len);
}
static int kv_del(const char *key)
{
if (!file) {
file = kv_open(KV_FILE_NAME);
if (!file) {
kv_err("kv_open failed");
return -1;
}
}
return __kv_del(file, key);
}
int HAL_Kv_Set(const char *key, const void *val, int len, int sync)
{
return kv_set(key, (void *)val, len);
}
int HAL_Kv_Get(const char *key, void *val, int *buffer_len)
{
return kv_get(key, val, buffer_len);
}
int HAL_Kv_Del(const char *key)
{
return kv_del(key);
}
#endif /* #if defined(HAL_KV) */

View File

@@ -0,0 +1,624 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <memory.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/time.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <net/if.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/reboot.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include "infra_config.h"
#include "infra_compat.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
#define PLATFORM_WAIT_INFINITE (~0)
#ifdef DYNAMIC_REGISTER
char _product_key[IOTX_PRODUCT_KEY_LEN + 1] = "a1ZETBPbycq";
char _product_secret[IOTX_PRODUCT_SECRET_LEN + 1] = "L68wCVXYUaNg1Ey9";
char _device_name[IOTX_DEVICE_NAME_LEN + 1] = "example1";
char _device_secret[IOTX_DEVICE_SECRET_LEN + 1] = "";
#else
#ifdef DEVICE_MODEL_ENABLED
char _product_key[IOTX_PRODUCT_KEY_LEN + 1] = "a1RIsMLz2BJ";
char _product_secret[IOTX_PRODUCT_SECRET_LEN + 1] = "fSAF0hle6xL0oRWd";
char _device_name[IOTX_DEVICE_NAME_LEN + 1] = "example1";
char _device_secret[IOTX_DEVICE_SECRET_LEN + 1] = "RDXf67itLqZCwdMCRrw0N5FHbv5D7jrE";
#else
char _product_key[IOTX_PRODUCT_KEY_LEN + 1] = "a1MZxOdcBnO";
char _product_secret[IOTX_PRODUCT_SECRET_LEN + 1] = "h4I4dneEFp7EImTv";
char _device_name[IOTX_DEVICE_NAME_LEN + 1] = "test_01";
char _device_secret[IOTX_DEVICE_SECRET_LEN + 1] = "t9GmMf2jb3LgWfXBaZD2r3aJrfVWBv56";
#endif
#endif
char _firmware_version[IOTX_FIRMWARE_VER_LEN] = "app-1.0.0-20180101.1000";
void *HAL_Malloc(uint32_t size)
{
return malloc(size);
}
void *HAL_Realloc(void *ptr, uint32_t size)
{
return realloc(ptr, size);
}
void HAL_Free(void *ptr)
{
free(ptr);
}
uint64_t HAL_UptimeMs(void)
{
uint64_t time_ms;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
time_ms = ((uint64_t)ts.tv_sec * (uint64_t)1000) + (ts.tv_nsec / 1000 / 1000);
return time_ms;
}
void HAL_SleepMs(uint32_t ms)
{
usleep(1000 * ms);
}
void HAL_Srandom(uint32_t seed)
{
srandom(seed);
}
uint32_t HAL_Random(uint32_t region)
{
FILE *handle;
ssize_t ret = 0;
uint32_t output = 0;
handle = fopen("/dev/urandom", "r");
if (handle == NULL) {
printf("open /dev/urandom failed\n");
return 0;
}
ret = fread(&output, sizeof(uint32_t), 1, handle);
if (ret != 1) {
printf("fread error: %d\n", (int)ret);
fclose(handle);
return 0;
}
fclose(handle);
return (region > 0) ? (output % region) : 0;
}
int HAL_Snprintf(char *str, const int len, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(str, len, fmt, args);
va_end(args);
return rc;
}
int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap)
{
return vsnprintf(str, len, format, ap);
}
void HAL_Printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
int HAL_GetPartnerID(char *pid_str)
{
memset(pid_str, 0x0, IOTX_PARTNER_ID_LEN);
strcpy(pid_str, "c-sdk-2.3.0-pid");
return strlen(pid_str);
}
int HAL_GetModuleID(char *mid_str)
{
memset(mid_str, 0x0, IOTX_MODULE_ID_LEN);
strcpy(mid_str, "c-sdk-2.3.0-mid");
return strlen(mid_str);
}
int HAL_SetProductKey(char *product_key)
{
int len = strlen(product_key);
if (len > IOTX_PRODUCT_KEY_LEN) {
return -1;
}
memset(_product_key, 0x0, IOTX_PRODUCT_KEY_LEN + 1);
strncpy(_product_key, product_key, len);
return len;
}
int HAL_SetDeviceName(char *device_name)
{
int len = strlen(device_name);
if (len > IOTX_DEVICE_NAME_LEN) {
return -1;
}
memset(_device_name, 0x0, IOTX_DEVICE_NAME_LEN + 1);
strncpy(_device_name, device_name, len);
return len;
}
int HAL_SetProductSecret(char *product_secret)
{
int len = strlen(product_secret);
if (len > IOTX_PRODUCT_SECRET_LEN) {
return -1;
}
memset(_product_secret, 0x0, IOTX_PRODUCT_SECRET_LEN + 1);
strncpy(_product_secret, product_secret, len);
return len;
}
int HAL_SetDeviceSecret(char *device_secret)
{
int len = strlen(device_secret);
if (len > IOTX_DEVICE_SECRET_LEN) {
return -1;
}
memset(_device_secret, 0x0, IOTX_DEVICE_SECRET_LEN + 1);
strncpy(_device_secret, device_secret, len);
return len;
}
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN + 1])
{
int len = strlen(_product_key);
memset(product_key, 0x0, IOTX_PRODUCT_KEY_LEN + 1);
strncpy(product_key, _product_key, len);
return len;
}
int HAL_GetProductSecret(char product_secret[IOTX_PRODUCT_SECRET_LEN + 1])
{
int len = strlen(_product_secret);
memset(product_secret, 0x0, IOTX_PRODUCT_SECRET_LEN + 1);
strncpy(product_secret, _product_secret, len);
return len;
}
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN + 1])
{
int len = strlen(_device_name);
memset(device_name, 0x0, IOTX_DEVICE_NAME_LEN + 1);
strncpy(device_name, _device_name, len);
return strlen(device_name);
}
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN + 1])
{
int len = strlen(_device_secret);
memset(device_secret, 0x0, IOTX_DEVICE_SECRET_LEN + 1);
strncpy(device_secret, _device_secret, len);
return len;
}
void HAL_Reboot(void)
{
if (system("reboot")) {
perror("HAL_Reboot failed");
}
}
#define ROUTER_INFO_PATH "/proc/net/route"
#define ROUTER_RECORD_SIZE 256
char *_get_default_routing_ifname(char *ifname, int ifname_size)
{
FILE *fp = NULL;
char line[ROUTER_RECORD_SIZE] = {0};
char iface[IFNAMSIZ] = {0};
char *result = NULL;
unsigned int destination, gateway, flags, mask;
unsigned int refCnt, use, metric, mtu, window, irtt;
char *buff = NULL;
fp = fopen(ROUTER_INFO_PATH, "r");
if (fp == NULL) {
perror("fopen");
return result;
}
buff = fgets(line, sizeof(line), fp);
if (buff == NULL) {
perror("fgets");
goto out;
}
while (fgets(line, sizeof(line), fp)) {
if (11 !=
sscanf(line, "%s %08x %08x %x %d %d %d %08x %d %d %d",
iface, &destination, &gateway, &flags, &refCnt, &use,
&metric, &mask, &mtu, &window, &irtt)) {
perror("sscanf");
continue;
}
/*default route */
if ((destination == 0) && (mask == 0)) {
strncpy(ifname, iface, ifname_size - 1);
result = ifname;
break;
}
}
out:
if (fp) {
fclose(fp);
}
return result;
}
uint32_t HAL_Wifi_Get_IP(char ip_str[NETWORK_ADDR_LEN], const char *ifname)
{
struct ifreq ifreq;
int sock = -1;
char ifname_buff[IFNAMSIZ] = {0};
if ((NULL == ifname || strlen(ifname) == 0) &&
NULL == (ifname = _get_default_routing_ifname(ifname_buff, sizeof(ifname_buff)))) {
perror("get default routeing ifname");
return -1;
}
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
return -1;
}
ifreq.ifr_addr.sa_family = AF_INET;
strncpy(ifreq.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(sock, SIOCGIFADDR, &ifreq) < 0) {
close(sock);
perror("ioctl");
return -1;
}
close(sock);
strncpy(ip_str,
inet_ntoa(((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr),
NETWORK_ADDR_LEN);
return ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
}
int HAL_GetFirmwareVersion(char *version)
{
char *ver = "app-1.0.0-20180101.1000";
int len = strlen(ver);
memset(version, 0x0, IOTX_FIRMWARE_VER_LEN);
strncpy(version, ver, IOTX_FIRMWARE_VER_LEN);
version[len] = '\0';
return strlen(version);
}
void *HAL_SemaphoreCreate(void)
{
sem_t *sem = (sem_t *)malloc(sizeof(sem_t));
if (NULL == sem) {
return NULL;
}
if (0 != sem_init(sem, 0, 0)) {
free(sem);
return NULL;
}
return sem;
}
void HAL_SemaphoreDestroy(void *sem)
{
sem_destroy((sem_t *)sem);
free(sem);
}
void HAL_SemaphorePost(void *sem)
{
sem_post((sem_t *)sem);
}
int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms)
{
if (PLATFORM_WAIT_INFINITE == timeout_ms) {
sem_wait(sem);
return 0;
} else {
struct timespec ts;
int s;
/* Restart if interrupted by handler */
do {
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
return -1;
}
s = 0;
ts.tv_nsec += (timeout_ms % 1000) * 1000000;
if (ts.tv_nsec >= 1000000000) {
ts.tv_nsec -= 1000000000;
s = 1;
}
ts.tv_sec += timeout_ms / 1000 + s;
} while (((s = sem_timedwait(sem, &ts)) != 0) && errno == EINTR);
return (s == 0) ? 0 : -1;
}
}
int HAL_ThreadCreate(
void **thread_handle,
void *(*work_routine)(void *),
void *arg,
hal_os_thread_param_t *hal_os_thread_param,
int *stack_used)
{
int ret = -1;
if (stack_used) {
*stack_used = 0;
}
ret = pthread_create((pthread_t *)thread_handle, NULL, work_routine, arg);
return ret;
}
void HAL_ThreadDetach(void *thread_handle)
{
pthread_detach((pthread_t)thread_handle);
}
void HAL_ThreadDelete(void *thread_handle)
{
if (NULL == thread_handle) {
pthread_exit(0);
} else {
/*main thread delete child thread*/
pthread_cancel((pthread_t)thread_handle);
pthread_join((pthread_t)thread_handle, 0);
}
}
static FILE *fp;
#define otafilename "/tmp/alinkota.bin"
void HAL_Firmware_Persistence_Start(void)
{
fp = fopen(otafilename, "w");
return;
}
int HAL_Firmware_Persistence_Write(char *buffer, uint32_t length)
{
unsigned int written_len = 0;
written_len = fwrite(buffer, 1, length, fp);
if (written_len != length) {
return -1;
}
return 0;
}
int HAL_Firmware_Persistence_Stop(void)
{
if (fp != NULL) {
fclose(fp);
}
/* check file md5, and burning it to flash ... finally reboot system */
return 0;
}
void *HAL_MutexCreate(void)
{
int err_num;
pthread_mutex_t *mutex = (pthread_mutex_t *)HAL_Malloc(sizeof(pthread_mutex_t));
if (NULL == mutex) {
return NULL;
}
if (0 != (err_num = pthread_mutex_init(mutex, NULL))) {
printf("create mutex failed\n");
HAL_Free(mutex);
return NULL;
}
return mutex;
}
void HAL_MutexDestroy(void *mutex)
{
int err_num;
if (!mutex) {
printf("mutex want to destroy is NULL!\n");
return;
}
if (0 != (err_num = pthread_mutex_destroy((pthread_mutex_t *)mutex))) {
printf("destroy mutex failed\n");
}
HAL_Free(mutex);
}
void HAL_MutexLock(void *mutex)
{
int err_num;
if (0 != (err_num = pthread_mutex_lock((pthread_mutex_t *)mutex))) {
printf("lock mutex failed: - '%s' (%d)\n", strerror(err_num), err_num);
}
}
void HAL_MutexUnlock(void *mutex)
{
int err_num;
if (0 != (err_num = pthread_mutex_unlock((pthread_mutex_t *)mutex))) {
printf("unlock mutex failed - '%s' (%d)\n", strerror(err_num), err_num);
}
}
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data)
{
timer_t *timer = NULL;
struct sigevent ent;
/* check parameter */
if (func == NULL) {
return NULL;
}
timer = (timer_t *)malloc(sizeof(time_t));
if (timer == NULL) {
return NULL;
}
/* Init */
memset(&ent, 0x00, sizeof(struct sigevent));
/* create a timer */
ent.sigev_notify = SIGEV_THREAD;
ent.sigev_notify_function = (void (*)(union sigval))func;
ent.sigev_value.sival_ptr = user_data;
printf("HAL_Timer_Create\n");
if (timer_create(CLOCK_MONOTONIC, &ent, timer) != 0) {
free(timer);
return NULL;
}
return (void *)timer;
}
int HAL_Timer_Start(void *timer, int ms)
{
struct itimerspec ts;
/* check parameter */
if (timer == NULL) {
return -1;
}
/* it_interval=0: timer run only once */
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
/* it_value=0: stop timer */
ts.it_value.tv_sec = ms / 1000;
ts.it_value.tv_nsec = (ms % 1000) * 1000000;
return timer_settime(*(timer_t *)timer, 0, &ts, NULL);
}
int HAL_Timer_Stop(void *timer)
{
struct itimerspec ts;
/* check parameter */
if (timer == NULL) {
return -1;
}
/* it_interval=0: timer run only once */
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
/* it_value=0: stop timer */
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 0;
return timer_settime(*(timer_t *)timer, 0, &ts, NULL);
}
int HAL_Timer_Delete(void *timer)
{
int ret = 0;
/* check parameter */
if (timer == NULL) {
return -1;
}
ret = timer_delete(*(timer_t *)timer);
free(timer);
return ret;
}
int HAL_GetNetifInfo(char *nif_str)
{
const char *net_info = "WiFi|03ACDEFF0032";
memset(nif_str, 0x0, IOTX_NETWORK_IF_LEN);
/* if the device have only WIFI, then list as follow, note that the len MUST NOT exceed NIF_STRLEN_MAX */
strncpy(nif_str, net_info, IOTX_NETWORK_IF_LEN);
/* if the device have ETH, WIFI, GSM connections, then list all of them as follow, note that the len MUST NOT exceed NIF_STRLEN_MAX */
/* const char *multi_net_info = "ETH|0123456789abcde|WiFi|03ACDEFF0032|Cellular|imei_0123456789abcde|iccid_0123456789abcdef01234|imsi_0123456789abcde|msisdn_86123456789ab"); */
/* strncpy(nif_str, multi_net_info, strlen(multi_net_info)); */
return strlen(nif_str);
}

View File

@@ -0,0 +1,269 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include "infra_config.h"
static uint64_t _linux_get_time_ms(void)
{
struct timeval tv = { 0 };
uint64_t time_ms;
gettimeofday(&tv, NULL);
time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
return time_ms;
}
static uint64_t _linux_time_left(uint64_t t_end, uint64_t t_now)
{
uint64_t t_left;
if (t_end > t_now) {
t_left = t_end - t_now;
} else {
t_left = 0;
}
return t_left;
}
uintptr_t HAL_TCP_Establish(const char *host, uint16_t port)
{
struct addrinfo hints;
struct addrinfo *addrInfoList = NULL;
struct addrinfo *cur = NULL;
int fd = 0;
int rc = 0;
char service[6];
uint8_t dns_retry = 0;
memset(&hints, 0, sizeof(hints));
printf("establish tcp connection with server(host='%s', port=[%u])\n", host, port);
hints.ai_family = AF_INET; /* only IPv4 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
sprintf(service, "%u", port);
while(dns_retry++ < 8) {
rc = getaddrinfo(host, service, &hints, &addrInfoList);
if (rc != 0) {
printf("getaddrinfo error[%d], res: %s, host: %s, port: %s\n", dns_retry, gai_strerror(rc), host, service);
sleep(1);
continue;
}else{
break;
}
}
if (rc != 0) {
printf("getaddrinfo error(%d), host = '%s', port = [%d]\n", rc, host, port);
return (uintptr_t)(-1);
}
for (cur = addrInfoList; cur != NULL; cur = cur->ai_next) {
if (cur->ai_family != AF_INET) {
printf("socket type error\n");
rc = -1;
continue;
}
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (fd < 0) {
printf("create socket error\n");
rc = -1;
continue;
}
if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
rc = fd;
break;
}
close(fd);
printf("connect error\n");
rc = -1;
}
if (-1 == rc) {
printf("fail to establish tcp\n");
} else {
printf("success to establish tcp, fd=%d\n", rc);
}
freeaddrinfo(addrInfoList);
return (uintptr_t)rc;
}
int HAL_TCP_Destroy(uintptr_t fd)
{
int rc;
/* Shutdown both send and receive operations. */
rc = shutdown((int) fd, 2);
if (0 != rc) {
printf("shutdown error\n");
return -1;
}
rc = close((int) fd);
if (0 != rc) {
printf("closesocket error\n");
return -1;
}
return 0;
}
int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms)
{
int ret,tcp_fd;
uint32_t len_sent;
uint64_t t_end, t_left;
fd_set sets;
int net_err = 0;
t_end = _linux_get_time_ms() + timeout_ms;
len_sent = 0;
ret = 1; /* send one time if timeout_ms is value 0 */
if (fd >= FD_SETSIZE) {
return -1;
}
tcp_fd = (int)fd;
do {
t_left = _linux_time_left(t_end, _linux_get_time_ms());
if (0 != t_left) {
struct timeval timeout;
FD_ZERO(&sets);
FD_SET(tcp_fd, &sets);
timeout.tv_sec = t_left / 1000;
timeout.tv_usec = (t_left % 1000) * 1000;
ret = select(tcp_fd + 1, NULL, &sets, NULL, &timeout);
if (ret > 0) {
if (0 == FD_ISSET(tcp_fd, &sets)) {
printf("Should NOT arrive\n");
/* If timeout in next loop, it will not sent any data */
ret = 0;
continue;
}
} else if (0 == ret) {
printf("select-write timeout %d\n", tcp_fd);
break;
} else {
if (EINTR == errno) {
printf("EINTR be caught\n");
continue;
}
printf("select-write fail, ret = select() = %d\n", ret);
net_err = 1;
break;
}
}
if (ret > 0) {
ret = send(tcp_fd, buf + len_sent, len - len_sent, 0);
if (ret > 0) {
len_sent += ret;
} else if (0 == ret) {
printf("No data be sent\n");
} else {
if (EINTR == errno) {
printf("EINTR be caught\n");
continue;
}
printf("send fail, ret = send() = %d\n", ret);
net_err = 1;
break;
}
}
} while (!net_err && (len_sent < len) && (_linux_time_left(t_end, _linux_get_time_ms()) > 0));
if (net_err) {
return -1;
} else {
return len_sent;
}
}
int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
{
int ret, err_code, tcp_fd;
uint32_t len_recv;
uint64_t t_end, t_left;
fd_set sets;
struct timeval timeout;
t_end = _linux_get_time_ms() + timeout_ms;
len_recv = 0;
err_code = 0;
if (fd >= FD_SETSIZE) {
return -1;
}
tcp_fd = (int)fd;
do {
t_left = _linux_time_left(t_end, _linux_get_time_ms());
if (0 == t_left) {
break;
}
FD_ZERO(&sets);
FD_SET(tcp_fd, &sets);
timeout.tv_sec = t_left / 1000;
timeout.tv_usec = (t_left % 1000) * 1000;
ret = select(tcp_fd + 1, &sets, NULL, NULL, &timeout);
if (ret > 0) {
ret = recv(tcp_fd, buf + len_recv, len - len_recv, 0);
if (ret > 0) {
len_recv += ret;
} else if (0 == ret) {
printf("connection is closed\n");
err_code = -1;
break;
} else {
if (EINTR == errno) {
continue;
}
printf("recv fail\n");
err_code = -2;
break;
}
} else if (0 == ret) {
break;
} else {
if (EINTR == errno) {
continue;
}
printf("select-recv fail\n");
err_code = -2;
break;
}
} while ((len_recv < len));
/* priority to return data bytes if any data be received from TCP connection. */
/* It will get error code on next calling */
return (0 != len_recv) ? len_recv : err_code;
}

View File

@@ -0,0 +1,218 @@
#include <stdint.h>
#include <errno.h>
#if defined(__UBUNTU_SDK_DEMO__)
#include <execinfo.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <sys/select.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include "infra_config.h"
#include "at_parser.h"
#include "at_wrapper.h"
static int at_uart_fd = -1;
static int read_and_discard_all_data(const int fd)
{
int was_msg_already_printed = 0;
int errno_code;
while (1) {
char buffer[1024];
const ssize_t read_count = read(fd, buffer, sizeof(buffer));
if (read_count == 0) {
/* "EOF" or "connection closed at the other end"*/
return 0;
}
if (read_count > 0) {
if (!was_msg_already_printed) {
printf("Some stale data was discarded.\r\n");
was_msg_already_printed = 1;
}
continue;
}
assert(read_count == -1); /* According to the specification. */
errno_code = errno;
if (errno_code == EINTR) {
continue;
}
if (errno_code == EAGAIN ||
errno_code == EWOULDBLOCK) {
/**
* We know that the file descriptor has been opened with
* O_NONBLOCK or O_NDELAY, and these codes mean that there
* is no data to read at present.
*/
return 0;
}
/* Some other error has occurred. */
return -1;
}
}
int32_t HAL_AT_Uart_Init(uart_dev_t *uart)
{
int fd;
struct termios t_opt;
speed_t baud;
if (uart->port != AT_UART_PORT) {
return 0;
}
if ((at_uart_fd = open(AT_UART_LINUX_DEV,
O_RDWR | O_NOCTTY | O_NDELAY)) == -1) {
printf("open at uart failed\r\n");
return -1;
}
switch (uart->config.baud_rate) {
case 115200:
baud = B115200;
break;
case 921600:
baud = B921600;
break;
default:
baud = B115200;
break;
}
fd = at_uart_fd;
/* set the serial port parameters */
fcntl(fd, F_SETFL, 0);
if (0 != tcgetattr(fd, &t_opt)) {
return -1;
}
if (0 != cfsetispeed(&t_opt, baud)) {
return -1;
}
if (0 != cfsetospeed(&t_opt, baud)) {
return -1;
}
/* 8N1, flow control, etc. */
t_opt.c_cflag |= (CLOCAL | CREAD);
if (uart->config.parity == NO_PARITY) {
t_opt.c_cflag &= ~PARENB;
}
if (uart->config.stop_bits == STOP_BITS_1) {
t_opt.c_cflag &= ~CSTOPB;
} else {
t_opt.c_cflag |= CSTOPB;
}
t_opt.c_cflag &= ~CSIZE;
switch (uart->config.data_width) {
case DATA_WIDTH_5BIT:
t_opt.c_cflag |= CS5;
break;
case DATA_WIDTH_6BIT:
t_opt.c_cflag |= CS6;
break;
case DATA_WIDTH_7BIT:
t_opt.c_cflag |= CS7;
break;
case DATA_WIDTH_8BIT:
t_opt.c_cflag |= CS8;
break;
default:
t_opt.c_cflag |= CS8;
break;
}
t_opt.c_lflag &= ~(ECHO | ECHOE | ISIG | ICANON);
/**
* AT is going to use a binary protocol, so make sure to
* turn off any CR/LF translation and the like.
*/
t_opt.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL);
t_opt.c_oflag &= ~OPOST;
t_opt.c_cc[VMIN] = 0;
t_opt.c_cc[VTIME] = 5;
if (0 != tcsetattr(fd, TCSANOW, &t_opt)) {
return -1;
}
printf("open at uart succeed\r\n");
/* clear uart buffer */
read_and_discard_all_data(fd);
return 0;
}
int32_t HAL_AT_Uart_Deinit(uart_dev_t *uart)
{
if (uart->port == AT_UART_PORT) {
close(at_uart_fd);
}
return 0;
}
int32_t HAL_AT_Uart_Send(uart_dev_t *uart, const void *data,
uint32_t size, uint32_t timeout)
{
uint32_t ret, rmd = size;
if (uart->port == AT_UART_PORT) {
while (rmd > 0) {
ret = write(at_uart_fd, data + size - rmd, rmd);
if (ret == -1) {
printf("write uart fd failed on error: %d.\r\n", errno);
return -1;
}
rmd -= ret;
}
} else {
if (write(1, data, size) < 0) {
printf("write failed\n");
}
}
return 0;
}
int32_t HAL_AT_Uart_Recv(uart_dev_t *uart, void *data, uint32_t expect_size,
uint32_t *recv_size, uint32_t timeout)
{
int fd, n;
if (uart->port == AT_UART_PORT) {
fd = at_uart_fd;
} else {
fd = 1;
}
if ((n = read(fd, data, expect_size)) == -1) {
return -1;
}
if (uart->port != AT_UART_PORT && *(char *)data == '\n') {
*(char *)data = '\r';
}
if (recv_size) {
*recv_size = n;
}
return 0;
}

View File

@@ -0,0 +1,375 @@
#include "infra_config.h"
#if defined(HAL_UDP)
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <pthread.h>
#include "infra_config.h"
#include "infra_compat.h"
intptr_t HAL_UDP_create(char *host, unsigned short port)
{
#define NETWORK_ADDR_LEN (16)
int rc = -1;
long socket_id = -1;
char port_ptr[6] = {0};
struct addrinfo hints;
char addr[NETWORK_ADDR_LEN] = {0};
struct addrinfo *res, *ainfo;
struct sockaddr_in *sa = NULL;
if (NULL == host) {
return (-1);
}
sprintf(port_ptr, "%u", port);
memset((char *)&hints, 0x00, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_UDP;
rc = getaddrinfo(host, port_ptr, &hints, &res);
if (0 != rc) {
printf("getaddrinfo error");
return (-1);
}
for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
if (AF_INET == ainfo->ai_family) {
sa = (struct sockaddr_in *)ainfo->ai_addr;
inet_ntop(AF_INET, &sa->sin_addr, addr, NETWORK_ADDR_LEN);
fprintf(stderr, "The host IP %s, port is %d\r\n", addr, ntohs(sa->sin_port));
socket_id = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
if (socket_id < 0) {
printf("create socket error");
continue;
}
if (0 == connect(socket_id, ainfo->ai_addr, ainfo->ai_addrlen)) {
break;
}
close(socket_id);
}
}
freeaddrinfo(res);
return socket_id;
#undef NETWORK_ADDR_LEN
}
void HAL_UDP_close(intptr_t p_socket)
{
long socket_id = -1;
socket_id = p_socket;
close(socket_id);
}
int HAL_UDP_write(intptr_t p_socket,
const unsigned char *p_data,
unsigned int datalen)
{
int rc = -1;
long socket_id = -1;
socket_id = (long)p_socket;
rc = send(socket_id, (char *)p_data, (int)datalen, 0);
if (-1 == rc) {
return -1;
}
return rc;
}
int HAL_UDP_readTimeout(intptr_t p_socket,
unsigned char *p_data,
unsigned int datalen,
unsigned int timeout)
{
int ret;
struct timeval tv;
fd_set read_fds;
long socket_id = -1;
if (0 == p_socket || NULL == p_data) {
return -1;
}
socket_id = (long)p_socket;
if (socket_id < 0) {
return -1;
}
FD_ZERO(&read_fds);
FD_SET(socket_id, &read_fds);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ret = select(socket_id + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
/* Zero fds ready means we timed out */
if (ret == 0) {
return -2; /* receive timeout */
}
if (ret < 0) {
if (errno == EINTR) {
return -3; /* want read */
}
return -4; /* receive failed */
}
/* This call will not block */
return read(p_socket, p_data, datalen);
}
intptr_t HAL_UDP_create_without_connect(const char *host, unsigned short port)
{
struct sockaddr_in addr;
long sockfd;
int opt_val = 1;
struct hostent *hp;
struct in_addr in;
uint32_t ip;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
printf("socket");
return -1;
}
if (0 == port) {
return (intptr_t)sockfd;
}
memset(&addr, 0, sizeof(struct sockaddr_in));
if (0 != setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST, &opt_val, sizeof(opt_val))) {
printf("setsockopt");
close(sockfd);
return -1;
}
if (NULL == host) {
addr.sin_addr.s_addr = htonl(INADDR_ANY);
} else {
if (inet_aton(host, &in)) {
ip = *(uint32_t *)&in;
} else {
hp = gethostbyname(host);
if (!hp) {
printf("can't resolute the host address \n");
close(sockfd);
return -1;
}
ip = *(uint32_t *)(hp->h_addr);
}
addr.sin_addr.s_addr = ip;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (-1 == bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
close(sockfd);
return -1;
}
printf("success to establish udp, fd=%d", (int)sockfd);
return (intptr_t)sockfd;
}
int HAL_UDP_connect(intptr_t sockfd,
const char *host,
unsigned short port)
{
int rc = -1;
char port_ptr[6] = {0};
struct addrinfo hints;
struct addrinfo *res, *ainfo;
if (NULL == host) {
return -1;
}
printf("HAL_UDP_connect, host=%s, port=%d", host, port);
sprintf(port_ptr, "%u", port);
memset((char *)&hints, 0x00, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_UDP;
rc = getaddrinfo(host, port_ptr, &hints, &res);
if (0 != rc) {
printf("getaddrinfo error");
return -1;
}
for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
if (AF_INET == ainfo->ai_family) {
if (0 == connect(sockfd, ainfo->ai_addr, ainfo->ai_addrlen)) {
freeaddrinfo(res);
return 0;
}
}
}
freeaddrinfo(res);
return -1;
}
int HAL_UDP_close_without_connect(intptr_t sockfd)
{
return close((int)sockfd);
}
int HAL_UDP_joinmulticast(intptr_t sockfd,
char *p_group)
{
int err = -1;
int socket_id = -1;
int loop = 0;
struct ip_mreq mreq;
if (NULL == p_group) {
return -1;
}
/*set loopback*/
socket_id = (int)sockfd;
err = setsockopt(socket_id, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
if (err < 0) {
printf("setsockopt");
return err;
}
mreq.imr_multiaddr.s_addr = inet_addr(p_group);
mreq.imr_interface.s_addr = htonl(INADDR_ANY); /*default networt interface*/
/*join to the multicast group*/
err = setsockopt(socket_id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if (err < 0) {
printf("setsockopt");
return err;
}
return 0;
}
int HAL_UDP_recvfrom(intptr_t sockfd,
NetworkAddr *p_remote,
unsigned char *p_data,
unsigned int datalen,
unsigned int timeout_ms)
{
int ret;
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
fd_set read_fds;
struct timeval timeout = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
FD_ZERO(&read_fds);
FD_SET(sockfd, &read_fds);
ret = select(sockfd + 1, &read_fds, NULL, NULL, &timeout);
if (ret == 0) {
return 0; /* receive timeout */
}
if (ret < 0) {
if (errno == EINTR) {
return -3; /* want read */
}
return -4; /* receive failed */
}
ret = recvfrom(sockfd, p_data, datalen, 0, (struct sockaddr *)&addr, &addr_len);
if (ret > 0) {
if (NULL != p_remote) {
p_remote->port = ntohs(addr.sin_port);
strcpy((char *)p_remote->addr, inet_ntoa(addr.sin_addr));
}
return ret;
}
return -1;
}
int HAL_UDP_sendto(intptr_t sockfd,
const NetworkAddr *p_remote,
const unsigned char *p_data,
unsigned int datalen,
unsigned int timeout_ms)
{
int ret;
uint32_t ip;
struct in_addr in;
struct hostent *hp;
struct sockaddr_in addr;
fd_set write_fds;
struct timeval timeout = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
if (inet_aton((char *)p_remote->addr, &in)) {
ip = *(uint32_t *)&in;
} else {
hp = gethostbyname((char *)p_remote->addr);
if (!hp) {
printf("can't resolute the host address \n");
return -1;
}
ip = *(uint32_t *)(hp->h_addr);
}
FD_ZERO(&write_fds);
FD_SET(sockfd, &write_fds);
ret = select(sockfd + 1, NULL, &write_fds, NULL, &timeout);
if (ret == 0) {
return 0; /* write timeout */
}
if (ret < 0) {
if (errno == EINTR) {
return -3; /* want write */
}
return -4; /* write failed */
}
addr.sin_addr.s_addr = ip;
addr.sin_family = AF_INET;
addr.sin_port = htons(p_remote->port);
ret = sendto(sockfd, p_data, datalen, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if (ret < 0) {
printf("sendto");
}
return (ret) > 0 ? ret : -1;
}
#endif /* #if defined(HAL_UDP) */

View File

@@ -0,0 +1,517 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "infra_config.h"
#ifdef COAP_DTLS_SUPPORT
#include "wrappers_defs.h"
#include "mbedtls/ssl.h"
#include "mbedtls/platform.h"
#include "mbedtls/sha256.h"
#include "mbedtls/debug.h"
#include "mbedtls/timing.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/net_sockets.h"
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
void HAL_Printf(const char *fmt, ...);
#define DTLS_TRC(...) HAL_Printf("[trc] "), HAL_Printf(__VA_ARGS__)
#define DTLS_DUMP(...) HAL_Printf("[dump] "), HAL_Printf(__VA_ARGS__)
#define DTLS_DEBUG(...) HAL_Printf("[dbg] "), HAL_Printf(__VA_ARGS__)
#define DTLS_INFO(...) HAL_Printf("[inf] "), HAL_Printf(__VA_ARGS__)
#define DTLS_ERR(...) HAL_Printf("[err] "), HAL_Printf(__VA_ARGS__)
#ifdef DTLS_SESSION_SAVE
mbedtls_ssl_session *saved_session = NULL;
#endif
typedef struct {
mbedtls_ssl_context context;
mbedtls_ssl_config conf;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
#ifdef MBEDTLS_X509_CRT_PARSE_C
mbedtls_x509_crt cacert;
#endif
mbedtls_net_context fd;
mbedtls_timing_delay_context timer;
mbedtls_ssl_cookie_ctx cookie_ctx;
} dtls_session_t;
#define MBEDTLS_MEM_TEST 1
#ifdef MBEDTLS_MEM_TEST
#define MBEDTLS_MEM_INFO_MAGIC 0x12345678
static unsigned int mbedtls_mem_used = 0;
static unsigned int mbedtls_max_mem_used = 0;
static dtls_hooks_t g_dtls_hooks = {HAL_Malloc, HAL_Free};
typedef struct {
int magic;
int size;
} mbedtls_mem_info_t;
void *_DTLSCalloc_wrapper(size_t n, size_t size)
{
void *buf = NULL;
mbedtls_mem_info_t *mem_info = NULL;
if (n == 0 || size == 0) {
return NULL;
}
buf = g_dtls_hooks.malloc(n * size + sizeof(mbedtls_mem_info_t));
if (NULL == buf) {
return NULL;
} else {
memset(buf, 0, n * size + sizeof(mbedtls_mem_info_t));
}
mem_info = (mbedtls_mem_info_t *)buf;
mem_info->magic = MBEDTLS_MEM_INFO_MAGIC;
mem_info->size = n * size;
buf += sizeof(mbedtls_mem_info_t);
mbedtls_mem_used += mem_info->size;
if (mbedtls_mem_used > mbedtls_max_mem_used) {
mbedtls_max_mem_used = mbedtls_mem_used;
}
/* DTLS_TRC("INFO -- mbedtls malloc: %p %d total used: %d max used: %d\r\n",
buf, (int)size, mbedtls_mem_used, mbedtls_max_mem_used); */
return buf;
}
void _DTLSFree_wrapper(void *ptr)
{
mbedtls_mem_info_t *mem_info = NULL;
if (NULL == ptr) {
return;
}
mem_info = ptr - sizeof(mbedtls_mem_info_t);
if (mem_info->magic != MBEDTLS_MEM_INFO_MAGIC) {
DTLS_TRC("Warning - invalid mem info magic: 0x%x\r\n", mem_info->magic);
return;
}
mbedtls_mem_used -= mem_info->size;
/* DTLS_TRC("INFO mbedtls free: %p %d total used: %d max used: %d\r\n",
ptr, mem_info->size, mbedtls_mem_used, mbedtls_max_mem_used);*/
g_dtls_hooks.free(mem_info);
}
#else
static void *_DTLSCalloc_wrapper(size_t n, size_t s)
{
void *ptr = NULL;
size_t len = n * s;
ptr = HAL_Malloc(len);
if (NULL != ptr) {
memset(ptr, 0x00, len);
}
return ptr;
}
static void _DTLSFree_wrapper(void *ptr)
{
if (NULL != ptr) {
HAL_Free(ptr);
ptr = NULL;
}
}
#endif
#ifdef DTLS_SESSION_SAVE
static int _DTLSSession_save(const mbedtls_ssl_session *session,
unsigned char *buf, size_t buf_len,
size_t *olen)
{
unsigned char *p = buf;
size_t left = buf_len;
#if defined(MBEDTLS_X509_CRT_PARSE_C)
size_t cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */
if (left < sizeof(mbedtls_ssl_session)) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
memcpy(p, session, sizeof(mbedtls_ssl_session));
p += sizeof(mbedtls_ssl_session);
left -= sizeof(mbedtls_ssl_session);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if (session->peer_cert == NULL) {
cert_len = 0;
} else {
cert_len = session->peer_cert->raw.len;
}
if (left < 3 + cert_len) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
*p++ = (unsigned char)(cert_len >> 16 & 0xFF);
*p++ = (unsigned char)(cert_len >> 8 & 0xFF);
*p++ = (unsigned char)(cert_len & 0xFF);
if (session->peer_cert != NULL) {
memcpy(p, session->peer_cert->raw.p, cert_len);
}
p += cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */
*olen = p - buf;
return (0);
}
#endif
static unsigned int _DTLSVerifyOptions_set(dtls_session_t *p_dtls_session, unsigned char *p_ca_cert_pem, char *host)
{
int result;
unsigned int err_code = DTLS_SUCCESS;
#ifdef MBEDTLS_X509_CRT_PARSE_C
if (p_ca_cert_pem != NULL) {
mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
if (strstr(host, "pre.iot-as-coap")) {
DTLS_TRC("host = '%s' so verify server OPTIONAL\r\n", host);
mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
}
DTLS_TRC("Call mbedtls_ssl_conf_authmode\r\n");
DTLS_TRC("x509 ca cert pem len %d\r\n%s\r\n", (int)strlen((char *)p_ca_cert_pem) + 1, p_ca_cert_pem);
result = mbedtls_x509_crt_parse(&p_dtls_session->cacert,
p_ca_cert_pem,
strlen((const char *)p_ca_cert_pem) + 1);
DTLS_TRC("mbedtls_x509_crt_parse result 0x%04x\r\n", result);
if (0 != result) {
err_code = DTLS_INVALID_CA_CERTIFICATE;
} else {
mbedtls_ssl_conf_ca_chain(&p_dtls_session->conf, &p_dtls_session->cacert, NULL);
}
} else
#endif
{
mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_NONE);
}
return err_code;
}
static void _DTLSLog_wrapper(void *p_ctx, int level,
const char *p_file, int line, const char *p_str)
{
DTLS_INFO("[mbedTLS]:[%s]:[%d]: %s\r\n", p_file, line, p_str);
}
static unsigned int _DTLSContext_setup(dtls_session_t *p_dtls_session, coap_dtls_options_t *p_options)
{
int result = 0;
mbedtls_ssl_init(&p_dtls_session->context);
result = mbedtls_ssl_setup(&p_dtls_session->context, &p_dtls_session->conf);
DTLS_TRC("mbedtls_ssl_setup result 0x%04x\r\n", result);
if (result == 0) {
if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
mbedtls_ssl_set_timer_cb(&p_dtls_session->context,
(void *)&p_dtls_session->timer,
mbedtls_timing_set_delay,
mbedtls_timing_get_delay);
}
#ifdef MBEDTLS_X509_CRT_PARSE_C
DTLS_TRC("mbedtls_ssl_set_hostname %s\r\n", p_options->p_host);
mbedtls_ssl_set_hostname(&p_dtls_session->context, p_options->p_host);
#endif
mbedtls_ssl_set_bio(&p_dtls_session->context,
(void *)&p_dtls_session->fd,
mbedtls_net_send,
mbedtls_net_recv,
mbedtls_net_recv_timeout);
DTLS_TRC("mbedtls_ssl_set_bio result 0x%04x\r\n", result);
#ifdef DTLS_SESSION_SAVE
if (NULL != saved_session) {
result = mbedtls_ssl_set_session(&p_dtls_session->context, saved_session);
DTLS_TRC("mbedtls_ssl_set_session return 0x%04x\r\n", result);
}
#endif
do {
result = mbedtls_ssl_handshake(&p_dtls_session->context);
} while (result == MBEDTLS_ERR_SSL_WANT_READ ||
result == MBEDTLS_ERR_SSL_WANT_WRITE);
DTLS_TRC("mbedtls_ssl_handshake result 0x%04x\r\n", result);
#ifdef MBEDTLS_MEM_TEST
DTLS_TRC("mbedtls handshake memory total used: %d max used: %d\r\n",
mbedtls_mem_used, mbedtls_max_mem_used);
#endif
#ifdef DTLS_SESSION_SAVE
if (0 == result) {
if (NULL == saved_session) {
saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
}
if (NULL != saved_session) {
memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
result = mbedtls_ssl_get_session(&p_dtls_session->context, saved_session);
DTLS_TRC("mbedtls_ssl_get_session return 0x%04x\r\n", result);
}
}
#endif
}
return (result ? DTLS_HANDSHAKE_FAILED : DTLS_SUCCESS);
}
dtls_session_t *_DTLSSession_init()
{
dtls_session_t *p_dtls_session = NULL;
p_dtls_session = HAL_Malloc(sizeof(dtls_session_t));
mbedtls_debug_set_threshold(0);
#ifdef MBEDTLS_MEM_TEST
mbedtls_mem_used = 0;
mbedtls_max_mem_used = 0;
#endif
mbedtls_platform_set_calloc_free(_DTLSCalloc_wrapper, _DTLSFree_wrapper);
if (NULL != p_dtls_session) {
mbedtls_net_init(&p_dtls_session->fd);
mbedtls_ssl_init(&p_dtls_session->context);
mbedtls_ssl_config_init(&p_dtls_session->conf);
mbedtls_net_init(&p_dtls_session->fd);
mbedtls_ssl_cookie_init(&p_dtls_session->cookie_ctx);
#ifdef MBEDTLS_X509_CRT_PARSE_C
mbedtls_x509_crt_init(&p_dtls_session->cacert);
#endif
mbedtls_ctr_drbg_init(&p_dtls_session->ctr_drbg);
mbedtls_entropy_init(&p_dtls_session->entropy);
DTLS_INFO("HAL_DTLSSession_init success\r\n");
}
return p_dtls_session;
}
unsigned int _DTLSSession_deinit(dtls_session_t *p_dtls_session)
{
int ret;
if (p_dtls_session != NULL) {
do {
ret = mbedtls_ssl_close_notify(&p_dtls_session->context);
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
mbedtls_net_free(&p_dtls_session->fd);
#ifdef MBEDTLS_X509_CRT_PARSE_C
mbedtls_x509_crt_free(&p_dtls_session->cacert);
#endif
mbedtls_ssl_cookie_free(&p_dtls_session->cookie_ctx);
mbedtls_ssl_config_free(&p_dtls_session->conf);
mbedtls_ssl_free(&p_dtls_session->context);
mbedtls_ctr_drbg_free(&p_dtls_session->ctr_drbg);
mbedtls_entropy_free(&p_dtls_session->entropy);
HAL_Free(p_dtls_session);
}
return DTLS_SUCCESS;
}
int HAL_DTLSHooks_set(dtls_hooks_t *hooks)
{
if (hooks == NULL || hooks->malloc == NULL || hooks->free == NULL) {
return DTLS_INVALID_PARAM;
}
g_dtls_hooks.malloc = hooks->malloc;
g_dtls_hooks.free = hooks->free;
return DTLS_SUCCESS;
}
DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options)
{
char port[6] = {0};
int result = 0;
dtls_session_t *p_dtls_session = NULL;
p_dtls_session = _DTLSSession_init();
if (NULL != p_dtls_session) {
mbedtls_ssl_config_init(&p_dtls_session->conf);
result = mbedtls_ctr_drbg_seed(&p_dtls_session->ctr_drbg, mbedtls_entropy_func, &p_dtls_session->entropy,
(const unsigned char *)"IoTx",
strlen("IoTx"));
if (0 != result) {
DTLS_ERR("mbedtls_ctr_drbg_seed result 0x%04x\r\n", result);
goto error;
}
result = mbedtls_ssl_config_defaults(&p_dtls_session->conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_DATAGRAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (0 != result) {
DTLS_ERR("mbedtls_ssl_config_defaults result 0x%04x\r\n", result);
goto error;
}
mbedtls_ssl_conf_rng(&p_dtls_session->conf, mbedtls_ctr_drbg_random, &p_dtls_session->ctr_drbg);
mbedtls_ssl_conf_dbg(&p_dtls_session->conf, _DTLSLog_wrapper, NULL);
result = mbedtls_ssl_cookie_setup(&p_dtls_session->cookie_ctx,
mbedtls_ctr_drbg_random, &p_dtls_session->ctr_drbg);
if (0 != result) {
DTLS_ERR("mbedtls_ssl_cookie_setup result 0x%04x\r\n", result);
goto error;
}
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
mbedtls_ssl_conf_dtls_cookies(&p_dtls_session->conf, mbedtls_ssl_cookie_write,
mbedtls_ssl_cookie_check, &p_dtls_session->cookie_ctx);
#endif
result = _DTLSVerifyOptions_set(p_dtls_session, p_options->p_ca_cert_pem, p_options->p_host);
if (DTLS_SUCCESS != result) {
DTLS_ERR("DTLSVerifyOptions_set result 0x%04x\r\n", result);
goto error;
}
sprintf(port, "%u", p_options->port);
result = mbedtls_net_connect(&p_dtls_session->fd, p_options->p_host,
port, MBEDTLS_NET_PROTO_UDP);
if (0 != result) {
DTLS_ERR("mbedtls_net_connect result 0x%04x\r\n", result);
goto error;
}
#ifdef MBEDTLS_SSL_PROTO_DTLS
if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
mbedtls_ssl_conf_min_version(&p_dtls_session->conf,
MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_max_version(&p_dtls_session->conf,
MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_handshake_timeout(&p_dtls_session->conf,
(MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2),
(MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4));
}
#endif
result = _DTLSContext_setup(p_dtls_session, p_options);
if (DTLS_SUCCESS != result) {
DTLS_ERR("DTLSVerifyOptions_set result 0x%04x\r\n", result);
goto error;
}
return (DTLSContext *)p_dtls_session;
}
error:
if (NULL != p_dtls_session) {
_DTLSSession_deinit(p_dtls_session);
}
return NULL;
}
unsigned int HAL_DTLSSession_write(DTLSContext *context,
const unsigned char *p_data,
unsigned int *p_datalen)
{
int len = 0;
unsigned int err_code = DTLS_SUCCESS;
dtls_session_t *p_dtls_session = (dtls_session_t *)context;
if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
len = (*p_datalen);
len = mbedtls_ssl_write(&p_dtls_session->context, p_data, len);
if (len < 0) {
if (len == MBEDTLS_ERR_SSL_CONN_EOF) {
if (p_dtls_session->context.state < MBEDTLS_SSL_HANDSHAKE_OVER) {
err_code = DTLS_HANDSHAKE_IN_PROGRESS;
}
}
} else {
(*p_datalen) = len;
err_code = DTLS_SUCCESS;
}
}
return err_code;
}
unsigned int HAL_DTLSSession_read(DTLSContext *context,
unsigned char *p_data,
unsigned int *p_datalen,
unsigned int timeout)
{
int len = 0;
unsigned int err_code = DTLS_READ_DATA_FAILED;
dtls_session_t *p_dtls_session = (dtls_session_t *)context;
if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
mbedtls_ssl_conf_read_timeout(&(p_dtls_session->conf), timeout);
len = mbedtls_ssl_read(&p_dtls_session->context, p_data, *p_datalen);
if (0 < len) {
*p_datalen = len;
err_code = DTLS_SUCCESS;
DTLS_TRC("mbedtls_ssl_read len %d bytes\r\n", len);
} else {
*p_datalen = 0;
if (MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == len) {
err_code = DTLS_FATAL_ALERT_MESSAGE;
DTLS_INFO("Recv peer fatal alert message\r\n");
} else if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == len) {
err_code = DTLS_PEER_CLOSE_NOTIFY;
DTLS_INFO("The DTLS session was closed by peer\r\n");
} else if (MBEDTLS_ERR_SSL_TIMEOUT == len) {
err_code = DTLS_SUCCESS;
DTLS_TRC("DTLS recv timeout\r\n");
} else {
DTLS_TRC("mbedtls_ssl_read error result (-0x%04x)\r\n", len);
}
}
}
return err_code;
}
unsigned int HAL_DTLSSession_free(DTLSContext *context)
{
dtls_session_t *p_dtls_session = NULL;
if (NULL != context) {
p_dtls_session = (dtls_session_t *)context;
return _DTLSSession_deinit(p_dtls_session);
}
return DTLS_INVALID_PARAM;
}
#endif

View File

@@ -0,0 +1,860 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#if defined(_PLATFORM_IS_LINUX_)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netdb.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#endif
#include "infra_config.h"
#include "mbedtls/error.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/pk.h"
#include "mbedtls/debug.h"
#include "mbedtls/platform.h"
#include "wrappers_defs.h"
#define SEND_TIMEOUT_SECONDS (10)
#define GUIDER_ONLINE_HOSTNAME ("iot-auth.cn-shanghai.aliyuncs.com")
#define GUIDER_PRE_ADDRESS ("100.67.80.107")
#ifndef CONFIG_MBEDTLS_DEBUG_LEVEL
#define CONFIG_MBEDTLS_DEBUG_LEVEL 0
#endif
typedef struct _TLSDataParams {
mbedtls_ssl_context ssl; /**< mbed TLS control context. */
mbedtls_net_context fd; /**< mbed TLS network context. */
mbedtls_ssl_config conf; /**< mbed TLS configuration context. */
mbedtls_x509_crt cacertl; /**< mbed TLS CA certification. */
mbedtls_x509_crt clicert; /**< mbed TLS Client certification. */
mbedtls_pk_context pkey; /**< mbed TLS Client key. */
} TLSDataParams_t, *TLSDataParams_pt;
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
static unsigned int mbedtls_mem_used = 0;
static unsigned int mbedtls_max_mem_used = 0;
static ssl_hooks_t g_ssl_hooks = {HAL_Malloc, HAL_Free};
#define MBEDTLS_MEM_INFO_MAGIC 0x12345678
typedef struct {
int magic;
int size;
} mbedtls_mem_info_t;
#if defined(TLS_SAVE_TICKET)
#define TLS_MAX_SESSION_BUF 384
#define KV_SESSION_KEY "TLS_SESSION"
extern int HAL_Kv_Set(const char *key, const void *val, int len, int sync);
extern int HAL_Kv_Get(const char *key, void *val, int *buffer_len);
static mbedtls_ssl_session *saved_session = NULL;
static int ssl_serialize_session(const mbedtls_ssl_session *session,
unsigned char *buf, size_t buf_len,
size_t *olen)
{
unsigned char *p = buf;
size_t left = buf_len;
if (left < sizeof(mbedtls_ssl_session)) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
memcpy(p, session, sizeof(mbedtls_ssl_session));
p += sizeof(mbedtls_ssl_session);
left -= sizeof(mbedtls_ssl_session);
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
if (left < sizeof(mbedtls_ssl_session)) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
memcpy(p, session->ticket, session->ticket_len);
p += session->ticket_len;
left -= session->ticket_len;
#endif
*olen = p - buf;
return (0);
}
static int ssl_deserialize_session(mbedtls_ssl_session *session,
const unsigned char *buf, size_t len)
{
const unsigned char *p = buf;
const unsigned char *const end = buf + len;
if (sizeof(mbedtls_ssl_session) > (size_t)(end - p)) {
return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
}
memcpy(session, p, sizeof(mbedtls_ssl_session));
p += sizeof(mbedtls_ssl_session);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
session->peer_cert = NULL;
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
if (session->ticket_len > 0) {
if (session->ticket_len > (size_t)(end - p)) {
return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
}
session->ticket = HAL_Malloc(session->ticket_len);
if (session->ticket == NULL) {
return (MBEDTLS_ERR_SSL_ALLOC_FAILED);
}
memcpy(session->ticket, p, session->ticket_len);
p += session->ticket_len;
printf("saved ticket len = %d \r\n", (int)session->ticket_len);
}
#endif
if (p != end) {
return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
}
return (0);
}
#endif
static unsigned int _avRandom()
{
return (((unsigned int)rand() << 16) + rand());
}
static int _ssl_random(void *p_rng, unsigned char *output, size_t output_len)
{
uint32_t rnglen = output_len;
uint8_t rngoffset = 0;
while (rnglen > 0) {
*(output + rngoffset) = (unsigned char)_avRandom() ;
rngoffset++;
rnglen--;
}
return 0;
}
static void _ssl_debug(void *ctx, int level, const char *file, int line, const char *str)
{
((void) level);
if (NULL != ctx) {
#if 0
fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
fflush((FILE *) ctx);
#endif
printf("%s\n", str);
}
}
static int _real_confirm(int verify_result)
{
printf("certificate verification result: 0x%02x\n", verify_result);
#if defined(FORCE_SSL_VERIFY)
if ((verify_result & MBEDTLS_X509_BADCERT_EXPIRED) != 0) {
printf("! fail ! ERROR_CERTIFICATE_EXPIRED\n");
return -1;
}
if ((verify_result & MBEDTLS_X509_BADCERT_REVOKED) != 0) {
printf("! fail ! server certificate has been revoked\n");
return -1;
}
if ((verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0) {
printf("! fail ! CN mismatch\n");
return -1;
}
if ((verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0) {
printf("! fail ! self-signed or not signed by a trusted CA\n");
return -1;
}
#endif
return 0;
}
static int _ssl_client_init(mbedtls_ssl_context *ssl,
mbedtls_net_context *tcp_fd,
mbedtls_ssl_config *conf,
mbedtls_x509_crt *crt509_ca, const char *ca_crt, size_t ca_len,
mbedtls_x509_crt *crt509_cli, const char *cli_crt, size_t cli_len,
mbedtls_pk_context *pk_cli, const char *cli_key, size_t key_len, const char *cli_pwd, size_t pwd_len
)
{
int ret = -1;
/*
* 0. Initialize the RNG and the session data
*/
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold((int)CONFIG_MBEDTLS_DEBUG_LEVEL);
#endif
mbedtls_net_init(tcp_fd);
mbedtls_ssl_init(ssl);
mbedtls_ssl_config_init(conf);
mbedtls_x509_crt_init(crt509_ca);
/*verify_source->trusted_ca_crt==NULL
* 0. Initialize certificates
*/
printf("Loading the CA root certificate ...\n");
if (NULL != ca_crt) {
if (0 != (ret = mbedtls_x509_crt_parse(crt509_ca, (const unsigned char *)ca_crt, ca_len))) {
printf(" failed ! x509parse_crt returned -0x%04x\n", -ret);
return ret;
}
}
printf(" ok (%d skipped)\n", ret);
/* Setup Client Cert/Key */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#if defined(MBEDTLS_CERTS_C)
mbedtls_x509_crt_init(crt509_cli);
mbedtls_pk_init(pk_cli);
#endif
if (cli_crt != NULL && cli_key != NULL) {
#if defined(MBEDTLS_CERTS_C)
printf("start prepare client cert .\n");
ret = mbedtls_x509_crt_parse(crt509_cli, (const unsigned char *) cli_crt, cli_len);
#else
{
ret = 1;
printf("MBEDTLS_CERTS_C not defined.\n");
}
#endif
if (ret != 0) {
printf(" failed! mbedtls_x509_crt_parse returned -0x%x\n", -ret);
return ret;
}
#if defined(MBEDTLS_CERTS_C)
printf("start mbedtls_pk_parse_key[%s]\n", cli_pwd);
ret = mbedtls_pk_parse_key(pk_cli, (const unsigned char *) cli_key, key_len, (const unsigned char *) cli_pwd, pwd_len);
#else
{
ret = 1;
printf("MBEDTLS_CERTS_C not defined.\n");
}
#endif
if (ret != 0) {
printf(" failed\n ! mbedtls_pk_parse_key returned -0x%x\n", -ret);
return ret;
}
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
return 0;
}
#if defined(_PLATFORM_IS_LINUX_)
static int net_prepare(void)
{
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32)
WSADATA wsaData;
static int wsa_init_done = 0;
if (wsa_init_done == 0) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return (MBEDTLS_ERR_NET_SOCKET_FAILED);
}
wsa_init_done = 1;
}
#else
#if !defined(EFIX64) && !defined(EFI32)
signal(SIGPIPE, SIG_IGN);
#endif
#endif
return (0);
}
static int mbedtls_net_connect_timeout(mbedtls_net_context *ctx, const char *host,
const char *port, int proto, unsigned int timeout)
{
int ret;
struct addrinfo hints, *addr_list, *cur;
struct timeval sendtimeout;
uint8_t dns_retry = 0;
if ((ret = net_prepare()) != 0) {
return (ret);
}
/* Do name resolution with both IPv6 and IPv4 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
while(dns_retry++ < 8) {
ret = getaddrinfo(host, port, &hints, &addr_list);
if (ret != 0) {
printf("getaddrinfo error[%d], res: %s, host: %s, port: %s\n", dns_retry, gai_strerror(ret), host, port);
sleep(1);
continue;
}else{
break;
}
}
if (ret != 0) {
return (MBEDTLS_ERR_NET_UNKNOWN_HOST);
}
/* Try the sockaddrs until a connection succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
char ip4_str[INET_ADDRSTRLEN];
ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
cur->ai_protocol);
if (ctx->fd < 0) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
sendtimeout.tv_sec = timeout;
sendtimeout.tv_usec = 0;
if (0 != setsockopt(ctx->fd, SOL_SOCKET, SO_SNDTIMEO, &sendtimeout, sizeof(sendtimeout))) {
perror("setsockopt");
printf("setsockopt error\n");
}
printf("setsockopt SO_SNDTIMEO timeout: %ds\n", (int)sendtimeout.tv_sec);
inet_ntop(AF_INET, &((const struct sockaddr_in *)cur->ai_addr)->sin_addr, ip4_str, INET_ADDRSTRLEN);
printf("connecting IP_ADDRESS: %s\n", ip4_str);
if (connect(ctx->fd, cur->ai_addr, cur->ai_addrlen) == 0) {
ret = 0;
break;
}
close(ctx->fd);
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
}
freeaddrinfo(addr_list);
return (ret);
}
#endif
void *_SSLCalloc_wrapper(size_t n, size_t size)
{
unsigned char *buf = NULL;
mbedtls_mem_info_t *mem_info = NULL;
if (n == 0 || size == 0) {
return NULL;
}
buf = (unsigned char *)(g_ssl_hooks.malloc(n * size + sizeof(mbedtls_mem_info_t)));
if (NULL == buf) {
return NULL;
} else {
memset(buf, 0, n * size + sizeof(mbedtls_mem_info_t));
}
mem_info = (mbedtls_mem_info_t *)buf;
mem_info->magic = MBEDTLS_MEM_INFO_MAGIC;
mem_info->size = n * size;
buf += sizeof(mbedtls_mem_info_t);
mbedtls_mem_used += mem_info->size;
if (mbedtls_mem_used > mbedtls_max_mem_used) {
mbedtls_max_mem_used = mbedtls_mem_used;
}
/* printf("INFO -- mbedtls malloc: %p %d total used: %d max used: %d\r\n",
buf, (int)size, mbedtls_mem_used, mbedtls_max_mem_used); */
return buf;
}
void _SSLFree_wrapper(void *ptr)
{
mbedtls_mem_info_t *mem_info = NULL;
if (NULL == ptr) {
return;
}
mem_info = (mbedtls_mem_info_t *)((unsigned char *)ptr - sizeof(mbedtls_mem_info_t));
if (mem_info->magic != MBEDTLS_MEM_INFO_MAGIC) {
printf("Warning - invalid mem info magic: 0x%x\r\n", mem_info->magic);
return;
}
mbedtls_mem_used -= mem_info->size;
/* printf("INFO mbedtls free: %p %d total used: %d max used: %d\r\n",
ptr, mem_info->size, mbedtls_mem_used, mbedtls_max_mem_used);*/
g_ssl_hooks.free(mem_info);
}
/**
* @brief This function connects to the specific SSL server with TLS, and returns a value that indicates whether the connection is create successfully or not. Call #NewNetwork() to initialize network structure before calling this function.
* @param[in] n is the the network structure pointer.
* @param[in] addr is the Server Host name or IP address.
* @param[in] port is the Server Port.
* @param[in] ca_crt is the Server's CA certification.
* @param[in] ca_crt_len is the length of Server's CA certification.
* @param[in] client_crt is the client certification.
* @param[in] client_crt_len is the length of client certification.
* @param[in] client_key is the client key.
* @param[in] client_key_len is the length of client key.
* @param[in] client_pwd is the password of client key.
* @param[in] client_pwd_len is the length of client key's password.
* @sa #NewNetwork();
* @return If the return value is 0, the connection is created successfully. If the return value is -1, then calling lwIP #socket() has failed. If the return value is -2, then calling lwIP #connect() has failed. Any other value indicates that calling lwIP #getaddrinfo() has failed.
*/
static int _TLSConnectNetwork(TLSDataParams_t *pTlsData, const char *addr, const char *port,
const char *ca_crt, size_t ca_crt_len,
const char *client_crt, size_t client_crt_len,
const char *client_key, size_t client_key_len,
const char *client_pwd, size_t client_pwd_len)
{
int ret = -1;
/*
* 0. Init
*/
if (0 != (ret = _ssl_client_init(&(pTlsData->ssl), &(pTlsData->fd), &(pTlsData->conf),
&(pTlsData->cacertl), ca_crt, ca_crt_len,
&(pTlsData->clicert), client_crt, client_crt_len,
&(pTlsData->pkey), client_key, client_key_len, client_pwd, client_pwd_len))) {
printf(" failed ! ssl_client_init returned -0x%04x\n", -ret);
return ret;
}
/*
* 1. Start the connection
*/
printf("Connecting to /%s/%s...\n", addr, port);
#if defined(_PLATFORM_IS_LINUX_)
if (0 != (ret = mbedtls_net_connect_timeout(&(pTlsData->fd), addr, port, MBEDTLS_NET_PROTO_TCP,
SEND_TIMEOUT_SECONDS))) {
printf(" failed ! net_connect returned -0x%04x\n", -ret);
return ret;
}
#else
if (0 != (ret = mbedtls_net_connect(&(pTlsData->fd), addr, port, MBEDTLS_NET_PROTO_TCP))) {
printf(" failed ! net_connect returned -0x%04x\n", -ret);
return ret;
}
#endif
printf(" ok\n");
/*
* 2. Setup stuff
*/
printf(" . Setting up the SSL/TLS structure...\n");
if ((ret = mbedtls_ssl_config_defaults(&(pTlsData->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
printf(" failed! mbedtls_ssl_config_defaults returned %d\n", ret);
return ret;
}
mbedtls_ssl_conf_max_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_min_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
printf(" ok\n");
/* OPTIONAL is not optimal for security, but makes interop easier in this simplified example */
if (ca_crt != NULL) {
#if defined(FORCE_SSL_VERIFY)
mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
#else
mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
#endif
} else {
mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_NONE);
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_ssl_conf_ca_chain(&(pTlsData->conf), &(pTlsData->cacertl), NULL);
if ((ret = mbedtls_ssl_conf_own_cert(&(pTlsData->conf), &(pTlsData->clicert), &(pTlsData->pkey))) != 0) {
printf(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n", ret);
return ret;
}
#endif
mbedtls_ssl_conf_rng(&(pTlsData->conf), _ssl_random, NULL);
mbedtls_ssl_conf_dbg(&(pTlsData->conf), _ssl_debug, NULL);
mbedtls_ssl_conf_dbg(&(pTlsData->conf), _ssl_debug, stdout);
if ((ret = mbedtls_ssl_setup(&(pTlsData->ssl), &(pTlsData->conf))) != 0) {
printf("failed! mbedtls_ssl_setup returned %d\n", ret);
return ret;
}
#if defined(ON_PRE) || defined(ON_DAILY)
printf("SKIPPING mbedtls_ssl_set_hostname() when ON_PRE or ON_DAILY defined!\n");
#else
mbedtls_ssl_set_hostname(&(pTlsData->ssl), addr);
#endif
mbedtls_ssl_set_bio(&(pTlsData->ssl), &(pTlsData->fd), mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
#if defined(TLS_SAVE_TICKET)
if (NULL == saved_session) {
do {
int len = TLS_MAX_SESSION_BUF;
unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF);
if (save_buf == NULL) {
printf(" malloc failed\r\n");
break;
}
saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
if (saved_session == NULL) {
printf(" malloc failed\r\n");
HAL_Free(save_buf);
save_buf = NULL;
break;
}
memset(save_buf, 0x00, TLS_MAX_SESSION_BUF);
memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
ret = HAL_Kv_Get(KV_SESSION_KEY, save_buf, &len);
if (ret != 0 || len == 0) {
printf(" kv get failed len=%d,ret = %d\r\n", len, ret);
HAL_Free(saved_session);
HAL_Free(save_buf);
save_buf = NULL;
saved_session = NULL;
break;
}
ret = ssl_deserialize_session(saved_session, save_buf, len);
if (ret < 0) {
printf("ssl_deserialize_session err,ret = %d\r\n", ret);
HAL_Free(saved_session);
HAL_Free(save_buf);
save_buf = NULL;
saved_session = NULL;
break;
}
HAL_Free(save_buf);
} while (0);
}
if (NULL != saved_session) {
mbedtls_ssl_set_session(&(pTlsData->ssl), saved_session);
printf("use saved session!!\r\n");
}
#endif
/*
* 4. Handshake
*/
mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), 10000);
printf("Performing the SSL/TLS handshake...\n");
while ((ret = mbedtls_ssl_handshake(&(pTlsData->ssl))) != 0) {
if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
printf("failed ! mbedtls_ssl_handshake returned -0x%04x\n", -ret);
return ret;
}
}
printf(" ok\n");
#if defined(TLS_SAVE_TICKET)
if (NULL == saved_session) {
do {
size_t real_session_len = 0;
unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF); //for test
if (save_buf == NULL) {
break;
}
saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
if (NULL == saved_session) {
HAL_Free(save_buf);
break;
}
memset(save_buf, 0x00, sizeof(TLS_MAX_SESSION_BUF));
memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
ret = mbedtls_ssl_get_session(&(pTlsData->ssl), saved_session);
if (ret != 0) {
HAL_Free(save_buf);
HAL_Free(saved_session);
saved_session = NULL;
break;
}
ret = ssl_serialize_session(saved_session, save_buf, TLS_MAX_SESSION_BUF, &real_session_len);
printf("mbedtls_ssl_get_session_session return 0x%04x real_len=%d\r\n", ret, (int)real_session_len);
if (ret == 0) {
HAL_Kv_Set(KV_SESSION_KEY, (void *)save_buf, real_session_len, 1);
}
HAL_Free(save_buf);
} while (0);
}
#endif
/*
* 5. Verify the server certificate
*/
printf(" . Verifying peer X.509 certificate..\n");
if (0 != (ret = _real_confirm(mbedtls_ssl_get_verify_result(&(pTlsData->ssl))))) {
printf(" failed ! verify result not confirmed.\n");
return ret;
}
/* n->my_socket = (int)((n->tlsdataparams.fd).fd); */
/* WRITE_IOT_DEBUG_LOG("my_socket=%d", n->my_socket); */
return 0;
}
static int _network_ssl_read(TLSDataParams_t *pTlsData, char *buffer, int len, int timeout_ms)
{
uint32_t readLen = 0;
static int net_status = 0;
int ret = -1;
char err_str[33];
mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), timeout_ms);
while (readLen < len) {
ret = mbedtls_ssl_read(&(pTlsData->ssl), (unsigned char *)(buffer + readLen), (len - readLen));
if (ret > 0) {
readLen += ret;
net_status = 0;
} else if (ret == 0) {
/* if ret is 0 and net_status is -2, indicate the connection is closed during last call */
return (net_status == -2) ? net_status : readLen;
} else {
if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret) {
mbedtls_strerror(ret, err_str, sizeof(err_str));
printf("ssl recv error: code = %d, err_str = '%s'\n", ret, err_str);
net_status = -2; /* connection is closed */
break;
} else if ((MBEDTLS_ERR_SSL_TIMEOUT == ret)
|| (MBEDTLS_ERR_SSL_CONN_EOF == ret)
|| (MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED == ret)
|| (MBEDTLS_ERR_SSL_NON_FATAL == ret)) {
/* read already complete */
/* if call mbedtls_ssl_read again, it will return 0 (means EOF) */
return readLen;
} else {
mbedtls_strerror(ret, err_str, sizeof(err_str));
printf("ssl recv error: code = %d, err_str = '%s'\n", ret, err_str);
net_status = -1;
return -1; /* Connection error */
}
}
}
return (readLen > 0) ? readLen : net_status;
}
static int _network_ssl_write(TLSDataParams_t *pTlsData, const char *buffer, int len, int timeout_ms)
{
#if defined(_PLATFORM_IS_LINUX_)
int32_t res = 0;
int32_t write_bytes = 0;
uint64_t timestart_ms = 0, timenow_ms = 0;
struct timeval timestart, timenow, timeout;
if (pTlsData == NULL) {
return -1;
}
/* timeout */
timeout.tv_sec = timeout_ms/1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
/* Start Time */
gettimeofday(&timestart, NULL);
timestart_ms = timestart.tv_sec * 1000 + timestart.tv_usec / 1000;
timenow_ms = timestart_ms;
res = setsockopt(pTlsData->fd.fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
if (res < 0) {
return -1;
}
do {
gettimeofday(&timenow, NULL);
timenow_ms = timenow.tv_sec * 1000 + timenow.tv_usec / 1000;
if (timenow_ms - timestart_ms >= timenow_ms ||
timeout_ms - (timenow_ms - timestart_ms) > timeout_ms) {
break;
}
res = mbedtls_ssl_write(&(pTlsData->ssl), (unsigned char *)buffer + write_bytes, len - write_bytes);
if (res < 0) {
if (res != MBEDTLS_ERR_SSL_WANT_READ &&
res != MBEDTLS_ERR_SSL_WANT_WRITE) {
if (write_bytes == 0) {
return -1;
}
break;
}
}else if (res == 0) {
break;
}else{
write_bytes += res;
}
}while(((timenow_ms - timestart_ms) < timeout_ms) && (write_bytes < len));
return write_bytes;
#else
uint32_t writtenLen = 0;
int ret = -1;
if (pTlsData == NULL) {
return -1;
}
while (writtenLen < len) {
ret = mbedtls_ssl_write(&(pTlsData->ssl), (unsigned char *)(buffer + writtenLen), (len - writtenLen));
if (ret > 0) {
writtenLen += ret;
continue;
} else if (ret == 0) {
printf("ssl write timeout\n");
return 0;
} else {
char err_str[33];
mbedtls_strerror(ret, err_str, sizeof(err_str));
printf("ssl write fail, code=%d, str=%s\n", ret, err_str);
return -1; /* Connnection error */
}
}
return writtenLen;
#endif
}
static void _network_ssl_disconnect(TLSDataParams_t *pTlsData)
{
mbedtls_ssl_close_notify(&(pTlsData->ssl));
mbedtls_net_free(&(pTlsData->fd));
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt_free(&(pTlsData->cacertl));
if ((pTlsData->pkey).pk_info != NULL) {
printf("need release client crt&key\n");
#if defined(MBEDTLS_CERTS_C)
mbedtls_x509_crt_free(&(pTlsData->clicert));
mbedtls_pk_free(&(pTlsData->pkey));
#endif
}
#endif
mbedtls_ssl_free(&(pTlsData->ssl));
mbedtls_ssl_config_free(&(pTlsData->conf));
printf("ssl_disconnect\n");
}
int HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms)
{
return _network_ssl_read((TLSDataParams_t *)handle, buf, len, timeout_ms);;
}
int HAL_SSL_Write(uintptr_t handle, const char *buf, int len, int timeout_ms)
{
return _network_ssl_write((TLSDataParams_t *)handle, buf, len, timeout_ms);
}
int32_t HAL_SSL_Destroy(uintptr_t handle)
{
if ((uintptr_t)NULL == handle) {
printf("handle is NULL\n");
return 0;
}
_network_ssl_disconnect((TLSDataParams_t *)handle);
g_ssl_hooks.free((void *)handle);
return 0;
}
int ssl_hooks_set(ssl_hooks_t *hooks)
{
if (hooks == NULL || hooks->malloc == NULL || hooks->free == NULL) {
return -1;
}
g_ssl_hooks.malloc = hooks->malloc;
g_ssl_hooks.free = hooks->free;
return 0;
}
uintptr_t HAL_SSL_Establish(const char *host,
uint16_t port,
const char *ca_crt,
uint32_t ca_crt_len)
{
char port_str[6];
const char *alter = host;
TLSDataParams_pt pTlsData;
if (host == NULL || ca_crt == NULL) {
printf("input params are NULL, abort\n");
return 0;
}
if (!strlen(host) || (strlen(host) < 8)) {
printf("invalid host: '%s'(len=%d), abort\n", host, (int)strlen(host));
return 0;
}
pTlsData = g_ssl_hooks.malloc(sizeof(TLSDataParams_t));
if (NULL == pTlsData) {
return (uintptr_t)NULL;
}
memset(pTlsData, 0x0, sizeof(TLSDataParams_t));
sprintf(port_str, "%u", port);
#if defined(ON_PRE)
if (!strcmp(GUIDER_ONLINE_HOSTNAME, host)) {
printf("ALTERING '%s' to '%s' since ON_PRE defined!\n", host, GUIDER_PRE_ADDRESS);
alter = GUIDER_PRE_ADDRESS;
}
#endif
mbedtls_platform_set_calloc_free(_SSLCalloc_wrapper, _SSLFree_wrapper);
if (0 != _TLSConnectNetwork(pTlsData, alter, port_str, ca_crt, ca_crt_len, NULL, 0, NULL, 0, NULL, 0)) {
_network_ssl_disconnect(pTlsData);
g_ssl_hooks.free((void *)pTlsData);
return (uintptr_t)NULL;
}
return (uintptr_t)pTlsData;
}

View File

@@ -0,0 +1,58 @@
#ifndef _WRAPPERS_DEFS_H_
#define _WRAPPERS_DEFS_H_
#include "infra_types.h"
#include "infra_defs.h"
#define PLATFORM_WAIT_INFINITE (~0)
typedef struct {
void *(*malloc)(uint32_t size);
void (*free)(void *ptr);
} ssl_hooks_t;
typedef enum {
os_thread_priority_idle = -3, /* priority: idle (lowest) */
os_thread_priority_low = -2, /* priority: low */
os_thread_priority_belowNormal = -1, /* priority: below normal */
os_thread_priority_normal = 0, /* priority: normal (default) */
os_thread_priority_aboveNormal = 1, /* priority: above normal */
os_thread_priority_high = 2, /* priority: high */
os_thread_priority_realtime = 3, /* priority: realtime (highest) */
os_thread_priority_error = 0x84, /* system cannot determine priority or thread has illegal priority */
} hal_os_thread_priority_t;
typedef struct _hal_os_thread {
hal_os_thread_priority_t priority; /*initial thread priority */
void *stack_addr; /* thread stack address malloced by caller, use system stack by . */
int stack_size; /* stack size requirements in bytes; 0 is default stack size */
int detach_state; /* 0: not detached state; otherwise: detached state. */
char *name; /* thread name. */
} hal_os_thread_param_t;
#define DTLS_ERROR_BASE (1<<24)
#define DTLS_SUCCESS (0)
#define DTLS_INVALID_PARAM (DTLS_ERROR_BASE | 1)
#define DTLS_INVALID_CA_CERTIFICATE (DTLS_ERROR_BASE | 2)
#define DTLS_HANDSHAKE_IN_PROGRESS (DTLS_ERROR_BASE | 3)
#define DTLS_HANDSHAKE_FAILED (DTLS_ERROR_BASE | 4)
#define DTLS_FATAL_ALERT_MESSAGE (DTLS_ERROR_BASE | 5)
#define DTLS_PEER_CLOSE_NOTIFY (DTLS_ERROR_BASE | 6)
#define DTLS_SESSION_CREATE_FAILED (DTLS_ERROR_BASE | 7)
#define DTLS_READ_DATA_FAILED (DTLS_ERROR_BASE | 8)
typedef struct {
void *(*malloc)(uint32_t size);
void (*free)(void *ptr);
} dtls_hooks_t;
typedef struct {
unsigned char *p_ca_cert_pem;
char *p_host;
unsigned short port;
} coap_dtls_options_t;
typedef void DTLSContext;
#endif