Commit be59c2bf authored by 黄振令's avatar 黄振令

【修改内容】增加ota功能,platform那层未完成

【提交人】huang.zhenling
parent 7d63f2f6
...@@ -27,10 +27,12 @@ int _kk_sendto_cloud(cJSON *root) ...@@ -27,10 +27,12 @@ int _kk_sendto_cloud(cJSON *root)
pTopic = cJSON_GetObjectItem(root, "topic"); pTopic = cJSON_GetObjectItem(root, "topic");
if(pTopic == NULL){ if(pTopic == NULL){
printf("[%s][%d] topic is null \n",__FUNCTION__,__LINE__);
return; return;
} }
pData = cJSON_GetObjectItem(root, "payload"); pData = cJSON_GetObjectItem(root, "payload");
if(pData == NULL){ if(pData == NULL){
printf("[%s][%d] payload is null \n",__FUNCTION__,__LINE__);
return; return;
} }
printf("[%s][%d] topic:%s\n",__FUNCTION__,__LINE__,pTopic->valuestring); printf("[%s][%d] topic:%s\n",__FUNCTION__,__LINE__,pTopic->valuestring);
...@@ -46,6 +48,7 @@ void KK_Data_FromDev(void* str,int len) ...@@ -46,6 +48,7 @@ void KK_Data_FromDev(void* str,int len)
} }
root=cJSON_Parse((char*)str); root=cJSON_Parse((char*)str);
if(root == NULL){ if(root == NULL){
printf("[%s][%d] root is null \n",__FUNCTION__,__LINE__);
return; return;
} }
cmd = cJSON_GetObjectItem(root, "cmd"); cmd = cJSON_GetObjectItem(root, "cmd");
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include "cJSON.h" #include "cJSON.h"
const char KK_URI_SYS_PREFIX[] = "/sys/%s/%s/#"; const char KK_URI_SYS_PREFIX[] = "/sys/%s/%s/#";
const char KK_URI_OTA_PREFIX[] = "/ota/device/upgrade/%s/%s/#";
int KK_Subdev_Subscribe(const cJSON *root) int KK_Subdev_Subscribe(const cJSON *root)
{ {
...@@ -28,14 +30,20 @@ int KK_Subdev_Subscribe(const cJSON *root) ...@@ -28,14 +30,20 @@ int KK_Subdev_Subscribe(const cJSON *root)
if(productCode == NULL){ if(productCode == NULL){
return -1; return -1;
} }
url_len = strlen(KK_URI_SYS_PREFIX) + strlen(productType->valuestring) + strlen(productCode->valuestring) + 1; url_len = strlen(KK_URI_OTA_PREFIX) + strlen(productType->valuestring) + strlen(productCode->valuestring) + 1;
char *url = malloc(url_len); char *url = malloc(url_len);
if (url == NULL) { if (url == NULL) {
return -1; return -1;
} }
memset(url, 0, url_len);
snprintf(url, url_len, KK_URI_OTA_PREFIX, productType->valuestring, productCode->valuestring);
printf("ota [%s][%d] URL:%s\n",__FUNCTION__,__LINE__,url);
res = KK_MQTT_SubTopic(url);
memset(url, 0, url_len); memset(url, 0, url_len);
snprintf(url, url_len, KK_URI_SYS_PREFIX, productType->valuestring, productCode->valuestring); snprintf(url, url_len, KK_URI_SYS_PREFIX, productType->valuestring, productCode->valuestring);
printf("[%s][%d] URL:%s\n",__FUNCTION__,__LINE__,url); printf("sys [%s][%d] URL:%s\n",__FUNCTION__,__LINE__,url);
res = KK_MQTT_SubTopic(url); res = KK_MQTT_SubTopic(url);
free(url); free(url);
return res; return res;
...@@ -48,15 +56,21 @@ static int _kk_client_subscribe(char productType[PRODUCT_TYPE_LEN], char product ...@@ -48,15 +56,21 @@ static int _kk_client_subscribe(char productType[PRODUCT_TYPE_LEN], char product
int url_len = 0; int url_len = 0;
printf("[%s][%d] \n",__FUNCTION__,__LINE__); printf("[%s][%d] \n",__FUNCTION__,__LINE__);
url_len = strlen(KK_URI_SYS_PREFIX) + strlen(productType) + strlen(productCode) + 1; url_len = strlen(KK_URI_OTA_PREFIX) + strlen(productType) + strlen(productCode) + 1;
char *url = malloc(url_len); char *url = malloc(url_len);
if (url == NULL) { if (url == NULL) {
return -1; return -1;
} }
memset(url, 0, url_len);
snprintf(url, url_len, KK_URI_OTA_PREFIX, productType, productCode);
printf("ota [%s][%d] URL:%s\n",__FUNCTION__,__LINE__,url);
res = KK_MQTT_SubTopic(url);
memset(url, 0, url_len); memset(url, 0, url_len);
snprintf(url, url_len, KK_URI_SYS_PREFIX, productType, productCode); snprintf(url, url_len, KK_URI_SYS_PREFIX, productType, productCode);
printf("[%s][%d] URL:%s\n",__FUNCTION__,__LINE__,url); printf("sys [%s][%d] URL:%s\n",__FUNCTION__,__LINE__,url);
res = KK_MQTT_SubTopic(url); res = KK_MQTT_SubTopic(url);
......
...@@ -352,16 +352,23 @@ void HAL_ThreadDelete(_IN_ void *thread_handle) ...@@ -352,16 +352,23 @@ void HAL_ThreadDelete(_IN_ void *thread_handle)
pthread_join((pthread_t)thread_handle, 0); pthread_join((pthread_t)thread_handle, 0);
} }
} }
#if 0 #if 1
static FILE *fp; static FILE *fp;
#define otafilename "/tmp/alinkota.bin" #define otafilename "/tmp/kkota.bin"
#define __DEMO__
void HAL_Firmware_Persistence_Start(void) void HAL_Firmware_Persistence_Start(void* fileName)
{ {
#ifdef __DEMO__ #ifdef __DEMO__
fp = fopen(otafilename, "w"); char * file = NULL;
if (fileName == NULL){
file = otafilename;
}else{
file = fileName;
}
fp = fopen(file, "w");
// assert(fp); // assert(fp);
#endif #endif
return; return;
......
/*
* 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;
}
/*
*
*/
//#include "../dm/iotx_dm_internal.h"
#include "dm_fota.h"
#include "../ota/ota_api.h"
#define dm_log_err printf
#define dm_log_debug printf
#define dm_log_info printf
static dm_fota_ctx_t g_dm_fota_ctx;
static dm_fota_ctx_t *_dm_fota_get_ctx(void)
{
return &g_dm_fota_ctx;
}
int dm_fota_init(void)
{
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
memset(ctx, 0, sizeof(dm_fota_ctx_t));
return SUCCESS_RETURN;
}
int dm_fota_deinit(void)
{
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
memset(ctx, 0, sizeof(dm_fota_ctx_t));
return SUCCESS_RETURN;
}
static int _dm_fota_send_new_config_to_user(void *ota_handle)
{
int res = 0, message_len = 0;
char *message = NULL;
char version[128] = {0};
const char *fota_new_config_fmt = "{\"version\":\"%s\"}";
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_VERSION, version, 128);
message_len = strlen(fota_new_config_fmt) + strlen(version) + 1;
message = malloc(message_len);
if (message == NULL) {
return MEMORY_NOT_ENOUGH;
}
memset(message, 0, message_len);
HAL_Snprintf(message, message_len, fota_new_config_fmt, version);
dm_log_info("Send To User: %s", message);
//res = _dm_msg_send_to_user(IOTX_DM_EVENT_FOTA_NEW_FIRMWARE, message);
if (res != SUCCESS_RETURN) {
if (message) {
free(message);
}
return FAIL_RETURN;
}
return SUCCESS_RETURN;
}
int dm_fota_perform_sync(_OU_ char *output, _IN_ int output_len)
{
int res = 0, file_download = 0;
uint32_t file_size = 0, file_downloaded = 0;
uint64_t percent_pre = 0, percent_now = 0;
unsigned long long report_pre = 0, report_now = 0;
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
void *ota_handle = NULL;
uint32_t ota_type = IOT_OTAT_NONE;
int ret = 0;
if (output == NULL || output_len <= 0) {
return INVALID_PARAMETER;
}
/* Get Ota Handle */
res = dm_ota_get_ota_handle(&ota_handle);
if (res != SUCCESS_RETURN) {
return FAIL_RETURN;
}
if (ota_handle == NULL) {
return FAIL_RETURN;
}
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
if (ota_type != IOT_OTAT_FOTA) {
return FAIL_RETURN;
}
/* reset the size_fetched in ota_handle to be 0 */
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_FETCHED_SIZE, ota_handle, 4);
/* Prepare Write Data To Storage */
HAL_Firmware_Persistence_Start(NULL);
while (1) {
file_download = IOT_OTA_FetchYield(ota_handle, output, output_len, 1);
if (file_download < 0) {
IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_FETCH_FAILED, NULL);
HAL_Firmware_Persistence_Stop();
ctx->is_report_new_config = 0;
return FAIL_RETURN;
}
/* Write Config File Into Stroage */
ret = HAL_Firmware_Persistence_Write(output, file_download);
if (-1 == ret) {
IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_BURN_FAILED, NULL);
dm_log_err("Fota write firmware failed");
HAL_Firmware_Persistence_Stop();
ctx->is_report_new_config = 0;
return FAIL_RETURN;
}
/* Get OTA information */
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FETCHED_SIZE, &file_downloaded, 4);
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FILE_SIZE, &file_size, 4);
/* Calculate Download Percent And Update Report Timestamp*/
percent_now = (file_downloaded * 100) / file_size;
report_now = HAL_UptimeMs();
/* Report Download Process To Cloud */
if (report_now < report_pre) {
report_pre = report_now;
}
if ((((percent_now - percent_pre) > 5) &&
((report_now - report_pre) > 50)) || (percent_now >= IOT_OTAP_FETCH_PERCENTAGE_MAX)) {
IOT_OTA_ReportProgress(ota_handle, percent_now, NULL);
percent_pre = percent_now;
report_pre = report_now;
}
/* Check If OTA Finished */
if (IOT_OTA_IsFetchFinish(ota_handle)) {
uint32_t file_isvalid = 0;
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_CHECK_FIRMWARE, &file_isvalid, 4);
if (file_isvalid == 0) {
HAL_Firmware_Persistence_Stop();
IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_CHECK_FALIED, NULL);
ctx->is_report_new_config = 0;
return FAIL_RETURN;
} else {
break;
}
}
}
HAL_Firmware_Persistence_Stop();
ctx->is_report_new_config = 0;
return SUCCESS_RETURN;
}
int dm_fota_status_check(void)
{
int res = 0;
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
void *ota_handle = NULL;
/* Get Ota Handle */
res = dm_ota_get_ota_handle(&ota_handle);
if (res != SUCCESS_RETURN) {
return FAIL_RETURN;
}
if (IOT_OTA_IsFetching(ota_handle)) {
uint32_t ota_type = IOT_OTAT_NONE;
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
if (ota_type == IOT_OTAT_FOTA) {
/* Send New Config Information To User */
if (ctx->is_report_new_config == 0) {
dm_log_debug("Fota Status Check");
res = _dm_fota_send_new_config_to_user(ota_handle);
if (res == SUCCESS_RETURN) {
ctx->is_report_new_config = 1;
}
}
}
}
return SUCCESS_RETURN;
}
int dm_fota_request_image(const char *version, int buffer_len)
{
int res = 0;
void *ota_handle = NULL;
char *version_str = NULL;
if (NULL == version || buffer_len <= 0) {
dm_log_info("invalid input");
return FAIL_RETURN;
}
/* Get Ota Handle */
res = dm_ota_get_ota_handle(&ota_handle);
if (res != SUCCESS_RETURN) {
return FAIL_RETURN;
}
version_str = malloc(buffer_len + 1);
if (NULL == version_str) {
dm_log_info("failed to malloc");
return FAIL_RETURN;
}
memset(version_str, 0, buffer_len + 1);
memcpy(version_str, version, buffer_len);
res = iotx_req_image(ota_handle, version_str);
free(version_str);
return res;
}
/*
*
*/
#ifndef _DM_FOTA_H_
#define _DM_FOTA_H_
#include "kk_tsl_common.h"
typedef struct {
int is_report_new_config;
} dm_fota_ctx_t;
int dm_fota_init(void);
int dm_fota_deinit(void);
int dm_fota_perform_sync(_OU_ char *output, _IN_ int output_len);
int dm_fota_status_check(void);
int dm_fota_request_image(_IN_ const char *version, _IN_ int buffer_len);
#endif
/*
*
*/
#include "iotx_ota_internal.h"
#include "dm_ota.h"
#include "cJSON.h"
#include "kk_dm_api.h"
static dm_ota_ctx_t g_dm_ota_ctx;
static dm_ota_ctx_t *_dm_ota_get_ctx(void)
{
return &g_dm_ota_ctx;
}
int dm_ota_init(void)
{
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
memset(ctx, 0, sizeof(dm_ota_ctx_t));
HAL_GetProduct_Type(ctx->product_key);
HAL_GetProduct_Code(ctx->device_name);
return SUCCESS_RETURN;
}
int dm_ota_sub(void)
{
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
void *handle = NULL;
/* Init OTA Handle */
handle = IOT_OTA_Init(ctx->product_key, ctx->device_name, NULL);
if (handle == NULL) {
return FAIL_RETURN;
}
ctx->ota_handle = handle;
return SUCCESS_RETURN;
}
int ota_uri_parse_pkdn(_IN_ char *uri, _IN_ int uri_len, _IN_ int start_deli, _IN_ int end_deli,
_OU_ char product_key[PRODUCT_KEY_MAXLEN], _OU_ char device_name[DEVICE_NAME_MAXLEN])
{
int res = 0, start = 0, end = 0, slice = 0;
int item_index = 0;
int count = 0;
if (uri == NULL || uri_len <= 0 || product_key == NULL || device_name == NULL ||
(strlen(product_key) >= PRODUCT_KEY_MAXLEN) || (strlen(device_name) >= DEVICE_NAME_MAXLEN)) {
return INVALID_PARAMETER;
}
for (item_index = 0; item_index < uri_len; item_index++) {
if (uri[item_index] == '/' && (item_index + 1) < uri_len) {
count++;
if (count == start_deli) {
start = item_index;
}else if (count == start_deli + 1){
slice = item_index;
}else if (count == end_deli){
end = item_index;
}
}
}
if (end == 0){
end = item_index;
}
/* dm_log_debug("URI Product Key: %.*s, Device Name: %.*s", slice - start - 1, uri + start + 1, end - slice - 1,
uri + slice + 1); */
memcpy(product_key, uri + start + 1, slice - start - 1);
memcpy(device_name, uri + slice + 1, end - slice - 1);
return SUCCESS_RETURN;
}
int dm_ota_setPKN(void* topic)
{
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
char product_key[PRODUCT_KEY_MAXLEN] = {0};
char device_name[DEVICE_NAME_MAXLEN] = {0};
int res = 0;
//ota topic:/ota/device/upgrade/{product_key}/{device_name}
res =ota_uri_parse_pkdn((char *)topic, strlen(topic), 4, 6, product_key,
device_name);
if (res != SUCCESS_RETURN) {
printf("dm_ota_setPKN error \n");
return FAIL_RETURN;
}
memset(ctx->product_key, 0, PRODUCT_KEY_MAXLEN);
memset(ctx->device_name, 0, DEVICE_NAME_MAXLEN);
memcpy(ctx->product_key, product_key, PRODUCT_KEY_MAXLEN);
memcpy(ctx->device_name, device_name, DEVICE_NAME_MAXLEN);
return SUCCESS_RETURN;
}
int dm_ota_deinit(void)
{
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
if (ctx->ota_handle) {
IOT_OTA_Deinit(ctx->ota_handle);
ctx->ota_handle = NULL;
}
return SUCCESS_RETURN;
}
#if 0
int dm_ota_switch_device(int devid)
{
char pk[PRODUCT_KEY_MAXLEN] = {0};
char dn[DEVICE_NAME_MAXLEN] = {0};
char ds[DEVICE_SECRET_MAXLEN] = {0};
int ret = dm_mgr_search_device_by_devid(devid, pk, dn, ds);
void *ota_handle = NULL;
int res = -1;
dm_ota_ctx_t *ctx = NULL;
if (SUCCESS_RETURN != ret) {
dm_log_err("could not find device by id, ret is %d", ret);
return FAIL_RETURN;
}
dm_log_info("do subdevice ota, pk, dn is %s, %s", pk, dn);
ota_handle = NULL;
res = dm_ota_get_ota_handle(&ota_handle);
if (res != SUCCESS_RETURN) {
return FAIL_RETURN;
}
/* if currently a device is doing OTA, do not interrupt */
if (IOT_OTA_IsFetching(ota_handle)) {
dm_log_info("OTA is processing, can not switch to another device");
return FAIL_RETURN;
}
dm_ota_deinit();
ctx = _dm_ota_get_ctx();
memset(ctx, 0, sizeof(dm_ota_ctx_t));
memcpy(ctx->product_key, pk, strlen(pk) + 1);
memcpy(ctx->device_name, dn, strlen(dn) + 1);
ret = dm_ota_sub();
if (ret < 0) {
dm_log_err("dm_ota_sub ret is %d, %s, %s\n", ret, pk, dn);
}
return ret;
}
#endif
int dm_ota_get_ota_handle(void **handle)
{
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
if (handle == NULL || *handle != NULL) {
return FAIL_RETURN;
}
if (ctx->ota_handle == NULL) {
return FAIL_RETURN;
}
*handle = ctx->ota_handle;
return SUCCESS_RETURN;
}
void dm_ota_handle(void *data){
printf("dm_ota_handle ================== [%s]\n",data);
char *out;
int res = 0;
cJSON *json;
cJSON *topic;
cJSON *payload;
json=cJSON_Parse(data);
if (!json) {
printf("Error before: [%s]\n","cJSON_Parse");
}
else{
topic = cJSON_GetObjectItem(json, "topic");
payload = cJSON_GetObjectItem(json, "payload");
printf("topic: [%s] ,payload= %s \n",topic->valuestring,payload->valuestring );
if (strstr(topic->valuestring, "/ota/device/upgrade") != NULL){
char buf[128] = {0};
int len = 128;
if (dm_ota_check(payload->valuestring, strlen(payload->valuestring)+1, IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE) == 0){
dm_ota_setPKN(topic->valuestring);
dm_fota_perform_sync(buf, len);
}else{
printf("parse params error !! \n");
}
}else {
printf("invaild ota topic: [%s]\n", topic->valuestring);
}
cJSON_Delete(json);
}
}
int dm_ota_check(void* payload, int len, iotx_ota_topic_types_t type){
void *ota_handle = NULL;
void* otaHandle = NULL;
dm_ota_get_ota_handle(&otaHandle);
return ota_callback(otaHandle, payload, len,type);
}
int dm_ota_yield(int timeout_ms)
{
void *data = NULL;
int count = 0;
if (timeout_ms <= 0) {
return INVALID_PARAMETER;
}
while (CONFIG_DISPATCH_QUEUE_MAXLEN == 0 || count++ < CONFIG_DISPATCH_QUEUE_MAXLEN) {
if (dm_queue_msg_next3(&data) == SUCCESS_RETURN) {
//dm_queue_msg_t *msg = (dm_queue_msg_t *)data;
printf("dm_ota_yield call \n");
dm_ota_handle(data);
free(data);
data = NULL;
} else {
break;
}
}
usleep(timeout_ms*1000);
return SUCCESS_RETURN;
}
/*
*
*/
#ifndef _DM_OTA_H_
#define _DM_OTA_H_
#include "kk_tsl_common.h"
typedef struct {
void *ota_handle;
char product_key[PRODUCT_KEY_MAXLEN];
char device_name[DEVICE_NAME_MAXLEN];
} dm_ota_ctx_t;
int dm_ota_init(void);
int dm_ota_sub(void);
int dm_ota_deinit(void);
int dm_ota_get_ota_handle(void **handle);
int dm_ota_switch_device(int devid);
#endif
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "kk_tsl_common.h" #include "kk_tsl_common.h"
#include "kk_dm_mng.h" #include "kk_dm_mng.h"
#include "com_api.h" #include "com_api.h"
#include "dm_ota.h"
static dm_api_ctx_t g_dm_api_ctx; static dm_api_ctx_t g_dm_api_ctx;
...@@ -96,7 +98,7 @@ int iotx_dm_subdev_topo_del(_IN_ int devid) ...@@ -96,7 +98,7 @@ int iotx_dm_subdev_topo_del(_IN_ int devid)
int res = 0; int res = 0;
if (devid < 0) { if (devid < 0) {
return DM_INVALID_PARAMETER; return INVALID_PARAMETER;
} }
_dm_api_lock(); _dm_api_lock();
...@@ -128,7 +130,7 @@ int iotx_dm_subdev_logout(_IN_ int devid) ...@@ -128,7 +130,7 @@ int iotx_dm_subdev_logout(_IN_ int devid)
int res = 0; int res = 0;
if (devid < 0) { if (devid < 0) {
return DM_INVALID_PARAMETER; return INVALID_PARAMETER;
} }
_dm_api_lock(); _dm_api_lock();
...@@ -198,6 +200,77 @@ int iotx_dm_connect(_IN_ iotx_dm_event_callback cb) ...@@ -198,6 +200,77 @@ int iotx_dm_connect(_IN_ iotx_dm_event_callback cb)
return SUCCESS_RETURN; return SUCCESS_RETURN;
} }
int iotx_dm_open(void)
{
int res = 0;
dm_api_ctx_t *ctx = _dm_api_get_ctx();
memset(ctx, 0, sizeof(dm_api_ctx_t));
/* DM Mutex Create*/
ctx->mutex = HAL_MutexCreate();
if (ctx->mutex == NULL) {
return MEMORY_NOT_ENOUGH;
}
/* DM OTA Module Init */
res = dm_ota_init();
if (res != SUCCESS_RETURN) {
goto ERROR;
}
/* DM Cloud Message Parse And Assemble Module Init */
//res = dm_msg_init();
//if (res != SUCCESS_RETURN) {
// goto ERROR;
//}
/* DM QUEUE Module Init */
res = dm_queue_init(CONFIG_DISPATCH_QUEUE_MAXLEN);
if (res != SUCCESS_RETURN) {
return FAIL_RETURN;
}
/* DM Manager Module Init */
res = dm_mgr_init();
if (res != SUCCESS_RETURN) {
goto ERROR;
}
/* DM OTA Module Init */
res = dm_ota_sub();
if (res == SUCCESS_RETURN) {
/* DM Config OTA Module Init */
//dm_cota_init();
/* DM Firmware OTA Mudule Init */
dm_fota_init();
}
return SUCCESS_RETURN;
ERROR:
dm_mgr_deinit();
dm_queue_deinit();
//dm_msg_deinit();
dm_ota_deinit();
if (ctx->mutex) {
HAL_MutexDestroy(ctx->mutex);
}
return FAIL_RETURN;
}
int iotx_dm_subscribe(_IN_ int devid) int iotx_dm_subscribe(_IN_ int devid)
{ {
int res = 0, dev_type = 0; int res = 0, dev_type = 0;
...@@ -241,4 +314,18 @@ int iotx_dm_subscribe(_IN_ int devid) ...@@ -241,4 +314,18 @@ int iotx_dm_subscribe(_IN_ int devid)
return SUCCESS_RETURN; return SUCCESS_RETURN;
} }
void kk_dm_ota_send(void *data, int len){
dm_queue_msg_insert3(data);
if (data != NULL){
void* buf = malloc(len);
memcpy(buf, data, len);
int res = dm_queue_msg_insert3((void *)buf);
if (res != SUCCESS_RETURN) {
free(buf);
return ;
}
}
}
/* /*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited *
*/ */
......
...@@ -356,6 +356,21 @@ int dm_mgr_get_devId_by_mac(_IN_ char device_mac[DEVICE_MAC_MAXLEN],_OU_ int *de ...@@ -356,6 +356,21 @@ int dm_mgr_get_devId_by_mac(_IN_ char device_mac[DEVICE_MAC_MAXLEN],_OU_ int *de
return SUCCESS_RETURN; return SUCCESS_RETURN;
} }
static void _dm_mgr_destroy_devlist(void)
{
dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
dm_mgr_dev_node_t *del_node = NULL;
dm_mgr_dev_node_t *next_node = NULL;
list_for_each_entry_safe(del_node, next_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
list_del(&del_node->linked_list);
//dm_shw_destroy(&del_node->dev_shadow);
free(del_node);
}
}
int dm_mgr_init(void) int dm_mgr_init(void)
{ {
int res = 0; int res = 0;
...@@ -398,6 +413,23 @@ ERROR: ...@@ -398,6 +413,23 @@ ERROR:
memset(ctx, 0, sizeof(dm_mgr_ctx)); memset(ctx, 0, sizeof(dm_mgr_ctx));
return FAIL_RETURN; return FAIL_RETURN;
} }
int dm_mgr_deinit(void)
{
dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
_dm_mgr_mutex_lock();
_dm_mgr_destroy_devlist();
_dm_mgr_mutex_unlock();
if (ctx->mutex) {
HAL_MutexDestroy(ctx->mutex);
}
return SUCCESS_RETURN;
}
const char DM_MSG_THING_UPSTREAM_REQUEST_PARAMS[] DM_READ_ONLY = const char DM_MSG_THING_UPSTREAM_REQUEST_PARAMS[] DM_READ_ONLY =
"{\"value\":%s,\"timestamp\":\"%s\"}"; "{\"value\":%s,\"timestamp\":\"%s\"}";
static int _dm_mgr_upstream_request_assemble(_IN_ int msgid, _IN_ int devid, _IN_ const char *service_prefix, static int _dm_mgr_upstream_request_assemble(_IN_ int msgid, _IN_ int devid, _IN_ const char *service_prefix,
......
...@@ -31,6 +31,15 @@ static void _dm_queue_lock2(void) ...@@ -31,6 +31,15 @@ static void _dm_queue_lock2(void)
} }
} }
static void _dm_queue_lock3(void)
{
dm_queue_t *ctx = _dm_queue_get_ctx();
if (ctx->mutex3) {
HAL_MutexLock(ctx->mutex3);
}
}
static void _dm_queue_unlock(void) static void _dm_queue_unlock(void)
{ {
...@@ -47,6 +56,15 @@ static void _dm_queue_unlock2(void) ...@@ -47,6 +56,15 @@ static void _dm_queue_unlock2(void)
} }
} }
static void _dm_queue_unlock3(void)
{
dm_queue_t *ctx = _dm_queue_get_ctx();
if (ctx->mutex3) {
HAL_MutexUnlock(ctx->mutex3);
}
}
int dm_queue_init(int max_size) int dm_queue_init(int max_size)
{ {
...@@ -66,11 +84,19 @@ int dm_queue_init(int max_size) ...@@ -66,11 +84,19 @@ int dm_queue_init(int max_size)
return INVALID_PARAMETER; return INVALID_PARAMETER;
} }
/* Create Mutex */
ctx->mutex3 = HAL_MutexCreate();
if (ctx->mutex3 == NULL) {
return INVALID_PARAMETER;
}
/* Init List */ /* Init List */
ctx->msg_list.max_size = max_size; ctx->msg_list.max_size = max_size;
INIT_LIST_HEAD(&ctx->msg_list.message_list); INIT_LIST_HEAD(&ctx->msg_list.message_list);
ctx->msg_list2.max_size = max_size; ctx->msg_list2.max_size = max_size;
INIT_LIST_HEAD(&ctx->msg_list2.message_list); INIT_LIST_HEAD(&ctx->msg_list2.message_list);
ctx->msg_list3.max_size = max_size;
INIT_LIST_HEAD(&ctx->msg_list3.message_list);
return SUCCESS_RETURN; return SUCCESS_RETURN;
} }
...@@ -121,6 +147,23 @@ void dm_queue_deinit(void) ...@@ -121,6 +147,23 @@ void dm_queue_deinit(void)
free(del_node); free(del_node);
} }
del_node = NULL;
next_node = NULL;
del_msg = NULL;
list_for_each_entry_safe(del_node, next_node, &ctx->msg_list3.message_list, linked_list, dm_queue_msg_node_t) {
/* Free Message */
del_msg = (dm_queue_msg_t *)del_node->data;
if (del_msg->data) {
free(del_msg->data);
}
free(del_msg);
del_msg = NULL;
/* Free Node */
list_del(&del_node->linked_list);
free(del_node);
}
} }
...@@ -245,3 +288,64 @@ int dm_queue_msg_next2(void **data) ...@@ -245,3 +288,64 @@ int dm_queue_msg_next2(void **data)
} }
int dm_queue_msg_insert3(void *data)
{
dm_queue_t *ctx = _dm_queue_get_ctx();
dm_queue_msg_node_t *node = NULL;
if (data == NULL) {
return INVALID_PARAMETER;
}
_dm_queue_lock3();
printf("dm msg list size: %d, max size: %d", ctx->msg_list3.size, ctx->msg_list3.max_size);
if (ctx->msg_list3.size >= ctx->msg_list3.max_size) {
printf("dm queue list full");
_dm_queue_unlock3();
return FAIL_RETURN;
}
node = malloc(sizeof(dm_queue_msg_node_t));
if (node == NULL) {
_dm_queue_unlock3();
return MEMORY_NOT_ENOUGH;
}
memset(node, 0, sizeof(dm_queue_msg_node_t));
node->data = data;
INIT_LIST_HEAD(&node->linked_list);
ctx->msg_list3.size++;
list_add_tail(&node->linked_list, &ctx->msg_list3.message_list);
_dm_queue_unlock3();
return SUCCESS_RETURN;
}
int dm_queue_msg_next3(void **data)
{
dm_queue_t *ctx = _dm_queue_get_ctx();
dm_queue_msg_node_t *node = NULL;
if (data == NULL || *data != NULL) {
return INVALID_PARAMETER;
}
_dm_queue_lock3();
if (list_empty(&ctx->msg_list3.message_list)) {
_dm_queue_unlock3();
return FAIL_RETURN;
}
node = list_first_entry(&ctx->msg_list3.message_list, dm_queue_msg_node_t, linked_list);
list_del(&node->linked_list);
ctx->msg_list3.size--;
*data = node->data;
free(node);
_dm_queue_unlock3();
return SUCCESS_RETURN;
}
...@@ -29,8 +29,10 @@ typedef struct { ...@@ -29,8 +29,10 @@ typedef struct {
typedef struct { typedef struct {
void *mutex; void *mutex;
void *mutex2; void *mutex2;
void *mutex3;
dm_queue_msg_list_t msg_list; dm_queue_msg_list_t msg_list;
dm_queue_msg_list_t msg_list2; dm_queue_msg_list_t msg_list2;
dm_queue_msg_list_t msg_list3;
} dm_queue_t; } dm_queue_t;
int dm_queue_init(int max_size); int dm_queue_init(int max_size);
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#define IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS 10000 #define IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS 10000
#define dm_log_err printf #define dm_log_err printf
#define dm_log_debug printf #define dm_log_debug printf
#define dm_log_info printf
...@@ -228,7 +230,9 @@ static void _iotx_linkkit_event_callback(iotx_dm_event_types_t type, char *data) ...@@ -228,7 +230,9 @@ static void _iotx_linkkit_event_callback(iotx_dm_event_types_t type, char *data)
printf("_iotx_linkkit_event_callback ================== [%s]\n",data); printf("_iotx_linkkit_event_callback ================== [%s]\n",data);
char *out; char *out;
int res = 0; int res = 0;
cJSON *json, *topic, *payload; cJSON *json;
cJSON *topic;
cJSON *payload;
json=cJSON_Parse(data); json=cJSON_Parse(data);
if (!json) { if (!json) {
...@@ -284,6 +288,10 @@ static void _iotx_linkkit_event_callback(iotx_dm_event_types_t type, char *data) ...@@ -284,6 +288,10 @@ static void _iotx_linkkit_event_callback(iotx_dm_event_types_t type, char *data)
printf("property set reply \n"); printf("property set reply \n");
dm_msg_thing_property_set_reply(topic->valuestring, payload->valuestring, strlen(payload->valuestring), NULL); dm_msg_thing_property_set_reply(topic->valuestring, payload->valuestring, strlen(payload->valuestring), NULL);
//kk_tsl_service_property_set(topic->valuestring, payload->valuestring, strlen(payload->valuestring), NULL); //kk_tsl_service_property_set(topic->valuestring, payload->valuestring, strlen(payload->valuestring), NULL);
}else if (strstr(topic->valuestring, "/ota/device/upgrade") != NULL){
printf("ota upgrade... \n");
kk_dm_ota_send(data, strlen(data)+1);
}else{ }else{
printf("Error 222222222222222 \n"); printf("Error 222222222222222 \n");
...@@ -946,9 +954,10 @@ int kk_init_dmproc(){ ...@@ -946,9 +954,10 @@ int kk_init_dmproc(){
int res = 0; int res = 0;
iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx(); iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
/* DM QUEUE Module Init */ res = iotx_dm_open();
res = dm_queue_init(CONFIG_DISPATCH_QUEUE_MAXLEN);
if (res != SUCCESS_RETURN) { if (res != SUCCESS_RETURN) {
dm_log_err("DM iotx_dm_open Failed");
return FAIL_RETURN; return FAIL_RETURN;
} }
......
...@@ -47,7 +47,8 @@ void mid_cb(void* data, int len){ ...@@ -47,7 +47,8 @@ void mid_cb(void* data, int len){
if (topic != NULL && (strstr(topic->valuestring, "register_reply") != NULL || if (topic != NULL && (strstr(topic->valuestring, "register_reply") != NULL ||
strstr(topic->valuestring, "add_reply") != NULL || strstr(topic->valuestring, "add_reply") != NULL ||
strstr(topic->valuestring, "login_reply") != NULL || strstr(topic->valuestring, "login_reply") != NULL ||
strstr(topic->valuestring, "offline_reply") != NULL)) strstr(topic->valuestring, "offline_reply") != NULL ||
strstr(topic->valuestring, "/ota/device/upgrade") != NULL))
{ {
printf("This topic don't send to platform: %s \r\n", topic->valuestring); printf("This topic don't send to platform: %s \r\n", topic->valuestring);
return; return;
...@@ -158,51 +159,6 @@ void kk_platMsg_dispatch(void) ...@@ -158,51 +159,6 @@ void kk_platMsg_dispatch(void)
} }
#define MYPORT 5555
#define BUFFER_SIZE 1024
void test_tcp(){
///定义sockfd
int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip
///连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("connect");
exit(1);
}
char sendbuf[BUFFER_SIZE]={0};
char recvbuf[BUFFER_SIZE];
//printf("midd: %s send \r\n", sendbuf);
//send(sock_cli, sendbuf, strlen(sendbuf),0);
while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
printf("midd: %s send \r\n", sendbuf);
send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送
if(strcmp(sendbuf,"exit\n")==0)
break;
//printf("midd: %s send \r\n", sendbuf);
recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收
fputs(recvbuf, stdout);
memset(sendbuf, 0, sizeof(sendbuf));
memset(recvbuf, 0, sizeof(recvbuf));
}
close(sock_cli);
}
time_t getSysTime(){ time_t getSysTime(){
time_t t; time_t t;
t = time(NULL); t = time(NULL);
...@@ -218,7 +174,9 @@ typedef struct { ...@@ -218,7 +174,9 @@ typedef struct {
int subdev_index; int subdev_index;
int permit_join; int permit_join;
void *g_mid_dispatch_thread; void *g_mid_dispatch_thread;
void *g_ota_dispatch_thread;
int g_mid_dispatch_thread_running; int g_mid_dispatch_thread_running;
int g_ota_dispatch_thread_running;
} mid_ctx_t; } mid_ctx_t;
#define MID_YIELD_TIMEOUT_MS (200) #define MID_YIELD_TIMEOUT_MS (200)
...@@ -241,6 +199,21 @@ void *mid_dispatch_yield(void *args) ...@@ -241,6 +199,21 @@ void *mid_dispatch_yield(void *args)
return NULL; return NULL;
} }
void *ota_dispatch_yield(void *args)
{
mid_ctx_t *mid_ctx = kk_mid_get_ctx();
while (mid_ctx->g_ota_dispatch_thread_running) {
dm_ota_yield(MID_YIELD_TIMEOUT_MS);
}
return NULL;
}
static int kk_set_product_info(void) static int kk_set_product_info(void)
{ {
HAL_SetProduct_Type(PRODUCT_TPYE); HAL_SetProduct_Type(PRODUCT_TPYE);
...@@ -262,7 +235,7 @@ int main(const int argc, const char **argv) ...@@ -262,7 +235,7 @@ int main(const int argc, const char **argv)
kk_tsl_api_init(); kk_tsl_api_init();
kk_ipc_init(IPC_MID2APP, mid_cb); kk_ipc_init(IPC_MID2APP, mid_cb);
kk_ipc_init(IPC_MID2PLAT, mid2p_cb); kk_ipc_init(IPC_MID2PLAT, mid2p_cb);
dm_mgr_init();
//DB_Init(); //DB_Init();
//test_tcp(); //test_tcp();
...@@ -282,6 +255,13 @@ int main(const int argc, const char **argv) ...@@ -282,6 +255,13 @@ int main(const int argc, const char **argv)
IOT_Linkkit_Close(mid_ctx->master_devid); IOT_Linkkit_Close(mid_ctx->master_devid);
return -1; return -1;
} }
mid_ctx->g_ota_dispatch_thread_running = 1;
res = pthread_create(&mid_ctx->g_ota_dispatch_thread, NULL, ota_dispatch_yield, NULL);
if (res < 0) {
printf("HAL_ThreadCreate Failed\n");
IOT_Linkkit_Close(mid_ctx->master_devid);
return -1;
}
int ct = 0; int ct = 0;
for (;;) { for (;;) {
......
/*
*
*/
#include "iotx_ota_internal.h"
#include "com_api.h"
#include "cJSON.h"
/*#if (OTA_SIGNAL_CHANNEL) == 1
#include "ota_mqtt.c"
#elif (OTA_SIGNAL_CHANNEL) == 2
#include "ota_coap.c"
#else
#error "NOT support yet!"
#endif*/
typedef struct {
const char *product_key; /* point to product key */
const char *device_name; /* point to device name */
uint32_t id; /* message id */
IOT_OTA_State_t state; /* OTA state */
IOT_OTA_Type_t type; /* OTA Type */
uint32_t size_last_fetched; /* size of last downloaded */
uint32_t size_fetched; /* size of already downloaded */
uint32_t size_file; /* size of file */
char *purl; /* point to URL */
char *version; /* point to string */
char md5sum[33]; /* MD5 string */
void *md5; /* MD5 handle */
void *sha256; /* Sha256 handle */
void *ch_signal; /* channel handle of signal exchanged with OTA server */
void *ch_fetch; /* channel handle of download */
/* cota */
char *configId;
uint32_t configSize;
char *sign;
char *signMethod;
char *cota_url;
char *getType;
int err; /* last error code */
ota_fetch_cb_fpt fetch_cb; /* fetch_callback */
void *user_data; /* fetch_callback's user_data */
cota_fetch_cb_fpt fetch_cota_cb;
void *cota_user_data;
} OTA_Struct_t, *OTA_Struct_pt;
/* check whether the progress state is valid or not */
/* return: true, valid progress state; false, invalid progress state. */
static int ota_check_progress(IOT_OTA_Progress_t progress)
{
return ((progress >= IOT_OTAP_BURN_FAILED)
&& (progress <= IOT_OTAP_FETCH_PERCENTAGE_MAX));
}
int iotx_ota_set_fetch_callback(void *pt, ota_fetch_cb_fpt fetch_cb, void *user_data)
{
OTA_Struct_pt ota_pt = (OTA_Struct_pt)pt;
if (NULL == ota_pt || NULL == fetch_cb) {
return -1;
}
ota_pt->fetch_cb = fetch_cb;
ota_pt->user_data = user_data;
return 0;
}
int iotx_ota_set_cota_fetch_callback(void *pt, cota_fetch_cb_fpt fetch_cb, void *user_data)
{
OTA_Struct_pt ota_pt = (OTA_Struct_pt)pt;
if (NULL == ota_pt || NULL == fetch_cb) {
return -1;
}
ota_pt->fetch_cota_cb = fetch_cb;
ota_pt->cota_user_data = user_data;
return 0;
}
int ota_callback(void *pcontext, const char *msg, uint32_t msg_len, iotx_ota_topic_types_t type)
{
const char *pvalue;
uint32_t val_len;
OTA_Struct_pt h_ota = (OTA_Struct_pt) pcontext;
if (h_ota->state == IOT_OTAS_FETCHING) {
OTA_LOG_INFO("In downloading state");
return -1;
}
switch (type) {
case IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST:
case IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE: {
pvalue = otalib_JsonValueOf(msg, msg_len, "message", &val_len);
if (NULL == pvalue) {
OTA_LOG_ERROR("invalid json doc of OTA ");
return -1;
}
/* check whether is positive message */
if (!((strlen("success") == val_len) && (0 == strncmp(pvalue, "success", val_len)))) {
OTA_LOG_ERROR("fail state of json doc of OTA");
return -1;
}
/* get value of 'data' key */
pvalue = otalib_JsonValueOf(msg, msg_len, "data", &val_len);
if (NULL == pvalue) {
OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
return -1;
}
if (0 != otalib_GetParams(pvalue, val_len, &h_ota->purl, &h_ota->version, h_ota->md5sum, &h_ota->size_file)) {
OTA_LOG_ERROR("Get config parameter failed");
return -1;
}
if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->purl))) {
OTA_LOG_ERROR("Initialize fetch module failed");
return -1;
}
h_ota->type = IOT_OTAT_FOTA;
h_ota->state = IOT_OTAS_FETCHING;
if (h_ota->fetch_cb) {
h_ota->fetch_cb(h_ota->user_data, 0, h_ota->size_file, h_ota->purl, h_ota->version);
}
}
break;
case IOTX_OTA_TOPIC_TYPE_CONFIG_GET: {
pvalue = otalib_JsonValueOf(msg, msg_len, "code", &val_len);
if (NULL == pvalue) {
OTA_LOG_ERROR("invalid json doc of OTA ");
return -1;
}
/* check whether is positive message */
if (!((strlen("200") == val_len) && (0 == strncmp(pvalue, "200", val_len)))) {
OTA_LOG_ERROR("fail state of json doc of OTA");
return -1;
}
/* get value of 'data' key */
pvalue = otalib_JsonValueOf(msg, msg_len, "data", &val_len);
if (NULL == pvalue) {
OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
return -1;
}
if (0 != otalib_GetConfigParams(pvalue, val_len, &h_ota->configId, &h_ota->configSize,
&h_ota->sign, &h_ota->signMethod, &h_ota->cota_url, &h_ota->getType)) {
OTA_LOG_ERROR("Get firmware parameter failed");
return -1;
}
h_ota->size_file = h_ota->configSize;
h_ota->size_fetched = 0;
if (NULL != h_ota->md5) {
otalib_MD5Deinit(h_ota->md5);
}
h_ota->md5 = otalib_MD5Init();
if (NULL != h_ota->sha256) {
otalib_Sha256Deinit(h_ota->sha256);
}
h_ota->sha256 = otalib_Sha256Init();
if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->cota_url))) {
OTA_LOG_ERROR("Initialize fetch module failed");
return -1;
}
h_ota->type = IOT_OTAT_COTA;
h_ota->state = IOT_OTAS_FETCHING;
if (h_ota->fetch_cota_cb) {
h_ota->fetch_cota_cb(h_ota->user_data, 0, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
h_ota->cota_url, h_ota->getType);
}
}
break;
case IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH: {
/* get value of 'params' key */
pvalue = otalib_JsonValueOf(msg, msg_len, "params", &val_len);
if (NULL == pvalue) {
OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
return -1;
}
if (0 != otalib_GetConfigParams(pvalue, val_len, &h_ota->configId, &h_ota->configSize,
&h_ota->sign, &h_ota->signMethod, &h_ota->cota_url, &h_ota->getType)) {
OTA_LOG_ERROR("Get firmware parameter failed");
return -1;
}
h_ota->size_file = h_ota->configSize;
h_ota->size_fetched = 0;
if (NULL != h_ota->md5) {
otalib_MD5Deinit(h_ota->md5);
}
h_ota->md5 = otalib_MD5Init();
if (NULL != h_ota->sha256) {
otalib_Sha256Deinit(h_ota->sha256);
}
h_ota->sha256 = otalib_Sha256Init();
if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->cota_url))) {
OTA_LOG_ERROR("Initialize fetch module failed");
return -1;
}
h_ota->type = IOT_OTAT_COTA;
h_ota->state = IOT_OTAS_FETCHING;
if (h_ota->fetch_cota_cb) {
h_ota->fetch_cota_cb(h_ota->user_data, 0, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
h_ota->cota_url, h_ota->getType);
}
}
break;
default:
return -1;
break;
}
return 0;
}
static int g_ota_is_initialized = 0;
/* Initialize OTA module */
void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal)
{
OTA_Struct_pt h_ota = NULL;
if (1 == g_ota_is_initialized) {
OTA_LOG_ERROR("iot ota has been initialized");
return NULL;
}
if ((NULL == product_key) || (NULL == device_name)) {
OTA_LOG_ERROR("one or more parameters is invalid");
return NULL;
}
if (NULL == (h_ota = OTA_MALLOC(sizeof(OTA_Struct_t)))) {
OTA_LOG_ERROR("allocate failed");
return NULL;
}
memset(h_ota, 0, sizeof(OTA_Struct_t));
h_ota->type = IOT_OTAT_NONE;
h_ota->state = IOT_OTAS_UNINITED;
/*h_ota->ch_signal = osc_Init(product_key, device_name, ch_signal, ota_callback, h_ota);
if (NULL == h_ota->ch_signal) {
OTA_LOG_ERROR("initialize signal channel failed");
goto do_exit;
}*/
h_ota->md5 = otalib_MD5Init();
if (NULL == h_ota->md5) {
OTA_LOG_ERROR("initialize md5 failed");
goto do_exit;
}
/*h_ota->sha256 = otalib_Sha256Init();
if (NULL == h_ota->sha256) {
OTA_LOG_ERROR("initialize sha256 failed");
goto do_exit;
}*/
h_ota->product_key = product_key;
h_ota->device_name = device_name;
h_ota->state = IOT_OTAS_INITED;
g_ota_is_initialized = 1;
return h_ota;
do_exit:
/*if (NULL != h_ota->ch_signal) {
osc_Deinit(h_ota->ch_signal);
}*/
if (NULL != h_ota->md5) {
otalib_MD5Deinit(h_ota->md5);
}
if (NULL != h_ota->sha256) {
otalib_Sha256Deinit(h_ota->sha256);
}
if (NULL != h_ota) {
OTA_FREE(h_ota);
}
return NULL;
#undef AOM_INFO_MSG_LEN
}
/* deinitialize OTA module */
int IOT_OTA_Deinit(void *handle)
{
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if (NULL == h_ota) {
OTA_LOG_ERROR("handle is NULL");
return IOT_OTAE_INVALID_PARAM;
}
if (IOT_OTAS_UNINITED == h_ota->state) {
OTA_LOG_ERROR("handle is uninitialized");
h_ota->err = IOT_OTAE_INVALID_STATE;
return -1;
}
g_ota_is_initialized = 0;
/*if (NULL != h_ota->ch_signal) {
osc_Deinit(h_ota->ch_signal);
}*/
if (NULL != h_ota->ch_fetch) {
ofc_Deinit(h_ota->ch_fetch);
}
if (NULL != h_ota->md5) {
otalib_MD5Deinit(h_ota->md5);
}
if (NULL != h_ota->sha256) {
otalib_Sha256Deinit(h_ota->sha256);
}
if (NULL != h_ota->purl) {
OTA_FREE(h_ota->purl);
}
if (NULL != h_ota->version) {
OTA_FREE(h_ota->version);
}
if (NULL != h_ota->configId) {
OTA_FREE(h_ota->configId);
}
if (NULL != h_ota->sign) {
OTA_FREE(h_ota->sign);
}
if (NULL != h_ota->signMethod) {
OTA_FREE(h_ota->signMethod);
}
if (NULL != h_ota->cota_url) {
OTA_FREE(h_ota->cota_url);
}
if (NULL != h_ota->getType) {
OTA_FREE(h_ota->getType);
}
OTA_FREE(h_ota);
return 0;
}
#define OTA_VERSION_STR_LEN_MIN (1)
#define OTA_VERSION_STR_LEN_MAX (32)
/*int IOT_OTA_ReportVersion(void *handle, const char *version)
{
#define MSG_INFORM_LEN (128)
int ret, len;
char *msg_informed;
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if ((NULL == h_ota) || (NULL == version)) {
OTA_LOG_ERROR("one or more invalid parameter");
return IOT_OTAE_INVALID_PARAM;
}
len = strlen(version);
if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
OTA_LOG_ERROR("version string is invalid: must be [1, 32] chars");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
if (IOT_OTAS_UNINITED == h_ota->state) {
OTA_LOG_ERROR("handle is uninitialized");
h_ota->err = IOT_OTAE_INVALID_STATE;
return -1;
}
if (NULL == (msg_informed = OTA_MALLOC(MSG_INFORM_LEN))) {
OTA_LOG_ERROR("allocate for msg_informed failed");
h_ota->err = IOT_OTAE_NOMEM;
return -1;
}
ret = otalib_GenInfoMsg(msg_informed, MSG_INFORM_LEN, h_ota->id, version);
if (ret != 0) {
OTA_LOG_ERROR("generate inform message failed");
h_ota->err = ret;
ret = -1;
goto do_exit;
}
ret = osc_ReportVersion(h_ota->ch_signal, msg_informed);
if (0 != ret) {
OTA_LOG_ERROR("Report version failed");
h_ota->err = ret;
ret = -1;
goto do_exit;
}
ret = 0;
do_exit:
if (NULL != msg_informed) {
OTA_FREE(msg_informed);
}
return ret;
#undef MSG_INFORM_LEN
}*/
int iotx_req_image(void *handle, const char *version)
{
#define MSG_REQUEST_LEN (128)
int ret, len;
char *msg_informed;
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if ((NULL == h_ota) || (NULL == version)) {
OTA_LOG_ERROR("one or more invalid parameter");
return IOT_OTAE_INVALID_PARAM;
}
len = strlen(version);
if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
OTA_LOG_ERROR("version string is invalid: must be [1, 32] chars");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
if (IOT_OTAS_UNINITED == h_ota->state) {
OTA_LOG_ERROR("handle is uninitialized");
h_ota->err = IOT_OTAE_INVALID_STATE;
return -1;
}
if (IOT_OTAS_FETCHING == h_ota->state) {
OTA_LOG_ERROR("ota is busying");
h_ota->err = IOT_OTAE_INVALID_STATE;
return -1;
}
if (NULL == (msg_informed = OTA_MALLOC(MSG_REQUEST_LEN))) {
OTA_LOG_ERROR("allocate for msg_informed failed");
h_ota->err = IOT_OTAE_NOMEM;
return -1;
}
ret = otalib_GenInfoMsg(msg_informed, MSG_REQUEST_LEN, h_ota->id, version);
if (ret != 0) {
OTA_LOG_ERROR("generate request image message failed");
h_ota->err = ret;
ret = -1;
goto do_exit;
}
//ret = osc_RequestImage(h_ota->ch_signal, msg_informed);
if (0 != ret) {
OTA_LOG_ERROR("Request image failed");
h_ota->err = ret;
ret = -1;
goto do_exit;
}
ret = 0;
do_exit:
if (NULL != msg_informed) {
OTA_FREE(msg_informed);
}
return ret;
#undef MSG_REQUEST_LEN
}
int OTA_publishProgress(void *handle, char* payload){
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if (NULL == handle) {
OTA_LOG_ERROR("handle is NULL");
return IOT_OTAE_INVALID_PARAM;
}
if (NULL == payload) {
OTA_LOG_ERROR("payload is NULL");
return IOT_OTAE_INVALID_PARAM;
}
/* inform OTA to topic: "/ota/device/progress/$(product_key)/$(device_name)" */
char topictmf[] = "/ota/device/progress/%s/%s";
int topicLen = strlen(topictmf) + strlen(h_ota->product_key) + strlen(h_ota->device_name) + 1;
char *topicBuf = malloc(topicLen);
HAL_Snprintf(topicBuf, topicLen, topictmf,h_ota->product_key, h_ota->device_name);
cJSON *root=cJSON_CreateObject();
cJSON_AddStringToObject(root, "topic", topicBuf);
cJSON_AddStringToObject(root, "payload", payload);
void *buf = cJSON_Print(root);
kk_ipc_send(IPC_MID2APP, buf, strlen(buf) + 1);
free(topicBuf);
free(buf);
cJSON_Delete(root);
return 0;
}
int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg)
{
#define MSG_REPORT_LEN (256)
int ret = -1;
char *msg_reported;
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if (NULL == handle) {
OTA_LOG_ERROR("handle is NULL");
return IOT_OTAE_INVALID_PARAM;
}
if (IOT_OTAS_UNINITED == h_ota->state) {
OTA_LOG_ERROR("handle is uninitialized");
h_ota->err = IOT_OTAE_INVALID_STATE;
return -1;
}
if (!ota_check_progress(progress)) {
OTA_LOG_ERROR("progress is a invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
if (NULL == (msg_reported = OTA_MALLOC(MSG_REPORT_LEN))) {
OTA_LOG_ERROR("allocate for msg_reported failed");
h_ota->err = IOT_OTAE_NOMEM;
return -1;
}
ret = otalib_GenReportMsg(msg_reported, MSG_REPORT_LEN, h_ota->id, progress, msg);
if (0 != ret) {
OTA_LOG_ERROR("generate reported message failed");
h_ota->err = ret;
goto do_exit;
}
ret = OTA_publishProgress(handle, msg_reported);
if (0 != ret) {
OTA_LOG_ERROR("Report progress failed");
h_ota->err = ret;
goto do_exit;
}
ret = 0;
do_exit:
if (NULL != msg_reported) {
OTA_FREE(msg_reported);
}
return ret;
#undef MSG_REPORT_LEN
}
/*int iotx_ota_get_config(void *handle, const char *configScope, const char *getType, const char *attributeKeys)
{
#define MSG_REPORT_LEN (256)
int ret = -1;
char *msg_get;
char topic[OTA_MQTT_TOPIC_LEN] = {0};
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
iotx_mqtt_topic_info_t topic_info;
memset(&topic_info, 0, sizeof(iotx_mqtt_topic_info_t));
if (NULL == handle) {
OTA_LOG_ERROR("handle is NULL");
return IOT_OTAE_INVALID_PARAM;
}
if (IOT_OTAS_UNINITED == h_ota->state) {
OTA_LOG_ERROR("handle is uninitialized");
h_ota->err = IOT_OTAE_INVALID_STATE;
return -1;
}
if (IOT_OTAS_FETCHING == h_ota->state) {
OTA_LOG_ERROR("ota is busying");
h_ota->err = IOT_OTAE_INVALID_STATE;
return -1;
}
if (NULL == (msg_get = OTA_MALLOC(MSG_REPORT_LEN))) {
OTA_LOG_ERROR("allocate for msg_reported failed");
h_ota->err = IOT_OTAE_NOMEM;
return -1;
}
if (0 > HAL_Snprintf(topic,
OTA_MQTT_TOPIC_LEN,
"/sys/%s/%s/thing/config/get",
h_ota->product_key,
h_ota->device_name)) {
goto do_exit;
};
if (0 > HAL_Snprintf(msg_get,
MSG_REPORT_LEN,
"{\"id\" : %d,\"version\":\"1.0\",\"params\":{\"configScope\":\"%s\",\"getType\":\"%s\",\"attributeKeys\":\"%s\"},\"method\":\"thing.config.get\"}",
h_ota->id,
configScope,
getType,
attributeKeys)) {
goto do_exit;
};
OTA_LOG_INFO(msg_get);
topic_info.qos = IOTX_MQTT_QOS0;
topic_info.payload = (void *)msg_get;
topic_info.payload_len = strlen(msg_get);
ret = osc_RequestConfig(h_ota->ch_signal, topic, &topic_info);
if (ret < 0) {
OTA_LOG_ERROR("publish failed");
return IOT_OTAE_OSC_FAILED;
}
ret = 0;
do_exit:
if (NULL != msg_get) {
OTA_FREE(msg_get);
}
return ret;
#undef MSG_REPORT_LEN
}*/
/* check whether is downloading */
int IOT_OTA_IsFetching(void *handle)
{
OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
if (NULL == handle) {
OTA_LOG_ERROR("handle is NULL");
return 0;
}
if (IOT_OTAS_UNINITED == h_ota->state) {
OTA_LOG_ERROR("handle is uninitialized");
h_ota->err = IOT_OTAE_INVALID_STATE;
return 0;
}
return (IOT_OTAS_FETCHING == h_ota->state);
}
/* check whether fetch over */
int IOT_OTA_IsFetchFinish(void *handle)
{
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if (NULL == handle) {
OTA_LOG_ERROR("handle is NULL");
return 0;
}
if (IOT_OTAS_UNINITED == h_ota->state) {
OTA_LOG_ERROR("handle is uninitialized");
h_ota->err = IOT_OTAE_INVALID_STATE;
return 0;
}
return (IOT_OTAS_FETCHED == h_ota->state);
}
int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s)
{
int ret;
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if ((NULL == handle) || (NULL == buf) || (0 == buf_len)) {
OTA_LOG_ERROR("invalid parameter");
return IOT_OTAE_INVALID_PARAM;
}
if (IOT_OTAS_FETCHING != h_ota->state) {
h_ota->err = IOT_OTAE_INVALID_STATE;
return IOT_OTAE_INVALID_STATE;
}
ret = ofc_Fetch(h_ota->ch_fetch, buf, buf_len, timeout_s);
if (ret < 0) {
OTA_LOG_ERROR("Fetch firmware failed");
h_ota->state = IOT_OTAS_FETCHED;
h_ota->type = IOT_OTAT_NONE;
h_ota->err = IOT_OTAE_FETCH_FAILED;
if (h_ota->fetch_cb && h_ota->purl) {
h_ota->fetch_cb(h_ota->user_data, 1, h_ota->size_file, h_ota->purl, h_ota->version);
/* remove */
h_ota->purl = NULL;
} else if (h_ota->fetch_cota_cb && h_ota->cota_url) {
h_ota->fetch_cota_cb(h_ota->user_data, 1, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
h_ota->cota_url, h_ota->getType);
/* remove */
h_ota->cota_url = NULL;
}
h_ota->size_fetched = 0;
return -1;
} else if (0 == h_ota->size_fetched) {
/* force report status in the first */
IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_PERCENTAGE_MIN, "Enter in downloading state");
}
otalib_MD5Update(h_ota->md5, buf, ret);
// otalib_Sha256Update(h_ota->sha256, buf, ret);
h_ota->size_last_fetched = ret;
h_ota->size_fetched += ret;
if (h_ota->size_fetched >= h_ota->size_file) {
h_ota->type = IOT_OTAT_NONE;
h_ota->state = IOT_OTAS_FETCHED;
if (h_ota->fetch_cb && h_ota->purl) {
h_ota->fetch_cb(h_ota->user_data, 1, h_ota->size_file, h_ota->purl, h_ota->version);
/* remove */
h_ota->purl = NULL;
} else if (h_ota->fetch_cota_cb && h_ota->cota_url) {
h_ota->fetch_cota_cb(h_ota->user_data, 1, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
h_ota->cota_url, h_ota->getType);
/* remove */
h_ota->cota_url = NULL;
}
}
return ret;
}
int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len)
{
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if ((NULL == handle) || (NULL == buf) || (0 == buf_len)) {
OTA_LOG_ERROR("invalid parameter");
return IOT_OTAE_INVALID_PARAM;
}
if (h_ota->state < IOT_OTAS_FETCHING) {
h_ota->err = IOT_OTAE_INVALID_STATE;
return IOT_OTAE_INVALID_STATE;
}
switch (type) {
case IOT_OTAG_COTA_CONFIG_ID: {
char **value = (char **)buf;
if (value == NULL || *value != NULL || h_ota->configId == NULL) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*value = OTA_API_MALLOC(strlen(h_ota->configId) + 1);
if (*value == NULL) {
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
memset(*value, 0, strlen(h_ota->configId) + 1);
memcpy(*value, h_ota->configId, strlen(h_ota->configId));
return 0;
}
}
break;
case IOT_OTAG_COTA_CONFIG_SIZE: {
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*((uint32_t *)buf) = h_ota->configSize;
return 0;
}
}
break;
case IOT_OTAG_COTA_SIGN: {
char **value = (char **)buf;
if (value == NULL || *value != NULL || h_ota->sign == NULL) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*value = OTA_API_MALLOC(strlen(h_ota->sign) + 1);
if (*value == NULL) {
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
memset(*value, 0, strlen(h_ota->sign) + 1);
memcpy(*value, h_ota->sign, strlen(h_ota->sign));
return 0;
}
}
break;
case IOT_OTAG_COTA_SIGN_METHOD: {
char **value = (char **)buf;
if (value == NULL || *value != NULL || h_ota->signMethod == NULL) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*value = OTA_API_MALLOC(strlen(h_ota->signMethod) + 1);
if (*value == NULL) {
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
memset(*value, 0, strlen(h_ota->signMethod) + 1);
memcpy(*value, h_ota->signMethod, strlen(h_ota->signMethod));
return 0;
}
}
break;
case IOT_OTAG_COTA_URL: {
char **value = (char **)buf;
if (value == NULL || *value != NULL || h_ota->cota_url == NULL) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*value = OTA_API_MALLOC(strlen(h_ota->cota_url) + 1);
if (*value == NULL) {
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
memset(*value, 0, strlen(h_ota->cota_url) + 1);
memcpy(*value, h_ota->cota_url, strlen(h_ota->cota_url));
return 0;
}
}
break;
case IOT_OTAG_COTA_GETTYPE: {
char **value = (char **)buf;
if (value == NULL || *value != NULL || h_ota->getType == NULL) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*value = OTA_API_MALLOC(strlen(h_ota->getType) + 1);
if (*value == NULL) {
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
memset(*value, 0, strlen(h_ota->getType) + 1);
memcpy(*value, h_ota->getType, strlen(h_ota->getType));
return 0;
}
}
break;
case IOT_OTAG_OTA_TYPE: {
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*((uint32_t *)buf) = h_ota->type;
return 0;
}
}
break;
case IOT_OTAG_FETCHED_SIZE:
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*((uint32_t *)buf) = h_ota->size_fetched;
return 0;
}
case IOT_OTAG_FILE_SIZE:
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else {
*((uint32_t *)buf) = h_ota->size_file;
return 0;
};
case IOT_OTAG_VERSION: {
strncpy(buf, h_ota->version, buf_len);
((char *)buf)[buf_len - 1] = '\0';
}
break;
case IOT_OTAG_MD5SUM:
strncpy(buf, h_ota->md5sum, buf_len);
((char *)buf)[buf_len - 1] = '\0';
break;
case IOT_OTAG_CHECK_FIRMWARE:
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else if (h_ota->state != IOT_OTAS_FETCHED) {
h_ota->err = IOT_OTAE_INVALID_STATE;
OTA_LOG_ERROR("Firmware can be checked in IOT_OTAS_FETCHED state only");
return -1;
} else {
char md5_str[33];
otalib_MD5Finalize(h_ota->md5, md5_str);
OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->md5sum, md5_str);
if (0 == strcmp(h_ota->md5sum, md5_str)) {
*((uint32_t *)buf) = 1;
} else {
*((uint32_t *)buf) = 0;
IOT_OTA_ReportProgress(h_ota, IOT_OTAP_CHECK_FALIED, NULL);
OTA_LOG_ERROR("image checksum compare failed");
}
return 0;
}
case IOT_OTAG_CHECK_CONFIG:
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
OTA_LOG_ERROR("Invalid parameter");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
} else if (h_ota->state != IOT_OTAS_FETCHED) {
h_ota->err = IOT_OTAE_INVALID_STATE;
OTA_LOG_ERROR("Config can be checked in IOT_OTAS_FETCHED state only");
return -1;
} else {
if (0 == strncmp(h_ota->signMethod, "Md5", strlen(h_ota->signMethod))) {
char md5_str[33];
otalib_MD5Finalize(h_ota->md5, md5_str);
OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->sign, md5_str);
if (0 == strcmp(h_ota->sign, md5_str)) {
*((uint32_t *)buf) = 1;
} else {
*((uint32_t *)buf) = 0;
}
}
if (0 == strncmp(h_ota->signMethod, "Sha256", strlen(h_ota->signMethod))) {
char sha256_str[65];
// otalib_Sha256Finalize(h_ota->sha256, sha256_str);
OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->sign, sha256_str);
if (0 == strcmp(h_ota->sign, sha256_str)) {
*((uint32_t *)buf) = 1;
} else {
*((uint32_t *)buf) = 0;
}
}
return 0;
}
case IOT_OTAG_RESET_FETCHED_SIZE: {
h_ota->size_fetched = 0;
return 0;
}
default:
OTA_LOG_ERROR("invalid cmd type");
h_ota->err = IOT_OTAE_INVALID_PARAM;
return -1;
}
return 0;
}
/* Get last error code */
int IOT_OTA_GetLastError(void *handle)
{
OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
if (NULL == handle) {
OTA_LOG_ERROR("handle is NULL");
return IOT_OTAE_INVALID_PARAM;
}
return h_ota->err;
}
/*
*
*/
#ifndef __IOTX_OTA_H__
#define __IOTX_OTA_H__
int iotx_ota_get_config(void *handle, const char *configScope, const char *getType,
const char *attributeKeys);
int iotx_req_image(void *handle, const char *version);
#endif /* #ifndef __IOTX_OTA_H__ */
/*
*
*/
#ifndef _IOTX_OTA_INTERNAL_H_
#define _IOTX_OTA_INTERNAL_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "infra_httpc.h"
#include "infra_string.h"
#include "infra_md5.h"
#include "infra_sha256.h"
#include "infra_json_parser.h"
#include "ota_api.h"
//#include "iotx_ota_config.h"
//#include "ota_wrapper.h"
#ifdef INFRA_MEM_STATS
#include "infra_mem_stats.h"
#define OTA_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "ota")
#define OTA_FREE(ptr) LITE_free(ptr)
#define OTA_API_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "ota.api")
#define OTA_API_FREE(ptr) LITE_free(ptr)
#else
#define OTA_MALLOC(size) HAL_Malloc(size)
#define OTA_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
#define OTA_API_MALLOC(size) HAL_Malloc(size)
#define OTA_API_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
#endif
#define OTA_SNPRINTF HAL_Snprintf
#ifdef INFRA_LOG
#include "infra_log.h"
#define OTA_LOG_CRIT(...) log_crit("ota", __VA_ARGS__)
#define OTA_LOG_ERROR(...) log_err("ota", __VA_ARGS__)
#define OTA_LOG_WRN(...) log_warning("ota", __VA_ARGS__)
#define OTA_LOG_INFO(...) log_info("ota", __VA_ARGS__)
#define OTA_LOG_DEBUG(...) log_debug("ota", __VA_ARGS__)
#else
#define OTA_LOG_CRIT(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_ERROR(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_WRN(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_INFO(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define OTA_LOG_DEBUG(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#endif
typedef enum {
IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST = 1,
IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE = 2,
IOTX_OTA_TOPIC_TYPE_CONFIG_GET = 3,
IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH = 4,
IOTX_OTA_TOPIC_TYPE_MAX
} iotx_ota_topic_types_t;
typedef int (*ota_cb_fpt)(void *pcontext, const char *msg, uint32_t msg_len, iotx_ota_topic_types_t type);
/* is_fetch = 0; start fetch */
/* is_fetch = 1; stop fetch */
typedef void(*ota_fetch_cb_fpt)(void *user_data, int is_fetch, uint32_t size_file, char *purl, char *version);
/* is_fetch = 0; start fetch */
/* is_fetch = 1; stop fetch */
typedef void(*cota_fetch_cb_fpt)(void *user_data, int is_fetch, char *configId, uint32_t configSize, char *sign, \
char *signMethod, char *url, char *getType);
int iotx_ota_set_fetch_callback(void *pt, ota_fetch_cb_fpt fetch_cb, void *user_data);
int iotx_ota_set_cota_fetch_callback(void *pt, cota_fetch_cb_fpt fetch_cb, void *user_data);
const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len);
void *otalib_MD5Init(void);
void otalib_MD5Update(void *md5, const char *buf, size_t buf_len);
void otalib_MD5Finalize(void *md5, char *output_str);
void otalib_MD5Deinit(void *md5);
void *otalib_Sha256Init(void);
void otalib_Sha256Update(void *sha256, const char *buf, size_t buf_len);
void otalib_Sha256Finalize(void *sha256, char *output_str);
void otalib_Sha256Deinit(void *sha256);
int otalib_GetFirmwareFixlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char *dest,
size_t dest_len);
int otalib_GetFirmwareVarlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char **dest);
int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char **version, char *md5,
uint32_t *file_size);
int otalib_GetConfigParams(const char *json_doc, uint32_t json_len, char **configId, uint32_t *configSize, char **sign,
char **signMethod, char **url, char **getType);
int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *version);
int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, const char *msg_detail);
void *ofc_Init(char *url);
int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s);
int ofc_Deinit(void *handle);
#endif /* _IOTX_OTA_INTERNAL_H_ */
/*
*
*/
#ifndef __OTA_EXPORT_H__
#define __OTA_EXPORT_H__
#include "infra_types.h"
#include "infra_defs.h"
#if defined(__cplusplus)
extern "C" {
#endif
#define OTA_CH_SIGNAL_MQTT (0)
#define OTA_CH_SIGNAL_COAP (1)
#define OTA_CH_FETCH_HTTP (1)
typedef enum {
IOT_OTAE_GENERAL = -1,
IOT_OTAE_INVALID_PARAM = -2,
IOT_OTAE_INVALID_STATE = -3,
IOT_OTAE_STR_TOO_LONG = -4,
IOT_OTAE_FETCH_FAILED = -5,
IOT_OTAE_NOMEM = -6,
IOT_OTAE_OSC_FAILED = -7,
IOT_OTAE_NONE = 0,
} IOT_OTA_Err_t;
/* State of OTA */
typedef enum {
IOT_OTAS_UNINITED = 0, /* Uninitialized State */
IOT_OTAS_INITED, /* Initialized State */
IOT_OTAS_FETCHING, /* Fetching firmware */
IOT_OTAS_FETCHED /* Fetching firmware finish */
} IOT_OTA_State_t;
typedef enum {
IOT_OTAT_NONE,
IOT_OTAT_COTA,
IOT_OTAT_FOTA
} IOT_OTA_Type_t;
/* Progress of OTA */
typedef enum {
/* Burn firmware file failed */
IOT_OTAP_BURN_FAILED = -4,
/* Check firmware file failed */
IOT_OTAP_CHECK_FALIED = -3,
/* Fetch firmware file failed */
IOT_OTAP_FETCH_FAILED = -2,
/* Initialized failed */
IOT_OTAP_GENERAL_FAILED = -1,
/* [0, 100], percentage of fetch progress */
/* The minimum percentage of fetch progress */
IOT_OTAP_FETCH_PERCENTAGE_MIN = 0,
/* The maximum percentage of fetch progress */
IOT_OTAP_FETCH_PERCENTAGE_MAX = 100
} IOT_OTA_Progress_t;
typedef enum {
IOT_OTAG_COTA_CONFIG_ID,
IOT_OTAG_COTA_CONFIG_SIZE,
IOT_OTAG_COTA_SIGN,
IOT_OTAG_COTA_SIGN_METHOD,
IOT_OTAG_COTA_URL,
IOT_OTAG_COTA_GETTYPE,
IOT_OTAG_OTA_TYPE,
IOT_OTAG_FETCHED_SIZE, /* option for get already fetched size */
IOT_OTAG_FILE_SIZE, /* size of file */
IOT_OTAG_MD5SUM, /* md5 in string format */
IOT_OTAG_VERSION, /* version in string format */
IOT_OTAG_CHECK_FIRMWARE, /* Check firmware is valid or not */
IOT_OTAG_CHECK_CONFIG, /* Check config file is valid or not */
IOT_OTAG_RESET_FETCHED_SIZE /* reset the size_fetched parameter to be 0 */
} IOT_OTA_CmdType_t;
/** @defgroup group_api api
* @{
*/
/** @defgroup group_api_ota ota
* @{
*/
/**
* @brief Initialize OTA module, and return handle.
* The MQTT client must be construct before calling this interface.
*
* @param [in] product_key: specify the product key.
* @param [in] device_name: specify the device name.
* @param [in] ch_signal: specify the signal channel.
*
* @retval 0 : Successful.
* @retval -1 : Failed.
* @see None.
*/
void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal);
/**
* @brief Deinitialize OTA module specified by the 'handle', and release the related resource.
* You must call this interface to release resource if reboot is not invoked after downloading.
*
* @param [in] handle: specify the OTA module.
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_Deinit(void *handle);
/**
* @brief Report firmware version information to OTA server (optional).
* NOTE: please
*
* @param [in] handle: specify the OTA module.
* @param [in] version: specify the firmware version in string format.
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_ReportVersion(void *handle, const char *version);
/**
* @brief Report detail progress to OTA server (optional).
* NOTE: please
*
* @param [in] handle: specify the OTA module.
* @param [in] progress: specify the progress defined by 'IOT_OTA_Progress_t'.
* @param [in] msg: detail progress information in string.
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg);
/**
* @brief Check whether is on fetching state
*
* @param [in] handle: specify the OTA module.
*
* @retval 1 : Yes.
* @retval 0 : No.
* @see None.
*/
int IOT_OTA_IsFetching(void *handle);
/**
* @brief Check whether is on end-of-fetch state.
*
* @param [in] handle: specify the OTA module.
*
* @retval 1 : Yes.
* @retval 0 : False.
* @see None.
*/
int IOT_OTA_IsFetchFinish(void *handle);
/**
* @brief fetch firmware from remote server with specific timeout value.
* NOTE: If you want to download more faster, the bigger 'buf' should be given.
*
* @param [in] handle: specify the OTA module.
* @param [out] buf: specify the space for storing firmware data.
* @param [in] buf_len: specify the length of 'buf' in bytes.
* @param [in] timeout_s: specify the timeout value in second.
*
* @retval < 0 : Error occur..
* @retval 0 : No any data be downloaded in 'timeout_s' timeout period.
* @retval (0, len] : The length of data be downloaded in 'timeout_s' timeout period in bytes.
* @see None.
*/
int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s);
/**
* @brief Get OTA information specified by 'type'.
* By this interface, you can get information like state, size of file, md5 of file, etc.
*
* @param [in] handle: handle of the specific OTA
* @param [in] type: specify what information you want, see detail 'IOT_OTA_CmdType_t'
* @param [out] buf: specify buffer for data exchange
* @param [in] buf_len: specify the length of 'buf' in byte.
* @return
@verbatim
NOTE:
1) When type is IOT_OTAG_FETCHED_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
2) When type is IOT_OTAG_FILE_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
3) When type is IOT_OTAG_MD5SUM, 'buf' should be a buffer, and 'buf_len' should be 33.
4) When type is IOT_OTAG_VERSION, 'buf' should be a buffer, and 'buf_len' should be OTA_VERSION_LEN_MAX.
5) When type is IOT_OTAG_CHECK_FIRMWARE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
0, firmware is invalid; 1, firmware is valid.
@endverbatim
*
* @retval 0 : Successful.
* @retval < 0 : Failed, the value is error code.
* @see None.
*/
int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len);
/**
* @brief Get last error code.
*
* @param [in] handle: specify the OTA module.
*
* @return The error code.
* @see None.
*/
int IOT_OTA_GetLastError(void *handle);
/** @} */ /* end of api_ota */
/** @} */ /* end of api */
#if defined(__cplusplus)
}
#endif
#endif /* __OTA_EXPORT_H__ */
/*
*
*/
#include "iotx_ota_internal.h"
/* ofc, OTA fetch channel */
typedef struct {
const char *url;
httpclient_t http; /* http client */
httpclient_data_t http_data; /* http client data */
} otahttp_Struct_t, *otahttp_Struct_pt;
extern int httpclient_common(httpclient_t *client,
const char *url,
int port,
const char *ca_crt,
HTTPCLIENT_REQUEST_TYPE method,
uint32_t timeout_ms,
httpclient_data_t *client_data);
void *ofc_Init(char *url)
{
otahttp_Struct_pt h_odc;
if (NULL == (h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t)))) {
OTA_LOG_ERROR("allocate for h_odc failed");
return NULL;
}
memset(h_odc, 0, sizeof(otahttp_Struct_t));
/* set http request-header parameter */
h_odc->http.header = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
#if defined(SUPPORT_ITLS)
char *s_ptr = strstr(url, "://");
if (strlen("https") == (s_ptr - url) && (0 == strncmp(url, "https", strlen("https")))) {
strncpy(url + 1, url, strlen("http"));
url++;
}
#endif
h_odc->url = url;
return h_odc;
}
extern const char *iotx_ca_crt;
int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s)
{
int diff;
otahttp_Struct_pt h_odc = (otahttp_Struct_pt)handle;
h_odc->http_data.response_buf = buf;
h_odc->http_data.response_buf_len = buf_len;
diff = h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len;
#if !defined(SUPPORT_TLS)
if (0 != httpclient_common(&h_odc->http, h_odc->url, 80, 0, HTTPCLIENT_GET, timeout_s * 1000,
&h_odc->http_data)) {
#else
if (0 != httpclient_common(&h_odc->http, h_odc->url, 443, iotx_ca_crt, HTTPCLIENT_GET, timeout_s * 1000,
&h_odc->http_data)) {
#endif
OTA_LOG_ERROR("fetch firmware failed");
return -1;
}
return h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len - diff;
}
int ofc_Deinit(void *handle)
{
if (NULL != handle) {
OTA_FREE(handle);
}
return 0;
}
/*
*
*/
#include "iotx_ota_internal.h"
const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len)
{
int length;
const char *val;
val = json_get_value_by_name((char *)json, json_len, (char *)key, &length, NULL);
if (NULL != val) {
*val_len = (uint32_t) length;
}
return val;
}
void *otalib_MD5Init(void)
{
iot_md5_context *ctx = OTA_MALLOC(sizeof(iot_md5_context));
if (NULL == ctx) {
return NULL;
}
utils_md5_init(ctx);
utils_md5_starts(ctx);
return ctx;
}
void otalib_MD5Update(void *md5, const char *buf, size_t buf_len)
{
utils_md5_update(md5, (unsigned char *)buf, buf_len);
}
void otalib_MD5Finalize(void *md5, char *output_str)
{
int i;
unsigned char buf_out[16];
utils_md5_finish(md5, buf_out);
for (i = 0; i < 16; ++i) {
output_str[i * 2] = infra_hex2char(buf_out[i] >> 4);
output_str[i * 2 + 1] = infra_hex2char(buf_out[i]);
}
output_str[32] = '\0';
}
void otalib_MD5Deinit(void *md5)
{
if (NULL != md5) {
OTA_FREE(md5);
}
}
void *otalib_Sha256Init(void)
{
iot_sha256_context *ctx = OTA_MALLOC(sizeof(iot_sha256_context));
if (NULL == ctx) {
return NULL;
}
utils_sha256_init(ctx);
utils_sha256_starts(ctx);
return ctx;
}
void otalib_Sha256Update(void *sha256, const char *buf, size_t buf_len)
{
utils_sha256_update(sha256, (unsigned char *)buf, buf_len);
}
void otalib_Sha256Finalize(void *sha256, char *output_str)
{
int i;
unsigned char buf_out[32];
utils_sha256_finish(sha256, buf_out);
for (i = 0; i < 32; ++i) {
output_str[i * 2] = infra_hex2char(buf_out[i] >> 4);
output_str[i * 2 + 1] = infra_hex2char(buf_out[i]);
}
output_str[64] = '\0';
}
void otalib_Sha256Deinit(void *sha256)
{
utils_sha256_free(sha256);
if (NULL != sha256) {
OTA_FREE(sha256);
}
}
/* Get the specific @key value, and copy to @dest */
/* 0, successful; -1, failed */
int otalib_GetFirmwareFixlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char *dest,
size_t dest_len)
{
const char *pvalue;
uint32_t val_len;
if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len))) {
OTA_LOG_ERROR("Not '%s' key in json doc of OTA", key);
return -1;
}
if (val_len > dest_len) {
OTA_LOG_ERROR("value length of the key is too long");
return -1;
}
memcpy(dest, pvalue, val_len);
return 0;
}
/* Get variant length parameter of firmware, and copy to @dest */
/* 0, successful; -1, failed */
int otalib_GetFirmwareVarlenPara(const char *json_doc,
size_t json_doc_len,
const char *key,
char **dest)
{
const char *pvalue;
uint32_t val_len;
if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len))) {
OTA_LOG_ERROR("Not %s key in json doc of OTA", key);
return -1;
}
if (NULL == (*dest = OTA_MALLOC(val_len + 1))) {
OTA_LOG_ERROR("allocate for dest failed");
return -1;
}
memcpy(*dest, pvalue, val_len);
(*dest)[val_len] = '\0';
return 0;
}
int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char **version, char *md5,
uint32_t *file_size)
{
#define OTA_FILESIZE_STR_LEN (16)
char file_size_str[OTA_FILESIZE_STR_LEN + 1] = {0};
/* get version */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "version", version)) {
OTA_LOG_ERROR("get value of version key failed");
return -1;
}
/* get URL */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url)) {
OTA_LOG_ERROR("get value of url key failed");
return -1;
}
/* get md5 */
if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "md5", md5, 32)) {
OTA_LOG_ERROR("get value of md5 key failed");
return -1;
}
/* get file size */
if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "size", file_size_str, OTA_FILESIZE_STR_LEN)) {
OTA_LOG_ERROR("get value of size key failed");
return -1;
}
file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
*file_size = atoi(file_size_str);
return 0;
#undef OTA_FILESIZE_STR_LEN
}
int otalib_GetConfigParams(const char *json_doc, uint32_t json_len, char **configId, uint32_t *configSize, char **sign,
char **signMethod, char **url, char **getType)
{
#define OTA_FILESIZE_STR_LEN (16)
char file_size_str[OTA_FILESIZE_STR_LEN + 1];
/* get configId */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "configId", configId)) {
OTA_LOG_ERROR("get value of configId key failed");
return -1;
}
/* get configSize */
if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "configSize", file_size_str, OTA_FILESIZE_STR_LEN)) {
OTA_LOG_ERROR("get value of size key failed");
return -1;
}
file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
*configSize = atoi(file_size_str);
/* get sign */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "sign", sign)) {
OTA_LOG_ERROR("get value of sign key failed");
return -1;
}
/* get signMethod */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "signMethod", signMethod)) {
OTA_LOG_ERROR("get value of signMethod key failed");
return -1;
}
/* get url */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url)) {
OTA_LOG_ERROR("get value of url key failed");
return -1;
}
/* get getType */
if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "getType", getType)) {
OTA_LOG_ERROR("get value of getType key failed");
return -1;
}
return 0;
#undef OTA_FILESIZE_STR_LEN
}
/* Generate firmware information according to @id, @version */
/* and then copy to @buf. */
/* 0, successful; -1, failed */
int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *version)
{
int ret;
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"version\":\"%s\"}}",
id,
version);
if (ret < 0) {
OTA_LOG_ERROR("HAL_Snprintf failed");
return -1;
}
return 0;
}
/* Generate report information according to @id, @msg */
/* and then copy to @buf. */
/* 0, successful; -1, failed */
int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, const char *msg_detail)
{
int ret;
if (NULL == msg_detail) {
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"\"}}",
id,
progress);
} else {
ret = HAL_Snprintf(buf,
buf_len,
"{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"%s\"}}",
id,
progress,
msg_detail);
}
if (ret < 0) {
OTA_LOG_ERROR("HAL_Snprintf failed");
return -1;
} else if (ret >= buf_len) {
OTA_LOG_ERROR("msg is too long");
return IOT_OTAE_STR_TOO_LONG;
}
return 0;
}
#ifndef _INFRA_CONFIG_H_
#define _INFRA_CONFIG_H_
#endif
#include "infra_config.h"
#include "infra_types.h"
#include "infra_defs.h"
const char * g_infra_mqtt_domain[IOTX_MQTT_DOMAIN_NUMBER] = {
"iot-as-mqtt.cn-shanghai.aliyuncs.com", /* Shanghai */
"iot-as-mqtt.ap-southeast-1.aliyuncs.com", /* Singapore */
"iot-as-mqtt.ap-northeast-1.aliyuncs.com", /* Japan */
"iot-as-mqtt.us-west-1.aliyuncs.com", /* America */
"iot-as-mqtt.eu-central-1.aliyuncs.com", /* Germany */
NULL, /* Custom */
};
const char *g_infra_http_domain[IOTX_HTTP_DOMAIN_NUMBER] = {
"iot-auth.cn-shanghai.aliyuncs.com", /* Shanghai */
"iot-auth.ap-southeast-1.aliyuncs.com", /* Singapore */
"iot-auth.ap-northeast-1.aliyuncs.com", /* Japan */
"iot-auth.us-west-1.aliyuncs.com", /* America */
"iot-auth.eu-central-1.aliyuncs.com", /* Germany */
NULL, /* Custom */
};
#ifndef _INFRA_DEFS_H_
#define _INFRA_DEFS_H_
#include "infra_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define IOTX_SDK_REVISION "20200114.infra-update-IOTX_FIRMWARE_VER_LEN-to-64bytes"
#define IOTX_SDK_VERSION "3.0.1"
#define IOTX_ALINK_VERSION "20"
#define IOTX_FIRMWARE_VERSION_LEN (32)
#define IOTX_PRODUCT_KEY_LEN (20)
#define IOTX_DEVICE_NAME_LEN (32)
#define IOTX_DEVICE_SECRET_LEN (64)
#define IOTX_DEVICE_ID_LEN (64)
#define IOTX_PRODUCT_SECRET_LEN (64)
#define IOTX_PARTNER_ID_LEN (64)
#define IOTX_MODULE_ID_LEN (64)
#define IOTX_NETWORK_IF_LEN (160)
#define IOTX_FIRMWARE_VER_LEN (64)
#define IOTX_URI_MAX_LEN (135)
#define IOTX_DOMAIN_MAX_LEN (64)
#define IOTX_CUSTOMIZE_INFO_LEN (80)
#define DEV_SIGN_SOURCE_MAXLEN (200)
#define DEV_SIGN_HOSTNAME_MAXLEN (64)
#define DEV_SIGN_CLIENT_ID_MAXLEN (200)
#define DEV_SIGN_USERNAME_MAXLEN (64)
#define DEV_SIGN_PASSWORD_MAXLEN (65)
#ifndef _IN_
#define _IN_
#endif
#ifndef _OU_
#define _OU_
#endif
#ifndef _IN_OPT_
#define _IN_OPT_
#endif
#define NETWORK_ADDR_LEN (16)
#define HAL_MAC_LEN (17 + 1) /* MAC地址的长度 */
#define STR_SHORT_LEN (32)
#ifndef ETH_ALEN
#define ETH_ALEN (6)
#endif
#define HAL_MAX_SSID_LEN (32 + 1) /* ssid: 32 octets at most, include the NULL-terminated */
#define HAL_MAX_PASSWD_LEN (64 + 1) /* password: 8-63 ascii */
#define WLAN_CONNECTION_TIMEOUT_MS (30 * 1000)
#if 1
typedef enum IOT_RETURN_CODES {
ERROR_DEVICE_NOT_EXIST = -311,
ERROR_NET_TIMEOUT = -310,
ERROR_CERT_VERIFY_FAIL = -309,
ERROR_NET_SETOPT_TIMEOUT = -308,
ERROR_NET_SOCKET = -307,
ERROR_NET_CONNECT = -306,
ERROR_NET_BIND = -305,
ERROR_NET_LISTEN = -304,
ERROR_NET_RECV = -303,
ERROR_NET_SEND = -302,
ERROR_NET_CONN = -301,
ERROR_NET_UNKNOWN_HOST = -300,
MQTT_SUBHANDLE_LIST_LEN_TOO_SHORT = -47,
MQTT_OFFLINE_LIST_LEN_TOO_SHORT = -46,
MQTT_TOPIC_LEN_TOO_SHORT = -45,
MQTT_CONNECT_BLOCK = -44,
MQTT_SUB_INFO_NOT_FOUND_ERROR = -43,
MQTT_PUSH_TO_LIST_ERROR = -42,
MQTT_TOPIC_FORMAT_ERROR = -41,
NETWORK_RECONNECT_TIMED_OUT_ERROR = -40,/** Returned when the Network is disconnected and the reconnect attempt has timed out */
MQTT_CONNACK_UNKNOWN_ERROR = -39,/** Connect request failed with the server returning an unknown error */
MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -38,/** Connect request failed with the server returning an unacceptable protocol version error */
MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = -37,/** Connect request failed with the server returning an identifier rejected error */
MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR = -36,/** Connect request failed with the server returning an unavailable error */
MQTT_CONNACK_BAD_USERDATA_ERROR = -35,/** Connect request failed with the server returning a bad userdata error */
MQTT_CONNACK_NOT_AUTHORIZED_ERROR = -34,/** Connect request failed with the server failing to authenticate the request */
MQTT_CONNECT_ERROR = -33,
MQTT_CREATE_THREAD_ERROR = -32,
MQTT_PING_PACKET_ERROR = -31,
MQTT_CONNECT_PACKET_ERROR = -30,
MQTT_CONNECT_ACK_PACKET_ERROR = -29,
MQTT_NETWORK_CONNECT_ERROR = -28,
MQTT_STATE_ERROR = -27,
MQTT_SUBSCRIBE_PACKET_ERROR = -26,
MQTT_SUBSCRIBE_ACK_PACKET_ERROR = -25,
MQTT_SUBSCRIBE_ACK_FAILURE = -24,
MQTT_SUBSCRIBE_QOS_ERROR = -23,
MQTT_UNSUBSCRIBE_PACKET_ERROR = -22,
MQTT_PUBLISH_PACKET_ERROR = -21,
MQTT_PUBLISH_QOS_ERROR = -20,
MQTT_PUBLISH_ACK_PACKET_ERROR = -19,
MQTT_PUBLISH_COMP_PACKET_ERROR = -18,
MQTT_PUBLISH_REC_PACKET_ERROR = -17,
MQTT_PUBLISH_REL_PACKET_ERROR = -16,
MQTT_UNSUBSCRIBE_ACK_PACKET_ERROR = -15,
MQTT_NETWORK_ERROR = -14,
MQTT_PUBLISH_ACK_TYPE_ERROR = -13,
ERROR_SHADOW_NO_METHOD = -2008,
ERROR_SHADOW_UNDEF_TYPE = -2007,
ERROR_SHADOW_UPDATE_TIMEOUT = -2006,
ERROR_SHADOW_UPDATE_NACK = -2005, /**< Negative ACK */
ERROR_SHADOW_NO_ATTRIBUTE = -2004,
ERROR_SHADOW_ATTR_NO_EXIST = -2003, /**< NO such attribute */
ERROR_SHADOW_ATTR_EXIST = -2002, /**< attribute already exists */
ERROR_SHADOW_WAIT_LIST_OVERFLOW = -2001,
ERROR_SHADOW_INVALID_STATE = -2000,
ERROR_SUBDEV_NULL_VALUE = -1501, /**< Indicating NULL value*/
ERROR_SUBDEV_NOT_NULL_VALUE = -1500, /**< Indicating value not NULL*/
ERROR_SUBDEV_STRING_NULL_VALUE = -1499, /**< Indicating NULL value or empty string */
ERROR_SUBDEV_INVALID_GATEWAY_HANDLE = -1498, /**< Indicating gateway handle is null or invalid*/
ERROR_SUBDEV_SESSION_NOT_FOUND = -1497, /**< Cannot find device session*/
ERROR_SUBDEV_RRPC_CB_NOT_NULL = -1496, /**< RRPC callback function has been set,needn't to set again*/
ERROR_SUBDEV_REPLY_TYPE_NOT_DEF = -1495, /**< Reply type not defined*/
ERROR_SUBDEV_GET_JSON_VAL = -1494, /**< Get value from reply payload fail*/
ERROR_SUBDEV_DATA_LEN_OVERFLOW = -1493, /**< Length of 'data' value from reply palyoad is large than limit(1024)*/
ERROR_SUBDEV_MSG_LEN = -1492, /**< Indicating msg len is not correct*/
ERROR_SUBDEV_REPLY_PROC = -1491, /**< Error occur when process publish reply */
ERROR_SUBDEV_REPLY_TOPIC_NOT_MATCH = -1490, /**< Indicating that topic received is unknown*/
ERROR_SUBDEV_REPLY_VAL_CHECK = -1489, /**< Indicating that value get from reply checked fail with local*/
ERROR_SUBDEV_REGISTER_TYPE_NOT_DEF = -1488, /**< Register type not support*/
ERROR_SUBDEV_PACKET_SPLICE_FAIL = -1487, /**< Splice packet error*/
ERROR_SUBDEV_MQTT_PUBLISH_FAIL = -1486, /**< MQTT publish fail*/
ERROR_SUBDEV_REPLY_PARSE_FAIL = -1485, /**< Parse reply fail*/
ERROR_SUBDEV_CREATE_SESSION_FAIL = -1484, /**< Create session fail*/
ERROR_SUBDEV_INVALID_CLEAN_SESSION_TYPE = -1483, /**< Clean session not support*/
ERROR_SUBDEV_HAS_BEEN_LOGIN = -1482, /**< Device has been login*/
ERROR_SUBDEV_SUB_UNSUB_FAIL = -1481, /**< subscribe or unsubscribe fail*/
ERROR_SUBDEV_SESSION_STATE_FAIL = -1480, /**< Session state is error,may not login*/
ERROR_SUBDEV_MEMORY_NOT_ENOUGH = -1479, /**< Set memory too small*/
ERROR_REPLY_TIMEOUT = -6099, /**< recieve reply timeout*/
ERROR_DEVICE_NOT_FOUND = -6100, /**< device not found*/
ERROR_TOO_LARGE_PAGE_SIZE = -6101, /**< page size must less than 200*/
ERROR_DEVICE_COUNT_FAULT = -6102, /**< device count query service fault*/
ERROR_DEVICE_DETAIL_FAULT = -6103, /**< device detail query service fault*/
ERROR_TOO_LARGE_LIST_SIZE = -6104, /**< list size must less than 200*/
ERROR_LIST_SIZE_CANNOT_BE_ZERO = -6105, /**< list size must greater than 0*/
ERROR_TOO_LARGE_MAP_SIZE = -6106, /**< map size must less than 200*/
ERROR_MAP_SIZE_CANNOT_BE_ZERO = -6107, /**< map size must greater than 0*/
ERROR_DEVICE_STATUS_FAULT = -6108, /**< device status query service fault*/
ERROR_DEVICE_INFO_FAULT = -6109, /**< device info query service fault*/
ERROR_SET_THING_PROPERTIES_ERROR = -6150, /**< set thing properties error*/
ERROR_INVOKE_THING_SERVICE_ERROR = -6151, /**< invoke thing service error*/
ERROR_SCRIPT_REL_NOT_EXIST = -6200, /**< script relation not exist*/
ERROR_SCRIPT_CONVERT_DATA_IS_NULL = -6201, /**< script convert data is null*/
ERROR_DEVICE_PRODUCT_NOT_EXIST = -6202, /**< product not exist*/
ERROR_TOPIC_NOT_EXIST = -6203, /**< topic not exist*/
ERROR_DEVICE_IS_DISABLED = -6204, /**< device is disabled*/
ERROR_IOT_MESSAGE_ERROR = -6205, /**< iot message service error*/
ERROR_PRODUCT_PROPERTY_NOT_EXIST = -6206, /**< product property not exist*/
ERROR_DATA_FORMAT_ERROR = -6207, /**< device data format is error*/
ERROR_THING_STATUS_PROHIBITED = -6208, /**< thing status is prohibited*/
ERROR_THING_STATUS_NOT_ACTIVE = -6209, /**< thing status not active*/
/**
*
* -6250 ~ -6299
*/
ERROR_PRODUCT_NOT_FOUND = -6250, /**< product not found*/
ERROR_DEVICE_EXISTS = -6251, /**< device has existed*/
ERROR_JUDGE_DEVICE_EXISTS_ERROR = -6252, /**< judge device exists error*/
ERROR_ADD_DEVICE_FAILED = -6253, /**< add device failed*/
ERROR_UPDATE_DEVICE_FAILED = -6254, /**< update device failed*/
ERROR_INSERT_DGR_FAILED = -6255, /**< insert device group relation failed*/
ERROR_SYN_DEVICE_FAILED = -6256, /**< device synchronization failed*/
ERROR_PRODUCT_DOMAIN_ILLEGAL = -6257, /**< product domain illegal*/
ERROR_TENANID_ILLEGAL = -6258, /**< tenantId illegal*/
ERROR_PRODUCT_REGION_ILLEGAL = -6259, /**< product region illegal*/
ERROR_PRODUCT_NETTYPE_ILLEGAL = -6260, /**< product nettype illegal*/
ERROR_INSERT_DEVICE_APPLY_DETAIL_FAILED = -6261, /**< insert device apply detail failed*/
ERROR_UPDATE_DEVICE_APPLY_STATUS_FAILED = -6262, /**< update device apply status failed*/
ERROR_DELERE_DGR_FAILED = -6263, /**< delete device group relation status*/
ERROR_DELETE_DEVICE_FAILED = -6264, /**< delete device failed*/
ERROR_QUERY_DEVICE_DETAIL_FAILED = -6265, /**< query device detail failed*/
ERROR_QUERY_DEVICE_COUNT_FAILED = -6266, /**< query device count failed*/
ERROR_QUERY_ACTIVE_DEVICE_COUNT_FAILED = -6267, /**< query active device count failed*/
ERROR_INSERT_AGR_FAILED = -6268, /**< insert apply group relation failed*/
ERROR_QUERY_DEVICE_APPLY_FAILED = -6269, /**< query device apply failed*/
ERROR_QUERY_PRODUCT_FAILED = -6270, /**< query product failed*/
ERROR_DEVICE_APPLY_NOT_FOUND = -6271, /**< device apply not found*/
ERROR_RELEASE_TRIAD_FAILED = -6272, /**< release triad failed*/
ERROR_UPDATE_DAD_STATUS_FAILED = -6273, /**< update device apply detail status failed*/
ERROR_REG_LORA_DEVICE_FAILED = -6274, /**< register lora device failed*/
ERROR_SYN_APPLY_DEVICE_FAILED = -6275, /**< device apply synchronization failed*/
ERROR_QUERY_DGR_FAILED = -6276, /**< query device group relation failed*/
ERROR_JUDGE_DGR_FAILED = -6277, /**< judge device group relation failed*/
ERROR_QUERY_AGR_FAILED = -6278, /**< query apply group relation failed*/
ERROR_JUDGE_AGR_FAILED = -6279, /**< judge apply group relation failed*/
ERROR_DEVICENAME_NOT_MEET_SPECS = -6280, /**< devicename not meet specs*/
ERROR_DELETE_APPLY_DEVICE_FAILED = -6281, /**< delete apply device failed*/
ERROR_GEN_DEVICEID_FAILED = -6282, /**< gennerate deviceId failed*/
ERROR_APPLY_ILLEGAL = -6283, /**< apply illegal*/
ERROR_LORA_DEVICE_METHOD_ERROR = -6284, /**< lora device cannot created by num*/
ERROR_APPLY_NOT_READY = -6285, /**< apply not ready*/
/**
* dsl
* -6300 ~ -6349
*/
ERROR_DSL_PARSE_METHOD_NOT_EXIST = -6300, /**< dsl parse: method not exist*/
ERROR_DSL_PARSE_PARAMS_FORMAT_ERROR = -6301, /**< dsl parse: params format must be JSONObject/JSONArray*/
ERROR_DSL_PARSE_PARAMS_VALUE_EMPTY = -6302, /**< dsl parse: params value empty*/
ERROR_DSL_PARSE_PARAMS_NUMBER_ERROR = -6303, /**< dsl parse: params number error*/
ERROR_DSL_PARSE_PARAMS_NOT_EXIST = -6304, /**< dsl parse: params not exist*/
ERROR_DSL_PARSE_PARAMS_TYPE_ERROR = -6305, /**< dsl parse: params type error*/
ERROR_DSL_PARSE_INT_SPECS_ERROR = -6306, /**< dsl parse: int specs error*/
ERROR_DSL_PARSE_FLOAT_SPECS_ERROR = -6307, /**< dsl parse: float specs error*/
ERROR_DSL_PARSE_BOOL_SPECS_ERROR = -6308, /**< dsl parse: bool specs error*/
ERROR_DSL_PARSE_ENUM_SPECS_ERROR = -6309, /**< dsl parse: enum specs error*/
ERROR_DSL_PARSE_STRING_SPECS_ERROR = -6310, /**< dsl parse: string specs error*/
ERROR_DSL_PARSE_DATE_SPECS_ERROR = -6311, /**< dsl parse: date specs error*/
ERROR_DSL_PARSE_STRUCT_SPECS_ERROR = -6312, /**< dsl parse: struct specs error*/
ERROR_DSL_SERVICE_NOT_AVAILABLE = -6313, /**< dsl service not available*/
ERROR_DSL_PARSE_DATA_TYPE_PARSE_ERROR = -6314, /**< dsl parse: data type parse error*/
ERROR_DATA_NOT_SATISFY_DSL = -6315, /**< dsl parse: data not satisfy dsl*/
ERROR_DSL_PARSE_SPECS_NUMBER_FORMAT_ERROR = -6316, /**< dsl parse: specs number format error*/
ERROR_DSL_PARSE_TEMPLATE_ERROR = -6317, /**< dsl parse: template error*/
ERROR_DSL_EXCEPTION = -6318, /**< dsl exception*/
ERROR_DSL_PARSE_EVENT_CALL_TYPE_ERROR = -6319, /**< dsl parse: event call type error*/
ERROR_DSL_PARSE_NO_PROPERTY = -6320, /**< dsl parse: no property exist in product*/
ERROR_DSL_PARSE_IDENTIFIER_IS_NULL = -6321, /**< dsl parse: template property/params idetifier is null*/
ERROR_DSL_DEVICE_NOT_EXIST_IN_PRODUCT = -6321, /**< dsl: device not exist in product*/
ERROR_DSL_PARSE_DOUBLE_SPECS_ERROR = -6322, /**< dsl parse: double specs error*/
/**
*
* -6350 ~ -6399
*/
ERROR_EVENT_PUT_ERROR = -6350, /**< thing event put error*/
ERROR_SERVICE_PUT_ERROR = -6351, /**< thing service put error*/
ERROR_DEVICE_GET_EVENT_FAULT = -6352, /**< thing event get error*/
ERROR_PRODUCT_KEY_ELEMENT_ALREADY_EXIST = -6353, /**< product key element already exist*/
/**
*
* -6400 ~ -6449
*/
ERROR_TOPO_RELATION_COUNT_EXCEED = -6400, /**< topo relation count exceed*/
ERROR_TOPO_RELATION_NOT_EXIST = -6401, /**< topo relation not exist*/
ERROR_TOPO_RELATION_CANNOT_ADD_BYSELF = -6402, /**< topo relation cannot add by self*/
/**
* alink
* -6450 ~ -6469
*/
ERROR_ALINK_METHOD_NOT_EXIST = -6450, /**< alink method not exist*/
/**
*
* -6550 ~ -6599
*/
ERROR_DEVICE_GROUP_NOT_FOUND = -6550, /**< device group not found*/
/**
* @brief dev_sign
*
* -1100 ~ -1200
*
*/
ERROR_DEV_SIGN_CUSTOM_DOMAIN_IS_NULL = -1105,
ERROR_DEV_SIGN_SOURCE_TOO_SHORT = -1104,
ERROR_DEV_SIGN_PASSWORD_TOO_SHORT = -1103,
ERROR_DEV_SIGN_USERNAME_TOO_SHORT = -1102,
ERROR_DEV_SIGN_CLIENT_ID_TOO_SHORT = -1101,
ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT = -1100,
ERROR_NO_MEM = -1016,
ERROR_CERTIFICATE_EXPIRED = -1015,
ERROR_MALLOC = -1014,
ERROR_NO_ENOUGH_MEM = -1013, /**< Writes more than size value. */
ERROR_NO_SUPPORT = -12,
ERROR_NO_PERSISTENCE = -11,
ERROR_HTTP_BREAK = -10,
ERROR_NULL_VALUE = -9,
ERROR_HTTP_CONN = -8, /**< Connection failed. */
ERROR_HTTP_PARSE = -7, /**< A URL parse error occurred. */
ERROR_HTTP_UNRESOLVED_DNS = -6, /**< Could not resolve the hostname. */
ERROR_HTTP_PRTCL = -5, /**< A protocol error occurred. */
ERROR_HTTP = -4, /**< An unknown error occurred. */
ERROR_HTTP_CLOSED = -3, /**< Connection was closed by a remote host. */
NULL_VALUE_ERROR = -2,
//FAIL_RETURN = -1, /**< generic error. */
//SUCCESS_RETURN = 0,
/* @value > 0, reserved for other usage */
} iotx_err_t;
#endif
typedef struct _iotx_dev_meta_info {
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
char product_secret[IOTX_PRODUCT_SECRET_LEN + 1];
char device_name[IOTX_DEVICE_NAME_LEN + 1];
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
} iotx_dev_meta_info_t;
typedef struct {
const char *region;
uint16_t port;
} iotx_region_item_t;
typedef enum {
IOTX_CLOUD_REGION_SHANGHAI, /* Shanghai */
IOTX_CLOUD_REGION_SINGAPORE, /* Singapore */
IOTX_CLOUD_REGION_JAPAN, /* Japan */
IOTX_CLOUD_REGION_USA_WEST, /* America */
IOTX_CLOUD_REGION_GERMANY, /* Germany */
IOTX_CLOUD_REGION_CUSTOM, /* Custom setting */
IOTX_CLOUD_DOMAIN_MAX /* Maximum number of domain */
} iotx_mqtt_region_types_t;
#define IOTX_MQTT_DOMAIN_NUMBER (6)
extern const char *g_infra_mqtt_domain[IOTX_MQTT_DOMAIN_NUMBER];
typedef enum {
IOTX_HTTP_REGION_SHANGHAI, /* Shanghai */
IOTX_HTTP_REGION_SINGAPORE, /* Singapore */
IOTX_HTTP_REGION_JAPAN, /* Japan */
IOTX_HTTP_REGION_AMERICA, /* America */
IOTX_HTTP_REGION_GERMANY, /* Germany */
IOTX_HTTP_REGION_CUSTOM, /* Custom setting */
IOTX_HTTP_REGION_MAX /* Maximum number of domain */
} iotx_http_region_types_t;
/**
* @brief contains iot_ioctl context
*
*/
typedef struct {
int domain_type;
int dynamic_register;
char cloud_custom_domain[IOTX_DOMAIN_MAX_LEN + 1];
uint16_t mqtt_port_num;
char http_custom_domain[IOTX_DOMAIN_MAX_LEN + 1];
char mqtt_customzie_info[IOTX_CUSTOMIZE_INFO_LEN + 1];
} sdk_impl_ctx_t;
typedef struct {
char hostname[DEV_SIGN_HOSTNAME_MAXLEN];
uint16_t port;
char clientid[DEV_SIGN_CLIENT_ID_MAXLEN];
char username[DEV_SIGN_USERNAME_MAXLEN];
char password[DEV_SIGN_PASSWORD_MAXLEN];
} iotx_sign_mqtt_t;
#define IOTX_HTTP_DOMAIN_NUMBER (6)
extern const char *g_infra_http_domain[IOTX_HTTP_DOMAIN_NUMBER];
extern int iotx_facility_json_print(const char *str, int level, ...);
#ifdef __cplusplus
}
#endif
#endif
/*
*
*/
#include "infra_config.h"
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include "infra_types.h"
#include "infra_defs.h"
#include "infra_httpc.h"
#include "infra_net.h"
#include "infra_timer.h"
#include "kk_tsl_common.h"
#include "infra_defs.h"
#ifdef INFRA_LOG
#include "infra_log.h"
#define httpc_err(...) log_err("httpc", __VA_ARGS__)
#define httpc_info(...) log_info("httpc", __VA_ARGS__)
#define httpc_debug(...) log_debug("httpc", __VA_ARGS__)
#else
#define httpc_err(...)
#define httpc_info(...)
#define httpc_debug(...)
#endif
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
void HAL_SleepMs(uint32_t ms);
#define HTTPCLIENT_MIN(x,y) (((x)<(y))?(x):(y))
#define HTTPCLIENT_MAX(x,y) (((x)>(y))?(x):(y))
#define HTTPCLIENT_READ_BUF_SIZE (1024) /* read payload */
#define HTTPCLIENT_RAED_HEAD_SIZE (32) /* read header */
#define HTTPCLIENT_SEND_BUF_SIZE (1024) /* send */
#define HTTPCLIENT_MAX_URL_LEN (256)
#define HTTP_RETRIEVE_MORE_DATA (1) /**< More data needs to be retrieved. */
#if defined(MBEDTLS_DEBUG_C)
#define DEBUG_LEVEL 2
#endif
#define HTTPCLIENT_CHUNK_SIZE (1024)
static int _utils_parse_url(const char *url, char *host, char *path);
static int _http_recv(httpclient_t *client, char *buf, int max_len, int *p_read_len,
uint32_t timeout);
static int _http_get_response_body(httpclient_t *client, char *data, int len, uint32_t timeout,
httpclient_data_t *client_data);
static int _http_parse_response_header(httpclient_t *client, char *data, int len, uint32_t timeout,
httpclient_data_t *client_data);
static int _utils_parse_url(const char *url, char *host,
char *path)
{
char *host_ptr = (char *) strstr(url, "://");
uint32_t host_len = 0;
uint32_t path_len;
/* char *port_ptr; */
char *path_ptr;
char *fragment_ptr;
if (host_ptr == NULL) {
return -1; /* URL is invalid */
}
host_ptr += 3;
path_ptr = strchr(host_ptr, '/');
if (NULL == path_ptr) {
return -2;
}
if (host_len == 0) {
host_len = path_ptr - host_ptr;
}
memcpy(host, host_ptr, host_len);
host[host_len] = '\0';
fragment_ptr = strchr(host_ptr, '#');
if (fragment_ptr != NULL) {
path_len = fragment_ptr - path_ptr;
} else {
path_len = strlen(path_ptr);
}
memcpy(path, path_ptr, path_len);
path[path_len] = '\0';
return SUCCESS_RETURN;
}
static int _utils_fill_tx_buffer(httpclient_t *client, char *send_buf, int *send_idx, char *buf,
uint32_t len) /* 0 on success, err code on failure */
{
int ret;
int cp_len;
int idx = *send_idx;
if (len == 0) {
len = strlen(buf);
}
do {
if ((HTTPCLIENT_SEND_BUF_SIZE - idx) >= len) {
cp_len = len;
} else {
cp_len = HTTPCLIENT_SEND_BUF_SIZE - idx;
}
memcpy(send_buf + idx, buf, cp_len);
idx += cp_len;
len -= cp_len;
if (idx == HTTPCLIENT_SEND_BUF_SIZE) {
ret = client->net.write(&client->net, send_buf, HTTPCLIENT_SEND_BUF_SIZE, 5000);
if (ret) {
return (ret);
}
}
} while (len);
*send_idx = idx;
return SUCCESS_RETURN;
}
static int _http_send_header(httpclient_t *client, const char *host, const char *path, int method,
httpclient_data_t *client_data)
{
int len;
char send_buf[HTTPCLIENT_SEND_BUF_SIZE] = { 0 };
char buf[HTTPCLIENT_SEND_BUF_SIZE] = { 0 };
char *meth = (method == HTTPCLIENT_GET) ? "GET" : (method == HTTPCLIENT_POST) ? "POST" :
(method == HTTPCLIENT_PUT) ? "PUT" : (method == HTTPCLIENT_DELETE) ? "DELETE" :
(method == HTTPCLIENT_HEAD) ? "HEAD" : "";
int ret;
/* Send request */
memset(send_buf, 0, HTTPCLIENT_SEND_BUF_SIZE);
len = 0; /* Reset send buffer */
HAL_Snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); /* Write request */
ret = _utils_fill_tx_buffer(client, send_buf, &len, buf, strlen(buf));
if (ret) {
/* httpc_err("Could not write request"); */
return ERROR_HTTP_CONN;
}
/* Add user header information */
if (client->header) {
_utils_fill_tx_buffer(client, send_buf, &len, (char *) client->header, strlen(client->header));
}
if (client_data->post_buf != NULL) {
HAL_Snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", client_data->post_buf_len);
_utils_fill_tx_buffer(client, send_buf, &len, buf, strlen(buf));
if (client_data->post_content_type != NULL) {
HAL_Snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", client_data->post_content_type);
_utils_fill_tx_buffer(client, send_buf, &len, buf, strlen(buf));
}
}
/* Close headers */
_utils_fill_tx_buffer(client, send_buf, &len, "\r\n", 0);
#ifdef INFRA_LOG
log_multi_line(LOG_DEBUG_LEVEL, "REQUEST", "%s", send_buf, ">");
#endif
/* ret = httpclient_tcp_send_all(client->net.handle, send_buf, len); */
ret = client->net.write(&client->net, send_buf, len, 5000);
if (ret <= 0) {
httpc_err("ret = client->net.write() = %d", ret);
return (ret == 0) ? ERROR_HTTP_CLOSED : ERROR_HTTP_CONN;
}
return SUCCESS_RETURN;
}
int _http_send_userdata(httpclient_t *client, httpclient_data_t *client_data)
{
int ret = 0;
if (client_data->post_buf && client_data->post_buf_len) {
/* ret = httpclient_tcp_send_all(client->handle, (char *)client_data->post_buf, client_data->post_buf_len); */
ret = client->net.write(&client->net, (char *)client_data->post_buf, client_data->post_buf_len, 5000);
httpc_debug("client_data->post_buf: %s, ret is %d", client_data->post_buf, ret);
if (ret <= 0) {
return (ret == 0) ? ERROR_HTTP_CLOSED : ERROR_HTTP_CONN; /* Connection was closed by server */
}
}
return SUCCESS_RETURN;
}
/* 0 on success, err code on failure */
static int _http_recv(httpclient_t *client, char *buf, int max_len, int *p_read_len,
uint32_t timeout_ms)
{
int ret = 0;
iotx_time_t timer;
iotx_time_init(&timer);
utils_time_countdown_ms(&timer, timeout_ms);
*p_read_len = 0;
ret = client->net.read(&client->net, buf, max_len, iotx_time_left(&timer));
/* httpc_debug("Recv: | %s", buf); */
httpc_info("ret of _http_recv is %d", ret);
if (ret > 0) {
*p_read_len = ret;
return 0;
} else if (ret == 0) {
/* timeout */
return FAIL_RETURN;
} else {
return ERROR_HTTP_CONN;
}
}
#define MIN_TIMEOUT (100)
#define MAX_RETRY_COUNT (600)
static int _utils_check_deadloop(int len, iotx_time_t *timer, int ret, unsigned int *dead_loop_count,
unsigned int *extend_count)
{
/* if timeout reduce to zero, it will be translated into NULL for select function in TLS lib */
/* it would lead to indenfinite behavior, so we avoid it */
if (iotx_time_left(timer) < MIN_TIMEOUT) {
(*extend_count)++;
utils_time_countdown_ms(timer, MIN_TIMEOUT);
}
/* if it falls into deadloop before reconnected to internet, we just quit*/
if ((0 == len) && (0 == iotx_time_left(timer)) && (FAIL_RETURN == ret)) {
(*dead_loop_count)++;
if (*dead_loop_count > MAX_RETRY_COUNT) {
httpc_err("deadloop detected, exit");
return ERROR_HTTP_CONN;
}
} else {
*dead_loop_count = 0;
}
/*if the internet connection is fixed during the loop, the download stream might be disconnected. we have to quit */
if ((0 == len) && (*extend_count > 2 * MAX_RETRY_COUNT) && (FAIL_RETURN == ret)) {
httpc_err("extend timer for too many times, exit");
return ERROR_HTTP_CONN;
}
return SUCCESS_RETURN;
}
static int _utils_fill_rx_buf(int *recv_count, int len_to_write_to_respons_buf, httpclient_data_t *client_data,
char *data)
{
int count = *recv_count;
if (count + len_to_write_to_respons_buf < client_data->response_buf_len - 1) {
memcpy(client_data->response_buf + count, data, len_to_write_to_respons_buf);
count += len_to_write_to_respons_buf;
client_data->response_buf[count] = '\0';
client_data->retrieve_len -= len_to_write_to_respons_buf;
*recv_count = count;
return SUCCESS_RETURN;
} else {
memcpy(client_data->response_buf + count, data, client_data->response_buf_len - 1 - count);
client_data->response_buf[client_data->response_buf_len - 1] = '\0';
client_data->retrieve_len -= (client_data->response_buf_len - 1 - count);
return HTTP_RETRIEVE_MORE_DATA;
}
}
static int _http_get_response_body(httpclient_t *client, char *data, int data_len_actually_received,
uint32_t timeout_ms, httpclient_data_t *client_data)
{
int written_response_buf_len = 0;
int len_to_write_to_respons_buf = 0;
iotx_time_t timer;
iotx_time_init(&timer);
utils_time_countdown_ms(&timer, timeout_ms);
/* Receive data */
/* httpc_debug("Current data: %s", data); */
client_data->is_more = IOT_TRUE;
/* the header is not received finished */
if (client_data->response_content_len == -1 && client_data->is_chunked == IOT_FALSE) {
/* can not enter this if */
/* TODO check the way to go into this branch */
httpc_err("header is not received yet");
return ERROR_HTTP_CONN;
}
while (1) {
unsigned int dead_loop_count = 0;
unsigned int extend_count = 0;
do {
int res;
/* move previous fetched data into response_buf */
len_to_write_to_respons_buf = HTTPCLIENT_MIN(data_len_actually_received, client_data->retrieve_len);
res = _utils_fill_rx_buf(&written_response_buf_len, len_to_write_to_respons_buf, client_data, data);
if (HTTP_RETRIEVE_MORE_DATA == res) {
return HTTP_RETRIEVE_MORE_DATA;
}
/* get data from internet and put into "data" buf temporary */
if (client_data->retrieve_len) {
int ret;
int max_len_to_receive = HTTPCLIENT_MIN(HTTPCLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - written_response_buf_len);
max_len_to_receive = HTTPCLIENT_MIN(max_len_to_receive, client_data->retrieve_len);
ret = _http_recv(client, data, max_len_to_receive, &data_len_actually_received, iotx_time_left(&timer));
if (ret == ERROR_HTTP_CONN) {
return ret;
}
httpc_debug("Total- remaind Payload: %d Bytes; currently Read: %d Bytes", client_data->retrieve_len, data_len_actually_received);
/* TODO add deadloop processing*/
ret = _utils_check_deadloop(data_len_actually_received, &timer, ret, &dead_loop_count,
&extend_count);
if (ERROR_HTTP_CONN == ret) {
return ret;
}
}
} while (client_data->retrieve_len);
client_data->is_more = IOT_FALSE;
break;
}
return SUCCESS_RETURN;
}
static int _http_parse_response_header(httpclient_t *client, char *data, int len, uint32_t timeout_ms,
httpclient_data_t *client_data)
{
int crlf_pos;
iotx_time_t timer;
char *tmp_ptr, *ptr_body_end;
int new_trf_len, ret;
char *crlf_ptr;
iotx_time_init(&timer);
utils_time_countdown_ms(&timer, timeout_ms);
client_data->response_content_len = -1;
/* http client response */
/* <status-line> HTTP/1.1 200 OK(CRLF)
<headers> ...(CRLF)
<blank line> (CRLF)
[<response-body>] */
crlf_ptr = strstr(data, "\r\n");
if (crlf_ptr == NULL) {
httpc_err("\r\n not found");
return ERROR_HTTP_UNRESOLVED_DNS;
}
crlf_pos = crlf_ptr - data;
data[crlf_pos] = '\0';
client->response_code = atoi(data + 9);
httpc_debug("Reading headers: %s", data);
memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2) + 1); /* Be sure to move NULL-terminating char as well */
len -= (crlf_pos + 2); /* remove status_line length */
client_data->is_chunked = IOT_FALSE;
/*If not ending of response body*/
/* try to read more header again until find response head ending "\r\n\r\n" */
while (NULL == (ptr_body_end = strstr(data, "\r\n\r\n"))) {
/* try to read more header */
int max_remain_len = HTTPCLIENT_READ_BUF_SIZE - len -1;
if (max_remain_len <= 0) {
httpc_debug("buffer exceeded max\n");
return ERROR_HTTP_PARSE;
}
max_remain_len = max_remain_len > HTTPCLIENT_RAED_HEAD_SIZE ? HTTPCLIENT_RAED_HEAD_SIZE : max_remain_len;
ret = _http_recv(client, data + len, max_remain_len, &new_trf_len, iotx_time_left(&timer));
if (ret == ERROR_HTTP_CONN) {
return ret;
}
len += new_trf_len;
data[len] = '\0';
}
/* parse response_content_len */
if (NULL != (tmp_ptr = strstr(data, "Content-Length"))) {
client_data->response_content_len = atoi(tmp_ptr + strlen("Content-Length: "));
client_data->retrieve_len = client_data->response_content_len;
} else {
httpc_err("Could not parse header");
return ERROR_HTTP;
}
/* remove header length */
/* len is Had read body's length */
/* if client_data->response_content_len != 0, it is know response length */
/* the remain length is client_data->response_content_len - len */
len = len - (ptr_body_end + 4 - data);
memmove(data, ptr_body_end + 4, len + 1);
client_data->response_received_len += len;
return _http_get_response_body(client, data, len, iotx_time_left(&timer), client_data);
}
int httpclient_connect(httpclient_t *client)
{
int retry_max = 3;
int retry_cnt = 1;
int retry_interval = 1000;
int rc = -1;
do {
client->net.handle = 0;
httpc_debug("calling TCP or TLS connect HAL for [%d/%d] iteration", retry_cnt, retry_max);
rc = client->net.connect(&client->net);
if (0 != rc) {
client->net.disconnect(&client->net);
httpc_err("TCP or TLS connect failed, rc = %d", rc);
HAL_SleepMs(retry_interval);
continue;
} else {
httpc_debug("rc = client->net.connect() = %d, success @ [%d/%d] iteration", rc, retry_cnt, retry_max);
break;
}
} while (++retry_cnt <= retry_max);
return SUCCESS_RETURN;
}
int _http_send_request(httpclient_t *client, const char *host, const char *path, HTTPCLIENT_REQUEST_TYPE method,
httpclient_data_t *client_data)
{
int ret = ERROR_HTTP_CONN;
if (0 == client->net.handle) {
return -1;
}
ret = _http_send_header(client, host, path, method, client_data);
if (ret != 0) {
return -2;
}
if (method == HTTPCLIENT_POST || method == HTTPCLIENT_PUT) {
ret = _http_send_userdata(client, client_data);
if (ret < 0) {
ret = -3;
}
}
return ret;
}
int httpclient_recv_response(httpclient_t *client, uint32_t timeout_ms, httpclient_data_t *client_data)
{
int reclen = 0, ret = ERROR_HTTP_CONN;
char buf[HTTPCLIENT_READ_BUF_SIZE] = { 0 };
iotx_time_t timer;
iotx_time_init(&timer);
utils_time_countdown_ms(&timer, timeout_ms);
if (0 == client->net.handle) {
httpc_err("not connection have been established");
return ret;
}
if (client_data->is_more) {
client_data->response_buf[0] = '\0';
ret = _http_get_response_body(client, buf, reclen, iotx_time_left(&timer), client_data);
} else {
client_data->is_more = 1;
/* try to read header */
ret = _http_recv(client, buf, HTTPCLIENT_RAED_HEAD_SIZE, &reclen, iotx_time_left(&timer));
if (ret != 0) {
return ret;
}
buf[reclen] = '\0';
if (reclen) {
#ifdef INFRA_LOG
log_multi_line(LOG_DEBUG_LEVEL, "RESPONSE", "%s", buf, "<");
#endif
ret = _http_parse_response_header(client, buf, reclen, iotx_time_left(&timer), client_data);
}
}
return ret;
}
void httpclient_close(httpclient_t *client)
{
if (client->net.handle > 0) {
client->net.disconnect(&client->net);
}
client->net.handle = 0;
httpc_info("client disconnected");
}
static int _http_send(httpclient_t *client, const char *url, int port, const char *ca_crt,
HTTPCLIENT_REQUEST_TYPE method, httpclient_data_t *client_data)
{
int ret;
char host[HTTPCLIENT_MAX_URL_LEN] = { 0 };
char path[HTTPCLIENT_MAX_URL_LEN] = { 0 };
/* First we need to parse the url (http[s]://host[:port][/[path]]) */
ret = _utils_parse_url(url, host, path);
if (ret != SUCCESS_RETURN) {
httpc_err("_utils_parse_url fail returned %d", ret);
return ret;
}
if (0 == client->net.handle) {
/* Establish connection if no. */
ret = iotx_net_init(&client->net, host, port, ca_crt);
if (0 != ret) {
return ret;
}
ret = httpclient_connect(client);
if (0 != ret) {
httpclient_close(client);
return ret;
}
ret = _http_send_request(client, host, path, method, client_data);
if (0 != ret) {
httpc_err("_http_send_request is error, ret = %d", ret);
httpclient_close(client);
return ret;
}
}
return SUCCESS_RETURN;
}
int httpclient_common(httpclient_t *client, const char *url, int port, const char *ca_crt,
HTTPCLIENT_REQUEST_TYPE method, uint32_t timeout_ms, httpclient_data_t *client_data)
{
iotx_time_t timer;
int ret = _http_send(client, url, port, ca_crt, method, client_data);
if (SUCCESS_RETURN != ret) {
return ret;
}
iotx_time_init(&timer);
utils_time_countdown_ms(&timer, timeout_ms);
if ((NULL != client_data->response_buf)
&& (0 != client_data->response_buf_len)) {
ret = httpclient_recv_response(client, iotx_time_left(&timer), client_data);
if (ret < 0) {
httpc_err("httpclient_recv_response is error,ret = %d", ret);
httpclient_close(client);
return ret;
}
}
if (! client_data->is_more) {
/* Close the HTTP if no more data. */
httpc_info("close http channel");
httpclient_close(client);
}
ret = 0;
return ret;
}
int iotx_post(httpclient_t *client,
const char *url,
int port,
const char *ca_crt,
httpclient_data_t *client_data)
{
return _http_send(client, url, port, ca_crt, HTTPCLIENT_POST, client_data);
}
/*
*
*/
#ifndef _INFRA_HTTPC_H_
#define _INFRA_HTTPC_H_
#include "infra_net.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup HttpClient
* @{
* HttpClient API implements the client-side of HTTP/1.1. It provides base interfaces to execute an HTTP request on a given URL. It also supports HTTPS (HTTP over TLS) to provide secure communication.\n
* @section HttpClient_Usage_Chapter How to use this module
* In this release, MediaTek provides two types of APIs: high level APIs and low level APIs.\n
* - \b The \b high \b level \b APIs
* - Enables to execute a single HTTP request on a given URL.
* - Call #httpclient_get(), #httpclient_post(), #httpclient_put() or #httpclient_delete() to get, post, put or delete and HTTP request.\n
* - \b The \b low \b level \b APIs
* - Enables to execute more than one HTTP requests during a Keep-Alive connection. Keep-alive is the idea of using a single TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new connection for every single request/response pair.
* - Step1: Call #httpclient_connect() to connect to a remote server.
* - Step2: Call #httpclient_send_request() to send an HTTP request to the server.
* - Step3: Call #httpclient_recv_response() to receive an HTTP response from the server.
* - Step4: Repeat Steps 2 and 3 to execute more requests.
* - Step5: Call #httpclient_close() to close the connection.
* - Sample code: Please refer to the example under <sdk_root>/project/mt7687_hdk/apps/http_client/http_client_keepalive folder.
*/
/** @defgroup httpclient_define Define
* @{
*/
/** @brief This macro defines the HTTP port. */
#define HTTP_PORT 80
/** @brief This macro defines the HTTPS port. */
#define HTTPS_PORT 443
/**
* @}
*/
/** @defgroup httpclient_enum Enum
* @{
*/
/** @brief This enumeration defines the HTTP request type. */
typedef enum {
HTTPCLIENT_GET,
HTTPCLIENT_POST,
HTTPCLIENT_PUT,
HTTPCLIENT_DELETE,
HTTPCLIENT_HEAD
} HTTPCLIENT_REQUEST_TYPE;
/** @defgroup httpclient_struct Struct
* @{
*/
/** @brief This structure defines the httpclient_t structure. */
typedef struct {
int remote_port; /**< HTTP or HTTPS port. */
utils_network_t net;
int response_code; /**< Response code. */
char *header; /**< Custom header. */
char *auth_user; /**< Username for basic authentication. */
char *auth_password; /**< Password for basic authentication. */
} httpclient_t;
/** @brief This structure defines the HTTP data structure. */
typedef struct {
int is_more; /**< Indicates if more data needs to be retrieved. */
int is_chunked; /**< Response data is encoded in portions/chunks.*/
int retrieve_len; /**< Content length to be retrieved. */
int response_content_len; /**< Response content length. */
int response_received_len; /**< Response have received length. */
int post_buf_len; /**< Post data length. */
int response_buf_len; /**< Response buffer length. */
char *post_content_type; /**< Content type of the post data. */
char *post_buf; /**< User data to be posted. */
char *response_buf; /**< Buffer to store the response data. */
} httpclient_data_t;
int iotx_post(httpclient_t *client,
const char *url,
int port,
const char *ca_crt,
httpclient_data_t *client_data);
int httpclient_recv_response(httpclient_t *client, uint32_t timeout_ms, httpclient_data_t *client_data);
int httpclient_common(httpclient_t *client, const char *url, int port, const char *ca_crt,
HTTPCLIENT_REQUEST_TYPE method, uint32_t timeout_ms, httpclient_data_t *client_data);
void httpclient_close(httpclient_t *client);
#ifdef __cplusplus
}
#endif
#endif /* __HTTPCLIENT_H__ */
/*
*
*/
#include "infra_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "infra_types.h"
#include "infra_json_parser.h"
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
#ifdef INFRA_LOG
#include "infra_log.h"
#define jparser_debug(...) log_debug("jparser", __VA_ARGS__)
#else
#define jparser_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#endif
#ifdef INFRA_MEM_STATS
#include "infra_mem_stats.h"
#define jparser_malloc(size) LITE_malloc(size, MEM_MAGIC, "jparser")
#define jparser_free(ptr) LITE_free(ptr)
#else
#define jparser_malloc(size) HAL_Malloc(size)
#define jparser_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
#endif
char *json_get_object(int type, char *str, char *str_end)
{
char *pos = NULL;
char ch = (type == JOBJECT) ? '{' : '[';
if (!str || !str_end) {
return NULL;
}
while (str != NULL && *str != 0 && str < str_end) {
if (*str == ' ') {
str++;
continue;
}
pos = (*str == ch) ? str : NULL;
break;
}
return pos;
}
char *json_get_next_object(int type, char *str, char *str_end, char **key, int *key_len,
char **val, int *val_len, int *val_type)
{
char JsonMark[JTYPEMAX][2] = { { '\"', '\"' }, { '{', '}' }, { '[', ']' }, { '0', ' ' } };
int iMarkDepth = 0, iValueType = JNONE, iNameLen = 0, iValueLen = 0, iStringDepth = 0;
char *p_cName = 0, *p_cValue = 0, *p_cPos = str;
if (type == JOBJECT) {
/* Get Key */
p_cPos = strchr(p_cPos, '\"');
if (!p_cPos) {
goto do_exit;
}
p_cName = ++p_cPos;
p_cPos = strchr(p_cPos, '\"');
if (!p_cPos) {
goto do_exit;
}
iNameLen = p_cPos - p_cName;
/* Get Value */
p_cPos = strchr(p_cPos, ':');
}
while (p_cPos && *p_cPos && p_cPos < str_end) {
if (*p_cPos == '\"') {
iValueType = JSTRING;
p_cValue = ++p_cPos;
break;
} else if (*p_cPos == '{') {
iValueType = JOBJECT;
p_cValue = p_cPos++;
break;
} else if (*p_cPos == '[') {
iValueType = JARRAY;
p_cValue = p_cPos++;
break;
} else if ((*p_cPos == '-') || (*p_cPos >= '0' && *p_cPos <= '9')) {
iValueType = JNUMBER;
p_cValue = p_cPos++;
break;
} else if (*p_cPos == 't' || *p_cPos == 'T' || *p_cPos == 'f' || *p_cPos == 'F') {
iValueType = JBOOLEAN;
p_cValue = p_cPos;
break;
}
p_cPos++;
}
while (p_cPos && *p_cPos && p_cPos < str_end && iValueType > JNONE) {
if (iValueType == JBOOLEAN) {
int len = strlen(p_cValue);
if ((*p_cValue == 't' || *p_cValue == 'T') && len >= 4
&& (!strncmp(p_cValue, "true", 4)
|| !strncmp(p_cValue, "TRUE", 4))) {
iValueLen = 4;
p_cPos = p_cValue + iValueLen;
break;
} else if ((*p_cValue == 'f' || *p_cValue == 'F') && len >= 5
&& (!strncmp(p_cValue, "false", 5)
|| !strncmp(p_cValue, "FALSE", 5))) {
iValueLen = 5;
p_cPos = p_cValue + iValueLen;
break;
}
} else if (iValueType == JNUMBER) {
if ((*p_cPos < '0' || *p_cPos > '9') && (*p_cPos != '.') && (*p_cPos != '+') \
&& (*p_cPos != '-') && ((*p_cPos != 'e')) && (*p_cPos != 'E')) {
iValueLen = p_cPos - p_cValue;
break;
}
} else if (iValueType == JSTRING) {
if (*p_cPos == '\"') {
iValueLen = p_cPos - p_cValue;
break;
}
} else if (*p_cPos == JsonMark[iValueType][1]) {
if (iStringDepth == 0) {
if (iMarkDepth == 0) {
iValueLen = p_cPos - p_cValue + 1;
p_cPos++;
break;
} else {
iMarkDepth--;
}
}
} else if (*p_cPos == JsonMark[iValueType][0]) {
if (iStringDepth == 0) {
iMarkDepth++;
}
} else if (*p_cPos == '\"') {
if (iStringDepth) {
iStringDepth = 0;
} else {
iStringDepth = 1;
}
}
p_cPos++;
}
if (type == JOBJECT) {
if ((p_cName + iNameLen) > str_end) {
goto do_exit;
}
*key = p_cName;
*key_len = iNameLen;
}
if ((p_cValue + iValueLen) > str_end) {
goto do_exit;
}
*val = p_cValue;
*val_len = iValueLen;
*val_type = iValueType;
if (iValueType == JSTRING) {
return p_cValue + iValueLen + 1;
} else {
return p_cValue + iValueLen;
}
do_exit:
*val = NULL;
*val_len = 0;
*key = NULL;
*key_len = 0;
return NULL;
}
int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData)
{
char *pos = 0, *key = 0, *val = 0;
int klen = 0, vlen = 0, vtype = 0;
int ret = JSON_RESULT_ERR;
if (p_cJsonStr == NULL || iStrLen == 0 || pfnCB == NULL) {
return ret;
}
json_object_for_each_kv(p_cJsonStr, iStrLen, pos, key, klen, val, vlen, vtype) {
if (key && klen && val && vlen) {
ret = JSON_RESULT_OK;
if (JSON_PARSE_FINISH == pfnCB(key, klen, val, vlen, vtype, p_CBData)) {
break;
}
}
}
return ret;
}
int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
void *p_CBData)
{
JSON_NV *p_stNameValue = (JSON_NV *)p_CBData;
#ifdef JSON_DEBUG
int i;
if (p_cName) {
jparser_debug("Name:");
for (i = 0; i < iNameLen; i++) {
jparser_debug("%c", *(p_cName + i));
}
}
if (p_cValue) {
jparser_debug("Value:");
for (i = 0; i < iValueLen; i++) {
jparser_debug("%c", *(p_cValue + i));
}
}
#endif
if ((iNameLen == p_stNameValue->nLen) && !strncmp(p_cName, p_stNameValue->pN, p_stNameValue->nLen)) {
p_stNameValue->pV = p_cValue;
p_stNameValue->vLen = iValueLen;
p_stNameValue->vType = iValueType;
return JSON_PARSE_FINISH;
} else {
return JSON_PARSE_OK;
}
}
char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType)
{
JSON_NV stNV;
memset(&stNV, 0, sizeof(stNV));
stNV.pN = p_cName;
stNV.nLen = strlen(p_cName);
if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) {
if (p_iValueLen) {
*p_iValueLen = stNV.vLen;
}
if (p_iValueType) {
*p_iValueType = stNV.vType;
}
}
return stNV.pV;
}
char *json_get_value_by_name_len(char *p_cJsonStr, int iStrLen, char *p_cName, int p_cNameLen, int *p_iValueLen,
int *p_iValueType)
{
JSON_NV stNV;
memset(&stNV, 0, sizeof(stNV));
stNV.pN = p_cName;
stNV.nLen = p_cNameLen;
if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) {
if (p_iValueLen) {
*p_iValueLen = stNV.vLen;
}
if (p_iValueType) {
*p_iValueType = stNV.vType;
}
}
return stNV.pV;
}
char *LITE_json_value_of(char *key, char *src, ...)
{
char *value = NULL;
char *ret = NULL;
char *delim = NULL;
char *key_iter;
char *key_next;
char *src_iter;
int key_len;
int value_len = -1;
int src_iter_len;
if (NULL == key || NULL == src) {
return NULL;
}
#if WITH_MEM_STATS_PER_MODULE
{
char *module_name = NULL;
int magic = 0;
va_list ap;
va_start(ap, src);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
}
#endif
src_iter = src;
src_iter_len = strlen(src_iter);
key_iter = key;
do {
if ((delim = strchr(key_iter, '.')) != NULL) {
key_len = delim - key_iter;
key_next = key_iter;
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
if (value == NULL) {
return NULL;
}
src_iter = value;
src_iter_len = value_len;
key_iter = delim + 1;
}
} while (delim);
key_len = strlen(key_iter);
key_next = key_iter;
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
if (NULL == value) {
return NULL;
}
ret = jparser_malloc((value_len + 1) * sizeof(char));
if (NULL == ret) {
return NULL;
}
HAL_Snprintf(ret, value_len + 1, "%s", value);
return ret;
}
#if WITH_JSON_KEYS_OF
static list_head_t *_LITE_json_keys_of(char *src, int src_len, char *prefix, ...)
{
static LIST_HEAD(keylist);
char *module_name = NULL;
char *iter_pre = NULL;
char *pos = 0, *key = 0, *val = 0;
int klen = 0, vlen = 0, vtype = 0;
int magic = 0;
unsigned int mlen = 0;
#if WITH_MEM_STATS_PER_MODULE
va_list ap;
va_start(ap, prefix);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
#endif
if (!strcmp("", prefix)) {
INIT_LIST_HEAD(&keylist);
}
json_object_for_each_kv(src, src_len, pos, key, klen, val, vlen, vtype) {
if (key && klen && val && vlen) {
json_key_t *entry = NULL;
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
if (NULL == entry) {
utils_err("jparser_malloc failed!");
return NULL;
}
memset(entry, 0, sizeof(json_key_t));
mlen = strlen(prefix) + klen + 1;
if (module_name) {
entry->key = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
} else {
entry->key = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
}
if (NULL == entry->key) {
jparser_free(entry);
return NULL;
}
list_add_tail(&entry->list, &keylist);
if (JOBJECT == vtype) {
mlen = strlen(prefix) + klen + 2;
if (module_name) {
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", magic, module_name, prefix, klen, key);
} else {
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", prefix, klen, key);
}
if (NULL == iter_pre) {
return NULL;
}
_LITE_json_keys_of(val, vlen, iter_pre, magic, module_name);
jparser_free(iter_pre);
}
}
}
if (!strcmp("", prefix)) {
json_key_t *entry = NULL;
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
if (NULL == entry) {
utils_err("jparser_malloc failed!");
return NULL;
}
memset(entry, 0, sizeof(json_key_t));
list_add_tail(&entry->list, &keylist);
return &keylist;
}
return NULL;
}
list_head_t *LITE_json_keys_of(char *src, char *prefix, ...)
{
char *module_name = NULL;
int magic = 0;
if (!src || !prefix) {
return NULL;
}
#if WITH_MEM_STATS_PER_MODULE
va_list ap;
va_start(ap, prefix);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
#endif
return _LITE_json_keys_of(src, strlen(src), prefix, magic, module_name);
}
#if WITH_JSON_TOKEN_EXT
static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, char *prefix, ...)
{
static LIST_HEAD(keylist);
char *module_name = NULL;
char *iter_pre = NULL;
char *pos = 0, *key = 0, *val = 0;
int klen = 0, vlen = 0, vtype = 0;
int magic = 0;
unsigned int count = 1;
unsigned int mlen = 0;
if (src == NULL || prefix == NULL) {
return NULL;
}
#if WITH_MEM_STATS_PER_MODULE
va_list ap;
va_start(ap, prefix);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
#endif
if (!strcmp("", prefix)) {
INIT_LIST_HEAD(&keylist);
}
if (JOBJECT == type) {
json_object_for_each_kv(src, src_len, pos, key, klen, val, vlen, vtype) {
if (key && klen && val && vlen) {
json_key_t *entry = NULL;
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
if (NULL == entry) {
utils_err("jparser_malloc failed!");
return NULL;
}
memset(entry, 0, sizeof(json_key_t));
mlen = strlen(prefix) + klen + 1;
if (module_name) {
entry->key = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
} else {
entry->key = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
}
if (NULL == entry->key) {
jparser_free(entry);
return NULL;
}
list_add_tail(&entry->list, &keylist);
if (JOBJECT == vtype) {
mlen = strlen(prefix) + klen + 2;
if (module_name) {
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", magic, module_name, prefix, klen, key);
} else {
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", prefix, klen, key);
}
if (NULL == iter_pre) {
return NULL;
}
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
jparser_free(iter_pre);
} else if (JARRAY == vtype) {
mlen = strlen(prefix) + klen + 1;
if (module_name) {
iter_pre = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
} else {
iter_pre = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
}
if (NULL == iter_pre) {
return NULL;
}
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
jparser_free(iter_pre);
}
}
}
} else if (JARRAY == type) {
json_array_for_each_entry(src, src_len, pos, val, vlen, vtype) {
if (val && vlen) {
json_key_t *entry = NULL;
unsigned int tmp = 0;
unsigned int arridxlen = 0;
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
if (NULL == entry) {
utils_err("jparser_malloc failed!");
return NULL;
}
memset(entry, 0, sizeof(json_key_t));
tmp = count;
do {
tmp /= 10;
++arridxlen;
} while (tmp);
mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen;
if (module_name) {
entry->key = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count);
} else {
entry->key = LITE_format_nstring(mlen, "%s[%d]", prefix, count);
}
if (NULL == entry->key) {
jparser_free(entry);
return NULL;
}
list_add_tail(&entry->list, &keylist);
if (JOBJECT == vtype) {
mlen = strlen("%s[%d].") + strlen(prefix) + arridxlen;
if (module_name) {
iter_pre = LITE_format_nstring(mlen, "%s[%d].", magic, module_name, prefix, count);
} else {
iter_pre = LITE_format_nstring(mlen, "%s[%d].", prefix, count);
}
if (NULL == iter_pre) {
return NULL;
}
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
jparser_free(iter_pre);
} else if (JARRAY == vtype) {
mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen;
if (module_name) {
iter_pre = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count);
} else {
iter_pre = LITE_format_nstring(mlen, "%s[%d]", prefix, count);
}
if (NULL == iter_pre) {
return NULL;
}
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
jparser_free(iter_pre);
}
++count;
}
}
}
if (!strcmp("", prefix)) {
json_key_t *entry = NULL;
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
if (NULL == entry) {
utils_err("jparser_malloc failed!");
return NULL;
}
memset(entry, 0, sizeof(json_key_t));
list_add_tail(&entry->list, &keylist);
return &keylist;
}
return NULL;
}
int contain_arr(const char *src, int src_len, const char **arr_pre)
{
int i = 0;
int ret = -1;
int deep = 0;
const char *pre = NULL;
if (NULL == src || NULL == arr_pre || src_len <= 0) {
return -1;
}
*arr_pre = NULL;
for (i = 0; i < src_len; ++i) {
switch (src[i]) {
case '[': {
if (deep != 0) {
return ret;
}
++deep;
if (!pre) {
pre = &src[i];
}
}
break;
case ']': {
if (deep != 1) {
return ret;
}
--deep;
if ('[' == src[i - 1]) {
return ret;
}
}
break;
default: {
if ((pre != NULL) && (0 == deep)) {
return ret;
}
}
break;
}
}
if ((NULL != pre) && (pre < src + src_len) && (pre >= src)) {
*arr_pre = pre;
ret = 0;
}
return ret;
}
static char *_json_value_by_arrname(char *src, int src_len, const char *key, int key_len, int *val_len)
{
char *pos = src;
char *entry = NULL;
const char *p = NULL;
const char *arr_pre = key;
const char *arr_suf = NULL;
int vtype;
int loop;
int loop_tmp = 0;
do {
loop = 0;
arr_pre = strchr(arr_pre, '[');
if (arr_pre && (arr_pre < key + key_len)) {
arr_suf = strchr(arr_pre, ']');
}
if (arr_pre && arr_suf && (arr_suf < key + key_len)) {
loop_tmp = 0;
for (p = arr_pre + 1; p < arr_suf; ++p) {
if (*p > '9' || *p < '0') {
return NULL;
}
loop_tmp *= 10;
loop_tmp += *p - '0';
}
pos = json_get_object(JARRAY, pos, src + src_len);
if (pos != 0 && *pos != 0) {
if (*pos == '[' && *(pos + 1) == ']') {
return NULL;
}
}
json_array_for_each_entry(src, src_len, pos, entry, *val_len, vtype) {
if (entry && *val_len) {
if (++loop >= loop_tmp) {
break;
}
}
}
if (loop != loop_tmp) {
return NULL;
}
src = entry;
arr_pre = arr_suf + 1;
}
} while (arr_pre && arr_suf && (arr_pre < key + key_len));
return entry;
}
void LITE_json_keys_release(list_head_t *keylist)
{
json_key_t *pos, *tmp;
if (NULL == keylist) {
return;
}
list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) {
if (pos->key) {
jparser_free(pos->key);
}
list_del(&pos->list);
jparser_free(pos);
}
}
list_head_t *LITE_json_keys_of_ext(char *src, char *prefix, ...)
{
char *module_name = NULL;
int magic = 0;
#if WITH_MEM_STATS_PER_MODULE
va_list ap;
va_start(ap, prefix);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
#endif
if (!src || !prefix) {
return NULL;
}
return _LITE_json_keys_of_ext(JOBJECT, src, strlen(src), prefix, magic, module_name);
}
static char *_LITE_json_value_of_ext(char *key, char *src, int src_len, int *val_len)
{
char *value = NULL;
char *delim = NULL;
char *key_iter;
char *key_next;
char *src_iter;
const char *arr_pre = NULL;
int value_len;
int key_len;
int obj_key_len = 0;
int key_type;
int src_iter_len;
src_iter = src;
src_iter_len = src_len;
key_iter = key;
value_len = src_iter_len;
do {
if ((delim = strchr(key_iter, '.')) != NULL) {
key_len = delim - key_iter;
key_type = JOBJECT;
key_next = key_iter;
if (0 == contain_arr(key_next, key_len, &arr_pre)) {
key_type = JARRAY;
obj_key_len = arr_pre - key_iter;
if (obj_key_len) {
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0);
} else {
value = src_iter;
}
} else {
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
}
if (NULL == value) {
return NULL;
}
if (key_type == JARRAY) {
if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) {
return NULL;
}
}
src_iter = value;
src_iter_len = value_len;
key_iter = delim + 1;
}
} while (delim);
key_len = strlen(key_iter);
key_next = key_iter;
key_type = JOBJECT;
if (0 == contain_arr(key_next, key_len, &arr_pre)) {
key_type = JARRAY;
obj_key_len = arr_pre - key_iter;
if (obj_key_len) {
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0);
} else {
value = src_iter;
}
} else {
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
}
if (NULL == value) {
return NULL;
}
if (key_type == JARRAY) {
if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) {
return NULL;
}
}
*val_len = value_len;
return value;
}
#endif /* #if WITH_JSON_TOKEN_EXT */
#endif /* #if WITH_JSON_KEYS_OF */
/*
*
*/
#ifndef _INFRA_JSON_PARSER_H_
#define _INFRA_JSON_PARSER_H_
/* #include "iotx_utils_internal.h" */
typedef struct JSON_NV {
int nLen;
int vLen;
int vType;
char *pN;
char *pV;
} JSON_NV;
/**
The descriptions of the json value node type
**/
enum JSONTYPE {
JNONE = -1,
JSTRING = 0,
JOBJECT,
JARRAY,
JNUMBER,
JBOOLEAN,
JTYPEMAX
};
/**
The error codes produced by the JSON parsers
**/
enum JSON_PARSE_CODE {
JSON_PARSE_ERR,
JSON_PARSE_OK,
JSON_PARSE_FINISH
};
/**
The return codes produced by the JSON parsers
**/
enum JSON_PARSE_RESULT {
JSON_RESULT_ERR = -1,
JSON_RESULT_OK
};
typedef int (*json_parse_cb)(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
void *p_Result);
/**
* @brief Parse the JSON string, and iterate through all keys and values,
* then handle the keys and values by callback function.
*
* @param[in] p_cJsonStr @n The JSON string
* @param[in] iStrLen @n The JSON string length
* @param[in] pfnCB @n Callback function
* @param[out] p_CBData @n User data
* @return JSON_RESULT_OK success, JSON_RESULT_ERR failed
* @see None.
* @note None.
**/
int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData);
/**
* @brief Get the value by a specified key from a json string
*
* @param[in] p_cJsonStr @n the JSON string
* @param[in] iStrLen @n the JSON string length
* @param[in] p_cName @n the specified key string
* @param[out] p_iValueLen @n the value length
* @param[out] p_iValueType @n the value type
* @return A pointer to the value
* @see None.
* @note None.
**/
char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType);
/**
* @brief Get the value by a specified key from a json string
*
* @param[in] p_cJsonStr @n the JSON string
* @param[in] iStrLen @n the JSON string length
* @param[in] p_cName @n the specified key string
* @param[in] p_cNameLen @n the specified key string length
* @param[out] p_iValueLen @n the value length
* @param[out] p_iValueType @n the value type
* @return A pointer to the value
* @see None.
* @note None.
**/
char *json_get_value_by_name_len(char *p_cJsonStr, int iStrLen, char *p_cName, int p_cNameLen, int *p_iValueLen,
int *p_iValueType);
/**
* @brief Get the JSON object point associate with a given type.
*
* @param[in] type @n The object type
* @param[in] str @n The JSON string
* @param[in] str_end @n The end point of Json string
* @returns The json object point with the given field type.
* @see None.
* @note None.
*/
char *json_get_object(int type, char *str, char *str_end);
char *json_get_next_object(int type, char *str, char *str_end, char **key, int *key_len, char **val, int *val_len,
int *val_type);
/**
* @brief retrieve each key&value pair from the json string
*
* @param[in] str @n Json string to revolve
* @param[in] slen @n The length of json string
* @param[in] pos @n cursor
* @param[out] key @n pointer to the next Key object
* @param[out] klen @n Key object length
* @param[out] val @n pointer to the next Value object
* @param[out] vlen @n Value object length
* @param[out] vtype @n Value object type(digital, string, object, array)
* @see None.
* @note None.
*/
#define json_object_for_each_kv(str, slen, pos, key, klen, val, vlen, vtype) \
for (pos = json_get_object(JOBJECT, str, str + slen); \
pos != NULL && *pos!= 0 && (pos=json_get_next_object(JOBJECT, pos, str + slen , &key, &klen, &val, &vlen, &vtype))!=0; )
/**
* @brief retrieve each entry from the json array
*
* @param[in] str @n Json array to revolve
* @param[in] slen @n the length of Json array
* @param[in] pos @n cursor
* @param[out] entry @n pointer to the next entry from the array
* @param[out] len @n entry length
* @param[out] type @n entry type(digital, string, object, array)
* @see None.
* @note None.
*/
#define json_array_for_each_entry(str, slen, pos, entry, len, type) \
for (pos = json_get_object(JARRAY, str, str + slen); \
pos != NULL && *pos!= 0 && (pos=json_get_next_object(JARRAY, ++pos, str + slen, 0, 0, &entry, &len, &type))!=0; )
/**
* @brief backup the last character to register parameters,
* and set the end character with '\0'
*
* @param[in] json_str @n json string
* @param[in] str_len @n json string lenth
* @param[out] register @n used to backup the last character
* @see None.
* @note None.
*/
#define backup_json_str_last_char(json_str, str_len, register) { \
register = *((char *)json_str + str_len); \
*((char *)json_str + str_len) = '\0'; \
}
/**
* @brief restore the last character from register parameters
*
* @param[in] json_str @n json string
* @param[in] str_len @n json string lenth
* @param[in] register @n used to restore the last character
* @see None.
* @note None.
*/
#define restore_json_str_last_char(json_str, str_len, register) { \
*((char *)json_str + str_len) = register; \
}
char *LITE_json_value_of(char *key, char *src, ...);
#endif /* __JSON_PARSER_H__ */
/*
*
*/
#include "infra_config.h"
#include <stdlib.h>
#include <string.h>
#include "infra_md5.h"
#define MD5_KEY_IOPAD_SIZE (64)
#define MD5_DIGEST_SIZE (16)
/* Implementation that should never be optimized out by the compiler */
static void utils_md5_zeroize(void *v, size_t n)
{
volatile unsigned char *p = v;
while (n--) {
*p++ = 0;
}
}
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef IOT_MD5_GET_UINT32_LE
#define IOT_MD5_GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef IOT_MD5_PUT_UINT32_LE
#define IOT_MD5_PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
}
#endif
void utils_md5_init(iot_md5_context *ctx)
{
memset(ctx, 0, sizeof(iot_md5_context));
}
void utils_md5_free(iot_md5_context *ctx)
{
if (ctx == NULL) {
return;
}
utils_md5_zeroize(ctx, sizeof(iot_md5_context));
}
void utils_md5_clone(iot_md5_context *dst,
const iot_md5_context *src)
{
*dst = *src;
}
/*
* MD5 context setup
*/
void utils_md5_starts(iot_md5_context *ctx)
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
}
void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64])
{
uint32_t X[16], A, B, C, D;
IOT_MD5_GET_UINT32_LE(X[ 0], data, 0);
IOT_MD5_GET_UINT32_LE(X[ 1], data, 4);
IOT_MD5_GET_UINT32_LE(X[ 2], data, 8);
IOT_MD5_GET_UINT32_LE(X[ 3], data, 12);
IOT_MD5_GET_UINT32_LE(X[ 4], data, 16);
IOT_MD5_GET_UINT32_LE(X[ 5], data, 20);
IOT_MD5_GET_UINT32_LE(X[ 6], data, 24);
IOT_MD5_GET_UINT32_LE(X[ 7], data, 28);
IOT_MD5_GET_UINT32_LE(X[ 8], data, 32);
IOT_MD5_GET_UINT32_LE(X[ 9], data, 36);
IOT_MD5_GET_UINT32_LE(X[10], data, 40);
IOT_MD5_GET_UINT32_LE(X[11], data, 44);
IOT_MD5_GET_UINT32_LE(X[12], data, 48);
IOT_MD5_GET_UINT32_LE(X[13], data, 52);
IOT_MD5_GET_UINT32_LE(X[14], data, 56);
IOT_MD5_GET_UINT32_LE(X[15], data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define P(a,b,c,d,k,s,t) \
{ \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x,y,z) (z ^ (x & (y ^ z)))
P(A, B, C, D, 0, 7, 0xD76AA478);
P(D, A, B, C, 1, 12, 0xE8C7B756);
P(C, D, A, B, 2, 17, 0x242070DB);
P(B, C, D, A, 3, 22, 0xC1BDCEEE);
P(A, B, C, D, 4, 7, 0xF57C0FAF);
P(D, A, B, C, 5, 12, 0x4787C62A);
P(C, D, A, B, 6, 17, 0xA8304613);
P(B, C, D, A, 7, 22, 0xFD469501);
P(A, B, C, D, 8, 7, 0x698098D8);
P(D, A, B, C, 9, 12, 0x8B44F7AF);
P(C, D, A, B, 10, 17, 0xFFFF5BB1);
P(B, C, D, A, 11, 22, 0x895CD7BE);
P(A, B, C, D, 12, 7, 0x6B901122);
P(D, A, B, C, 13, 12, 0xFD987193);
P(C, D, A, B, 14, 17, 0xA679438E);
P(B, C, D, A, 15, 22, 0x49B40821);
#undef F
#define F(x,y,z) (y ^ (z & (x ^ y)))
P(A, B, C, D, 1, 5, 0xF61E2562);
P(D, A, B, C, 6, 9, 0xC040B340);
P(C, D, A, B, 11, 14, 0x265E5A51);
P(B, C, D, A, 0, 20, 0xE9B6C7AA);
P(A, B, C, D, 5, 5, 0xD62F105D);
P(D, A, B, C, 10, 9, 0x02441453);
P(C, D, A, B, 15, 14, 0xD8A1E681);
P(B, C, D, A, 4, 20, 0xE7D3FBC8);
P(A, B, C, D, 9, 5, 0x21E1CDE6);
P(D, A, B, C, 14, 9, 0xC33707D6);
P(C, D, A, B, 3, 14, 0xF4D50D87);
P(B, C, D, A, 8, 20, 0x455A14ED);
P(A, B, C, D, 13, 5, 0xA9E3E905);
P(D, A, B, C, 2, 9, 0xFCEFA3F8);
P(C, D, A, B, 7, 14, 0x676F02D9);
P(B, C, D, A, 12, 20, 0x8D2A4C8A);
#undef F
#define F(x,y,z) (x ^ y ^ z)
P(A, B, C, D, 5, 4, 0xFFFA3942);
P(D, A, B, C, 8, 11, 0x8771F681);
P(C, D, A, B, 11, 16, 0x6D9D6122);
P(B, C, D, A, 14, 23, 0xFDE5380C);
P(A, B, C, D, 1, 4, 0xA4BEEA44);
P(D, A, B, C, 4, 11, 0x4BDECFA9);
P(C, D, A, B, 7, 16, 0xF6BB4B60);
P(B, C, D, A, 10, 23, 0xBEBFBC70);
P(A, B, C, D, 13, 4, 0x289B7EC6);
P(D, A, B, C, 0, 11, 0xEAA127FA);
P(C, D, A, B, 3, 16, 0xD4EF3085);
P(B, C, D, A, 6, 23, 0x04881D05);
P(A, B, C, D, 9, 4, 0xD9D4D039);
P(D, A, B, C, 12, 11, 0xE6DB99E5);
P(C, D, A, B, 15, 16, 0x1FA27CF8);
P(B, C, D, A, 2, 23, 0xC4AC5665);
#undef F
#define F(x,y,z) (y ^ (x | ~z))
P(A, B, C, D, 0, 6, 0xF4292244);
P(D, A, B, C, 7, 10, 0x432AFF97);
P(C, D, A, B, 14, 15, 0xAB9423A7);
P(B, C, D, A, 5, 21, 0xFC93A039);
P(A, B, C, D, 12, 6, 0x655B59C3);
P(D, A, B, C, 3, 10, 0x8F0CCC92);
P(C, D, A, B, 10, 15, 0xFFEFF47D);
P(B, C, D, A, 1, 21, 0x85845DD1);
P(A, B, C, D, 8, 6, 0x6FA87E4F);
P(D, A, B, C, 15, 10, 0xFE2CE6E0);
P(C, D, A, B, 6, 15, 0xA3014314);
P(B, C, D, A, 13, 21, 0x4E0811A1);
P(A, B, C, D, 4, 6, 0xF7537E82);
P(D, A, B, C, 11, 10, 0xBD3AF235);
P(C, D, A, B, 2, 15, 0x2AD7D2BB);
P(B, C, D, A, 9, 21, 0xEB86D391);
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
/*
* MD5 process buffer
*/
void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen)
{
uint32_t fill;
uint32_t left;
if (ilen == 0) {
return;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if (ctx->total[0] < (uint32_t) ilen) {
ctx->total[1]++;
}
if (left && ilen >= fill) {
memcpy((void *)(ctx->buffer + left), input, fill);
utils_md5_process(ctx, ctx->buffer);
input += fill;
ilen -= fill;
left = 0;
}
while (ilen >= 64) {
utils_md5_process(ctx, input);
input += 64;
ilen -= 64;
}
if (ilen > 0) {
memcpy((void *)(ctx->buffer + left), input, ilen);
}
}
static const unsigned char iot_md5_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD5 final digest
*/
void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16])
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = (ctx->total[0] >> 29)
| (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
IOT_MD5_PUT_UINT32_LE(low, msglen, 0);
IOT_MD5_PUT_UINT32_LE(high, msglen, 4);
last = ctx->total[0] & 0x3F;
padn = (last < 56) ? (56 - last) : (120 - last);
utils_md5_update(ctx, iot_md5_padding, padn);
utils_md5_update(ctx, msglen, 8);
IOT_MD5_PUT_UINT32_LE(ctx->state[0], output, 0);
IOT_MD5_PUT_UINT32_LE(ctx->state[1], output, 4);
IOT_MD5_PUT_UINT32_LE(ctx->state[2], output, 8);
IOT_MD5_PUT_UINT32_LE(ctx->state[3], output, 12);
}
/*
* output = MD5( input buffer )
*/
void utils_md5(const unsigned char *input, uint32_t ilen, unsigned char output[16])
{
iot_md5_context ctx;
utils_md5_init(&ctx);
utils_md5_starts(&ctx);
utils_md5_update(&ctx, input, ilen);
utils_md5_finish(&ctx, output);
utils_md5_free(&ctx);
}
static int8_t utils_hb2hex(uint8_t hb)
{
hb = hb & 0xF;
return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
}
void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len)
{
iot_md5_context context;
unsigned char k_ipad[MD5_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
unsigned char k_opad[MD5_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
unsigned char out[MD5_DIGEST_SIZE];
int i;
if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
return;
}
if (key_len > MD5_KEY_IOPAD_SIZE) {
return;
}
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < MD5_KEY_IOPAD_SIZE; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner MD5 */
utils_md5_init(&context); /* init context for 1st pass */
utils_md5_starts(&context); /* setup context for 1st pass */
utils_md5_update(&context, k_ipad, MD5_KEY_IOPAD_SIZE); /* start with inner pad */
utils_md5_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
utils_md5_finish(&context, out); /* finish up 1st pass */
/* perform outer MD5 */
utils_md5_init(&context); /* init context for 2nd pass */
utils_md5_starts(&context); /* setup context for 2nd pass */
utils_md5_update(&context, k_opad, MD5_KEY_IOPAD_SIZE); /* start with outer pad */
utils_md5_update(&context, out, MD5_DIGEST_SIZE); /* then results of 1st hash */
utils_md5_finish(&context, out); /* finish up 2nd pass */
for (i = 0; i < MD5_DIGEST_SIZE; ++i) {
digest[i * 2] = utils_hb2hex(out[i] >> 4);
digest[i * 2 + 1] = utils_hb2hex(out[i]);
}
}
/*
*
*/
#ifndef _INFRA_MD5_H_
#define _INFRA_MD5_H_
#include "infra_types.h"
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
} iot_md5_context;
/**
* \brief Initialize MD5 context
*
* \param ctx MD5 context to be initialized
*/
void utils_md5_init(iot_md5_context *ctx);
/**
* \brief Clear MD5 context
*
* \param ctx MD5 context to be cleared
*/
void utils_md5_free(iot_md5_context *ctx);
/**
* \brief Clone (the state of) an MD5 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void utils_md5_clone(iot_md5_context *dst,
const iot_md5_context *src);
/**
* \brief MD5 context setup
*
* \param ctx context to be initialized
*/
void utils_md5_starts(iot_md5_context *ctx);
/**
* \brief MD5 process buffer
*
* \param ctx MD5 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen);
/**
* \brief MD5 final digest
*
* \param ctx MD5 context
* \param output MD5 checksum result
*/
void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]);
/* Internal use */
void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]);
/**
* \brief Output = MD5( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD5 checksum result
*/
void utils_md5(const unsigned char *input, uint32_t ilen, unsigned char output[16]);
void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len);
#endif
/*
*
*/
#include "infra_config.h"
#include <stdio.h>
#include <string.h>
#include "infra_defs.h"
#include "infra_net.h"
//#include "wrappers_defs.h"
#ifdef INFRA_LOG
#include "infra_log.h"
#define net_err(...) log_err("infra_net", __VA_ARGS__)
#else
#define net_err(...)
#endif
/*** SSL connection ***/
#ifdef SUPPORT_TLS
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
#ifdef INFRA_MEM_STATS
#include "infra_mem_stats.h"
#define NET_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "infra_net")
#define NET_FREE(ptr) LITE_free(ptr)
#else
#define NET_MALLOC(size) HAL_Malloc(size)
#define NET_FREE(ptr) HAL_Free(ptr)
#endif
static void *ssl_malloc(uint32_t size)
{
return NET_MALLOC(size);
}
static void ssl_free(void *ptr)
{
NET_FREE(ptr);
}
#endif
#if defined(SUPPORT_TLS)
uintptr_t HAL_SSL_Establish(const char *host, uint16_t port, const char *ca_crt, uint32_t ca_crt_len);
int32_t HAL_SSL_Destroy(uintptr_t handle);
int HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms);
int HAL_SSL_Write(uintptr_t handle, const char *buf, int len, int timeout_ms);
int ssl_hooks_set(ssl_hooks_t *hooks);
int HAL_GetProductKey(char *product_key);
int HAL_GetProductSecret(char *product_secret);
static int read_ssl(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
if (NULL == pNetwork) {
net_err("network is null");
return -1;
}
return HAL_SSL_Read((uintptr_t)pNetwork->handle, buffer, len, timeout_ms);
}
static int write_ssl(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
if (NULL == pNetwork) {
net_err("network is null");
return -1;
}
return HAL_SSL_Write((uintptr_t)pNetwork->handle, buffer, len, timeout_ms);
}
static int disconnect_ssl(utils_network_pt pNetwork)
{
if (NULL == pNetwork) {
net_err("network is null");
return -1;
}
HAL_SSL_Destroy((uintptr_t)pNetwork->handle);
pNetwork->handle = 0;
return 0;
}
static int connect_ssl(utils_network_pt pNetwork)
{
ssl_hooks_t ssl_hooks;
if (NULL == pNetwork) {
net_err("network is null");
return 1;
}
#ifdef INFRA_MEM_STATS
memset(&ssl_hooks, 0, sizeof(ssl_hooks_t));
ssl_hooks.malloc = ssl_malloc;
ssl_hooks.free = ssl_free;
ssl_hooks_set(&ssl_hooks);
#else
(void)ssl_hooks;
#endif
if (0 != (pNetwork->handle = (intptr_t)HAL_SSL_Establish(
pNetwork->pHostAddress,
pNetwork->port,
pNetwork->ca_crt,
pNetwork->ca_crt_len + 1))) {
return 0;
}
else {
/* TODO SHOLUD not remove this handle space */
/* The space will be freed by calling disconnect_ssl() */
/* utils_memory_free((void *)pNetwork->handle); */
#ifdef INFRA_EVENT
iotx_event_post(IOTX_CONN_CLOUD_FAIL);
#endif
return -1;
}
}
#elif defined(AT_TCP_ENABLED)
uintptr_t AT_TCP_Establish(const char *host, uint16_t port);
int AT_TCP_Destroy(uintptr_t fd);
int32_t AT_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms);
int32_t AT_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms);
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
/*** TCP connection ***/
static int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
return AT_TCP_Read(pNetwork->handle, buffer, len, timeout_ms);
}
static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
return AT_TCP_Write(pNetwork->handle, buffer, len, timeout_ms);
}
static int disconnect_tcp(utils_network_pt pNetwork)
{
if (pNetwork->handle == (uintptr_t)(-1)) {
net_err("Network->handle = -1");
return -1;
}
AT_TCP_Destroy(pNetwork->handle);
pNetwork->handle = (uintptr_t)(-1);
return 0;
}
static int connect_tcp(utils_network_pt pNetwork)
{
if (NULL == pNetwork) {
net_err("network is null");
return 1;
}
pNetwork->handle = AT_TCP_Establish(pNetwork->pHostAddress, pNetwork->port);
if (pNetwork->handle == (uintptr_t)(-1)) {
return -1;
}
return 0;
}
#else
uintptr_t HAL_TCP_Establish(const char *host, uint16_t port);
int HAL_TCP_Destroy(uintptr_t fd);
int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms);
int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms);
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
/*** TCP connection ***/
static int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
return HAL_TCP_Read(pNetwork->handle, buffer, len, timeout_ms);
}
static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
return HAL_TCP_Write(pNetwork->handle, buffer, len, timeout_ms);
}
static int disconnect_tcp(utils_network_pt pNetwork)
{
if (pNetwork->handle == (uintptr_t)(-1)) {
net_err("Network->handle = -1");
return -1;
}
HAL_TCP_Destroy(pNetwork->handle);
pNetwork->handle = (uintptr_t)(-1);
return 0;
}
static int connect_tcp(utils_network_pt pNetwork)
{
if (NULL == pNetwork) {
net_err("network is null");
return 1;
}
pNetwork->handle = HAL_TCP_Establish(pNetwork->pHostAddress, pNetwork->port);
if (pNetwork->handle == (uintptr_t)(-1)) {
return -1;
}
return 0;
}
#endif /* #ifdef SUPPORT_TLS */
/****** network interface ******/
int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
int ret = 0;
#ifdef SUPPORT_TLS
if (NULL != pNetwork->ca_crt) {
ret = read_ssl(pNetwork, buffer, len, timeout_ms);
}
#else
if (NULL == pNetwork->ca_crt) {
ret = read_tcp(pNetwork, buffer, len, timeout_ms);
}
#endif
else {
ret = -1;
net_err("no method match!");
}
return ret;
}
int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
int ret = 0;
#ifdef SUPPORT_TLS
if (NULL != pNetwork->ca_crt) {
ret = write_ssl(pNetwork, buffer, len, timeout_ms);
}
#else
if (NULL == pNetwork->ca_crt) {
ret = write_tcp(pNetwork, buffer, len, timeout_ms);
}
#endif
else {
ret = -1;
net_err("no method match!");
}
return ret;
}
int iotx_net_disconnect(utils_network_pt pNetwork)
{
int ret = 0;
#ifdef SUPPORT_TLS
if (NULL != pNetwork->ca_crt) {
ret = disconnect_ssl(pNetwork);
}
#else
if (NULL == pNetwork->ca_crt) {
ret = disconnect_tcp(pNetwork);
}
#endif
else {
ret = -1;
net_err("no method match!");
}
return ret;
}
int iotx_net_connect(utils_network_pt pNetwork)
{
int ret = 0;
#ifdef SUPPORT_TLS
if (NULL != pNetwork->ca_crt) {
ret = connect_ssl(pNetwork);
}
#else
if (NULL == pNetwork->ca_crt) {
ret = connect_tcp(pNetwork);
}
#endif
else {
ret = -1;
net_err("no method match!");
}
return ret;
}
int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt)
{
if (!pNetwork || !host) {
net_err("parameter error! pNetwork=%p, host = %p", pNetwork, host);
return -1;
}
pNetwork->pHostAddress = host;
pNetwork->port = port;
pNetwork->ca_crt = ca_crt;
if (NULL == ca_crt) {
pNetwork->ca_crt_len = 0;
} else {
pNetwork->ca_crt_len = strlen(ca_crt);
}
pNetwork->handle = 0;
pNetwork->read = utils_net_read;
pNetwork->write = utils_net_write;
pNetwork->disconnect = iotx_net_disconnect;
pNetwork->connect = iotx_net_connect;
return 0;
}
/*
*
*/
#ifndef _INFRA_NET_H_
#define _INFRA_NET_H_
#include "infra_types.h"
/**
* @brief The structure of network connection(TCP or SSL).
* The user has to allocate memory for this structure.
*/
struct utils_network;
typedef struct utils_network utils_network_t, *utils_network_pt;
struct utils_network {
const char *pHostAddress;
uint16_t port;
uint16_t ca_crt_len;
/**< NULL, TCP connection; NOT NULL, SSL connection */
const char *ca_crt;
/**< NOT NULL,iTLS connection*/
char *product_key;
/**< connection handle: 0, NOT connection; NOT 0, handle of the connection */
uintptr_t handle;
/**< Read data from server function pointer. */
int (*read)(utils_network_pt, char *, uint32_t, uint32_t);
/**< Send data to server function pointer. */
int (*write)(utils_network_pt, const char *, uint32_t, uint32_t);
/**< Disconnect the network */
int (*disconnect)(utils_network_pt);
/**< Establish the network */
int (*connect)(utils_network_pt);
};
int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms);
int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms);
int iotx_net_disconnect(utils_network_pt pNetwork);
int iotx_net_connect(utils_network_pt pNetwork);
int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt);
#endif /* IOTX_COMMON_NET_H */
/*
*
*/
#include "infra_config.h"
#ifdef INFRA_SHA256
#define INFRA_SHA256_SMALLER
#include <stdlib.h>
#include <string.h>
#include "infra_sha256.h"
#define SHA256_KEY_IOPAD_SIZE (64)
#define SHA256_DIGEST_SIZE (32)
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
static void utils_sha256_zeroize(void *v, uint32_t n)
{
volatile unsigned char *p = v;
while (n--) {
*p++ = 0;
}
}
void utils_sha256_init(iot_sha256_context *ctx)
{
memset(ctx, 0, sizeof(iot_sha256_context));
}
void utils_sha256_free(iot_sha256_context *ctx)
{
if (NULL == ctx) {
return;
}
utils_sha256_zeroize(ctx, sizeof(iot_sha256_context));
}
void utils_sha256_starts(iot_sha256_context *ctx)
{
int is224 = 0;
ctx->total[0] = 0;
ctx->total[1] = 0;
if (is224 == 0) {
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
ctx->is224 = is224;
}
static const uint32_t K[] = {
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
};
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
void utils_sha256_process(iot_sha256_context *ctx, const unsigned char data[64])
{
uint32_t temp1, temp2, W[64];
uint32_t A[8];
unsigned int i;
for (i = 0; i < 8; i++) {
A[i] = ctx->state[i];
}
#if defined(INFRA_SHA256_SMALLER)
for (i = 0; i < 64; i++) {
if (i < 16) {
GET_UINT32_BE(W[i], data, 4 * i);
} else {
R(i);
}
P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i]);
temp1 = A[7];
A[7] = A[6];
A[6] = A[5];
A[5] = A[4];
A[4] = A[3];
A[3] = A[2];
A[2] = A[1];
A[1] = A[0];
A[0] = temp1;
}
#else /* INFRA_SHA256_SMALLER */
for (i = 0; i < 16; i++) {
GET_UINT32_BE(W[i], data, 4 * i);
}
for (i = 0; i < 16; i += 8) {
P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0]);
P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1]);
P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2]);
P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3]);
P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4]);
P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5]);
P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6]);
P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7]);
}
for (i = 16; i < 64; i += 8) {
P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0]);
P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1]);
P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2]);
P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3]);
P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4]);
P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5]);
P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6]);
P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7]);
}
#endif /* INFRA_SHA256_SMALLER */
for (i = 0; i < 8; i++) {
ctx->state[i] += A[i];
}
}
void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, uint32_t ilen)
{
size_t fill;
uint32_t left;
if (ilen == 0) {
return;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if (ctx->total[0] < (uint32_t) ilen) {
ctx->total[1]++;
}
if (left && ilen >= fill) {
memcpy((void *)(ctx->buffer + left), input, fill);
utils_sha256_process(ctx, ctx->buffer);
input += fill;
ilen -= fill;
left = 0;
}
while (ilen >= 64) {
utils_sha256_process(ctx, input);
input += 64;
ilen -= 64;
}
if (ilen > 0) {
memcpy((void *)(ctx->buffer + left), input, ilen);
}
}
static const unsigned char sha256_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
void utils_sha256_finish(iot_sha256_context *ctx, uint8_t output[32])
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = (ctx->total[0] >> 29)
| (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
PUT_UINT32_BE(high, msglen, 0);
PUT_UINT32_BE(low, msglen, 4);
last = ctx->total[0] & 0x3F;
padn = (last < 56) ? (56 - last) : (120 - last);
utils_sha256_update(ctx, sha256_padding, padn);
utils_sha256_update(ctx, msglen, 8);
PUT_UINT32_BE(ctx->state[0], output, 0);
PUT_UINT32_BE(ctx->state[1], output, 4);
PUT_UINT32_BE(ctx->state[2], output, 8);
PUT_UINT32_BE(ctx->state[3], output, 12);
PUT_UINT32_BE(ctx->state[4], output, 16);
PUT_UINT32_BE(ctx->state[5], output, 20);
PUT_UINT32_BE(ctx->state[6], output, 24);
if (ctx->is224 == 0) {
PUT_UINT32_BE(ctx->state[7], output, 28);
}
}
void utils_sha256(const uint8_t *input, uint32_t ilen, uint8_t output[32])
{
iot_sha256_context ctx;
utils_sha256_init(&ctx);
utils_sha256_starts(&ctx);
utils_sha256_update(&ctx, input, ilen);
utils_sha256_finish(&ctx, output);
utils_sha256_free(&ctx);
}
void utils_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32])
{
iot_sha256_context context;
uint8_t k_ipad[SHA256_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
uint8_t k_opad[SHA256_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
int32_t i;
if ((NULL == msg) || (NULL == key) || (NULL == output)) {
return;
}
if (key_len > SHA256_KEY_IOPAD_SIZE) {
return;
}
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < SHA256_KEY_IOPAD_SIZE; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner SHA */
utils_sha256_init(&context); /* init context for 1st pass */
utils_sha256_starts(&context); /* setup context for 1st pass */
utils_sha256_update(&context, k_ipad, SHA256_KEY_IOPAD_SIZE); /* start with inner pad */
utils_sha256_update(&context, msg, msg_len); /* then text of datagram */
utils_sha256_finish(&context, output); /* finish up 1st pass */
/* perform outer SHA */
utils_sha256_init(&context); /* init context for 2nd pass */
utils_sha256_starts(&context); /* setup context for 2nd pass */
utils_sha256_update(&context, k_opad, SHA256_KEY_IOPAD_SIZE); /* start with outer pad */
utils_sha256_update(&context, output, SHA256_DIGEST_SIZE); /* then results of 1st hash */
utils_sha256_finish(&context, output); /* finish up 2nd pass */
}
#endif
/*
*
*/
#ifndef _IOTX_COMMON_SHA256_H_
#define _IOTX_COMMON_SHA256_H_
#include <stdint.h>
#define SHA256_DIGEST_LENGTH (32)
#define SHA256_BLOCK_LENGTH (64)
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
/**
* \brief SHA-256 context structure
*/
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int is224; /*!< 0 => SHA-256, else SHA-224 */
} iot_sha256_context;
typedef union {
char sptr[8];
uint64_t lint;
} u_retLen;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void utils_sha256_init(iot_sha256_context *ctx);
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void utils_sha256_free(iot_sha256_context *ctx);
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
*/
void utils_sha256_starts(iot_sha256_context *ctx);
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, uint32_t ilen);
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-256 checksum result
*/
void utils_sha256_finish(iot_sha256_context *ctx, uint8_t output[32]);
/* Internal use */
void utils_sha256_process(iot_sha256_context *ctx, const unsigned char data[64]);
/**
* \brief Output = SHA-256( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-256 checksum result
*/
void utils_sha256(const uint8_t *input, uint32_t ilen, uint8_t output[32]);
void utils_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32]);
#endif
#include "infra_config.h"
#ifdef INFRA_STRING
#include <stdio.h>
#include <string.h>
#include "infra_types.h"
#include "infra_string.h"
int8_t infra_hex2char(uint8_t hex)
{
hex = hex & 0xF;
return (int8_t)(hex < 10 ? '0' + hex : hex - 10 + 'a');
}
void infra_hex2str(uint8_t *input, uint16_t input_len, char *output)
{
char *zEncode = "0123456789ABCDEF";
int i = 0, j = 0;
for (i = 0; i < input_len; i++) {
output[j++] = zEncode[(input[i] >> 4) & 0xf];
output[j++] = zEncode[(input[i]) & 0xf];
}
}
void infra_int2str(uint32_t input, char output[10])
{
uint8_t i = 0, j = 0;
char tmp[10] = {0};
do {
tmp[i++] = input%10 + '0';
}while((input/=10)>0);
do {
output[--i] = tmp[j++];
}while(i > 0);
}
char *infra_strtok(char *str, const char *delim)
{
int only_delim = 1;
static char *pos = NULL;
static char *target = NULL;
pos = (str == NULL)?(pos):(str);
if (pos == NULL || delim == NULL ||
strlen(pos) <= strlen(delim)) {
return NULL;
}
target = pos;
while (strlen(pos) >= strlen(delim)) {
if (memcmp(pos,delim,strlen(delim)) != 0) {
only_delim = 0;
pos++;
continue;
}
if (strlen(pos) == strlen(delim)) {
memset(pos,0,strlen(delim));
if (only_delim) {
return NULL;
}
return target;
}
if (target == pos) {
pos += strlen(delim);
target = pos;
}else{
memset(pos,0,strlen(delim));
pos += strlen(delim);
break;
}
}
return target;
}
#define LITE_isdigit(c) (((c) <= '9' && (c) >= '0') ? (1) : (0))
static uint8_t _hexval_of_char(char hex)
{
if (LITE_isdigit(hex)) {
return (hex - '0');
}
if (hex >= 'a' && hex <= 'f') {
return (hex - 'a' + 10);
}
if (hex >= 'A' && hex <= 'F') {
return (hex - 'A' + 10);
}
return 0;
}
void LITE_hexstr_convert(char *input, int input_len, unsigned char *output, int output_len)
{
int i = 0;
uint8_t ch0, ch1;
if (input_len % 2 != 0) {
return;
}
while (i < input_len / 2 && i < output_len) {
ch0 = _hexval_of_char((char)input[2 * i]);
ch1 = _hexval_of_char((char)input[2 * i + 1]);
output[i] = (ch0 << 4 | ch1);
i++;
}
}
void LITE_hexbuf_convert(unsigned char *digest, char *out, int in_len, int uppercase)
{
static char *zEncode[] = {"0123456789abcdef", "0123456789ABCDEF"};
int j = 0;
int i = 0;
int idx = uppercase ? 1 : 0;
for (i = 0; i < in_len; i ++) {
int a = digest[i];
out[j++] = zEncode[idx][(a >> 4) & 0xf];
out[j++] = zEncode[idx][a & 0xf];
}
}
int infra_str2int(const char *input, int *val)
{
int sign = 0;
int temp = 0;
if (input == NULL || val == NULL) {
return -1;
}
while(*input == ' ') { /* only support skipping space */
input++;
}
if (*input == '+') {
input++;
}
else if (*input == '-') {
input++;
sign = -1;
}
while (*input != 0) {
if (*input < '0' || *input > '9') {
break;
}
temp = temp * 10 + (*input - '0');
input++;
}
if (sign == -1) {
temp = -temp;
}
*val = temp;
return 0;
}
#endif
#ifdef INFRA_RANDOM
uint64_t HAL_UptimeMs(void);
void HAL_Srandom(uint32_t seed);
uint32_t HAL_Random(uint32_t region);
int infra_randstr(char *random, int length)
{
int index = 0;
HAL_Srandom(HAL_UptimeMs());
for (index = 0; index < length; index++) {
switch (HAL_Random(3)) {
case 0: {
random[index] = 'A' + HAL_Random(26);
}
break;
case 1: {
random[index] = 'a' + HAL_Random(26);
}
break;
case 2: {
random[index] = '0' + HAL_Random(10);
}
break;
default: {
return -1;
}
}
}
return 0;
}
#endif
#ifndef _INFRA_STRING_H_
#define _INFRA_STRING_H_
#include "infra_types.h"
int8_t infra_hex2char(uint8_t hex);
void infra_hex2str(uint8_t *input, uint16_t input_len, char *output);
void infra_int2str(uint32_t input, char output[10]);
char *infra_strtok(char *str, const char *delim);
int infra_randstr(char *random, int length);
void LITE_hexstr_convert(char *input, int input_len, unsigned char *output, int output_len);
int infra_str2int(const char *input, int *val);
void LITE_hexbuf_convert(unsigned char *digest, char *out, int in_len, int uppercase);
#endif
#include "infra_config.h"
#ifdef INFRA_TIMER
/*
*
*/
#include "infra_types.h"
#include "infra_timer.h"
uint64_t HAL_UptimeMs(void);
void iotx_time_start(iotx_time_t *timer)
{
if (!timer) {
return;
}
timer->time = HAL_UptimeMs();
}
uint32_t utils_time_spend(iotx_time_t *start)
{
uint32_t now, res;
if (!start) {
return 0;
}
now = HAL_UptimeMs();
res = now - start->time;
return res;
}
uint32_t iotx_time_left(iotx_time_t *end)
{
uint32_t now, res;
if (!end) {
return 0;
}
if (utils_time_is_expired(end)) {
return 0;
}
now = HAL_UptimeMs();
res = end->time - now;
return res;
}
uint32_t utils_time_is_expired(iotx_time_t *timer)
{
uint32_t cur_time;
if (!timer) {
return 1;
}
cur_time = HAL_UptimeMs();
/*
* WARNING: Do NOT change the following code until you know exactly what it do!
*
* check whether it reach destination time or not.
*/
if ((cur_time - timer->time) < (UINT32_MAX / 2)) {
return 1;
} else {
return 0;
}
}
void iotx_time_init(iotx_time_t *timer)
{
if (!timer) {
return;
}
timer->time = 0;
}
void utils_time_countdown_ms(iotx_time_t *timer, uint32_t millisecond)
{
if (!timer) {
return;
}
timer->time = HAL_UptimeMs() + millisecond;
}
uint32_t utils_time_get_ms(void)
{
return HAL_UptimeMs();
}
#endif
/*
*
*/
#ifndef _INFRA_TIMER_H_
#define _INFRA_TIMER_H_
#include "infra_types.h"
typedef struct {
uint32_t time;
} iotx_time_t;
void iotx_time_start(iotx_time_t *timer);
uint32_t utils_time_spend(iotx_time_t *start);
uint32_t iotx_time_left(iotx_time_t *end);
uint32_t utils_time_is_expired(iotx_time_t *timer);
void iotx_time_init(iotx_time_t *timer);
void utils_time_countdown_ms(iotx_time_t *timer, uint32_t millisecond);
uint32_t utils_time_get_ms(void);
#endif /* _IOTX_COMMON_TIMER_H_ */
#ifndef _INFRA_TYPES_H_
#define _INFRA_TYPES_H_
#include <stddef.h>
#include "infra_config.h"
#define IOT_TRUE (1) /* indicate boolean value true */
#define IOT_FALSE (0) /* indicate boolean value false */
#if !defined(PLATFORM_HAS_STDINT)
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef unsigned long int uint64_t;
typedef signed long int int64_t;
typedef unsigned int uintptr_t;
#else
#include <stdint.h>
#endif /* #if !defined(PLATFORM_HAS_STDINT) */
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment