support aliyun sdk on TencentOS tiny

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,336 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef INFRA_AES_H
#define INFRA_AES_H
#if !defined(INFRA_AES_CONFIG_FILE)
#include "infra_aes_config.h"
#endif
#include <stddef.h>
#include <stdint.h>
/* padlock.c and aesni.c rely on these values! */
#define INFRA_AES_ENCRYPT 1
#define INFRA_AES_DECRYPT 0
#define INFRA_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define INFRA_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
#if !defined(INFRA_AES_ALT)
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES context structure
*
* \note buf is able to hold 32 extra bytes, which can be used:
* - for alignment purposes if VIA padlock is used, and/or
* - to simplify key expansion in the 256-bit case by
* generating an extra round key
*/
typedef struct {
int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */
}
infra_aes_context;
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void infra_aes_init(infra_aes_context *ctx);
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void infra_aes_free(infra_aes_context *ctx);
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or INFRA_ERR_AES_INVALID_KEY_LENGTH
*/
int infra_aes_setkey_enc(infra_aes_context *ctx, const unsigned char *key,
unsigned int keybits);
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or INFRA_ERR_AES_INVALID_KEY_LENGTH
*/
int infra_aes_setkey_dec(infra_aes_context *ctx, const unsigned char *key,
unsigned int keybits);
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int infra_aes_crypt_ecb(infra_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16]);
#if defined(INFRA_CIPHER_MODE_CBC)
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or INFRA_ERR_AES_INVALID_INPUT_LENGTH
*/
int infra_aes_crypt_cbc(infra_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output);
#endif /* INFRA_CIPHER_MODE_CBC */
#if defined(INFRA_CIPHER_MODE_CFB)
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* infra_aes_setkey_enc() for both INFRA_AES_ENCRYPT and INFRA_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int infra_aes_crypt_cfb128(infra_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output);
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* infra_aes_setkey_enc() for both INFRA_AES_ENCRYPT and INFRA_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int infra_aes_crypt_cfb8(infra_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output);
#endif /*INFRA_CIPHER_MODE_CFB */
#if defined(INFRA_CIPHER_MODE_CTR)
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* infra_aes_setkey_enc() for both INFRA_AES_ENCRYPT and INFRA_AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int infra_aes_crypt_ctr(infra_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output);
#endif /* INFRA_CIPHER_MODE_CTR */
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see INFRA_AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*
* \return 0 if successful
*/
int infra_internal_aes_encrypt(infra_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16]);
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see INFRA_AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*
* \return 0 if successful
*/
int infra_internal_aes_decrypt(infra_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16]);
#if !defined(INFRA_DEPRECATED_REMOVED)
#if defined(INFRA_DEPRECATED_WARNING)
#define INFRA_DEPRECATED __attribute__((deprecated))
#else
#define INFRA_DEPRECATED
#endif
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see INFRA_AES_ENCRYPT_ALT)
*
* \deprecated Superseded by infra_aes_encrypt_ext() in 2.5.0
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
#if 0
INFRA_DEPRECATED static inline void infra_aes_encrypt(
infra_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16])
{
infra_internal_aes_encrypt(ctx, input, output);
}
#endif
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see INFRA_AES_DECRYPT_ALT)
*
* \deprecated Superseded by infra_aes_decrypt_ext() in 2.5.0
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
#if 0
INFRA_DEPRECATED static inline void infra_aes_decrypt(
infra_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16])
{
infra_internal_aes_decrypt(ctx, input, output);
}
#endif
#undef INFRA_DEPRECATED
#endif /* !INFRA_DEPRECATED_REMOVED */
#ifdef __cplusplus
}
#endif
#else /* INFRA_AES_ALT */
#include "aes_alt.h"
#endif /* INFRA_AES_ALT */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int infra_aes_self_test(int verbose);
#ifdef __cplusplus
}
#endif
#endif /* aes.h */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef _INFRA_CJSON_H_
#define _INFRA_CJSON_H_
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#ifndef LITE_CJSON_NESTING_LIMIT
#define LITE_CJSON_NESTING_LIMIT 1000
#endif
/* The cJSON structure: */
typedef struct lite_cjson_st {
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *value;
int value_length;
/* The item's size, if type == cJSON_Array and type == cJSON_Object */
int size;
double value_double;
int value_int;
} lite_cjson_t;
int lite_cjson_parse(const char *src, int src_len, lite_cjson_t *lite);
int lite_cjson_is_false(lite_cjson_t *lite);
int lite_cjson_is_true(lite_cjson_t *lite);
int lite_cjson_is_null(lite_cjson_t *lite);
int lite_cjson_is_number(lite_cjson_t *lite);
int lite_cjson_is_string(lite_cjson_t *lite);
int lite_cjson_is_array(lite_cjson_t *lite);
int lite_cjson_is_object(lite_cjson_t *lite);
int lite_cjson_array_item(lite_cjson_t *lite, int index, lite_cjson_t *lite_item);
int lite_cjson_object_item(
lite_cjson_t *lite,
const char *key,
int key_len,
lite_cjson_t *lite_item);
int lite_cjson_object_item_by_index(
lite_cjson_t *lite,
int index,
lite_cjson_t *lite_item_key,
lite_cjson_t *lite_item_value);
/*** lite_cjson create, add and print ***/
typedef int cJSON_bool;
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct lite_cjson_item_t {
struct lite_cjson_item_t *next,
*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct lite_cjson_item_t
*child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} lite_cjson_item_t;
typedef struct {
void *(*malloc_fn)(unsigned int sz);
void(*free_fn)(void *ptr);
} lite_cjson_hooks;
void lite_cjson_init_hooks(lite_cjson_hooks *hooks);
/* Render a lite_cjson_item_t entity to text for transfer/storage. Free the char* when finished. */
char *lite_cjson_print(lite_cjson_item_t *item);
char *lite_cjson_print_unformatted(lite_cjson_item_t *item);
/* Delete a lite_cjson_item_t entity and all subentities. */
void lite_cjson_delete(lite_cjson_item_t *item);
/* Append item to specific object */
void lite_cjson_add_item_to_array(lite_cjson_item_t *array, lite_cjson_item_t *item);
void lite_cjson_add_item_to_object(lite_cjson_item_t *object, const char *string, lite_cjson_item_t *item);
/* These calls create a lite_cjson_item_t item of the appropriate type. */
lite_cjson_item_t *lite_cjson_create_null(void);
lite_cjson_item_t *lite_cjson_create_true(void);
lite_cjson_item_t *lite_cjson_create_false(void);
lite_cjson_item_t *lite_cjson_create_bool(int b);
lite_cjson_item_t *lite_cjson_create_number(double num);
lite_cjson_item_t *lite_cjson_create_string(const char *string);
lite_cjson_item_t *lite_cjson_create_array(void);
lite_cjson_item_t *lite_cjson_create_object(void);
/* These utilities create an Array of count items. */
lite_cjson_item_t *lite_cjson_create_intArray(const int *numbers, int count);
lite_cjson_item_t *lite_cjson_create_floatArray(const float *numbers, int count);
lite_cjson_item_t *lite_cjson_create_doubleArray(const double *numbers, int count);
lite_cjson_item_t *lite_cjson_create_stringArray(const char **strings, int count);
/* Macros for creating things quickly. */
#define lite_cjson_add_null_to_object(object,name) lite_cjson_add_item_to_object(object, name, lite_cjson_create_null())
#define lite_cjson_add_true_to_object(object,name) lite_cjson_add_item_to_object(object, name, lite_cjson_create_true())
#define lite_cjson_add_false_to_object(object,name) lite_cjson_add_item_to_object(object, name, lite_cjson_create_false())
#define lite_cjson_add_bool_to_object(object,name,b) lite_cjson_add_item_to_object(object, name, lite_cjson_create_bool(b))
#define lite_cjson_add_number_to_object(object,name,n) lite_cjson_add_item_to_object(object, name, lite_cjson_create_number(n))
#define lite_cjson_add_string_to_object(object,name,s) lite_cjson_add_item_to_object(object, name, lite_cjson_create_string(s))
#endif

View File

@@ -0,0 +1,287 @@
#include "infra_config.h"
#ifdef INFRA_COMPAT
#include <string.h>
#include "infra_types.h"
#include "infra_defs.h"
#include "infra_compat.h"
sdk_impl_ctx_t g_sdk_impl_ctx = {0};
#if !defined(INFRA_LOG)
void IOT_SetLogLevel(IOT_LogLevel level) {}
#endif
#ifdef MQTT_COMM_ENABLED
#include "dev_sign_api.h"
#include "mqtt_api.h"
#ifdef INFRA_LOG
#include "infra_log.h"
#define sdk_err(...) log_err("infra_compat", __VA_ARGS__)
#define sdk_info(...) log_info("infra_compat", __VA_ARGS__)
#else
#define sdk_err(...)
#define sdk_info(...)
#endif
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
/* global variable for mqtt construction */
static iotx_conn_info_t g_iotx_conn_info = {0};
static char g_empty_string[1] = "";
int IOT_SetupConnInfo(const char *product_key,
const char *device_name,
const char *device_secret,
void **info_ptr)
{
if (product_key == NULL || device_name == NULL || device_secret == NULL ||
strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
strlen(device_name) > IOTX_DEVICE_NAME_LEN ||
strlen(device_secret) > IOTX_DEVICE_SECRET_LEN) {
return NULL_VALUE_ERROR;
}
if (info_ptr) {
memset(&g_iotx_conn_info, 0, sizeof(iotx_conn_info_t));
g_iotx_conn_info.host_name = g_empty_string;
g_iotx_conn_info.client_id = g_empty_string;
g_iotx_conn_info.username = g_empty_string;
g_iotx_conn_info.password = g_empty_string;
g_iotx_conn_info.pub_key = g_empty_string;
*info_ptr = &g_iotx_conn_info;
}
return SUCCESS_RETURN;
}
#endif /* #ifdef MQTT_COMM_ENABLED */
#if defined(DEVICE_MODEL_CLASSIC) && defined(DEVICE_MODEL_ENABLED)
#include "iotx_dm.h"
#endif
#if defined(DEVICE_MODEL_GATEWAY)
extern int iot_linkkit_subdev_query_id(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
#endif
int IOT_Ioctl(int option, void *data)
{
int res = SUCCESS_RETURN;
sdk_impl_ctx_t *ctx = NULL;
ctx = &g_sdk_impl_ctx;
if (option < 0 || data == NULL) {
return FAIL_RETURN;
}
switch (option) {
case IOTX_IOCTL_SET_REGION: {
ctx->domain_type = *(iotx_mqtt_region_types_t *)data;
/* iotx_guider_set_region(*(int *)data); */
res = SUCCESS_RETURN;
}
break;
case IOTX_IOCTL_GET_REGION: {
*(iotx_mqtt_region_types_t *)data = ctx->domain_type;
res = SUCCESS_RETURN;
}
break;
case IOTX_IOCTL_SET_MQTT_DOMAIN: {
ctx->domain_type = IOTX_CLOUD_REGION_CUSTOM;
if (strlen(data) > IOTX_DOMAIN_MAX_LEN) {
return FAIL_RETURN;
}
memset(ctx->cloud_custom_domain, 0, strlen((char *)data) + 1);
memcpy(ctx->cloud_custom_domain, data, strlen((char *)data));
g_infra_mqtt_domain[IOTX_CLOUD_REGION_CUSTOM] = (const char *)ctx->cloud_custom_domain;
res = SUCCESS_RETURN;
}
break;
case IOTX_IOCTL_SET_HTTP_DOMAIN: {
ctx->domain_type = IOTX_HTTP_REGION_CUSTOM;
if (strlen(data) > IOTX_DOMAIN_MAX_LEN) {
return FAIL_RETURN;
}
memset(ctx->http_custom_domain, 0, strlen((char *)data) + 1);
memcpy(ctx->http_custom_domain, data, strlen((char *)data));
g_infra_http_domain[IOTX_CLOUD_REGION_CUSTOM] = (const char *)ctx->http_custom_domain;
res = SUCCESS_RETURN;
}
break;
case IOTX_IOCTL_SET_DYNAMIC_REGISTER: {
ctx->dynamic_register = *(int *)data;
res = SUCCESS_RETURN;
}
break;
case IOTX_IOCTL_GET_DYNAMIC_REGISTER: {
*(int *)data = ctx->dynamic_register;
res = SUCCESS_RETURN;
}
break;
#if defined(DEVICE_MODEL_CLASSIC) && defined(DEVICE_MODEL_ENABLED) && !defined(DEPRECATED_LINKKIT)
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
case IOTX_IOCTL_RECV_EVENT_REPLY:
case IOTX_IOCTL_RECV_PROP_REPLY: {
res = iotx_dm_set_opt(IMPL_LINKKIT_IOCTL_SWITCH_EVENT_POST_REPLY, data);
}
break;
case IOTX_IOCTL_SEND_PROP_SET_REPLY : {
res = iotx_dm_set_opt(IMPL_LINKKIT_IOCTL_SWITCH_PROPERTY_SET_REPLY, data);
}
break;
#endif
case IOTX_IOCTL_SET_SUBDEV_SIGN: {
/* todo */
}
break;
case IOTX_IOCTL_GET_SUBDEV_LOGIN: {
/* todo */
}
break;
#if defined(DEVICE_MODEL_CLASSIC) && defined(DEVICE_MODEL_GATEWAY)
#ifdef DEVICE_MODEL_SUBDEV_OTA
case IOTX_IOCTL_SET_OTA_DEV_ID: {
int devid = *(int *)(data);
res = iotx_dm_ota_switch_device(devid);
}
break;
#endif
#endif
#else
case IOTX_IOCTL_RECV_EVENT_REPLY:
case IOTX_IOCTL_RECV_PROP_REPLY:
case IOTX_IOCTL_SEND_PROP_SET_REPLY:
case IOTX_IOCTL_GET_SUBDEV_LOGIN: {
res = SUCCESS_RETURN;
}
break;
#endif
#if defined(DEVICE_MODEL_GATEWAY)
case IOTX_IOCTL_QUERY_DEVID: {
iotx_dev_meta_info_t *dev_info = (iotx_dev_meta_info_t *)data;
res = iot_linkkit_subdev_query_id(dev_info->product_key, dev_info->device_name);
}
break;
#endif
case IOTX_IOCTL_SET_CUSTOMIZE_INFO: {
if (strlen(data) > IOTX_CUSTOMIZE_INFO_LEN) {
return FAIL_RETURN;
}
memset(ctx->mqtt_customzie_info, 0, strlen((char *)data) + 1);
memcpy(ctx->mqtt_customzie_info, data, strlen((char *)data));
res = SUCCESS_RETURN;
}
break;
default: {
res = FAIL_RETURN;
}
break;
}
return res;
}
void IOT_DumpMemoryStats(IOT_LogLevel level)
{
#ifdef INFRA_MEM_STATS
int lvl = (int)level;
if (lvl > LOG_DEBUG_LEVEL) {
lvl = LOG_DEBUG_LEVEL;
HAL_Printf("Invalid input level, using default: %d => %d", level, lvl);
}
LITE_dump_malloc_free_stats(lvl);
#endif
}
static void *g_event_monitor = NULL;
int iotx_event_regist_cb(void (*monitor_cb)(int event))
{
g_event_monitor = (void *)monitor_cb;
return 0;
}
int iotx_event_post(int event)
{
if (g_event_monitor == NULL) {
return -1;
}
((void (*)(int))g_event_monitor)(event);
return 0;
}
typedef struct {
int eventid;
void *callback;
} impl_event_map_t;
static impl_event_map_t g_impl_event_map[] = {
{ITE_AWSS_STATUS, NULL},
{ITE_CONNECT_SUCC, NULL},
{ITE_CONNECT_FAIL, NULL},
{ITE_DISCONNECTED, NULL},
{ITE_RAWDATA_ARRIVED, NULL},
{ITE_SERVICE_REQUEST, NULL},
{ITE_PROPERTY_SET, NULL},
{ITE_PROPERTY_GET, NULL},
#ifdef DEVICE_MODEL_SHADOW
{ITE_PROPERTY_DESIRED_GET_REPLY, NULL},
#endif
{ITE_REPORT_REPLY, NULL},
{ITE_TRIGGER_EVENT_REPLY, NULL},
{ITE_TIMESTAMP_REPLY, NULL},
{ITE_TOPOLIST_REPLY, NULL},
{ITE_PERMIT_JOIN, NULL},
{ITE_INITIALIZE_COMPLETED, NULL},
{ITE_FOTA, NULL},
{ITE_COTA, NULL},
{ITE_MQTT_CONNECT_SUCC, NULL}
};
void *iotx_event_callback(int evt)
{
if (evt < 0 || evt >= sizeof(g_impl_event_map) / sizeof(impl_event_map_t)) {
return NULL;
}
return g_impl_event_map[evt].callback;
}
DEFINE_EVENT_CALLBACK(ITE_AWSS_STATUS, int (*callback)(int))
DEFINE_EVENT_CALLBACK(ITE_CONNECT_SUCC, int (*callback)(void))
DEFINE_EVENT_CALLBACK(ITE_CONNECT_FAIL, int (*callback)(void))
DEFINE_EVENT_CALLBACK(ITE_DISCONNECTED, int (*callback)(void))
DEFINE_EVENT_CALLBACK(ITE_RAWDATA_ARRIVED, int (*callback)(const int, const unsigned char *, const int))
DEFINE_EVENT_CALLBACK(ITE_SERVICE_REQUEST, int (*callback)(const int, const char *, const int, const char *,
const int, char **, int *))
DEFINE_EVENT_CALLBACK(ITE_PROPERTY_SET, int (*callback)(const int, const char *, const int))
#ifdef DEVICE_MODEL_SHADOW
DEFINE_EVENT_CALLBACK(ITE_PROPERTY_DESIRED_GET_REPLY, int (*callback)(const char *, const int))
#endif
DEFINE_EVENT_CALLBACK(ITE_PROPERTY_GET, int (*callback)(const int, const char *, const int, char **, int *))
DEFINE_EVENT_CALLBACK(ITE_REPORT_REPLY, int (*callback)(const int, const int, const int, const char *,
const int))
DEFINE_EVENT_CALLBACK(ITE_TRIGGER_EVENT_REPLY, int (*callback)(const int, const int, const int, const char *,
const int, const char *, const int))
DEFINE_EVENT_CALLBACK(ITE_TIMESTAMP_REPLY, int (*callback)(const char *))
DEFINE_EVENT_CALLBACK(ITE_TOPOLIST_REPLY, int (*callback)(const int, const int, const int, const char *,
const int))
DEFINE_EVENT_CALLBACK(ITE_PERMIT_JOIN, int (*callback)(const char *, int))
DEFINE_EVENT_CALLBACK(ITE_INITIALIZE_COMPLETED, int (*callback)(const int))
DEFINE_EVENT_CALLBACK(ITE_FOTA, int (*callback)(const int, const char *))
DEFINE_EVENT_CALLBACK(ITE_COTA, int (*callback)(const int, const char *, int, const char *,
const char *, const char *, const char *))
DEFINE_EVENT_CALLBACK(ITE_MQTT_CONNECT_SUCC, int (*callback)(void))
#endif

View File

@@ -0,0 +1,284 @@
#ifndef _INFRA_COMPAT_H_
#define _INFRA_COMPAT_H_
#include "infra_defs.h"
#include "infra_list.h"
#undef being_deprecated
#define being_deprecated
typedef enum _IOT_LogLevel {
IOT_LOG_NONE = 0,
IOT_LOG_CRIT,
IOT_LOG_ERROR,
IOT_LOG_WARNING,
IOT_LOG_INFO,
IOT_LOG_DEBUG,
} IOT_LogLevel;
void IOT_SetLogLevel(IOT_LogLevel level);
void IOT_DumpMemoryStats(IOT_LogLevel level);
/**
* @brief event list used for iotx_regist_event_monitor_cb
*/
enum iotx_event_t {
IOTX_AWSS_START = 0x1000, /* AWSS start without enbale, just supports device discover */
IOTX_AWSS_ENABLE, /* AWSS enable */
IOTX_AWSS_LOCK_CHAN, /* AWSS lock channel(Got AWSS sync packet) */
IOTX_AWSS_CS_ERR, /* AWSS AWSS checksum is error */
IOTX_AWSS_PASSWD_ERR, /* AWSS decrypt passwd error */
IOTX_AWSS_GOT_SSID_PASSWD, /* AWSS parse ssid and passwd successfully */
IOTX_AWSS_CONNECT_ADHA, /* AWSS try to connnect adha (device discover, router solution) */
IOTX_AWSS_CONNECT_ADHA_FAIL, /* AWSS fails to connect adha */
IOTX_AWSS_CONNECT_AHA, /* AWSS try to connect aha (AP solution) */
IOTX_AWSS_CONNECT_AHA_FAIL, /* AWSS fails to connect aha */
IOTX_AWSS_SETUP_NOTIFY, /* AWSS sends out device setup information (AP and router solution) */
IOTX_AWSS_CONNECT_ROUTER, /* AWSS try to connect destination router */
IOTX_AWSS_CONNECT_ROUTER_FAIL, /* AWSS fails to connect destination router. */
IOTX_AWSS_GOT_IP, /* AWSS connects destination successfully and got ip address */
IOTX_AWSS_SUC_NOTIFY, /* AWSS sends out success notify (AWSS sucess) */
IOTX_AWSS_BIND_NOTIFY, /* AWSS sends out bind notify information to support bind between user and device */
IOTX_AWSS_ENABLE_TIMEOUT, /* AWSS enable timeout(user needs to call awss_config_press again to enable awss) */
IOTX_CONN_CLOUD = 0x2000, /* Device try to connect cloud */
IOTX_CONN_CLOUD_FAIL, /* Device fails to connect cloud, refer to net_sockets.h for error code */
IOTX_CONN_CLOUD_SUC, /* Device connects cloud successfully */
IOTX_RESET = 0x3000, /* Linkkit reset success (just got reset response from cloud without any other operation) */
};
/**
* @brief register callback to monitor all event from system.
*
* @param callback, when some event occurs, the system will trigger callback to user.
* refer to enum iotx_event_t for event list supported.
*
* @return 0 when success, -1 when fail.
* @note: user should make sure that callback is not block and runs to complete fast.
*/
int iotx_event_regist_cb(void (*monitor_cb)(int event));
/**
* @brief post event to trigger callback resitered by iotx_event_regist_cb
*
* @param event, event id, refer to iotx_event_t
*
* @return 0 when success, -1 when fail.
*/
int iotx_event_post(int event);
#ifndef BUILD_AOS
#ifndef VERSION_NUM_SIZE
#define VERSION_NUM_SIZE 4
#endif
#ifndef RANDOM_NUM_SIZE
#define RANDOM_NUM_SIZE 4
#endif
#ifndef MAC_ADDRESS_SIZE
#define MAC_ADDRESS_SIZE 8
#endif
#ifndef CHIP_CODE_SIZE
#define CHIP_CODE_SIZE 4
#endif
#define AOS_ACTIVE_INFO_LEN (81)
unsigned int aos_get_version_info(unsigned char version_num[VERSION_NUM_SIZE],
unsigned char random_num[RANDOM_NUM_SIZE],
unsigned char mac_address[MAC_ADDRESS_SIZE],
unsigned char chip_code[CHIP_CODE_SIZE],
unsigned char *output_buffer,
unsigned int output_buffer_size);
#endif
typedef enum {
ITE_AWSS_STATUS,
ITE_CONNECT_SUCC,
ITE_CONNECT_FAIL,
ITE_DISCONNECTED,
ITE_RAWDATA_ARRIVED,
ITE_SERVICE_REQUEST,
ITE_PROPERTY_SET,
ITE_PROPERTY_GET,
#ifdef DEVICE_MODEL_SHADOW
ITE_PROPERTY_DESIRED_GET_REPLY,
#endif
ITE_REPORT_REPLY,
ITE_TRIGGER_EVENT_REPLY,
ITE_TIMESTAMP_REPLY,
ITE_TOPOLIST_REPLY,
ITE_PERMIT_JOIN,
ITE_INITIALIZE_COMPLETED,
ITE_FOTA,
ITE_COTA,
ITE_MQTT_CONNECT_SUCC
} iotx_ioctl_event_t;
#define IOT_RegisterCallback(evt, cb) iotx_register_for_##evt(cb);
#define DECLARE_EVENT_CALLBACK(evt, cb) int iotx_register_for_##evt(cb);
#define DEFINE_EVENT_CALLBACK(evt, cb) int iotx_register_for_##evt(cb) { \
if (evt < 0 || evt >= sizeof(g_impl_event_map)/sizeof(impl_event_map_t)) {return -1;} \
g_impl_event_map[evt].callback = (void *)callback;return 0;}
DECLARE_EVENT_CALLBACK(ITE_AWSS_STATUS, int (*cb)(int))
DECLARE_EVENT_CALLBACK(ITE_CONNECT_SUCC, int (*cb)(void))
DECLARE_EVENT_CALLBACK(ITE_CONNECT_FAIL, int (*cb)(void))
DECLARE_EVENT_CALLBACK(ITE_DISCONNECTED, int (*cb)(void))
DECLARE_EVENT_CALLBACK(ITE_RAWDATA_ARRIVED, int (*cb)(const int, const unsigned char *, const int))
DECLARE_EVENT_CALLBACK(ITE_SERVICE_REQUEST, int (*cb)(const int, const char *, const int, const char *, const int,
char **, int *))
DECLARE_EVENT_CALLBACK(ITE_PROPERTY_SET, int (*cb)(const int, const char *, const int))
DECLARE_EVENT_CALLBACK(ITE_PROPERTY_DESIRED_GET_REPLY, int (*cb)(const char *, const int))
DECLARE_EVENT_CALLBACK(ITE_PROPERTY_GET, int (*cb)(const int, const char *, const int, char **, int *))
DECLARE_EVENT_CALLBACK(ITE_REPORT_REPLY, int (*cb)(const int, const int, const int, const char *, const int))
DECLARE_EVENT_CALLBACK(ITE_TRIGGER_EVENT_REPLY, int (*cb)(const int, const int, const int, const char *, const int,
const char *, const int))
DECLARE_EVENT_CALLBACK(ITE_TIMESTAMP_REPLY, int (*cb)(const char *))
DECLARE_EVENT_CALLBACK(ITE_TOPOLIST_REPLY, int (*cb)(const int, const int, const int, const char *, const int))
DECLARE_EVENT_CALLBACK(ITE_PERMIT_JOIN, int (*cb)(const char *, const int))
DECLARE_EVENT_CALLBACK(ITE_INITIALIZE_COMPLETED, int (*cb)(const int))
DECLARE_EVENT_CALLBACK(ITE_FOTA, int (*cb)(const int, const char *))
DECLARE_EVENT_CALLBACK(ITE_COTA, int (*cb)(const int, const char *, int, const char *, const char *,
const char *, const char *))
DECLARE_EVENT_CALLBACK(ITE_MQTT_CONNECT_SUCC, int (*cb)(void))
void *iotx_event_callback(int evt);
#ifndef offset_of
#define offset_of aos_offsetof
#endif
#ifndef container_of
#define container_of aos_container_of
#endif
#define LIST_HEAD AOS_DLIST_HEAD
#define LIST_HEAD_INIT AOS_DLIST_INIT
#define INIT_LIST_HEAD INIT_AOS_DLIST_HEAD
#define LIST_INIT AOS_DLIST_INIT
#define list_head dlist_s
#define list_head_t dlist_t
#define list_add dlist_add
#define list_add_tail dlist_add_tail
#define list_del dlist_del
#define list_empty dlist_empty
#define list_entry_number dlist_entry_number
#define list_first_entry dlist_first_entry
#define list_for_each dlist_for_each
#define list_for_each_entry_reverse dlist_for_each_entry_reverse
#define list_for_each_safe dlist_for_each_safe
#define list_init dlist_init
#define list_for_each_entry(pos, head, member, type) \
dlist_for_each_entry(head, pos, type, member)
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
#define list_next_entry(pos, member, type) \
list_entry((pos)->member.next, type, member)
static inline void list_del_init(struct list_head *entry)
{
list_del(entry);
INIT_LIST_HEAD(entry);
}
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
typedef struct {
uint16_t port;
uint8_t init;
char *host_name;
char *client_id;
char *username;
char *password;
const char *pub_key;
} iotx_conn_info_t, *iotx_conn_info_pt;
int IOT_SetupConnInfo(const char *product_key,
const char *device_name,
const char *device_secret,
void **info_ptr);
typedef enum {
IOTX_IOCTL_SET_REGION, /* value(int*): iotx_cloud_region_types_t */
IOTX_IOCTL_GET_REGION, /* value(int*) */
IOTX_IOCTL_SET_MQTT_DOMAIN, /* value(const char*): point to mqtt domain string */
IOTX_IOCTL_SET_HTTP_DOMAIN, /* value(const char*): point to http domain string */
IOTX_IOCTL_SET_DYNAMIC_REGISTER, /* value(int*): 0 - Disable Dynamic Register, 1 - Enable Dynamic Register */
IOTX_IOCTL_GET_DYNAMIC_REGISTER, /* value(int*) */
IOTX_IOCTL_RECV_PROP_REPLY, /* value(int*): 0 - Disable property post reply by cloud; 1 - Enable property post reply by cloud */
IOTX_IOCTL_RECV_EVENT_REPLY, /* value(int*): 0 - Disable event post reply by cloud; 1 - Enable event post reply by cloud */
IOTX_IOCTL_SEND_PROP_SET_REPLY, /* value(int*): 0 - Disable send post set reply by devid; 1 - Enable property set reply by devid */
IOTX_IOCTL_SET_SUBDEV_SIGN, /* value(const char*): only for slave device, set signature of subdevice */
IOTX_IOCTL_GET_SUBDEV_LOGIN, /* value(int*): 0 - SubDev is logout; 1 - SubDev is login */
IOTX_IOCTL_SET_OTA_DEV_ID, /* value(int*): select the device to do OTA according to devid */
IOTX_IOCTL_QUERY_DEVID, /* value(iotx_dev_meta_info_t*): device meta info, only productKey and deviceName is required, ret value is subdev_id or -1 */
IOTX_IOCTL_SET_CUSTOMIZE_INFO, /* value(char*): set mqtt clientID customize information */
} iotx_ioctl_option_t;
typedef enum {
IMPL_LINKKIT_IOCTL_SWITCH_PROPERTY_POST_REPLY, /* only for master device, choose whether you need receive property post reply message */
IMPL_LINKKIT_IOCTL_SWITCH_EVENT_POST_REPLY, /* only for master device, choose whether you need receive event post reply message */
IMPL_LINKKIT_IOCTL_SWITCH_PROPERTY_SET_REPLY, /* only for master device, choose whether you need send property set reply message */
IMPL_LINKKIT_IOCTL_MAX
} impl_linkkit_ioctl_cmd_t;
/**
* @brief Setup Demain type, should be called before MQTT connection.
*
* @param [in] option: see iotx_ioctl_option_t.
*
* @return None.
* @see None.
*/
int IOT_Ioctl(int option, void *data);
#ifdef INFRA_MEM_STATS
#include "infra_mem_stats.h"
#endif
/* compatible for V2.3.0 */
#define IOTX_CLOUD_DOMAIN_SH IOTX_CLOUD_REGION_SHANGHAI
#define IOTX_CLOUD_DOMAIN_SG IOTX_CLOUD_REGION_SINGAPORE
#define IOTX_CLOUD_DOMAIN_JP IOTX_CLOUD_REGION_JAPAN
#define IOTX_CLOUD_DOMAIN_US IOTX_CLOUD_REGION_USA_WEST
#define IOTX_CLOUD_DOMAIN_GER IOTX_CLOUD_REGION_GERMANY
#define IOTX_IOCTL_SET_DOMAIN IOTX_IOCTL_SET_REGION
#define IOTX_IOCTL_GET_DOMAIN IOTX_IOCTL_GET_REGION
#define IOT_OpenLog(arg)
#define IOT_CloseLog() IOT_SetLogLevel(IOT_LOG_NONE)
#define IOT_LOG_EMERG IOT_LOG_NONE
#define IOT_Linkkit_Post IOT_Linkkit_Report
/* compatible for V2.3.0 end */
typedef enum {
HAL_AES_ENCRYPTION = 0,
HAL_AES_DECRYPTION = 1,
} AES_DIR_t;
typedef void *p_HAL_Aes128_t;
#define NETWORK_ADDR_LEN (16)
typedef struct _network_addr_t {
unsigned char
addr[NETWORK_ADDR_LEN];
unsigned short port;
} NetworkAddr;
#endif /* _INFRA_COMPAT_H_ */

View File

@@ -0,0 +1,5 @@
#ifndef _INFRA_CONFIG_H_
#define _INFRA_CONFIG_H_
#endif

View File

@@ -0,0 +1,23 @@
#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 */
};

View File

@@ -0,0 +1,363 @@
#ifndef _INFRA_DEFS_H_
#define _INFRA_DEFS_H_
#include "infra_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#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 (32)
#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)
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;
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

View File

@@ -0,0 +1,583 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_HTTPC
#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"
#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 */
ret = _http_recv(client, data + len, HTTPCLIENT_RAED_HEAD_SIZE, &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);
}
#endif

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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__ */

View File

@@ -0,0 +1,845 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_JSON_PARSER
#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 */
#endif

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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__ */

View File

@@ -0,0 +1,346 @@
#ifndef _INFRA_LIST_H_
#define _INFRA_LIST_H_
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) || defined(__GNUC__)) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* Get offset of a member variable.
*
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the variable within the struct.
*/
#define aos_offsetof(type, member) ((size_t)&(((type *)0)->member))
/*
* Get the struct for this entry.
*
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the variable within the struct.
*/
#define aos_container_of(ptr, type, member) \
((type *) ((char *) (ptr) - aos_offsetof(type, member)))
/* for double link list */
typedef struct dlist_s {
struct dlist_s *prev;
struct dlist_s *next;
} dlist_t;
static inline void __dlist_add(dlist_t *node, dlist_t *prev, dlist_t *next)
{
node->next = next;
node->prev = prev;
prev->next = node;
next->prev = node;
}
/*
* Get the struct for this entry.
*
* @param[in] addr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the dlist_t within the struct.
*/
#define dlist_entry(addr, type, member) \
((type *)((long)addr - aos_offsetof(type, member)))
static inline void dlist_add(dlist_t *node, dlist_t *queue)
{
__dlist_add(node, queue, queue->next);
}
static inline void dlist_add_tail(dlist_t *node, dlist_t *queue)
{
__dlist_add(node, queue->prev, queue);
}
static inline void dlist_del(dlist_t *node)
{
dlist_t *prev = node->prev;
dlist_t *next = node->next;
prev->next = next;
next->prev = prev;
}
static inline void dlist_init(dlist_t *node)
{
node->next = node->prev = node;
}
static inline void INIT_AOS_DLIST_HEAD(dlist_t *list)
{
list->next = list;
list->prev = list;
}
static inline int dlist_empty(const dlist_t *head)
{
return head->next == head;
}
/*
* Initialise the list.
*
* @param[in] list the list to be inited.
*/
#define AOS_DLIST_INIT(list) {&(list), &(list)}
/*
* Get the first element from a list
*
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the dlist_t within the struct.
*/
#define dlist_first_entry(ptr, type, member) \
dlist_entry((ptr)->next, type, member)
/*
* Iterate over a list.
*
* @param[in] pos the &struct dlist_t to use as a loop cursor.
* @param[in] head he head for your list.
*/
#define dlist_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/*
* Iterate over a list safe against removal of list entry.
*
* @param[in] pos the &struct dlist_t to use as a loop cursor.
* @param[in] n another &struct dlist_t to use as temporary storage.
* @param[in] head he head for your list.
*/
#define dlist_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/*
* Iterate over list of given type.
*
* @param[in] queue he head for your list.
* @param[in] node the &struct dlist_t to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the dlist_t within the struct.
*/
#define dlist_for_each_entry(queue, node, type, member) \
for (node = aos_container_of((queue)->next, type, member); \
&node->member != (queue); \
node = aos_container_of(node->member.next, type, member))
/*
* Iterate over list of given type safe against removal of list entry.
*
* @param[in] queue the head for your list.
* @param[in] n the type * to use as a temp.
* @param[in] node the type * to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the dlist_t within the struct.
*/
#define dlist_for_each_entry_safe(queue, n, node, type, member) \
for (node = aos_container_of((queue)->next, type, member), \
n = (queue)->next ? (queue)->next->next : NULL; \
&node->member != (queue); \
node = aos_container_of(n, type, member), n = n ? n->next : NULL)
/*
* Get the struct for this entry.
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the variable within the struct.
*/
#define list_entry(ptr, type, member) \
aos_container_of(ptr, type, member)
/*
* Iterate backwards over list of given type.
*
* @param[in] pos the type * to use as a loop cursor.
* @param[in] head he head for your list.
* @param[in] member the name of the dlist_t within the struct.
* @param[in] type the type of the struct this is embedded in.
*/
#define dlist_for_each_entry_reverse(pos, head, member, type) \
for (pos = list_entry((head)->prev, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, type, member))
/*
* Get the list length.
*
* @param[in] queue the head for your list.
*/
static inline int __dlist_entry_number(dlist_t *queue)
{
int num;
dlist_t *cur = queue;
for (num = 0; cur->next != queue; cur = cur->next, num++)
;
return num;
}
/*
* Get the list length.
*
* @param[in] queue the head for your list.
*/
#define dlist_entry_number(head) \
__dlist_entry_number(head)
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define AOS_DLIST_HEAD_INIT(name) { &(name), &(name) }
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define AOS_DLIST_HEAD(name) \
dlist_t name = AOS_DLIST_HEAD_INIT(name)
/* for single link list */
typedef struct slist_s {
struct slist_s *next;
} slist_t;
static inline void slist_add(slist_t *node, slist_t *head)
{
node->next = head->next;
head->next = node;
}
static inline void slist_add_tail(slist_t *node, slist_t *head)
{
while (head->next) {
head = head->next;
}
slist_add(node, head);
}
static inline void slist_del(slist_t *node, slist_t *head)
{
while (head->next) {
if (head->next == node) {
head->next = node->next;
break;
}
head = head->next;
}
}
static inline int slist_empty(const slist_t *head)
{
return !head->next;
}
static inline void slist_init(slist_t *head)
{
head->next = 0;
}
/*
* Iterate over list of given type.
*
* @param[in] queue he head for your list.
* @param[in] node the type * to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the slist_t within the struct.
*/
#define slist_for_each_entry(queue, node, type, member) \
for (node = aos_container_of((queue)->next, type, member); \
&node->member; \
node = aos_container_of(node->member.next, type, member))
/*
* Iterate over list of given type safe against removal of list entry.
*
* @param[in] queue the head for your list.
* @param[in] tmp the type * to use as a temp.
* @param[in] node the type * to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the slist_t within the struct.
*/
#define slist_for_each_entry_safe(queue, tmp, node, type, member) \
for (node = aos_container_of((queue)->next, type, member), \
tmp = (queue)->next ? (queue)->next->next : NULL; \
&node->member; \
node = aos_container_of(tmp, type, member), tmp = tmp ? tmp->next : tmp)
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define AOS_SLIST_HEAD_INIT(name) {0}
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define AOS_SLIST_HEAD(name) \
slist_t name = AOS_SLIST_HEAD_INIT(name)
/*
* Get the struct for this entry.
* @param[in] addr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the slist_t within the struct.
*/
#define slist_entry(addr, type, member) ( \
addr ? (type *)((long)addr - aos_offsetof(type, member)) : (type *)addr \
)
/*
* Get the first element from a list.
*
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the slist_t within the struct.
*/
#define slist_first_entry(ptr, type, member) \
slist_entry((ptr)->next, type, member)
/*
* Get the list length.
*
* @param[in] queue the head for your list.
*/
static inline int slist_entry_number(slist_t *queue)
{
int num;
slist_t *cur = queue;
for (num = 0; cur->next; cur = cur->next, num++)
;
return num;
}
#include "infra_compat.h"
#ifdef __cplusplus
}
#endif
#endif /* AOS_LIST_H */

View File

@@ -0,0 +1,266 @@
#include "infra_config.h"
extern void **LITE_get_mem_mutex(void);
extern void *HAL_MutexCreate(void);
extern void HAL_MutexDestroy(void *);
#include <string.h>
#include <stdarg.h>
#include "infra_compat.h"
#include "infra_log.h"
#if defined(INFRA_CJSON)
#include "infra_cjson.h"
#endif
#if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED)
static log_client logcb = {
.name = "linkkit",
.priority = LOG_DEBUG_LEVEL,
.text_buf = {0}
};
static char *lvl_names[] = {
"non", "crt", "err", "wrn", "inf", "dbg", "flw"
};
/* 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white. */
char *lvl_color[] = {
"[0m", "[1;31m", "[1;31m", "[1;35m", "[1;33m", "[1;36m", "[1;37m"
};
void LITE_syslog_routine(char *m, const char *f, const int l, const int level, const char *fmt, va_list *params)
{
char *tmpbuf = logcb.text_buf;
char *o = tmpbuf;
int truncated = 0;
if (LITE_get_loglevel() < level || level < LOG_NONE_LEVEL) {
return;
}
#if !defined(_WIN32)
LITE_printf("%s%s", "\033", lvl_color[level]);
LITE_printf(LOG_PREFIX_FMT, lvl_names[level], f, l);
#endif /* #if !defined(_WIN32) */
memset(tmpbuf, 0, sizeof(logcb.text_buf));
o = tmpbuf;
o += LITE_vsnprintf(o, LOG_MSG_MAXLEN + 1, fmt, *params);
if (o - tmpbuf > LOG_MSG_MAXLEN) {
o = tmpbuf + strlen(tmpbuf);
truncated = 1;
}
if (strlen(tmpbuf) == LOG_MSG_MAXLEN) {
truncated = 1;
}
LITE_printf("%s", tmpbuf);
if (truncated) {
LITE_printf(" ...");
}
if (tmpbuf[strlen(tmpbuf) - 1] != '\n') {
LITE_printf("\r\n");
}
#if !defined(_WIN32)
LITE_printf("%s", "\033[0m");
#endif /* #if !defined(_WIN32) */
return;
}
void LITE_syslog(char *m, const char *f, const int l, const int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
LITE_syslog_routine(m, f, l, level, fmt, &ap);
va_end(ap);
}
int LITE_get_loglevel(void)
{
return logcb.priority;
}
void LITE_set_loglevel(int pri)
{
void **mutex = NULL;
logcb.priority = pri;
#if WITH_MEM_STATS
mutex = LITE_get_mem_mutex();
if (pri != LOG_NONE_LEVEL) {
if (*mutex == NULL) {
*mutex = HAL_MutexCreate();
if (*mutex == NULL) {
LITE_printf("\nCreate memStats mutex error\n");
}
}
} else if (*mutex != NULL) {
HAL_MutexDestroy(*mutex);
*mutex = NULL;
}
#endif
}
void LITE_rich_hexdump(const char *f, const int l,
const int level,
const char *buf_str,
const void *buf_ptr,
const int buf_len)
{
if (LITE_get_loglevel() < level) {
return;
}
LITE_printf("%s%s", "\033", lvl_color[level]);
LITE_printf(LOG_PREFIX_FMT, lvl_names[level], f, l);
LITE_printf("HEXDUMP %s @ %p[%d]\r\n", buf_str, buf_ptr, buf_len);
LITE_hexdump(buf_str, buf_ptr, buf_len);
LITE_printf("%s", "\033[0m");
return;
}
int log_multi_line_internal(const char *f, const int l,
const char *title, int level, char *payload, const char *mark)
{
const char *pos;
const char *endl;
int i;
if (LITE_get_loglevel() < level) {
return 1;
}
LITE_printf("[%s] %s(%d): %s (Length: %d Bytes)\r\n",
lvl_names[LITE_get_loglevel()], f, l, title, (int)strlen(payload));
pos = payload;
while (pos && *pos) {
LITE_printf("%s ", mark);
if (*pos == '\r') {
LITE_printf("\r\n");
pos += 2;
continue;
}
endl = strchr(pos + 1, '\r');
if (endl == NULL) {
endl = pos;
do {
++endl;
} while (*endl);
}
for (i = 0; i < endl - pos; ++i) {
LITE_printf("%c", pos[i]);
}
LITE_printf("\r\n");
pos = *endl ? endl + 2 : 0;
}
return 0;
}
#define LITE_HEXDUMP_DRAWLINE(start_mark, len, end_mark) \
do { \
int i; \
\
LITE_printf("%s", start_mark); \
for(i = 0; i < len; ++i) { LITE_printf("-"); } \
LITE_printf("%s", end_mark); \
LITE_printf("\r\n"); \
\
} while(0)
int LITE_hexdump(const char *title, const void *buff, const int len)
{
int i, j, written;
unsigned char ascii[20] = {0};
char header[64] = {0};
unsigned char *buf = (unsigned char *)buff;
LITE_snprintf(header, sizeof(header), "| %s: (len=%d) |\r\n", title, (int)len);
LITE_HEXDUMP_DRAWLINE("+", strlen(header) - 4, "+");
LITE_printf("%s", header);
LITE_printf("%s\r\n", HEXDUMP_SEP_LINE);
written = 0;
for (i = 0; i < len; ++ i) {
if (i % 16 == 0) {
LITE_printf("| %08X: ", (unsigned int)(i + (long)buff));
written += 8;
}
LITE_printf("%02X", buf[i]);
written += 2;
if (i % 2 == 1) {
LITE_printf(" ");
written += 1;
}
LITE_snprintf((char *)ascii + i % 16, (1 + 1), "%c", ((buf[i] >= ' ' && buf[i] <= '~') ? buf[i] : '.'));
if (((i + 1) % 16 == 0) || (i == len - 1)) {
for (j = 0; j < 48 - written; ++j) {
LITE_printf(" ");
}
LITE_printf(" %s", ascii);
LITE_printf("\r\n");
written = 0;
memset(ascii, 0, sizeof(ascii));
}
}
LITE_printf("%s\r\n", HEXDUMP_SEP_LINE);
return 0;
}
void IOT_SetLogLevel(IOT_LogLevel level)
{
int lvl = (int)level;
if (lvl > LOG_DEBUG_LEVEL) {
HAL_Printf("Invalid input level: %d out of [%d, %d]", level,
LOG_NONE_LEVEL,
LOG_DEBUG_LEVEL);
return;
}
LITE_set_loglevel(lvl);
HAL_Printf("[prt] log level set as: [ %d ]\r\n", lvl);
}
#else
void IOT_SetLogLevel(IOT_LogLevel level)
{
return;
}
int log_multi_line_internal(const char *f, const int l,
const char *title, int level, char *payload, const char *mark)
{
return 0;
}
void LITE_rich_hexdump(const char *f, const int l,
const int level,
const char *buf_str,
const void *buf_ptr,
const int buf_len)
{
return;
}
#endif /* #if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED) */

View File

@@ -0,0 +1,119 @@
#ifndef _INFRA_LOG_H_
#define _INFRA_LOG_H_
#include <stdarg.h>
#include "infra_defs.h"
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
void HAL_Printf(const char *fmt, ...);
int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap);
#define LITE_printf HAL_Printf
#define LITE_snprintf HAL_Snprintf
#define LITE_vsnprintf HAL_Vsnprintf
#define LITE_LOG_ENABLED
#define LOG_MSG_MAXLEN (255)
#define LOG_MOD_NAME_LEN (7)
#define LOG_PREFIX_FMT "[%s] %s(%d): "
#define HEXDUMP_SEP_LINE "+" \
"-----------------------" \
"-----------------------" \
"-----------------------"
#if defined(_PLATFORM_IS_LINUX_)
#undef LOG_MSG_MAXLEN
#define LOG_MSG_MAXLEN (512)
#endif
typedef struct {
char name[LOG_MOD_NAME_LEN + 1];
int priority;
char text_buf[LOG_MSG_MAXLEN + 1];
} log_client;
int LITE_get_loglevel(void);
void LITE_set_loglevel(int level);
int LITE_hexdump(const char *title, const void *buf, const int len);
void LITE_syslog_routine(char *m, const char *f, const int l, const int level, const char *fmt, va_list *params);
void LITE_syslog(char *m, const char *f, const int l, const int level, const char *fmt, ...);
#define LOG_NONE_LEVEL (0) /* no log printed at all */
#define LOG_CRIT_LEVEL (1) /* current application aborting */
#define LOG_ERR_LEVEL (2) /* current app-module error */
#define LOG_WARNING_LEVEL (3) /* using default parameters */
#define LOG_INFO_LEVEL (4) /* running messages */
#define LOG_DEBUG_LEVEL (5) /* debugging messages */
#define LOG_FLOW_LEVEL (6) /* code/packet flow messages */
#if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED)
#if defined(INFRA_LOG_MUTE_FLW)
#define log_flow(mod, ...)
#else
#define log_flow(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_FLOW_LEVEL, __VA_ARGS__)
#endif
#if defined(INFRA_LOG_MUTE_DBG)
#define log_debug(mod, ...)
#else
#define log_debug(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_DEBUG_LEVEL, __VA_ARGS__)
#endif
#if defined(INFRA_LOG_MUTE_INF)
#define log_info(mod, ...)
#else
#define log_info(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_INFO_LEVEL, __VA_ARGS__)
#endif
#if defined(INFRA_LOG_MUTE_WRN)
#define log_warning(mod, ...)
#else
#define log_warning(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_WARNING_LEVEL, __VA_ARGS__)
#endif
#if defined(INFRA_LOG_MUTE_ERR)
#define log_err(mod, ...)
#else
#define log_err(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_ERR_LEVEL, __VA_ARGS__)
#endif
#if defined(INFRA_LOG_MUTE_CRT)
#define log_crit(mod, ...)
#else
#define log_crit(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_CRIT_LEVEL, __VA_ARGS__)
#endif
#else /* #if defined(INFRA_LOG) */
#define log_flow(mod, ...)
#define log_debug(mod, ...)
#define log_info(mod, ...)
#define log_warning(mod, ...)
#define log_err(mod, ...)
#define log_crit(mod, ...)
#endif
int log_multi_line_internal(const char *f, const int l,
const char *title, int level, char *payload, const char *mark);
#define log_multi_line(level, title, fmt, payload, mark) \
log_multi_line_internal(__func__, __LINE__, title, level, payload, mark)
void LITE_rich_hexdump(const char *f, const int l,
const int level,
const char *buf_str,
const void *buf_ptr,
const int buf_len
);
#define HEXDUMP_DEBUG(buf, len) \
LITE_rich_hexdump(__func__, __LINE__, LOG_DEBUG_LEVEL, #buf, (const void *)buf, (const int)len)
#define HEXDUMP_INFO(buf, len) \
LITE_rich_hexdump(__func__, __LINE__, LOG_INFO_LEVEL, #buf, (const void *)buf, (const int)len)
int iotx_facility_json_print(const char *str, int level, ...);
#endif

View File

@@ -0,0 +1,351 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_MD5
#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]);
}
}
#endif

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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

View File

@@ -0,0 +1,711 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_MEM_STATS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include "infra_mem_stats.h"
#ifdef INFRA_LOG
#include "infra_log.h"
#define utils_emerg(...) log_emerg("util", __VA_ARGS__)
#define utils_crit(...) log_crit("util", __VA_ARGS__)
#define utils_err(...) log_err("util", __VA_ARGS__)
#define utils_warning(...) log_warning("util", __VA_ARGS__)
#define utils_info(...) log_info("util", __VA_ARGS__)
#define utils_debug(...) log_debug("util", __VA_ARGS__)
#else
#define utils_emerg(...)
#define utils_crit(...)
#define utils_err(...)
#define utils_warning(...)
#define utils_info(...)
#define utils_debug(...)
#endif
extern void *HAL_Malloc(uint32_t size);
extern void HAL_Free(void *ptr);
void *HAL_MutexCreate(void);
void HAL_MutexDestroy(void *mutex);
void HAL_MutexLock(void *mutex);
void HAL_MutexUnlock(void *mutex);
LIST_HEAD(mem_recs);
LIST_HEAD(mem_module_statis);
typedef struct {
char *func_name;
int line;
list_head_t func_head;
} calling_stack_t;
typedef struct {
char module_name[32];
calling_stack_t calling_stack;
int bytes_total_allocated;
int bytes_total_freed;
int bytes_total_in_use;
int bytes_max_allocated;
int bytes_max_in_use;
int iterations_allocated;
int iterations_freed;
int iterations_in_use;
int iterations_max_in_use;
} mem_statis_t;
typedef struct {
mem_statis_t mem_statis;
list_head_t list;
} module_mem_t;
/* sort module used */
static int _mem_cmp_max_used(list_head_t *a, list_head_t *b)
{
module_mem_t *temp_a = list_entry(a, module_mem_t, list);
module_mem_t *temp_b = list_entry(b, module_mem_t, list);
if (a == NULL || b == NULL) {
return 0;
}
/* return true to swap if a < b */
return (temp_a->mem_statis.bytes_max_in_use < temp_b->mem_statis.bytes_max_in_use);
}
static void _mem_swap_module_pos(list_head_t *a, list_head_t *b)
{
list_head_t temp = {NULL, NULL};
if (a == NULL || a == NULL) {
return;
}
list_add(&temp, b);
list_del(b);
list_add(b, a);
list_del(a);
list_add(a, &temp);
list_del(&temp);
}
static void _mem_sort_module_pos(list_head_t *head)
{
list_head_t *start = NULL;
list_head_t *end = NULL;
if (head == NULL) {
return;
}
for (end = head->prev; end != head; end = end->prev) { /* list_for_each_prev */
list_for_each(start, head) {
if (start == end) {
break;
}
if (_mem_cmp_max_used(start, start->next)) {
_mem_swap_module_pos(start, start->next);
start = start->prev;
if (start == end) {
end = end->next;
}
}
}
}
}
static void *mutex_mem_stats = NULL;
static int bytes_total_allocated;
static int bytes_total_freed;
static int bytes_total_in_use;
static int bytes_max_allocated;
static int bytes_max_in_use;
static int iterations_allocated;
static int iterations_freed;
static int iterations_in_use;
static int iterations_max_in_use;
#if defined(__UBUNTU_SDK_DEMO__)
static int tracking_malloc_callstack = 1;
char *LITE_strdup(const char *src, ...)
{
int len = 0;
char *dst = NULL;
if (!src) {
return NULL;
}
len = strlen(src) + 1;
if (len > 1024) {
utils_err("Too long string to duplicate, abort! len = %d", len);
return NULL;
}
dst = (char *)HAL_Malloc(sizeof(char) * len);
if (!dst) {
return NULL;
}
strncpy(dst, src, len);
return dst;
}
static int record_backtrace(int *level, char *** trace)
{
#define MAX_BT_LEVEL 8
void *buffer[MAX_BT_LEVEL];
*level = backtrace(buffer, MAX_BT_LEVEL);
*trace = backtrace_symbols(buffer, *level);
if (*trace == NULL) {
utils_err("backtrace_symbols returns NULL!");
return -1;
}
return 0;
}
void LITE_track_malloc_callstack(int state)
{
tracking_malloc_callstack = state;
}
#else
void LITE_track_malloc_callstack(int state)
{
}
#endif /* defined(__UBUNTU_SDK_DEMO__) */
void *LITE_realloc_internal(const char *f, const int l, void *ptr, int size, ...)
{
void *temp = NULL;
int magic = 0;
char *module_name = NULL;
va_list ap;
if (size <= 0) {
return NULL;
}
va_start(ap, size);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
temp = LITE_malloc_internal(f, l, size, magic, module_name);
if (NULL == temp) {
utils_err("allocate %d bytes from %s(%d) failed", size, f, l);
return NULL;
}
if (ptr) {
memcpy(temp, ptr, size);
LITE_free(ptr);
}
return temp;
}
void *_create_mem_table(char *module_name, struct list_head *list_head)
{
module_mem_t *pos = NULL;
int len = 0;
if (!module_name || !list_head) {
return NULL;
}
pos = HAL_Malloc(sizeof(module_mem_t));
if (!pos) {
return NULL;
}
memset(pos, 0, sizeof(module_mem_t));
len = strlen(module_name);
memcpy(pos->mem_statis.module_name, module_name,
(len >= sizeof(pos->mem_statis.module_name)) ? (sizeof(pos->mem_statis.module_name) - 1) : len);
INIT_LIST_HEAD(&pos->mem_statis.calling_stack.func_head);
list_add_tail(&pos->list, list_head);
return (void *)pos;
}
void *_find_mem_table(char *module_name, struct list_head *list_head)
{
module_mem_t *pos = NULL, *tmp = NULL;
if (!module_name || !list_head) {
return NULL;
}
list_for_each_entry_safe(pos, tmp, list_head, list, module_mem_t) {
if (!strcmp(module_name, pos->mem_statis.module_name)) {
return (void *)pos;
}
}
return NULL;
}
int _del_mem_table(char *module_name, struct list_head *list_head)
{
int ret = -1;
calling_stack_t *calling_stack_pos = NULL, *tmp = NULL;
module_mem_t *table_pos = (module_mem_t *)_find_mem_table(module_name, list_head);
if (table_pos) {
list_for_each_entry_safe(calling_stack_pos, tmp, \
&table_pos->mem_statis.calling_stack.func_head, func_head, calling_stack_t) {
if (calling_stack_pos) {
list_del(&calling_stack_pos->func_head);
if (calling_stack_pos->func_name) {
HAL_Free(calling_stack_pos->func_name);
calling_stack_pos->func_name = NULL;
}
HAL_Free(calling_stack_pos);
calling_stack_pos = NULL;
}
}
list_del(&table_pos->list);
HAL_Free(table_pos);
table_pos = NULL;
ret = 0;
}
return ret;
}
int _count_malloc_internal(const char *f, const int l, OS_malloc_record *os_malloc_pos, va_list ap)
{
int ret = -1;
int magic = 0;
char is_repeat = 0;
char *module_name = NULL;
module_mem_t *pos = NULL;
calling_stack_t *call_pos, *call_tmp;
calling_stack_t *entry = NULL;
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
} else {
module_name = "unknown";
}
pos = (module_mem_t *)_find_mem_table(module_name, &mem_module_statis);
if (!pos) {
if (NULL == (pos = (module_mem_t *)_create_mem_table(module_name, &mem_module_statis))) {
utils_err("create_mem_table:[%s] failed!", module_name);
return ret;
}
}
os_malloc_pos->mem_table = (void *)pos;
if (!strcmp(pos->mem_statis.module_name, "unknown")) {
list_for_each_entry_safe(call_pos, call_tmp, &pos->mem_statis.calling_stack.func_head, func_head, calling_stack_t) {
if (!strcmp(call_pos->func_name, f) && (call_pos->line == l)) {
is_repeat = 1;
break;
}
}
if (!is_repeat) {
entry = HAL_Malloc(sizeof(calling_stack_t));
if (!entry) {
return ret;
}
memset(entry, 0, sizeof(calling_stack_t));
entry->func_name = LITE_strdup(f);
entry->line = l;
list_add(&entry->func_head, &pos->mem_statis.calling_stack.func_head);
}
}
pos->mem_statis.iterations_allocated += 1;
pos->mem_statis.bytes_total_allocated += os_malloc_pos->buflen;
pos->mem_statis.bytes_total_in_use += os_malloc_pos->buflen;
pos->mem_statis.bytes_max_in_use = (pos->mem_statis.bytes_max_in_use > pos->mem_statis.bytes_total_in_use) ?
pos->mem_statis.bytes_max_in_use : pos->mem_statis.bytes_total_in_use;
pos->mem_statis.bytes_max_allocated = (pos->mem_statis.bytes_max_allocated >= os_malloc_pos->buflen) ?
pos->mem_statis.bytes_max_allocated : os_malloc_pos->buflen;
pos->mem_statis.iterations_in_use += 1;
pos->mem_statis.iterations_max_in_use = (pos->mem_statis.iterations_in_use > pos->mem_statis.iterations_max_in_use) ?
pos->mem_statis.iterations_in_use : pos->mem_statis.iterations_max_in_use;
ret = 0;
return ret;
}
void _count_free_internal(void *ptr, OS_malloc_record *os_malloc_pos)
{
module_mem_t *pos = NULL;
pos = (module_mem_t *)(os_malloc_pos->mem_table);
if (!pos) {
utils_err("find mem_table faild");
return;
}
pos->mem_statis.iterations_freed += 1;
pos->mem_statis.iterations_in_use -= 1;
pos->mem_statis.bytes_total_freed += os_malloc_pos->buflen;
pos->mem_statis.bytes_total_in_use -= os_malloc_pos->buflen;
}
void *LITE_malloc_internal(const char *f, const int l, int size, ...)
{
void *ptr = NULL;
OS_malloc_record *pos;
if (size <= 0) {
return NULL;
}
ptr = HAL_Malloc(size);
if (!ptr) {
return NULL;
}
if (mutex_mem_stats == NULL) {
mutex_mem_stats = HAL_MutexCreate();
}
HAL_MutexLock(mutex_mem_stats);
iterations_allocated += 1;
bytes_total_allocated += size;
bytes_total_in_use += size;
bytes_max_in_use = (bytes_max_in_use > bytes_total_in_use) ? bytes_max_in_use : bytes_total_in_use;
bytes_max_allocated = (bytes_max_allocated >= size) ? bytes_max_allocated : size;
#if defined(WITH_TOTAL_COST_WARNING)
if (bytes_total_in_use > WITH_TOTAL_COST_WARNING) {
utils_debug(" ");
utils_debug("==== PRETTY HIGH TOTAL IN USE: %d BYTES ====", bytes_total_in_use);
LITE_dump_malloc_free_stats(LOG_DEBUG_LEVEL);
}
#endif
iterations_in_use += 1;
iterations_max_in_use = (iterations_in_use > iterations_max_in_use) ? iterations_in_use : iterations_max_in_use;
pos = HAL_Malloc(sizeof(OS_malloc_record));
if (NULL == pos) {
HAL_Free(ptr);
HAL_MutexUnlock(mutex_mem_stats);
return NULL;
}
memset(pos, 0, sizeof(OS_malloc_record));
pos->buf = ptr;
pos->buflen = size;
pos->func = (char *)f;
pos->line = (int)l;
#if defined(__UBUNTU_SDK_DEMO__)
if (tracking_malloc_callstack) {
record_backtrace(&pos->bt_level, &pos->bt_symbols);
}
#endif
list_add_tail(&pos->list, &mem_recs);
{
va_list ap;
va_start(ap, size);
_count_malloc_internal(f, l, pos, ap);
va_end(ap);
}
#if defined(WITH_ALLOC_WARNING_THRESHOLD)
if (size > WITH_ALLOC_WARNING_THRESHOLD) {
int k;
log_warning("utils", "large allocating @ %s(%d) for %04d bytes!", f, l, size);
LITE_printf("\r\n");
#if defined(__UBUNTU_SDK_DEMO__)
for (k = 0; k < pos->bt_level; ++k) {
int m;
const char *p = strchr(pos->bt_symbols[k], '(');
if (p[1] == ')') {
continue;
}
for (m = 0; m < k; ++m) {
LITE_printf(" ");
}
LITE_printf("%s\r\n", p);
}
#endif
LITE_printf("\r\n");
}
#endif
memset(ptr, 0, size);
HAL_MutexUnlock(mutex_mem_stats);
return ptr;
}
void LITE_free_internal(void *ptr)
{
OS_malloc_record *pos;
OS_malloc_record *next;
int found = 0;
if (!ptr) {
return;
}
HAL_MutexLock(mutex_mem_stats);
pos = NULL;
list_for_each_entry_safe(pos, next, &mem_recs, list, OS_malloc_record) {
if (pos->buf == ptr) {
found = 1;
break;
}
}
if (!found) {
pos = NULL;
}
if (NULL == pos) {
log_warning("utils", "Cannot find %p allocated! Skip stat ...", ptr);
HAL_MutexUnlock(mutex_mem_stats);
return;
} else {
iterations_freed += 1;
iterations_in_use -= 1;
bytes_total_freed += pos->buflen;
bytes_total_in_use -= pos->buflen;
_count_free_internal(ptr, pos);
if (pos->buf && pos->buflen > 0) {
memset(pos->buf, 0xEE, pos->buflen);
}
pos->buf = 0;
pos->buflen = 0;
pos->func = "";
pos->line = 0;
#if defined(__UBUNTU_SDK_DEMO__)
pos->bt_level = 0;
HAL_Free(pos->bt_symbols);
pos->bt_symbols = 0;
#endif
list_del(&pos->list);
HAL_Free(pos);
}
HAL_MutexUnlock(mutex_mem_stats);
HAL_Free(ptr);
}
void *LITE_malloc_routine(int size, ...)
{
int magic = 0;
char *module_name = NULL;
va_list ap;
va_start(ap, size);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
return LITE_malloc(size, magic, module_name);
}
void *LITE_calloc_routine(size_t n, size_t s, ...)
{
int magic = 0;
char *module_name = NULL;
va_list ap;
va_start(ap, s);
magic = va_arg(ap, int);
if (MEM_MAGIC == magic) {
module_name = va_arg(ap, char *);
}
va_end(ap);
return LITE_malloc(n * s, magic, module_name);;
}
void LITE_free_routine(void *ptr)
{
LITE_free(ptr);
}
void LITE_dump_malloc_free_stats(int level)
{
OS_malloc_record *pos;
module_mem_t *module_pos, *tmp;
module_mem_t *unknown_mod = NULL;
if (level > LITE_get_loglevel()) {
return;
}
utils_debug("");
utils_debug("---------------------------------------------------");
utils_debug(". bytes_total_allocated: %d", bytes_total_allocated);
utils_debug(". bytes_total_freed: %d", bytes_total_freed);
utils_debug(". bytes_total_in_use: %d", bytes_total_in_use);
utils_warning(". bytes_max_allocated: %d", bytes_max_allocated);
utils_info(". bytes_max_in_use: %d", bytes_max_in_use);
utils_debug(". iterations_allocated: %d", iterations_allocated);
utils_debug(". iterations_freed: %d", iterations_freed);
utils_debug(". iterations_in_use: %d", iterations_in_use);
utils_debug(". iterations_max_in_use: %d", iterations_max_in_use);
utils_debug("---------------------------------------------------");
utils_debug("");
_mem_sort_module_pos(&mem_module_statis);
LITE_printf("\r\n");
LITE_printf("| | max_in_use | max_allocated | total_allocated | total_free\r\n");
LITE_printf("|---------------|----------------------|------------------|-----------------------|----------------------\r\n");
list_for_each_entry_safe(module_pos, tmp, &mem_module_statis, list, module_mem_t) {
if (module_pos) {
LITE_printf("| %-13s | %6d bytes / %-5d | %6d bytes | %6d bytes / %-5d | %6d bytes / %-5d \r\n",
module_pos->mem_statis.module_name,
module_pos->mem_statis.bytes_max_in_use,
module_pos->mem_statis.iterations_max_in_use,
module_pos->mem_statis.bytes_max_allocated,
module_pos->mem_statis.bytes_total_allocated,
module_pos->mem_statis.iterations_allocated,
module_pos->mem_statis.bytes_total_freed,
module_pos->mem_statis.iterations_freed
);
/*
LITE_printf("\x1B[1;32mMODULE_NAME: [%s]\x1B[0m\r\n", module_pos->mem_statis.module_name);
LITE_printf("---------------------------------------------------\r\n");
LITE_printf(". bytes_total_allocated: %d\r\n", module_pos->mem_statis.bytes_total_allocated);
LITE_printf(". bytes_total_freed: %d\r\n", module_pos->mem_statis.bytes_total_freed);
LITE_printf(". bytes_total_in_use: %d\r\n", module_pos->mem_statis.bytes_total_in_use);
LITE_printf(". bytes_max_allocated: %d\r\n", module_pos->mem_statis.bytes_max_allocated);
LITE_printf(". bytes_max_in_use: %d\r\n", module_pos->mem_statis.bytes_max_in_use);
LITE_printf(". iterations_allocated: %d\r\n", module_pos->mem_statis.iterations_allocated);
LITE_printf(". iterations_freed: %d\r\n", module_pos->mem_statis.iterations_freed);
LITE_printf(". iterations_in_use: %d\r\n", module_pos->mem_statis.iterations_in_use);
LITE_printf(". iterations_max_in_use: %d\r\n", module_pos->mem_statis.iterations_max_in_use);
LITE_printf("---------------------------------------------------\r\n");
*/
if (!strcmp(module_pos->mem_statis.module_name, "unknown")) {
unknown_mod = module_pos;
} else {
HAL_Free(module_pos->mem_statis.calling_stack.func_name);
}
}
}
if (unknown_mod) {
calling_stack_t *call_pos, *tmp;
LITE_printf("\r\n");
LITE_printf("\x1B[1;33mMissing module-name references:\x1B[0m\r\n");
LITE_printf("---------------------------------------------------\r\n");
list_for_each_entry_safe(call_pos, tmp, &unknown_mod->mem_statis.calling_stack.func_head, func_head, calling_stack_t) {
if (call_pos->func_name) {
LITE_printf(". \x1B[1;31m%s \x1B[0m Ln:%d\r\n", call_pos->func_name, call_pos->line);
/* free memery of func_name and calling_stack */
HAL_Free(call_pos->func_name);
list_del(&call_pos->func_head);
HAL_Free(call_pos);
}
}
LITE_printf("\r\n");
}
list_for_each_entry_safe(module_pos, tmp, &mem_module_statis, list, module_mem_t) {
list_del(&module_pos->list);
HAL_Free(module_pos);
}
LITE_printf("\r\n");
if (LITE_get_loglevel() == level) {
int j;
int cnt = 0;
list_for_each_entry(pos, &mem_recs, list, OS_malloc_record) {
if (pos->buf) {
LITE_printf("%4d. %-24s Ln:%-5d @ %p: %4d bytes [",
++cnt,
pos->func,
pos->line,
pos->buf,
pos->buflen);
for (j = 0; j < 32 && j < pos->buflen; ++j) {
char c;
c = *(char *)(pos->buf + j);
if (c < ' ' || c > '~') {
c = '.';
}
LITE_printf("%c", c);
}
LITE_printf("]\r\n");
#if defined(__UBUNTU_SDK_DEMO__)
{
int k;
LITE_printf("\r\n");
for (k = 0; k < pos->bt_level; ++k) {
int m;
const char *p = strchr(pos->bt_symbols[k], '(');
if (p[1] == ')') {
continue;
}
LITE_printf(" ");
for (m = 0; m < k; ++m) {
LITE_printf(" ");
}
LITE_printf("%s\r\n", p);
}
}
#endif
LITE_printf("\r\n");
}
}
}
return;
}
void **LITE_get_mem_mutex(void)
{
return &mutex_mem_stats;
}
#endif

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __MEM_STATS_H__
#define __MEM_STATS_H__
#include "infra_list.h"
#include "infra_log.h"
#if defined(__UBUNTU_SDK_DEMO__)
#include <execinfo.h>
#endif
typedef struct {
void *buf;
int buflen;
char *func;
int line;
#if defined(_PLATFORM_IS_LINUX_)
char **bt_symbols;
int bt_level;
#endif
list_head_t list;
void *mem_table;
} OS_malloc_record;
#define MEM_MAGIC (0x1234)
#define LITE_calloc(num, size, ...) LITE_malloc_internal(__func__, __LINE__, (num * size), ##__VA_ARGS__)
#define LITE_malloc(size, ...) LITE_malloc_internal(__func__, __LINE__, size, ##__VA_ARGS__)
#define LITE_realloc(ptr, size, ...) LITE_realloc_internal(__func__, __LINE__, ptr, size, ##__VA_ARGS__)
#define LITE_free(ptr) \
do { \
if (!ptr) { \
log_warning("utils", "%s == NULL! LITE_free(%s) aborted.", #ptr, #ptr); \
break; \
} \
\
LITE_free_internal((void *)ptr); \
ptr = NULL; \
} while(0)
void *LITE_malloc_internal(const char *f, const int l, int size, ...);
void *LITE_realloc_internal(const char *f, const int l, void *ptr, int size, ...);
void LITE_free_internal(void *ptr);
void LITE_dump_malloc_free_stats(int level);
void **LITE_get_mem_mutex(void);
#endif /* __MEM_STATS_H__ */

View File

@@ -0,0 +1,328 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_NET
#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;
}
#endif

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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 */

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_PREAUTH
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "infra_types.h"
#include "infra_defs.h"
#include "infra_httpc.h"
#include "infra_preauth.h"
#include "infra_string.h"
#define PREAUTH_HTTP_REQ_LEN 300
#define PREAUTH_HTTP_RSP_LEN 300
#define PREAUTH_IOT_ID_MAXLEN (64)
#define PREAUTH_IOT_TOKEN_MAXLEN (65)
#define PREAUTH_IOT_HOST_MAXLEN (64)
#ifndef CONFIG_GUIDER_AUTH_TIMEOUT
#define CONFIG_GUIDER_AUTH_TIMEOUT (10 * 1000)
#endif
#ifdef SUPPORT_TLS
extern const char *iotx_ca_crt;
#endif
int _preauth_assemble_auth_req_string(const iotx_dev_meta_info_t *dev_meta, const char *sign,
const char *device_id, char *request_buff, uint32_t buff_len)
{
uint8_t i = 0;
const char *kv[][2] = {
{ "productKey", NULL },
{ "deviceName", NULL },
{ "signmethod", "hmacsha256"},
{ "sign", NULL },
{ "version", "default" },
{ "clientId", NULL },
{ "timestamp", "2524608000000" },
{ "resources", "mqtt" }
};
if (dev_meta == NULL || sign == NULL || device_id == NULL || request_buff == NULL) {
return FAIL_RETURN;
}
kv[0][1] = dev_meta->product_key;
kv[1][1] = dev_meta->device_name;
kv[3][1] = sign;
kv[5][1] = device_id;
for (i = 0; i < (sizeof(kv) / (sizeof(kv[0]))); i++) {
if ((strlen(request_buff) + strlen(kv[i][0]) + strlen(kv[i][1]) + 2) >=
buff_len) {
return FAIL_RETURN;
}
memcpy(request_buff + strlen(request_buff), kv[i][0], strlen(kv[i][0]));
memcpy(request_buff + strlen(request_buff), "=", 1);
memcpy(request_buff + strlen(request_buff), kv[i][1], strlen(kv[i][1]));
memcpy(request_buff + strlen(request_buff), "&", 1);
}
memset(request_buff + strlen(request_buff) - 1, '\0', 1);
return SUCCESS_RETURN;
}
static int _preauth_get_string_value(char *p_string, char *value_buff, uint32_t buff_len)
{
char *p = p_string;
char *p_start = NULL;
char *p_end = NULL;
uint32_t len = 0;
while (*(++p) != ',' || *p != '}') {
if (*p == '\"') {
if (p_start) {
p_end = p;
break;
} else {
p_start = p + 1;
}
}
}
if (p_start == NULL || p_end == NULL) {
return FAIL_RETURN;
}
len = p_end - p_start;
if (len > buff_len) {
return FAIL_RETURN;
}
memcpy(value_buff, p_start, len);
return SUCCESS_RETURN;
}
static int _preauth_parse_auth_rsp_string(char *json_string, uint32_t string_len, iotx_sign_mqtt_t *output)
{
int res = FAIL_RETURN;
char *p = json_string;
char *p_start, *p_end, *pt;
uint8_t len;
int code = 0;
while (p < (json_string + string_len)) {
while (*(++p) != ':') {
if (p >= (json_string + string_len)) {
if (code != 200) {
return FAIL_RETURN;
}
else {
return SUCCESS_RETURN;
}
}
}
pt = p;
p_start = p_end = NULL;
while (--pt > json_string) {
if (*pt == '\"') {
if (p_end != NULL) {
p_start = pt + 1;
break;
} else {
p_end = pt;
}
}
}
if (p_start == NULL || p_end == NULL) {
return FAIL_RETURN;
}
len = p_end - p_start;
if (strlen("code") == len && !memcmp(p_start, "code", len)) {
infra_str2int(++p, &code);
if (code != 200) {
return FAIL_RETURN;
}
} else if (strlen("iotId") == len && !memcmp(p_start, "iotId", len)) {
res = _preauth_get_string_value(p, output->username, PREAUTH_IOT_ID_MAXLEN);
if (res < SUCCESS_RETURN) {
return res;
}
} else if (strlen("iotToken") == len && !memcmp(p_start, "iotToken", len)) {
res = _preauth_get_string_value(p, output->password, PREAUTH_IOT_TOKEN_MAXLEN);
if (res < SUCCESS_RETURN) {
return res;
}
} else if (strlen("host") == len && !memcmp(p_start, "host", len)) {
res = _preauth_get_string_value(p, output->hostname, PREAUTH_IOT_HOST_MAXLEN);
if (res < SUCCESS_RETURN) {
return res;
}
} else if (strlen("port") == len && !memcmp(p_start, "port", len)) {
int port_temp;
infra_str2int(++p, &port_temp);
output->port = port_temp;
}
}
return SUCCESS_RETURN;
}
int preauth_get_connection_info(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *dev_meta,
const char *sign, const char *device_id, iotx_sign_mqtt_t *preauth_output)
{
char http_url[128] = "http://";
char http_url_frag[] = "/auth/devicename";
#ifdef SUPPORT_TLS
int http_port = 443;
#else
int http_port = 80;
#endif
int res = FAIL_RETURN;
httpclient_t httpc;
httpclient_data_t httpc_data;
char request_buff[PREAUTH_HTTP_REQ_LEN] = {0};
char response_buff[PREAUTH_HTTP_RSP_LEN] = {0};
if (g_infra_http_domain[region] == NULL) {
return FAIL_RETURN;
}
memset(&httpc, 0, sizeof(httpclient_t));
memset(&httpc_data, 0, sizeof(httpclient_data_t));
memcpy(http_url + strlen(http_url), g_infra_http_domain[region], strlen(g_infra_http_domain[region]));
memcpy(http_url + strlen(http_url), http_url_frag, sizeof(http_url_frag));
httpc.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n";
_preauth_assemble_auth_req_string(dev_meta, sign, device_id, request_buff, sizeof(request_buff));
httpc_data.post_content_type = "application/x-www-form-urlencoded;charset=utf-8";
httpc_data.post_buf = request_buff;
httpc_data.post_buf_len = strlen(request_buff);
httpc_data.response_buf = response_buff;
httpc_data.response_buf_len = sizeof(response_buff);
res = httpclient_common(&httpc,
http_url,
http_port,
#ifdef SUPPORT_TLS
iotx_ca_crt,
#else
NULL,
#endif
HTTPCLIENT_POST,
CONFIG_GUIDER_AUTH_TIMEOUT,
&httpc_data);
if (res < SUCCESS_RETURN) {
return res;
}
#ifdef INFRA_LOG_NETWORK_PAYLOAD
preauth_info("Downstream Payload:");
iotx_facility_json_print(response_buff, LOG_INFO_LEVEL, '<');
#endif
res = _preauth_parse_auth_rsp_string(response_buff, strlen(response_buff), preauth_output);
return res;
}
#endif /* #ifdef MQTT_PRE_AUTH */

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __INFRA_PREAUTH__
#define __INFRA_PREAUTH__
#include "infra_defs.h"
#include "infra_types.h"
#ifdef INFRA_LOG
#include "infra_log.h"
#define preauth_err(...) log_err("preauth", __VA_ARGS__)
#define preauth_info(...) log_info("preauth", __VA_ARGS__)
#define preauth_debug(...) log_debug("preauth", __VA_ARGS__)
#else
#define preauth_err(...)
#define preauth_info(...)
#define preauth_debug(...)
#endif
int preauth_get_connection_info(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *dev_meta,
const char *sign, const char *device_id, iotx_sign_mqtt_t *preauth_output);
#endif /* #ifndef __INFRA_PREAUTH__ */

View File

@@ -0,0 +1,159 @@
#include "infra_config.h"
#ifdef INFRA_LOG_NETWORK_PAYLOAD
#include <string.h>
#include <stdarg.h>
#include "infra_log.h"
#if defined(INFRA_CJSON)
#include "infra_cjson.h"
#endif
#define JSON_NEWLINE "\r\n"
#define JSON_INDENT " "
#define JSON_PRINT_NEWSTR HAL_Printf("%s", newstr);
#define JSON_PRINT_NEWLINE \
do { \
HAL_Printf("%s", JSON_NEWLINE); \
if (mark == '>' || mark == '<' || mark == ':') { \
HAL_Printf("%c ", mark); \
} \
} while(0)
/* 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white. */
static char *_color[] = {
"[0m", "[1;31m", "[1;31m", "[1;35m", "[1;33m", "[1;36m", "[1;37m"
};
int iotx_facility_json_print(const char *str, int level, ...)
{
int length = 0;
char newstr[2];
int quoted = 0;
int escaped = 0;
int indent = 0;
int i = 0, j = 0;
#if defined(INFRA_CJSON)
int res = -1;
lite_cjson_t lite;
#endif
va_list ap;
int mark = ' ';
newstr[0] = 0x00;
newstr[1] = 0x00;
if (str == NULL || strlen(str) == 0) {
return -1;
}
#if defined(INFRA_CJSON)
res = lite_cjson_parse(str, strlen(str), &lite);
if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite)) {
return -2;
}
#endif
length = strlen(str);
HAL_Printf("%s%s", "\033", _color[level]);
va_start(ap, level);
mark = va_arg(ap, int);
JSON_PRINT_NEWLINE;
va_end(ap);
for (i = 0 ; i < length ; i++) {
char ch = str[i];
switch (ch) {
case '{':
case '[':
newstr[0] = ch;
JSON_PRINT_NEWSTR;
if (!quoted) {
JSON_PRINT_NEWLINE;
if (!(str[i + 1] == '}' || str[i + 1] == ']')) {
++indent;
for (j = 0 ; j < indent ; j++) {
HAL_Printf("%s", JSON_INDENT);
}
}
}
break;
case '}':
case ']':
if (!quoted) {
if ((i > 0) && (!(str[i - 1] == '{' || str[i - 1] == '['))) {
JSON_PRINT_NEWLINE;
--indent;
for (j = 0 ; j < indent ; j++) {
HAL_Printf("%s", JSON_INDENT);
}
} else if ((i > 0) && ((str[i - 1] == '[' && ch == ']') || (str[i - 1] == '{' && ch == '}'))) {
for (j = 0 ; j < indent ; j++) {
HAL_Printf("%s", JSON_INDENT);
}
}
}
newstr[0] = ch;
JSON_PRINT_NEWSTR;
break;
case '"':
newstr[0] = ch;
JSON_PRINT_NEWSTR;
escaped = 1;
if (i > 0 && str[i - 1] == '\\') {
escaped = !escaped;
}
if (!escaped) {
quoted = !quoted;
}
break;
case ',':
newstr[0] = ch;
JSON_PRINT_NEWSTR;
if (!quoted) {
JSON_PRINT_NEWLINE;
for (j = 0 ; j < indent ; j++) {
HAL_Printf("%s", JSON_INDENT);
}
}
break;
case ':':
newstr[0] = ch;
JSON_PRINT_NEWSTR;
if (!quoted) {
HAL_Printf("%s", " ");
}
break;
default:
newstr[0] = ch;
JSON_PRINT_NEWSTR;
break;
}
}
HAL_Printf("%s", JSON_NEWLINE JSON_NEWLINE);
HAL_Printf("%s", "\033[0m");
return 0;
}
#endif /* #ifdef INFRA_LOG_NETWORK_PAYLOAD */

View File

@@ -0,0 +1,266 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_REPORT
#include <stdio.h>
#include <string.h>
#include "infra_types.h"
#include "infra_defs.h"
#include "infra_string.h"
#include "infra_report.h"
void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
void HAL_Printf(const char *fmt, ...);
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
uint64_t HAL_UptimeMs(void);
int HAL_GetFirmwareVersion(char *version);
#ifdef INFRA_MEM_STATS
#include "infra_mem_stats.h"
#define SYS_REPORT_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "sys.report")
#define SYS_REPORT_FREE(ptr) LITE_free(ptr)
#else
#define SYS_REPORT_MALLOC(size) HAL_Malloc(size)
#define SYS_REPORT_FREE(ptr) HAL_Free(ptr)
#endif
#ifdef INFRA_LOG
#include "infra_log.h"
#define VERSION_DEBUG(...) log_debug("version", __VA_ARGS__)
#define VERSION_ERR(...) log_err("version", __VA_ARGS__)
#else
#define VERSION_DEBUG(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#define VERSION_ERR(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
#endif
static unsigned int g_report_id = 0;
int iotx_report_id(void)
{
return g_report_id++;
}
static info_report_func_pt info_report_func = NULL;
void iotx_set_report_func(info_report_func_pt func)
{
info_report_func = func;
}
/* aos will implement this function */
#if defined(BUILD_AOS)
extern void aos_get_version_hex(unsigned char version[VERSION_NUM_SIZE]);
#else
void aos_get_version_hex(unsigned char version[VERSION_NUM_SIZE])
{
const char *p_version = IOTX_SDK_VERSION;
int i = 0, j = 0;
unsigned char res = 0;
for (j = 0; j < 3; j++) {
for (res = 0; p_version[i] <= '9' && p_version[i] >= '0'; i++) {
res = res * 10 + p_version[i] - '0';
}
version[j] = res;
i++;
}
version[3] = 0x00;
}
#endif
/* aos will implement this function */
#if defined(BUILD_AOS)
extern void aos_get_mac_hex(unsigned char mac[MAC_ADDRESS_SIZE]);
#else
void aos_get_mac_hex(unsigned char mac[MAC_ADDRESS_SIZE])
{
memcpy(mac, "\x01\x02\x03\x04\x05\x06\x07\x08", MAC_ADDRESS_SIZE);
}
#endif
/* aos will implement this function */
#if defined(BUILD_AOS)
extern void aos_get_chip_code(unsigned char chip_code[CHIP_CODE_SIZE]);
#else
void aos_get_chip_code(unsigned char chip_code[CHIP_CODE_SIZE])
{
memcpy(chip_code, "\x01\x02\x03\x04", CHIP_CODE_SIZE);
}
#endif
const char *DEVICE_INFO_UPDATE_FMT = "{\"id\":\"%d\",\"version\":\"1.0\",\"params\":["
"{\"attrKey\":\"SYS_LP_SDK_VERSION\",\"attrValue\":\"%s\",\"domain\":\"SYSTEM\"},"
"{\"attrKey\":\"SYS_SDK_LANGUAGE\",\"attrValue\":\"C\",\"domain\":\"SYSTEM\"}"
"],\"method\":\"thing.deviceinfo.update\"}";
int iotx_report_devinfo(void *pclient)
{
int ret = 0;
char topic_name[IOTX_URI_MAX_LEN + 1] = {0};
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
char *msg = NULL;
int msg_len = 0;
if (info_report_func == NULL) {
VERSION_ERR("report func not register!");
return -1;
}
HAL_GetProductKey(product_key);
HAL_GetDeviceName(device_name);
VERSION_DEBUG("devinfo report");
/* devinfo update topic name */
ret = HAL_Snprintf(topic_name,
IOTX_URI_MAX_LEN,
"/sys/%s/%s/thing/deviceinfo/update",
product_key,
device_name);
if (ret <= 0) {
VERSION_ERR("topic generate err");
return FAIL_RETURN;
}
VERSION_DEBUG("devinfo report topic: %s", topic_name);
msg_len = strlen(DEVICE_INFO_UPDATE_FMT) + 10 + strlen(IOTX_SDK_VERSION) + 1;
msg = (char *)SYS_REPORT_MALLOC(msg_len);
if (msg == NULL) {
VERSION_ERR("malloc err");
return FAIL_RETURN;
}
memset(msg, 0, msg_len);
/* devinfo update message */
ret = HAL_Snprintf(msg,
msg_len,
DEVICE_INFO_UPDATE_FMT,
iotx_report_id(),
IOTX_SDK_VERSION
);
if (ret <= 0) {
VERSION_ERR("topic msg generate err");
SYS_REPORT_FREE(msg);
return FAIL_RETURN;
}
VERSION_DEBUG("devinfo report data: %s", msg);
if (info_report_func != NULL) {
info_report_func(pclient, topic_name, 1, msg, strlen(msg));
}
SYS_REPORT_FREE(msg);
if (ret < 0) {
VERSION_ERR("publish failed, ret = %d", ret);
return FAIL_RETURN;
}
VERSION_DEBUG("devinfo report succeed");
return SUCCESS_RETURN;
}
/* report Firmware version */
int iotx_report_firmware_version(void *pclient)
{
int ret;
char topic_name[IOTX_URI_MAX_LEN + 1] = {0};
char msg[FIRMWARE_VERSION_MSG_LEN] = {0};
char version[IOTX_FIRMWARE_VERSION_LEN + 1] = {0};
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
if (info_report_func == NULL) {
VERSION_ERR("report func not register!");
return -1;
}
HAL_GetProductKey(product_key);
HAL_GetDeviceName(device_name);
ret = HAL_GetFirmwareVersion(version);
if (ret <= 0) {
VERSION_ERR("firmware version does not implement");
return FAIL_RETURN;
}
VERSION_DEBUG("firmware version report start in MQTT");
/* firmware report topic name generate */
ret = HAL_Snprintf(topic_name,
IOTX_URI_MAX_LEN,
"/ota/device/inform/%s/%s",
product_key,
device_name
);
if (ret <= 0) {
VERSION_ERR("firmware report topic generate err");
return FAIL_RETURN;
}
VERSION_DEBUG("firmware report topic: %s", topic_name);
/* firmware report message json data generate */
ret = HAL_Snprintf(msg,
FIRMWARE_VERSION_MSG_LEN,
"{\"id\":\"%d\",\"params\":{\"version\":\"%s\"}}",
iotx_report_id(),
version
);
if (ret <= 0) {
VERSION_ERR("firmware report message json data generate err");
return FAIL_RETURN;
}
VERSION_DEBUG("firmware report data: %s", msg);
ret = info_report_func(pclient, topic_name, 1, msg, strlen(msg));
if (ret < 0) {
VERSION_ERR("publish failed, ret = %d", ret);
return ret;
}
VERSION_DEBUG("firmware version report finished, iotx_publish() = %d", ret);
return SUCCESS_RETURN;
}
/* report ModuleID */
int iotx_report_mid(void *pclient)
{
return SUCCESS_RETURN;
}
#ifndef BUILD_AOS
unsigned int aos_get_version_info(unsigned char version_num[VERSION_NUM_SIZE],
unsigned char random_num[RANDOM_NUM_SIZE], unsigned char mac_address[MAC_ADDRESS_SIZE],
unsigned char chip_code[CHIP_CODE_SIZE], unsigned char *output_buffer, unsigned int output_buffer_size)
{
char *p = (char *)output_buffer;
if (output_buffer_size < AOS_ACTIVE_INFO_LEN) {
return 1;
}
memset(p, 0, output_buffer_size);
infra_hex2str(version_num, VERSION_NUM_SIZE, p);
p += VERSION_NUM_SIZE * 2;
infra_hex2str(random_num, RANDOM_NUM_SIZE, p);
p += RANDOM_NUM_SIZE * 2;
infra_hex2str(mac_address, MAC_ADDRESS_SIZE, p);
p += MAC_ADDRESS_SIZE * 2;
infra_hex2str(chip_code, CHIP_CODE_SIZE, p);
p += CHIP_CODE_SIZE * 2;
strcat(p, "1111111111222222222233333333334444444444");
return 0;
}
#endif
#endif

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_defs.h"
#ifndef _INFRA_REPORT_H_
#define _INFRA_REPORT_H_
#ifndef VERSION_NUM_SIZE
#define VERSION_NUM_SIZE 4
#endif
#ifndef RANDOM_NUM_SIZE
#define RANDOM_NUM_SIZE 4
#endif
#ifndef MAC_ADDRESS_SIZE
#define MAC_ADDRESS_SIZE 8
#endif
#ifndef CHIP_CODE_SIZE
#define CHIP_CODE_SIZE 4
#endif
#define AOS_ACTIVE_INFO_LEN (81)
/* activation device type */
typedef enum {
ACTIVE_SUBDEV, /* it's a subDevice */
ACTIVE_SINGLE_GW /* it s a single or gateway device */
} active_device_type_t;
/* activation system type */
typedef enum {
ACTIVE_LINKKIT_ONLY, /* only linkkit implement */
ACTIVE_LINKKIT_AOS, /* both linkkit and AOS implement */
ACTIVE_LINKKIT_OTHERS /* linkkit and 3-party OS implement */
} active_system_type_t;
typedef int (*info_report_func_pt)(void *handle, const char *topic_name,int req_ack,void *data, int len);
#define MIDREPORT_PAYLOAD_LEN (62 + IOTX_PARTNER_ID_LEN + IOTX_MODULE_ID_LEN + 32 +1)
#define MIDREPORT_REQID_LEN (IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 6)
#define AOS_VERSON_MSG_LEN (256)
#define LINKKIT_VERSION_MSG_LEN (192)
#define FIRMWARE_VERSION_MSG_LEN (64)
#define DEBUG_REPORT_MID_DEVINFO_FIRMWARE (1)
int iotx_report_id(void);
int iotx_midreport_reqid(char *requestId, char *product_key, char *device_name);
int iotx_midreport_payload(char *msg, char *requestId, char *mid, char *pid);
int iotx_midreport_topic(char *topic_name, char *topic_head, char *product_key, char *device_name);
/* AOS version report API */
int iotx_gen_aos_report_topic(char *topic_name, char *product_key, char *device_name);
int iotx_gen_aos_report_payload(char *msg, int requestId, char *versionData);
void aos_get_version_hex(unsigned char version[VERSION_NUM_SIZE]);
#ifndef BUILD_AOS
unsigned int aos_get_version_info(unsigned char version_num[VERSION_NUM_SIZE],
unsigned char random_num[RANDOM_NUM_SIZE], unsigned char mac_address[MAC_ADDRESS_SIZE],
unsigned char chip_code[CHIP_CODE_SIZE], unsigned char *output_buffer, unsigned int output_buffer_size);
#endif
void iotx_set_report_func(info_report_func_pt func);
int iotx_report_devinfo(void *pclient);
int iotx_report_mid(void *pclient);
int iotx_report_firmware_version(void *pclient);
#endif

View File

@@ -0,0 +1,423 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "infra_config.h"
#ifdef INFRA_SHA1
#include <stdlib.h>
#include <string.h>
#include "infra_sha1.h"
#define SHA1_KEY_IOPAD_SIZE (64)
#define SHA1_DIGEST_SIZE (20)
/* Implementation that should never be optimized out by the compiler */
static void utils_sha1_zeroize( void *v, uint32_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(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) ); \
}
#endif
void utils_sha1_init(iot_sha1_context *ctx)
{
memset(ctx, 0, sizeof(iot_sha1_context));
}
void utils_sha1_free(iot_sha1_context *ctx)
{
if (ctx == NULL) {
return;
}
utils_sha1_zeroize(ctx, sizeof(iot_sha1_context));
}
void utils_sha1_clone(iot_sha1_context *dst,
const iot_sha1_context *src)
{
*dst = *src;
}
/*
* SHA-1 context setup
*/
void utils_sha1_starts(iot_sha1_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;
ctx->state[4] = 0xC3D2E1F0;
}
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void utils_sha1_update(iot_sha1_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_sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
utils_sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha1_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
};
/*
* SHA-1 final digest
*/
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
{
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_sha1_update( ctx, sha1_padding, padn );
utils_sha1_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 );
}
/*
* output = SHA-1( input buffer )
*/
void utils_sha1(const unsigned char *input, uint32_t ilen, unsigned char output[20])
{
iot_sha1_context ctx;
utils_sha1_init(&ctx);
utils_sha1_starts(&ctx);
utils_sha1_update(&ctx, input, ilen);
utils_sha1_finish(&ctx, output);
utils_sha1_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_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len)
{
iot_sha1_context context;
unsigned char k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
unsigned char k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
unsigned char out[SHA1_DIGEST_SIZE];
int i;
if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
return;
}
if (key_len > SHA1_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 < SHA1_KEY_IOPAD_SIZE; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner SHA */
utils_sha1_init(&context); /* init context for 1st pass */
utils_sha1_starts(&context); /* setup context for 1st pass */
utils_sha1_update(&context, k_ipad, SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
utils_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
utils_sha1_finish(&context, out); /* finish up 1st pass */
/* perform outer SHA */
utils_sha1_init(&context); /* init context for 2nd pass */
utils_sha1_starts(&context); /* setup context for 2nd pass */
utils_sha1_update(&context, k_opad, SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
utils_sha1_finish(&context, out); /* finish up 2nd pass */
for (i = 0; i < SHA1_DIGEST_SIZE; ++i) {
digest[i * 2] = utils_hb2hex(out[i] >> 4);
digest[i * 2 + 1] = utils_hb2hex(out[i]);
}
}
void utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len)
{
iot_sha1_context context;
unsigned char k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
unsigned char k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
unsigned char out[SHA1_DIGEST_SIZE];
int i;
if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
return;
}
if (key_len > SHA1_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 < SHA1_KEY_IOPAD_SIZE; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner SHA */
utils_sha1_init(&context); /* init context for 1st pass */
utils_sha1_starts(&context); /* setup context for 1st pass */
utils_sha1_update(&context, k_ipad, SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
utils_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
utils_sha1_finish(&context, out); /* finish up 1st pass */
/* perform outer SHA */
utils_sha1_init(&context); /* init context for 2nd pass */
utils_sha1_starts(&context); /* setup context for 2nd pass */
utils_sha1_update(&context, k_opad, SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
utils_sha1_finish(&context, out); /* finish up 2nd pass */
memcpy(digest, out, SHA1_DIGEST_SIZE);
}
#endif

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef _INFRA_SHA1_H_
#define _INFRA_SHA1_H_
#include "infra_types.h"
#define SHA1_DIGEST_SIZE (20)
/**
* \brief SHA-1 context structure
*/
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
} iot_sha1_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void utils_sha1_init(iot_sha1_context *ctx);
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void utils_sha1_free(iot_sha1_context *ctx);
/**
* \brief Clone (the state of) a SHA-1 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void utils_sha1_clone(iot_sha1_context *dst,
const iot_sha1_context *src);
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void utils_sha1_starts(iot_sha1_context *ctx);
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, uint32_t ilen);
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]);
/* Internal use */
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]);
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void utils_sha1(const unsigned char *input, uint32_t ilen, unsigned char output[20]);
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
void utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len);
#endif

View File

@@ -0,0 +1,321 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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

View File

@@ -0,0 +1,207 @@
#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

View File

@@ -0,0 +1,16 @@
#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

View File

@@ -0,0 +1,95 @@
#include "infra_config.h"
#ifdef INFRA_TIMER
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#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_ */

View File

@@ -0,0 +1,29 @@
#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

View File

@@ -0,0 +1 @@
LIBA_TARGET := libiot_infra.a