HTTP 开发指导_Rev1.2
修订记录
版本 |
日期 |
作者 |
修订内容 |
|---|---|---|---|
Rev1.0 |
2023-09-14 |
CLY |
创建文档 |
Rev1.1 |
2024-03-25 |
sxx |
更改文档名称 |
Rev1.2 |
2025-10-28 |
LXH |
增加发送、接收超时时间设置 |
1 简介
本文档介绍 NT26F HTTP函数接口, 函数接口位于 components/kernel/lierda_api/liot_http/liot_http.h 文件声明。
2 API 函数概览
函数 |
说明 |
|---|---|
|
创建一个新的HTTP客户端句柄并初始化HTTP客户端资源 |
|
发送 HTTP 请求 |
|
停止HTTP请求 |
|
释放 HTTP 客户端资源 |
|
配置 HTTP 客户端属性 |
|
获取HTTP消息头信息 |
|
配置 HTTP 表单属性。 |
|
判断HTTP客户端是否处于运行态 |
|
解析URL |
3 类型说明
3.1 liot_httpc_method_e
HTTP请求方法。
声明
typedef enum
{
LIOT_HTTPC_METHOD_NONE = 0,
LIOT_HTTPC_METHOD_GET = 1,
LIOT_HTTPC_METHOD_POST = 2,
LIOT_HTTPC_METHOD_PUT = 3,
LIOT_HTTPC_METHOD_HEAD = 4,
LIOT_HTTPC_METHOD_LAST = 5,
LIOT_HTTPC_METHOD_DELETE = 6,
} liot_httpc_method_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTPC_METHOD_NONE |
无请求 |
LIOT_HTTPC_METHOD_GET |
HTTP GET请求 |
LIOT_HTTPC_METHOD_POST |
HTTP POST请求 |
LIOT_HTTPC_METHOD_PUT |
HTTP PUT 请求,暂不支持 |
LIOT_HTTPC_METHOD_HEAD |
HTTP HEAD请求 |
LIOT_HTTPC_METHOD_LAST |
上一次的请求,暂不支持 |
LIOT_HTTPC_METHOD_DELETE |
HTTP DELETE请求 |
3.2 liot_http_client_t
HTTP客户端句柄。
声明
typedef int liot_http_client_t;
4 API 函数详解
4.1 liot_httpc_new
该函数用于创建一个新的 HTTP 客户端句柄并初始化 HTTP 客户端资源。
声明
int liot_httpc_new(liot_http_client_t *client, liot_http_client_event_cb_t cb, void *arg);
参数
client:
[Out] HTTP客户端句柄。
cb:
[In] HTTP请求事件回调处理函数。参考liot_http_client_event_cb_t。
arg:
[In] HTTP请求事件回调处理函数的参数。
返回值
执行结果码,请参考liot_httpc_result_code_e。
4.1.1 liot_http_client_event_cb_t
请求事件回调处理函数。
声明
typedef void (*liot_http_client_event_cb_t)(liot_http_client_t *client, int evt, int evt_code, void *arg);
参数
client:
[Out] http客户端句柄。
evt:
[In] http请求事件类型。参考liot_httpc_event_id_e。
evt_code:
[In] http请求事件结果类型。参考liot_httpc_event_type_e。
arg:
[In] http请求事件回调处理函数的参数。
返回值
执行结果码,请参考 liot_httpc_result_code_e。
4.1.2 liot_httpc_event_id_e
HTTP API 执行结果错误码。
声明
typedef enum
{
LIOT_HTTP_EVENT_SESSION_ESTABLISH = 0,
LIOT_HTTP_EVENT_RESPONE_STATE_LINE = 1,
LIOT_HTTP_EVENT_SESSION_DISCONNECT = 2,
} liot_httpc_event_id_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTP_EVENT_SESSION_ESTABLISH |
HTTP请求连接建立成功 |
LIOT_HTTP_EVENT_RESPONE_STATE_LINE |
HTTP请求开始响应 |
LIOT_HTTP_EVENT_SESSION_DISCONNECT |
HTTP请求连接断开连接 |
4.1.3 liot_httpc_event_type_e
HTTP请求过程中触发事件的状态。
声明
typedef enum
{
LIOT_HTTPC_SESSION_OPEN = 1,
LIOT_HTTPC_UPLOAD_START = 2,
LIOT_HTTPC_UPLOAD_END = 3,
LIOT_HTTPC_RESPONSE_STATUS = 4,
LIOT_HTTPC_RESPONSE_COMPLETE = 5,
LIOT_HTTPC_RESPONSE_TIMEOUT = 6,
LIOT_HTTPC_SESSION_CLOSE = 7,
LIOT_HTTPC_RAW_REQ_START = 8,
LIOT_HTTPC_RAW_REQ_END = 9,
} liot_httpc_event_type_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTPC_SESSION_OPEN |
HTTP客户端连接建立成功事件状态 |
LIOT_HTTPC_UPLOAD_START |
HTTP客户端开始上传文件事件状态,暂不支持 |
LIOT_HTTPC_UPLOAD_END |
HTTP客户端完成上传文件事件,暂不支持 |
LIOT_HTTPC_RESPONSE_STATUS |
HTTP客户端开始接收响应数据事件 |
LIOT_HTTPC_RESPONSE_COMPLETE |
HTTP客户端完成接收响应数据事件 |
LIOT_HTTPC_RESPONSE_TIMEOUT |
HTTP客户端接收响应数据超时事件 |
LIOT_HTTPC_SESSION_CLOSE |
HTTP客户端链路已关闭事件 |
LIOT_HTTPC_RAW_REQ_START |
HTTP客户端开始上传RAW文件事件,暂不支持 |
LIOT_HTTPC_RAW_REQ_END |
HTTP客户端上传RAW文件已完成事件,暂不支持 |
4.1.4 liot_httpc_result_code_e
HTTP API 执行结果错误码。
声明
typedef enum
{
LIOT_HTTPC_SUCCESS = LIOT_SUCCESS,
LIOT_HTTPC_ERR_INVALID_PARAM = 1 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_UNKNOWN = 2 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_OUT_OF_MEM = 3 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_SOCKET_FAILURE = 4 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_NOT_SUPPORT = 5 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_NOT_ALLOW = 6 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_NO_NETWORK = 7 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_NO_SSL_CERT = 8 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_ERR_TIMEOUT = 9 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_EMPTY_URL = 10 | LIOT_HTTP_ERRCODE_BASE,
LIOT_HTTPC_SSL_ERROR = 11 | LIOT_HTTP_ERRCODE_BASE,
} liot_httpc_result_code_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTPC_SUCCESS |
成功 |
LIOT_HTTPC_ERR_INVALID_PARAM |
函数参数错误 |
LIOT_HTTPC_ERR_UNKNOWN |
未知的错误 |
LIOT_HTTPC_ERR_OUT_OF_MEM |
空间不足 |
LIOT_HTTPC_ERR_SOCKET_FAILURE |
socket失败 |
LIOT_HTTPC_ERR_NOT_SUPPORT |
功能不支持 |
LIOT_HTTPC_ERR_NOT_ALLOW |
操作不允许 |
LIOT_HTTPC_ERR_NO_NETWORK |
无网络 |
LIOT_HTTPC_ERR_NO_SSL_CERT |
SSL无证书 |
LIOT_HTTPC_ERR_TIMEOUT |
超时 |
LIOT_HTTPC_EMPTY_URL |
URL为空 |
LIOT_HTTPC_SSL_ERROR |
SSL错误 |
4.2 liot_httpc_perform
发送 HTTP 请求。
声明
int liot_httpc_perform(liot_http_client_t *client);
参数
client:
[In] HTTP请求客户端句柄。
返回值
执行结果码,请参考 liot_httpc_result_code_e。
4.3 liot_httpc_stop
该函数用于停止HTTP客户端请求。
声明
int liot_httpc_stop(liot_http_client_t *client);
参数
client:
[In] HTTP请求客户端句柄。
返回值
执行结果码,请参考 liot_httpc_result_code_e。
4.4 liot_httpc_release
该函数用于释放HTTP请求客户端。
声明
int liot_httpc_release(liot_http_client_t *client);
参数
client:
[In] HTTP请求客户端句柄。
返回值
执行结果码,请参考 liot_httpc_result_code_e。
4.5 liot_httpc_setopt
该函数用于设置HTTP相关属性。
声明
int liot_httpc_setopt(liot_http_client_t *client, int opt_tag, ...);
参数
client:
[In] HTTP请求客户端句柄。
opt_tag:
[In] HTTP属性标签。参考第5.5.3章,相关liot_httpc_option_e说明。
…
[In] HTTP属性值。
返回值
执行结果码,请参考 liot_httpc_result_code_e。
4.5.1 liot_http_client_write_data_cb_t
收到 HTTP 响应数据后,会自动调用该回调函数进行数据处理。
声明
typedef int (*liot_http_client_write_data_cb_t)(
liot_http_client_t *client, void *arg, char *data, int size, unsigned char end);
参数
client:
[In] HTTP客户端句柄。
arg:
[In] HTTP回调处理函数的参数。
data:
[In] HTTP请求响应的数据。
size:
[In] HTTP请求响应数据的长度。
end:
[In] HTTP请求响应结束符。
false:数据接收未结束。
true:数据接收完毕。
返回值
接收处理的数据长度。
4.5.2 liot_http_client_read_data_cb_t
当发生 HTTP POST/PUT 请求时,会自动调用该回调函数读取待上传的数据。。
声明
typedef int (*liot_http_client_read_data_cb_t)(
liot_http_client_t *client, void *arg, char *data, int size);
参数
client:
[In] HTTP客户端句柄。
arg:
[In] HTTP回调处理函数的参数。
data:
[Out] 用于存储待上传数据的空间。
size:
[In] 指定长度。
返回值
实际读取的数据长度。
4.5.3 liot_httpc_option_e
HTTP相关属性。
声明
typedef enum
{
LIOT_HTTP_CLIENT_OPT_PDPCID = 1,
LIOT_HTTP_CLIENT_OPT_BASIC_AUTH,
LIOT_HTTP_CLIENT_OPT_REQUEST_HEADER,
LIOT_HTTP_CLIENT_OPT_WRITE_HEADER,
LIOT_HTTP_CLIENT_OPT_INTERVAL_TIME,
LIOT_HTTP_CLIENT_OPT_METHOD,
LIOT_HTTP_CLIENT_OPT_WRITE_FUNC,
LIOT_HTTP_CLIENT_OPT_WRITE_DATA,
LIOT_HTTP_CLIENT_OPT_READ_FUNC,
LIOT_HTTP_CLIENT_OPT_READ_DATA,
LIOT_HTTP_CLIENT_OPT_UPLOAD_LEN,
LIOT_HTTP_CLIENT_OPT_URL,
LIOT_HTTP_CLIENT_OPT_URI,
LIOT_HTTP_CLIENT_OPT_SIM_ID,
LIOT_HTTP_CLIENT_OPT_RAW_REQUEST,
LIOT_HTTP_CLIENT_OPT_RAW_FILE,
LIOT_HTTP_CLIENT_OPT_AUTH_INFO,
LIOT_HTTP_CLIENT_OPT_RESPONSE_TIME,
LIOT_HTTP_CLIENT_OPT_BODY_DATA_TYPE,
LIOT_HTTP_CLIENT_OPT_FORM_OPTION,
LIOT_HTTP_CLIENT_OPT_CUSTOME_HEADER,
LIOT_HTTP_CLIENT_OPT_SEND_TIMEOUT,
LIOT_HTTP_CLIENT_OPT_RECV_TIMEOUT,
LIOT_HTTP_CLIENT_OPT_SSLCTXID,
LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL,
LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH,
LIOT_HTTP_CLIENT_OPT_SSL_OWNCERT_PATH,
LIOT_HTTP_CLIENT_OPT_SSL_SNI,
LIOT_HTTP_CLIENT_OPT_SSL_VERSION,
LIOT_HTTP_CLIENT_OPT_SSL_HS_TIMEOUT,
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_LOCALTM,
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN,
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM,
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_MULTI_CERTCHAIN_VERIFY,
} liot_httpc_option_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTP_CLIENT_OPT_PDPCID |
设置 HTTP 客户端使用的数据通道号,即执行数据拨号操作时使用的PDP上下文ID。 |
LIOT_HTTP_CLIENT_OPT_BASIC_AUTH |
设置 HTTP 基本认证的用户名和密码。 |
LIOT_HTTP_CLIENT_OPT_REQUEST_HEADER |
设置自定义 HTTP 请求头属性。 |
LIOT_HTTP_CLIENT_OPT_WRITE_HEADER |
设置HTTP响应头。 |
LIOT_HTTP_CLIENT_OPT_INTERVAL_TIME |
设置等待 HTTP 响应数据的最大间隔时间。 |
LIOT_HTTP_CLIENT_OPT_METHOD |
设置 HTTP 请求方式。 |
LIOT_HTTP_CLIENT_OPT_WRITE_FUNC |
设置处理 HTTP 响应数据的回调函数。参数类型:http_client_write_data_cb_t |
LIOT_HTTP_CLIENT_OPT_WRITE_DATA |
设置处理 HTTP 响应数据的回调函数的参数。参数类型:void * |
LIOT_HTTP_CLIENT_OPT_READ_FUNC |
设置读取HTTP请求上传数据的回调函数。 |
LIOT_HTTP_CLIENT_OPT_READ_DATA |
设置读取HTTP请求上传数据的回调函数的入参。参数类型:void * |
LIOT_HTTP_CLIENT_OPT_UPLOAD_LEN |
设置读取HTTP请求上传数据的长度。长度最新的SDK V05.03以及之后为不超过100K,之前的老版本为20kb。 |
LIOT_HTTP_CLIENT_OPT_URL |
设置HTTP请求的URL,字符串类型,长度不超过512字节。 |
LIOT_HTTP_CLIENT_OPT_URI |
设置HTTP请求的URI,字符串类型,长度不超过512字节。 |
LIOT_HTTP_CLIENT_OPT_SIM_ID |
执行数据拨号操作时使用的(U)SIM 卡,当前不支持。 |
LIOT_HTTP_CLIENT_OPT_RAW_REQUEST |
设置HTTP请求上传数据格式。 |
LIOT_HTTP_CLIENT_OPT_RAW_FILE |
设置HTTP请求文件名称。类型:char*。 |
LIOT_HTTP_CLIENT_OPT_AUTH_INFO |
设置HTTP请求头中auth属性,暂不支持。 |
LIOT_HTTP_CLIENT_OPT_RESPONSE_TIME |
设置HTTP请求响应时间。暂不支持。 |
LIOT_HTTP_CLIENT_OPT_BODY_DATA_TYPE |
暂不支持。 |
LIOT_HTTP_CLIENT_OPT_FORM_OPTION |
暂不支持。 |
LIOT_HTTP_CLIENT_OPT_CUSTOME_HEADER |
暂不支持。 |
LIOT_HTTP_CLIENT_OPT_SEND_TIMEOUT |
设置发送数据的超时时间,默认2s。(V05.04及之后版本支持) |
LIOT_HTTP_CLIENT_OPT_RECV_TIMEOUT |
设置接收数据的超时时间,默认20s。(V05.04及之后版本支持) |
LIOT_HTTP_CLIENT_OPT_SSLCTXID |
设置SSL上下文ID。范围:0~5。 |
LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL |
设置SSL的校验等级。范围:0~2。参考第 [liot_https_verify_level_e]。 |
LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH |
设置SSL的CA证书路径。字符串类型,长度不超过255。 |
LIOT_HTTP_CLIENT_OPT_SSL_OWNCERT_PATH |
设置SSL的本地证书的路径。字符串类型,长度不超过255。 |
LIOT_HTTP_CLIENT_OPT_SSL_SNI |
设置SSL是否支持SNI扩展。 |
LIOT_HTTP_CLIENT_OPT_SSL_VERSION |
设置SSL上下文的SSL版本。范围0~4。 |
LIOT_HTTP_CLIENT_OPT_SSL_HS_TIMEOUT |
设置SSL上下文握手的超时时间。范围1~65535,单位秒。 |
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_LOCALTM |
设置SSL上下文忽略本地时间与证书有效期之间的不匹配。暂不支持。 |
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN |
设置SSL上下文忽略证书签名无效。暂不支持。 |
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM |
设置SSL上下文忽略证书项验证。暂不支持。 |
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_MULTI_CERTCHAIN_VERIFY |
设置SSL上下文忽略证书链中存在多条证书的验证错误。暂不支持。 |
4.5.4 liot_https_verify_level_e
HTTPS 连接认证类型。
声明
typedef enum
{
LIOT_HTTPS_VERIFY_NONE = 0,
LIOT_HTTPS_VERIFY_SERVER = 1,
LIOT_HTTPS_VERIFY_SERVER_CLIENT = 2,
} liot_https_verify_level_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTPS_VERIFY_NONE |
无认证 |
LIOT_HTTPS_VERIFY_SERVER |
单向认证,即服务器认证 |
LIOT_HTTPS_VERIFY_SERVER_CLIENT |
双向认证,即客户端认证 |
4.6 liot_httpc_getinfo
该函数用于获取HTTP请求响应头部相关信息。
声明
int liot_httpc_getinfo(liot_http_client_t *client, int info, ...);
参数
client:
[In] HTTP请求客户端句柄。
opt_tag:
[In] HTTP属性标签。参考 liot_httpc_info_type_e说明。
…
[In] HTTP属性值。
返回值
执行结果码,请参考liot_httpc_result_code_e。
4.6.1 liot_httpc_info_type_e
HTTP响应头信息结构体部分属性定义。
typedef enum
{
LIOT_HTTPC_STATUS_CODE = 1,
LIOT_HTTPC_CHUNK_ENCODE = 2,
LIOT_HTTPC_CONTENT_LEN = 3,
LIOT_HTTPC_CONTENT_RANGE = 4,
LIOT_HTTPC_DATE = 5,
LIOT_HTTPC_LOCATION = 6,
LIOT_HTTPC_NREAD_DATA_LEN = 7,
} liot_httpc_info_type_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTPC_STATUS_CODE |
HTTP请求响应码 |
LIOT_HTTPC_CHUNK_ENCODE |
获取响应体数据是否为 chunk 编码格式。 |
LIOT_HTTPC_CONTENT_LEN |
获取内容长度。该值仅当 HTTP 响应头中带有内容长度时方可获取。 |
LIOT_HTTPC_CONTENT_RANGE |
分包下载时获取整包大小(4.01版本后支持) |
LIOT_HTTPC_DATE |
获取时间。参数类型:char*。 |
LIOT_HTTPC_LOCATION |
获取重定向的 URL。该值仅当响应码为 3xx 时方可获取。 |
LIOT_HTTPC_NREAD_DATA_LEN |
暂不支持 |
4.7 liot_httpc_formadd
该函数用于配置HTTP表单属性。
声明
int liot_httpc_formadd(liot_http_client_t *client, int opt_tag, ...);
参数
client:
[In] HTTP请求客户端句柄。
opt_tag:
[In] HTTP表单属性标签。参考 liot_httpc_formopt_e说明。
…
[In] HTTP表单属性值。
返回值
执行结果码,请参考 liot_httpc_result_code_e。
4.7.1 liot_httpc_formopt_e
HTTP请求表单属性定义。
typedef enum
{
LIOT_HTTP_FORM_NAME = 1,
LIOT_HTTP_FORM_FILENAME = 2,
LIOT_HTTP_FORM_CONTENT_TYPE = 3,
} liot_httpc_formopt_e;
参数
参数 |
说明 |
|---|---|
LIOT_HTTP_FORM_NAME |
设置上传数据在服务器上的存储格式为file或image等。 |
LIOT_HTTP_FORM_FILENAME |
设置上传数据在服务器保存的名字。仅在LIOT_HTTP_FORM_NAME 配置为 file 时有效。 |
LIOT_HTTP_FORM_CONTENT_TYPE |
设 置 上 传 数 据 对 应 的 内 容 类 型。仅LIOT_HTTP_FORM_NAME 配置为 file 时有效。 |
4.8 liot_httpc_is_running
该函数用于判断当前HTTP客户端是否处于运行状态。
声明
bool liot_httpc_is_running(liot_http_client_t *client);
参数
client:
[In] HTTP请求客户端句柄。
返回值
true:HTTP客户端处于运行状态。
false:HTTP客户端处于非运行状态。
4.9 liot_httpc_url_parse
该函数用于解析HTTP请求URL。
声明
bool liot_httpc_url_parse(char *url_str, liot_httpc_url_s *url);
参数
url_str:
[In] 输入的HTTP请求URL。
url:
[Out] 解析后的数据格式。详情见 liot_httpc_url_s。
返回值
true:解析成功。
false:解析失败。
4.9.1 liot_httpc_url_s
选择的运营商信息结构体定义
typedef struct
{
liot_httpc_scheme_e scheme;
char *host;
unsigned short port;
char *uri;
} liot_httpc_url_s;
参数
类型 |
参数 |
描述 |
|---|---|---|
liot_httpc_scheme_e |
scheme |
HTTP请求类型,参考第5.9.2 liot_httpc_scheme_e |
char * |
host |
HTTP请求host,最大长度不超过512字节 |
unsigned short |
port |
HTTP请求地址端口号,范围0~65535 |
char * |
uri |
HTTP请求的URI,最大长度不超过512字节 |
4.9.2 liot_httpc_scheme_e
定义HTTP请求类型。
声明
typedef enum
{
LIOT_HTTPC_SCHEME_INVALID = 0,
LIOT_HTTPC_SCHEME_HTTP = 1,
LIOT_HTTPC_SCHEME_HTTPS = 2
} liot_httpc_scheme_e
参数
参数 |
说明 |
|---|---|
LIOT_HTTPC_SCHEME_INVALID |
无效参数 |
LIOT_HTTPC_SCHEME_HTTP |
HTTP协议 |
LIOT_HTTPC_SCHEME_HTTPS |
HTTPS协议 |
5 代码示例
示例代码参考 examples/demo/src/demo_http.c 文件。
static liot_sem_t http_semp;
static liot_sem_t http_semp1;
// #define LIOT_HTTP_DEMO_SSL_TEST 1
char *liot_http_ca_cert_path = "UFS:http_ca_cert.pem";
char *liot_http_user_cert_path = "UFS:http_user_cert.pem";
char *liot_http_user_key_path = "UFS:http_user_key.pem";
char *liot_http_upload_path = "UFS:http_test.txt";
char *liot_http_upload_data = "http_upload_test";
int liot_http_upload_len = 0;
char *liot_http_ca_cert_data ="...";//配置为相应CA证书内容
char *liot_http_user_cert_data ="...";//配置相应用户证书
char *liot_http_user_key_data ="...";//配置相应用户私钥
static int http_uploadfile_init(void)
{
int ret = 0;
LFILE fp = -1;
if (liot_file_exist(liot_http_upload_path) != LIOT_FS_NOT_EXIST)
{
liot_remove(liot_http_upload_path);
}
fp = liot_fopen(liot_http_upload_path, "w+");
if (fp < 0)
{
liot_trace("open file:%s failed!!!!", liot_http_upload_path);
return -1;
}
ret = liot_fwrite(liot_http_upload_data, strlen(liot_http_upload_data), 1, fp);
liot_trace("%s:%d", __FUNCTION__, __LINE__);
liot_trace("ret:%d,%s", ret, liot_http_upload_data);
liot_http_upload_len = liot_fsize(fp);
liot_trace("%s:%d liot_http_upload_len:%d", __FUNCTION__, __LINE__, liot_http_upload_len);
if (ret != strlen(liot_http_upload_data))
{
liot_trace("ret:%d", ret);
liot_fclose(fp);
return -1;
}
liot_fclose(fp);
return 0;
}
static int http_ca_cert_init(void)
{
int ret = 0;
LFILE fp = -1;
if (liot_file_exist(liot_http_ca_cert_path) != LIOT_FS_NOT_EXIST)
{
liot_remove(liot_http_ca_cert_path);
}
fp = liot_fopen(liot_http_ca_cert_path, "w+");
if (fp < 0)
{
liot_trace("open file:%s failed!!!!", liot_http_ca_cert_path);
return -1;
}
ret = liot_fwrite(liot_http_ca_cert_data, strlen(liot_http_ca_cert_data), 1, fp);
liot_trace("%s:%d", __FUNCTION__, __LINE__);
liot_trace("ret:%d", ret);
if (ret != strlen(liot_http_ca_cert_data))
{
liot_trace("ret:%d", ret);
liot_fclose(fp);
return -1;
}
liot_fclose(fp);
return 0;
}
static int http_user_cert_init(void)
{
int ret = 0;
LFILE fp = -1;
if (liot_file_exist(liot_http_user_cert_path) != LIOT_FS_NOT_EXIST)
{
liot_remove(liot_http_user_cert_path);
}
fp = liot_fopen(liot_http_user_cert_path, "w+");
if (fp < 0)
{
liot_trace("open file:%s failed!!!!", liot_http_user_cert_path);
return -1;
}
ret = liot_fwrite(liot_http_user_cert_data, strlen(liot_http_user_cert_data), 1, fp);
liot_trace("%s:%d", __FUNCTION__, __LINE__);
liot_trace("ret:%d", ret);
if (ret != strlen(liot_http_user_cert_data))
{
liot_trace("ret:%d", ret);
liot_fclose(fp);
return -1;
}
liot_fclose(fp);
return 0;
}
static int http_user_key_init(void)
{
int ret = 0;
LFILE fp = -1;
if (liot_file_exist(liot_http_user_key_path) != LIOT_FS_NOT_EXIST)
{
liot_remove(liot_http_user_key_path);
}
fp = liot_fopen(liot_http_user_key_path, "w+");
if (fp < 0)
{
liot_trace("open file:%s failed!!!!", liot_http_user_key_path);
return -1;
}
ret = liot_fwrite(liot_http_user_key_data, strlen(liot_http_user_key_data), 1, fp);
liot_trace("%s:%d", __FUNCTION__, __LINE__);
liot_trace("ret:%d", ret);
if (ret != strlen(liot_http_user_key_data))
{
liot_trace("ret:%d", ret);
liot_fclose(fp);
return -1;
}
liot_fclose(fp);
return 0;
}
static void http_event_cb(liot_http_client_t *client, int evt, int evt_code, void *arg)
{
liot_trace("===http_event_cb=== evt:%d,evt_code:%d,%p", evt, evt_code, client);
switch (evt)
{
case LIOT_HTTPC_SESSION_OPEN:
{
if (evt_code != LIOT_HTTPC_SUCCESS)
{
liot_trace("http session open fail");
liot_rtos_semaphore_release(http_semp);
}
}
break;
case LIOT_HTTPC_UPLOAD_START:
{
liot_httpc_user_notify(client, LIOT_HTTPC_READ);
}
break;
case LIOT_HTTPC_UPLOAD_END:
{
}
break;
case LIOT_HTTPC_RESPONSE_STATUS:
{
if (evt_code == LIOT_HTTPC_SUCCESS)
{
int resp_code = 0;
int content_length = 0;
int chunk_encode = 0;
char *location = NULL;
char *date = NULL;
liot_httpc_getinfo(client, LIOT_HTTPC_STATUS_CODE, &resp_code);
liot_httpc_getinfo(client, LIOT_HTTPC_CHUNK_ENCODE, &chunk_encode);
liot_httpc_getinfo(client, LIOT_HTTPC_DATE, &date);
if (date != NULL)
{
liot_trace("===http_event_cb=== Date:%s", date);
free(location);
}
liot_trace("===http_event_cb=== resp_code:%d,chunk_encode:%d", resp_code, chunk_encode);
if (chunk_encode == 0)
{
liot_httpc_getinfo(client, LIOT_HTTPC_CONTENT_LEN, &content_length);
liot_trace("===http_event_cb=== content_length:%d", content_length);
}
else
{
liot_trace("http chunk encode");
}
if (resp_code >= 300 && resp_code < 400)
{
liot_httpc_getinfo(client, LIOT_HTTPC_LOCATION, &location);
liot_trace("===http_event_cb=== location:%s", location);
free(location);
}
}
}
break;
case LIOT_HTTPC_RESPONSE_COMPLETE:
{
if (evt_code == LIOT_HTTPC_SUCCESS)
{
liot_trace("http transfer success");
}
else
{
liot_trace("http transfer fail");
}
liot_rtos_semaphore_release(http_semp);
}
break;
case LIOT_HTTPC_SESSION_CLOSE:
{
liot_trace("http LIOT_HTTPC_SESSION_CLOSE success");
liot_rtos_semaphore_release(http_semp1);
}
break;
}
}
static int http_response_write_data_cb(liot_http_client_t *client, void *arg, char *data, int size, unsigned char end)
{
liot_trace(">>>>>client:%p", client);
liot_trace("===http_response_write_data_cb=== size:%d", size);
unsigned char *recv_buf = NULL;
recv_buf = malloc(size + 1);
if (recv_buf != NULL)
{
memset(recv_buf, 0, size + 1);
memcpy(recv_buf, data, size);
liot_trace("===http_response_write_data_cb=== recv_buf:%s", recv_buf);
free(recv_buf);
recv_buf = NULL;
}
return size;
}
static int http_request_read_data_cb(liot_http_client_t *client, void *arg, char *data, int size)
{
int ret = 0;
LFILE fp = -1;
liot_trace(">>>>>client:%p", client);
if (client == NULL)
{
return 0;
}
fp = liot_fopen(liot_http_upload_path, "r+");
if (fp < 0)
{
liot_trace("open file:%s failed!!!!", liot_http_upload_path);
return 0;
}
ret = liot_fread(data, 1, size, fp);
liot_fclose(fp);
liot_trace("http_request_read_data_cb data:%s", data);
liot_trace("http_request_read_data_cb size:%d", size);
return ret;
}
void liot_http_demo_thread(void *arg)
{
liot_http_client_t http_client = 0;
int ret = 0;
int cid = 1;
liot_data_call_info_t info;
uint8_t nSim = 0;
int times = 0;
while (LIOT_DATACALL_SUCCESS != (ret = liot_network_register_wait(nSim, 120)) && times < 10)
{
times++;
liot_rtos_task_sleep_s(1);
}
if (LIOT_DATACALL_SUCCESS != ret)
{
liot_trace("====network register failure!!!!!====");
if (LIOT_OSI_SUCCESS != liot_rtos_task_delete(NULL))
{
liot_trace("task deleted failed");
}
return;
}
ret = liot_start_data_call(nSim, cid, LIOT_DATA_TYPE_IP, "APNTEST", "", "", LIOT_DATA_AUTH_TYPE_NONE);
if (ret != 0)
{
liot_trace("====data call failure!!!!=====");
}
// liot_rtos_task_sleep_ms(1000);
ret = liot_get_data_call_info(nSim, cid, &info);
if (ret != 0)
{
liot_trace("liot_get_data_call_info ret: %d", ret);
liot_stop_data_call(nSim, cid);
goto exit;
}
liot_rtos_semaphore_create(&http_semp, 0);
liot_rtos_semaphore_create(&http_semp1, 0);
liot_trace("info->profile_idx: %d", info.cid);
liot_trace("info->ip_version: %d", info.ip_version);
liot_trace("info->v4.state: %d", info.v4.state);
liot_ip4addr_ntoa(&info.v4.addr.ip);
liot_trace("info.v4.addr.ip: %s\r\n", liot_ip4addr_ntoa(&info.v4.addr.ip));
liot_ip4addr_ntoa(&info.v4.addr.pri_dns);
liot_trace("info.v4.addr.pri_dns: %s\r\n", liot_ip4addr_ntoa(&info.v4.addr.pri_dns));
liot_ip4addr_ntoa(&info.v4.addr.sec_dns);
liot_trace("info.v4.addr.sec_dns: %s\r\n", liot_ip4addr_ntoa(&info.v4.addr.sec_dns));
http_ca_cert_init();
http_user_cert_init();
http_user_key_init();
http_uploadfile_init();
int http_method = LIOT_HTTPC_METHOD_POST;
liot_httpc_url_s *url = NULL;
url = malloc(sizeof(liot_httpc_url_s));
#if LIOT_HTTP_DEMO_SSL_TEST
int verify_level = LIOT_HTTPS_VERIFY_SERVER_CLIENT;
url->host = "112.31.84.164";
url->scheme = LIOT_HTTPC_SCHEME_HTTPS;
if (verify_level == LIOT_HTTPS_VERIFY_SERVER_CLIENT)
{
url->port = 8303;
url->uri = "/1K.txt";
}
else
{
url->port = 8301;
url->uri = "/9X07-QAT/1K.txt";
}
#else
url->host = "cmp-net-monitor.xiot.senthink.com";
url->port = 0;
url->scheme = LIOT_HTTPC_SCHEME_HTTP;
url->uri = "/getData-1";
#endif
if (liot_httpc_new(&http_client, http_event_cb, NULL) != LIOT_HTTPC_SUCCESS)
{
liot_trace("http client create failed!!!!");
goto exit;
}
liot_trace("%s:%d %p,%p", __FUNCTION__, __LINE__, &http_client, http_client);
if (http_method == LIOT_HTTPC_METHOD_POST)
{
url->host = "cmp-net-monitor.xiot.senthink.com";
url->port = 0;
url->uri = "/pushData-1";
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_REQUEST_HEADER, "Content-type: multipart/form-data");
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_READ_FUNC, http_request_read_data_cb);
// liot_trace("%s:%d %p %p", __FUNCTION__, __LINE__,&http_client,(void *)&http_client);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_READ_DATA, (void *)&http_client);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_UPLOAD_LEN, liot_http_upload_len);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_BODY_DATA_TYPE, LIOT_HTTPC_FORM_DATA);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_RAW_REQUEST, 0);
liot_httpc_formadd(&http_client, LIOT_HTTP_FORM_NAME, "file");
liot_httpc_formadd(&http_client, LIOT_HTTP_FORM_FILENAME, "http_upload.txt", liot_http_upload_len);
//设置上传数据在服务器保存的名字 和本地文件的名字无关
liot_httpc_formadd(&http_client, LIOT_HTTP_FORM_CONTENT_TYPE, "text/plain");
}
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SIM_ID, nSim);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_PDPCID, cid);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_METHOD, http_method);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_URL, url);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_WRITE_FUNC, http_response_write_data_cb);
#if LIOT_HTTP_DEMO_SSL_TEST
unsigned short hs_timeout = 300;
char *ca_cert_path = liot_http_ca_cert_path;
liot_ssl_user_cert user_cert = {liot_http_user_cert_path, liot_http_user_key_path, NULL};
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSLCTXID, 1);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_VERSION, LIOT_SSL_VERSION_3);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_HS_TIMEOUT, hs_timeout);
// liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_SNI, 0);
liot_trace("%s:%d verify_level:%d ", __FUNCTION__, __LINE__, verify_level);
switch (verify_level)
{
case LIOT_HTTPS_VERIFY_SERVER:
{
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL, LIOT_HTTPS_VERIFY_SERVER);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH, ca_cert_path);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN, 1);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM, MBEDTLS_X509_BADCERT_FUTURE);
}
break;
case LIOT_HTTPS_VERIFY_SERVER_CLIENT:
{
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL, LIOT_HTTPS_VERIFY_SERVER_CLIENT);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH, ca_cert_path);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_OWNCERT_PATH, user_cert);
liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN, 1);
liot_httpc_setopt(&http_client,
LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM,
MBEDTLS_X509_BADCERT_FUTURE | MBEDTLS_X509_BADCERT_NOT_TRUSTED);
}
break;
}
liot_trace(">>>>>verify_level:%d ", verify_level);
#endif
if (liot_httpc_perform(&http_client) == LIOT_HTTPC_SUCCESS)
{
liot_trace(">>>>>%p", http_semp);
liot_rtos_semaphore_wait(http_semp, LIOT_WAIT_FOREVER);
liot_trace("http perform success");
}
else
{
liot_trace("http perform fail");
}
liot_httpc_stop(&http_client);
liot_rtos_semaphore_wait(http_semp1, LIOT_WAIT_FOREVER);
liot_httpc_release(&http_client);
exit:
liot_rtos_semaphore_delete(http_semp);
liot_rtos_semaphore_delete(http_semp1);
liot_trace("===liot_http_app_thread exit===");
liot_rtos_task_delete(NULL);
}
运行结果:
其他疑问补充需确认
