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:
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "http2_upload_api.h"
|
||||
#include "http2_wrapper.h"
|
||||
|
||||
|
||||
#define HTTP2_ONLINE_SERVER_URL "a1IgnOND7vI.iot-as-http2.cn-shanghai.aliyuncs.com"
|
||||
#define HTTP2_ONLINE_SERVER_PORT 443
|
||||
#define HTTP2_PRODUCT_KEY "a1IgnOND7vI"
|
||||
#define HTTP2_DEVICE_NAME "H2_FS01"
|
||||
#define HTTP2_DEVICE_SECRET "r9XSyeZOu6swgV8etCcCGmgQhBSpGBau"
|
||||
|
||||
#define EXAMPLE_TRACE(fmt, ...) \
|
||||
do { \
|
||||
HAL_Printf("%s|%03d :: ", __func__, __LINE__); \
|
||||
HAL_Printf(fmt, ##__VA_ARGS__); \
|
||||
HAL_Printf("%s", "\r\n"); \
|
||||
} while (0)
|
||||
|
||||
#define UPLOAD_RETRY_TIME 50
|
||||
|
||||
static int upload_result = 1;
|
||||
static char g_upload_id[50] = {0};
|
||||
static uint8_t is_connected = 0;
|
||||
|
||||
void upload_file_result(const char *file_path, int result, void *user_data)
|
||||
{
|
||||
upload_result = result;
|
||||
|
||||
EXAMPLE_TRACE("=========== file_path = %s, result = %d ===========", file_path, upload_result);
|
||||
}
|
||||
|
||||
void upload_id_received_handle(const char *file_path, const char *upload_id, void *user_data)
|
||||
{
|
||||
EXAMPLE_TRACE("=========== file_path = %s, upload_id = %s ===========", file_path, upload_id);
|
||||
|
||||
if (upload_id != NULL) {
|
||||
memset(g_upload_id, 0, sizeof(g_upload_id));
|
||||
strncpy(g_upload_id, upload_id, sizeof(g_upload_id) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_http2_reconnect(void)
|
||||
{
|
||||
EXAMPLE_TRACE("http2 reconnected");
|
||||
|
||||
is_connected = 1;
|
||||
}
|
||||
|
||||
static void _on_http2_disconnect(void)
|
||||
{
|
||||
EXAMPLE_TRACE("http2 disconnected");
|
||||
|
||||
is_connected = 0;
|
||||
}
|
||||
|
||||
static int http2_stream_test(char **argv,int argc)
|
||||
{
|
||||
http2_upload_conn_info_t conn_info;
|
||||
http2_status_cb_t status_cb;
|
||||
http2_upload_result_cb_t result_cb;
|
||||
void *handle;
|
||||
uint32_t retry_time = 0;
|
||||
int ret;
|
||||
|
||||
memset(&conn_info, 0, sizeof( http2_upload_conn_info_t));
|
||||
conn_info.product_key = HTTP2_PRODUCT_KEY;
|
||||
conn_info.device_name = HTTP2_DEVICE_NAME;
|
||||
conn_info.device_secret = HTTP2_DEVICE_SECRET;
|
||||
conn_info.url = HTTP2_ONLINE_SERVER_URL;
|
||||
conn_info.port = HTTP2_ONLINE_SERVER_PORT;
|
||||
|
||||
memset(&status_cb, 0, sizeof(http2_status_cb_t));
|
||||
status_cb.on_reconnect_cb = _on_http2_reconnect;
|
||||
status_cb.on_disconnect_cb = _on_http2_disconnect;
|
||||
|
||||
memset(&result_cb, 0, sizeof(http2_upload_result_cb_t));
|
||||
result_cb.upload_completed_cb = upload_file_result;
|
||||
result_cb.upload_id_received_cb = upload_id_received_handle;
|
||||
|
||||
handle = IOT_HTTP2_UploadFile_Connect(&conn_info, &status_cb);
|
||||
if(handle == NULL) {
|
||||
return -1;
|
||||
}
|
||||
is_connected = 1;
|
||||
|
||||
http2_upload_params_t fs_params;
|
||||
memset(&fs_params, 0, sizeof(fs_params));
|
||||
fs_params.file_path = argv[1];
|
||||
fs_params.opt_bit_map = UPLOAD_FILE_OPT_BIT_OVERWRITE;
|
||||
|
||||
ret = IOT_HTTP2_UploadFile_Request(handle, &fs_params, &result_cb, NULL);
|
||||
if(ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* wait until upload end */
|
||||
while (upload_result == 1) {
|
||||
HAL_SleepMs(200);
|
||||
}
|
||||
|
||||
/* check the result */
|
||||
if (upload_result == UPLOAD_SUCCESS) {
|
||||
EXAMPLE_TRACE("upload succeed");
|
||||
ret = IOT_HTTP2_UploadFile_Disconnect(handle);
|
||||
EXAMPLE_TRACE("close connect %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* check if upload_id receivced */
|
||||
if (g_upload_id[0] == '\0') {
|
||||
EXAMPLE_TRACE("upload id is NULL, resume is impossible!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* into resume routine */
|
||||
do {
|
||||
/* TODO: assume that http2 disconnected */
|
||||
if (upload_result < 0 && is_connected == 1) {
|
||||
HAL_SleepMs(30000);
|
||||
}
|
||||
|
||||
/* wait until connected */
|
||||
while (is_connected == 0) {
|
||||
HAL_SleepMs(200);
|
||||
}
|
||||
|
||||
/* reset upload result */
|
||||
upload_result = 1;
|
||||
|
||||
/* use resume option to upload file */
|
||||
fs_params.file_path = argv[1];
|
||||
fs_params.upload_len = 0;
|
||||
fs_params.upload_id = g_upload_id;
|
||||
fs_params.opt_bit_map = UPLOAD_FILE_OPT_BIT_RESUME; /* resume option used */
|
||||
ret = IOT_HTTP2_UploadFile_Request(handle, &fs_params, &result_cb, NULL);
|
||||
if (ret < 0) {
|
||||
EXAMPLE_TRACE("upload file request error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (upload_result == 1) {
|
||||
HAL_SleepMs(200);
|
||||
}
|
||||
|
||||
} while (upload_result != UPLOAD_SUCCESS && (++retry_time < UPLOAD_RETRY_TIME));
|
||||
|
||||
EXAMPLE_TRACE("upload succeed %d\n", ret);
|
||||
|
||||
ret = IOT_HTTP2_UploadFile_Disconnect(handle);
|
||||
EXAMPLE_TRACE("close connect %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (argc < 2) {
|
||||
HAL_Printf("no file name input!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = http2_stream_test(argv, argc);
|
||||
return ret;
|
||||
}
|
||||
|
250
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_stream.c
vendored
Normal file
250
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_stream.c
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "http2_api.h"
|
||||
#include "http2_wrapper.h"
|
||||
|
||||
#ifndef ON_DAILY
|
||||
#define ON_DAILY
|
||||
#endif
|
||||
#if defined(ON_DAILY)
|
||||
#define HTTP2_ONLINE_SERVER_URL "10.101.12.205"
|
||||
#define HTTP2_ONLINE_SERVER_PORT 9999
|
||||
#define HTTP2_PRODUCT_KEY "a1L5EUOh21s"
|
||||
#define HTTP2_DEVICE_NAME "zhangmei_test01"
|
||||
#define HTTP2_DEVICE_SECRET "KQCftfEDCx35LChyEwZoYY6FCYidTOp0"
|
||||
#elif defined(ON_PRE)
|
||||
#define HTTP2_ONLINE_SERVER_URL "100.67.141.158"
|
||||
#define HTTP2_ONLINE_SERVER_PORT 8443
|
||||
#define HTTP2_PRODUCT_KEY "b1XVhqfan1X"
|
||||
#define HTTP2_DEVICE_NAME "YvhjziEQmKusCFUgRpeo"
|
||||
#define HTTP2_DEVICE_SECRET "QjkhCrAX0SbNWgKpIamuiDdLkk23Q1r7"
|
||||
#else
|
||||
#define HTTP2_ONLINE_SERVER_URL NULL
|
||||
#define HTTP2_ONLINE_SERVER_PORT 443
|
||||
#define HTTP2_PRODUCT_KEY "DM5b8zbTWJs"
|
||||
#define HTTP2_DEVICE_NAME "mydevice1"
|
||||
#define HTTP2_DEVICE_SECRET "q4tiwQuICYfr6JQ8aUFjWxocuXJ5ruEx"
|
||||
#endif
|
||||
|
||||
#define EXAMPLE_TRACE(fmt, ...) \
|
||||
do { \
|
||||
HAL_Printf("%s|%03d :: ", __func__, __LINE__); \
|
||||
HAL_Printf(fmt, ##__VA_ARGS__); \
|
||||
HAL_Printf("%s", "\r\n"); \
|
||||
} while (0)
|
||||
|
||||
|
||||
void* pid1;
|
||||
|
||||
static const char UPLOAD_STRING[] =
|
||||
"It was almost December, and Jonas was beginning to be frightened. No. Wrong word, Jonas thought."
|
||||
"Frightened meant that deep, sickening feeling of something terrible about to happen. Frightened was"
|
||||
" the way he had felt a year ago when an unidentified aircraft had overflown the community twice."
|
||||
" He had seen it both times. Squinting toward the sky, he had seen the sleek jet, almost a blur at"
|
||||
" its high speed, go past, and a second later heard the blast of sound that followed. Then one more time,"
|
||||
" a moment later, from the opposite direction, the same plane. At first, he had been only fascinated. "
|
||||
"He had never seen aircraft so close, for it was against the rules for Pilots to fly over the community."
|
||||
" Occasionally, when supplies were delivered by cargo planes to the landing field across the river,"
|
||||
" the children rode their bicycles to the riverbank and watched, intrigued, the unloading and then the "
|
||||
"takeoff directed to the west, always away from the community. But the aircraft a year ago had been different."
|
||||
" It was not a squat, fat-bellied cargo plane but a needle-nosed single-pilot jet. Jonas, looking around"
|
||||
" anxiously, had seen others — adults as well as children — stop what they were doing and wait, confused,"
|
||||
" for an explanation of the frightening event. Then all of the citizens had been ordered to go into the nearest"
|
||||
" building and stay there. IMMEDIATELY, the rasping voice through the speakers had said. LEAVE YOUR BICYCLES "
|
||||
"WHERE THEY ARE. Instantly, obediently, Jonas had dropped his bike on its side on the path behind his family's "
|
||||
"dwelling. He had run indoors and stayed there, alone. His parents were both at work, and his little sister,"
|
||||
" Lily, was at the Childcare Center where she spent her after-school hours. Looking through the front window,"
|
||||
" he had seen no people: none of the busy afternoon crew of Street Cleaners, Landscape Workers, and Food "
|
||||
"Delivery people who usually populated the community at that time of day. He saw only the abandoned bikes here "
|
||||
"and there on their sides; an upturned wheel on one was still revolving slowly. He had been frightened then. "
|
||||
"The sense of his own community silent, waiting, had made his stomach churn. He had trembled. But it had been "
|
||||
"nothing. Within minutes the speakers had crackled again, and the voice, reassuring now and less urgent, "
|
||||
"had explained that a Pilot-in-Training had misread his navigational instructions and made a wrong turn. "
|
||||
"Desperately the Pilot had been trying to make his way back before his error was noticed. NEEDLESS TO SAY, "
|
||||
"HE WILL BE RELEASED, the voice had said, followed by silence. There was an ironic tone to that final message, "
|
||||
"as if the Speaker found it amusing; and Jonas had smiled a little, though he knew what a grim statement it had"
|
||||
" been. For a contributing citizen to be released from the community was a final decision, a terrible punishment,"
|
||||
" an overwhelming statement of failure. Even the children were scolded if they used the term lightly at play, "
|
||||
"jeering at a teammate who missed a catch or stumbled in a race. Jonas had done it once, had shouted at his "
|
||||
"best friend, "That's it, Asher! You're released!" when Asher's clumsy error had lost a match for "
|
||||
"his team. He had been taken aside for a brief and serious talk by the coach, had hung his head with guilt and "
|
||||
"embarrassment, and apologized to Asher after the game. Now, thinking about the feeling of fear as he pedaled "
|
||||
"home along the river path, he remembered that moment of palpable, stomach-sinking terror when the aircraft had"
|
||||
" streaked above. It was not what he was feeling now with December approaching. He searched for the right word"
|
||||
" to describe his own feeling. Jonas was careful about language. Not like his friend, Asher, who talked too "
|
||||
"fast and mixed things up, scrambling words and phrases until they were barely recognizable and often very funny. "
|
||||
"Jonas grinned, remembering the morning that Asher had dashed into the classroom, late as usual, arriving "
|
||||
"breathlessly in the middle of the chanting of the morning anthem. When the class took their seats at the "
|
||||
"conclusion of the patriotic hymn, Asher remained standing to make his public apology as was required. "
|
||||
""I apologize for inconveniencing my learning community." Asher ran through the standard apology"
|
||||
" phrase rapidly, still catching his breath. The Instructor and class waited patiently for his explanation."
|
||||
" The students had all been grinning, because they had listened to Asher's explanations so many times before. "
|
||||
""I left home at the correct time but when I was riding along near the hatchery, the crew was separating "
|
||||
"some salmon. I guess I just got distraught, watching them. "I apologize to my classmates," Asher"
|
||||
" concluded. He smoothed his rumpled tunic and sat down. "We accept your apology, Asher." The class"
|
||||
" recited the standard response in unison. Many of the students were biting their lips to keep from laughing."
|
||||
" "I accept your apology, Asher," the Instructor said. He was smiling. "And I thank you, because "
|
||||
"once again you have provided an opportunity for a lesson in language. "Distraught' is too strong an adjective"
|
||||
" to describe salmon-viewing." He turned and wrote "distraught" on the instructional board. "
|
||||
"Beside it he wrote "distracted." Jonas, nearing his home now, smiled at the recollection. Thinking, "
|
||||
"still, as he wheeled his bike into its narrow port beside the door, he realized that frightened was the wrong "
|
||||
"word to describe his feelings, now that December was almost here. It was too strong an adjective. He had waited a"
|
||||
" long time for this special December. Now that it was almost upon him, he wasn't frightened, but he was ... eager,"
|
||||
" he decided. He was eager for it to come. And he was excited, certainly. All of the Elevens were excited about the"
|
||||
" event that would be coming so soon. But there was a little shudder of nervousness when he thought about it, about"
|
||||
" what might happen. Apprehensive, Jonas decided. That's what I am. "Who wants to be the first tonight, for "
|
||||
"feelings?" Jonas's father asked, at the conclusion of their evening meal. It was one of the rituals,"
|
||||
" the evening telling of feelings. Sometimes Jonas and his sister, Lily, argued over turns, over who would get to go first."
|
||||
" Their parents, of course, were part of the ritual; they, too, told their feelings each evening. But like all parents — "
|
||||
"all adults — they didn't fight and wheedle for their turn. Nor did Jonas, tonight. His feelings were too complicated this evening.";
|
||||
|
||||
|
||||
static void on_header(uint32_t stream_id, char *channel_id,int cat,const uint8_t *name,uint32_t namelen,
|
||||
const uint8_t *value,uint32_t valuelen, uint8_t flags ,void *user_data)
|
||||
{
|
||||
EXAMPLE_TRACE("~~~~~stream_id = %d, channel_id=%s, name = %s, value = %s, flag = %d user_data =%p\n", stream_id,channel_id,name,value,flags ,user_data);
|
||||
}
|
||||
|
||||
static void on_chunk_recv(uint32_t stream_id, char *channel_id,const uint8_t *data, uint32_t len,uint8_t flags,void *user_data)
|
||||
{
|
||||
EXAMPLE_TRACE("~~~~~stream_id = %d, channel_id=%s, data = %.*s, len = %d flag = %d\n", stream_id, channel_id, len, data, len, flags);
|
||||
}
|
||||
static void on_stream_close(uint32_t stream_id, char *channel_id,uint32_t error_code,void *user_data)
|
||||
{
|
||||
EXAMPLE_TRACE("~~~~~stream_id = %d channel_id=%s, error_code = %d\n", stream_id,channel_id,error_code);
|
||||
}
|
||||
static void on_stream_frame_send(uint32_t stream_id, char *channel_id, int type, uint8_t flags,void *user_data){
|
||||
EXAMPLE_TRACE("~~~~~stream_id = %d user_data =%p, type = %d\n", stream_id,user_data,type);
|
||||
}
|
||||
|
||||
static http2_stream_cb_t my_cb = {
|
||||
.on_stream_header_cb = on_header,
|
||||
.on_stream_chunk_recv_cb = on_chunk_recv,
|
||||
.on_stream_close_cb = on_stream_close,
|
||||
.on_stream_frame_send_cb = on_stream_frame_send,
|
||||
};
|
||||
|
||||
static int test_user_data;
|
||||
|
||||
static int http2_stream_test()
|
||||
{
|
||||
int ret;
|
||||
device_conn_info_t conn_info;
|
||||
void *handle;
|
||||
memset(&conn_info, 0, sizeof( device_conn_info_t));
|
||||
conn_info.product_key = HTTP2_PRODUCT_KEY;
|
||||
conn_info.device_name = HTTP2_DEVICE_NAME;
|
||||
conn_info.device_secret = HTTP2_DEVICE_SECRET;
|
||||
conn_info.url = HTTP2_ONLINE_SERVER_URL;
|
||||
conn_info.port = HTTP2_ONLINE_SERVER_PORT;
|
||||
|
||||
handle = IOT_HTTP2_Connect(&conn_info,&my_cb);
|
||||
if(handle == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
http2_header header[] = {
|
||||
MAKE_HEADER("test_name", "test_http2_header"),
|
||||
MAKE_HEADER("x-for-test", "hello world"),
|
||||
};
|
||||
|
||||
header_ext_info_t my_header_info = {
|
||||
header,
|
||||
2
|
||||
};
|
||||
stream_data_info_t info_upload, info_download;
|
||||
memset(&info_upload,0,sizeof(stream_data_info_t));
|
||||
|
||||
//info_upload.identify = "com/aliyun/iotx/vision/picture/device/upstream";
|
||||
info_upload.identify = "iotx/vision/voice/intercom/live";
|
||||
|
||||
memset(&info_download, 0, sizeof(stream_data_info_t));
|
||||
info_download.identify = "iotx/vision/voice/intercom/live";
|
||||
info_download.user_data = (void *)&test_user_data;
|
||||
|
||||
EXAMPLE_TRACE("----------usr_data =%p\n",(void *)&test_user_data);
|
||||
ret = IOT_HTTP2_Stream_Open(handle, &info_download, &my_header_info);
|
||||
if (ret < 0) {
|
||||
EXAMPLE_TRACE("=========iotx_http2_downstream_open failed %d!!!!!\n", ret);
|
||||
IOT_HTTP2_Disconnect(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = IOT_HTTP2_Stream_Query(handle, &info_download, &my_header_info);
|
||||
if (ret < 0) {
|
||||
EXAMPLE_TRACE("=========iotx_http2_downstream_query failed %d!!!!!\n", ret);
|
||||
IOT_HTTP2_Stream_Close(handle, &info_download);
|
||||
IOT_HTTP2_Disconnect(handle);
|
||||
return -1;
|
||||
}
|
||||
info_upload.user_data = (void *)&test_user_data;
|
||||
ret = IOT_HTTP2_Stream_Open(handle, &info_upload, &my_header_info);
|
||||
if(ret < 0) {
|
||||
EXAMPLE_TRACE("=========iotx_http2_upstream_open failed %d!!!!!\n", ret);
|
||||
IOT_HTTP2_Stream_Close(handle, &info_download);
|
||||
IOT_HTTP2_Disconnect(handle);
|
||||
return -1;
|
||||
}
|
||||
//send request 1
|
||||
info_upload.stream = (char *)UPLOAD_STRING;
|
||||
info_upload.stream_len= sizeof(UPLOAD_STRING);
|
||||
info_upload.send_len = 0;
|
||||
info_upload.packet_len=2048;
|
||||
|
||||
while(info_upload.send_len<info_upload.stream_len) {
|
||||
info_upload.stream = (char *)UPLOAD_STRING + info_upload.send_len;
|
||||
if(info_upload.stream_len-info_upload.send_len<info_upload.packet_len) {
|
||||
info_upload.packet_len = info_upload.stream_len-info_upload.send_len;
|
||||
}
|
||||
ret = IOT_HTTP2_Stream_Send(handle, &info_upload, &my_header_info);
|
||||
if(ret <0 ) {
|
||||
EXAMPLE_TRACE("send err, ret = %d\n",ret);
|
||||
break;
|
||||
}
|
||||
EXAMPLE_TRACE("iotx_http2_stream_send info_upload.send_len =%d ret = %d\n", info_upload.send_len,ret);
|
||||
}
|
||||
|
||||
//send request 2
|
||||
info_upload.stream = (char *)UPLOAD_STRING;
|
||||
info_upload.stream_len= sizeof(UPLOAD_STRING);
|
||||
info_upload.send_len = 0;
|
||||
info_upload.packet_len=1024;
|
||||
|
||||
while(info_upload.send_len<info_upload.stream_len) {
|
||||
info_upload.stream = (char *)UPLOAD_STRING + info_upload.send_len;
|
||||
if(info_upload.stream_len-info_upload.send_len<info_upload.packet_len) {
|
||||
info_upload.packet_len = info_upload.stream_len-info_upload.send_len;
|
||||
}
|
||||
ret = IOT_HTTP2_Stream_Send(handle, &info_upload, &my_header_info);
|
||||
if(ret <0 ) {
|
||||
EXAMPLE_TRACE("send err, ret = %d\n",ret);
|
||||
break;
|
||||
}
|
||||
EXAMPLE_TRACE("iotx_http2_stream_send info_upload.send_len =%d ret = %d\n", info_upload.send_len,ret);
|
||||
}
|
||||
|
||||
EXAMPLE_TRACE("=========Wait 20 seconds to receive downstream data\n");
|
||||
HAL_SleepMs(20000);
|
||||
|
||||
IOT_HTTP2_Stream_Close(handle, &info_upload);
|
||||
IOT_HTTP2_Stream_Close(handle, &info_download);
|
||||
HAL_SleepMs(2000);
|
||||
|
||||
ret = IOT_HTTP2_Disconnect(handle);
|
||||
EXAMPLE_TRACE("close connect %d\n",ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = http2_stream_test();
|
||||
|
||||
return ret;
|
||||
}
|
102
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_uploadfile.c
vendored
Normal file
102
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_uploadfile.c
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "http2_upload_api.h"
|
||||
#include "http2_wrapper.h"
|
||||
|
||||
|
||||
#define HTTP2_ONLINE_SERVER_URL "a1IgnOND7vI.iot-as-http2.cn-shanghai.aliyuncs.com"
|
||||
#define HTTP2_ONLINE_SERVER_PORT 443
|
||||
#define HTTP2_PRODUCT_KEY "a1IgnOND7vI"
|
||||
#define HTTP2_DEVICE_NAME "H2_FS01"
|
||||
#define HTTP2_DEVICE_SECRET "r9XSyeZOu6swgV8etCcCGmgQhBSpGBau"
|
||||
|
||||
|
||||
#define EXAMPLE_TRACE(fmt, ...) \
|
||||
do { \
|
||||
HAL_Printf("%s|%03d :: ", __func__, __LINE__); \
|
||||
HAL_Printf(fmt, ##__VA_ARGS__); \
|
||||
HAL_Printf("%s", "\r\n"); \
|
||||
} while (0)
|
||||
|
||||
static int upload_end = 0;
|
||||
static char g_upload_id[50] = {0};
|
||||
|
||||
void upload_file_result(const char *file_path, int result, void *user_data)
|
||||
{
|
||||
upload_end++;
|
||||
EXAMPLE_TRACE("=========== file_path = %s, result = %d, finish num = %d ===========", file_path, result, upload_end);
|
||||
}
|
||||
|
||||
void upload_id_received_handle(const char *file_path, const char *upload_id, void *user_data)
|
||||
{
|
||||
EXAMPLE_TRACE("=========== file_path = %s, upload_id = %s ===========", file_path, upload_id);
|
||||
|
||||
if (upload_id != NULL) {
|
||||
memset(g_upload_id, 0, sizeof(g_upload_id));
|
||||
strncpy(g_upload_id, upload_id, sizeof(g_upload_id) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int http2_stream_test(char **argv,int argc)
|
||||
{
|
||||
int ret;
|
||||
http2_upload_conn_info_t conn_info;
|
||||
http2_upload_result_cb_t result_cb;
|
||||
void *handle;
|
||||
int goal_num = 0;
|
||||
int i;
|
||||
|
||||
memset(&conn_info, 0, sizeof(http2_upload_conn_info_t));
|
||||
conn_info.product_key = HTTP2_PRODUCT_KEY;
|
||||
conn_info.device_name = HTTP2_DEVICE_NAME;
|
||||
conn_info.device_secret = HTTP2_DEVICE_SECRET;
|
||||
conn_info.url = HTTP2_ONLINE_SERVER_URL;
|
||||
conn_info.port = HTTP2_ONLINE_SERVER_PORT;
|
||||
|
||||
memset(&result_cb, 0, sizeof(http2_upload_result_cb_t));
|
||||
result_cb.upload_completed_cb = upload_file_result;
|
||||
result_cb.upload_id_received_cb = upload_id_received_handle;
|
||||
|
||||
handle = IOT_HTTP2_UploadFile_Connect(&conn_info, NULL);
|
||||
if(handle == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=1; i<argc; i++) {
|
||||
http2_upload_params_t fs_params;
|
||||
memset(&fs_params, 0, sizeof(fs_params));
|
||||
fs_params.file_path = argv[i];
|
||||
fs_params.upload_len = 1024 * 1024 * 100;
|
||||
fs_params.opt_bit_map = UPLOAD_FILE_OPT_BIT_OVERWRITE;
|
||||
|
||||
ret = IOT_HTTP2_UploadFile_Request(handle, &fs_params, &result_cb, NULL);
|
||||
if(ret == 0) {
|
||||
goal_num++;
|
||||
}
|
||||
}
|
||||
while(upload_end != goal_num) {
|
||||
HAL_SleepMs(200);
|
||||
}
|
||||
|
||||
ret = IOT_HTTP2_UploadFile_Disconnect(handle);
|
||||
EXAMPLE_TRACE("close connect %d\n",ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (argc < 2) {
|
||||
HAL_Printf("no file name input!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = http2_stream_test(argv, argc);
|
||||
return ret;
|
||||
}
|
1159
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_api.c
vendored
Normal file
1159
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_api.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
106
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_api.h
vendored
Normal file
106
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_api.h
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef IOT_EXPORT_HTTP2_STREAM_H
|
||||
#define IOT_EXPORT_HTTP2_STREAM_H
|
||||
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IOT_HTTP2_RES_OVERTIME_MS (10000)
|
||||
#define IOT_HTTP2_KEEP_ALIVE_CNT (1)
|
||||
#define IOT_HTTP2_KEEP_ALIVE_TIME (30*1000) /* in seconds */
|
||||
|
||||
#define MAKE_HEADER(NAME, VALUE) \
|
||||
{ \
|
||||
(char *) NAME, (char *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 \
|
||||
}
|
||||
|
||||
#define MAKE_HEADER_CS(NAME, VALUE) \
|
||||
{ \
|
||||
(char *) NAME, (char *)VALUE, strlen(NAME) , strlen(VALUE) \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *product_key;
|
||||
char *device_name;
|
||||
char *device_secret;
|
||||
char *url;
|
||||
int port;
|
||||
} device_conn_info_t;
|
||||
|
||||
typedef struct http2_header_struct {
|
||||
char *name; /* header name */
|
||||
char *value; /* the value of name */
|
||||
int namelen; /* the length of header name */
|
||||
int valuelen; /* the length of value */
|
||||
} http2_header;
|
||||
|
||||
typedef struct {
|
||||
http2_header *nva;
|
||||
int num;
|
||||
} header_ext_info_t;
|
||||
|
||||
typedef enum {
|
||||
STREAM_TYPE_DOWNLOAD,
|
||||
STREAM_TYPE_UPLOAD,
|
||||
STREAM_TYPE_AUXILIARY,
|
||||
STREAM_TYPE_NUM
|
||||
} stream_type_t;
|
||||
|
||||
typedef void (*on_stream_header_callback)(uint32_t stream_id, char *channel_id, int cat, const uint8_t *name,
|
||||
uint32_t namelen, const uint8_t *value, uint32_t valuelen, uint8_t flags, void *user_data);
|
||||
|
||||
typedef void (*on_stream_chunk_recv_callback)(uint32_t stream_id, char *channel_id,
|
||||
const uint8_t *data, uint32_t len, uint8_t flags, void *user_data);
|
||||
|
||||
typedef void (*on_stream_close_callback)(uint32_t stream_id, char *channel_id, uint32_t error_code, void *user_data);
|
||||
|
||||
typedef void (*on_stream_frame_send_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags, void *user_data);
|
||||
|
||||
typedef void (*on_stream_frame_recv_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags,void *user_data);
|
||||
|
||||
typedef void (*on_reconnect_callback)();
|
||||
typedef void (*on_disconnect_callback)();
|
||||
|
||||
typedef struct {
|
||||
on_stream_header_callback on_stream_header_cb;
|
||||
on_stream_chunk_recv_callback on_stream_chunk_recv_cb;
|
||||
on_stream_close_callback on_stream_close_cb;
|
||||
on_stream_frame_send_callback on_stream_frame_send_cb;
|
||||
on_stream_frame_recv_callback on_stream_frame_recv_cb;
|
||||
on_reconnect_callback on_reconnect_cb;
|
||||
on_disconnect_callback on_disconnect_cb;
|
||||
} http2_stream_cb_t;
|
||||
|
||||
typedef struct {
|
||||
char *stream; /* point to stream data buffer */
|
||||
uint32_t stream_len; /* file content length */
|
||||
uint32_t send_len; /* data had sent length */
|
||||
uint32_t packet_len; /* one packet length */
|
||||
const char *identify; /* path string to identify a stream service */
|
||||
int h2_stream_id; /* stream identifier which is a field in HTTP2 frame */
|
||||
char *channel_id; /* string return by server to identify a specific stream channel,
|
||||
different from stream identifier which is a field in HTTP2 frame */
|
||||
void *user_data; /* user data brought in at stream open */
|
||||
} stream_data_info_t;
|
||||
|
||||
void *IOT_HTTP2_Connect(device_conn_info_t *conn_info, http2_stream_cb_t *user_cb);
|
||||
int IOT_HTTP2_Stream_Open(void *handle, stream_data_info_t *info, header_ext_info_t *header);
|
||||
int IOT_HTTP2_Stream_Send(void *handle, stream_data_info_t *info, header_ext_info_t *header);
|
||||
int IOT_HTTP2_Stream_Query(void *handle, stream_data_info_t *info, header_ext_info_t *header);
|
||||
int IOT_HTTP2_Stream_Close(void *handle, stream_data_info_t *info);
|
||||
int IOT_HTTP2_Stream_Send_Message(void *handle, const char *identify,char *channel_id, char *data,
|
||||
uint32_t data_len, header_ext_info_t *header);
|
||||
int IOT_HTTP2_Disconnect(void *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* IOT_EXPORT_FILE_UPLOADER_H */
|
20
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_config.h
vendored
Normal file
20
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_config.h
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _HTTP2_CONFIG_H
|
||||
#define _HTTP2_CONFIG_H
|
||||
|
||||
/* maximum packet len in one http2 frame */
|
||||
#ifndef FS_UPLOAD_PACKET_LEN
|
||||
#define FS_UPLOAD_PACKET_LEN 10240 /* must < 16384 */
|
||||
#endif
|
||||
|
||||
/* maximum content len of the http2 request */
|
||||
#ifndef FS_UPLOAD_PART_LEN
|
||||
#define FS_UPLOAD_PART_LEN (1024 * 1024 * 4) /* 100KB ~ 100MB */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* #ifdef _HTTP2_CONFIG_H */
|
||||
|
192
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_internal.h
vendored
Normal file
192
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_internal.h
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef IOT_EXPORT_HTTP2_H
|
||||
#define IOT_EXPORT_HTTP2_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "http2_api.h"
|
||||
#include "http2_wrapper.h"
|
||||
|
||||
#ifdef INFRA_LOG
|
||||
#include "infra_log.h"
|
||||
#define h2_emerg(...) log_emerg("h2", __VA_ARGS__)
|
||||
#define h2_crit(...) log_crit("h2", __VA_ARGS__)
|
||||
#define h2_err(...) log_err("h2", __VA_ARGS__)
|
||||
#define h2_warning(...) log_warning("h2", __VA_ARGS__)
|
||||
#define h2_info(...) log_info("h2", __VA_ARGS__)
|
||||
#define h2_debug(...) log_debug("h2", __VA_ARGS__)
|
||||
#else
|
||||
#define h2_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define h2_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define h2_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define h2_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define h2_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define h2_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#endif
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define HTTP2_STREAM_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "http2.stream")
|
||||
#define HTTP2_STREAM_FREE(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define HTTP2_STREAM_MALLOC(size) HAL_Malloc(size)
|
||||
#define HTTP2_STREAM_FREE(ptr) do{if(ptr != NULL) {HAL_Free(ptr);ptr = NULL;}}while(0)
|
||||
#endif /* #ifdef INFRA_MEM_STATS */
|
||||
|
||||
#define POINTER_SANITY_CHECK(ptr, err) \
|
||||
do { \
|
||||
if (NULL == (ptr)) { \
|
||||
return (err); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ARGUMENT_SANITY_CHECK(expr, err) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
return (err); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
typedef enum {
|
||||
|
||||
HTTP2_FLAG_NONE = 0,
|
||||
|
||||
HTTP2_FLAG_END_STREAM = 0x01,
|
||||
|
||||
} http2_flag;
|
||||
|
||||
typedef struct http2_list_s {
|
||||
struct http2_list_s *prev;
|
||||
struct http2_list_s *next;
|
||||
} http2_list_t;
|
||||
|
||||
typedef void (*on_user_header_callback)(int32_t stream_id, int cat, const uint8_t *name, uint32_t namelen,
|
||||
const uint8_t *value, uint32_t valuelen, uint8_t flags);
|
||||
|
||||
typedef void (*on_user_chunk_recv_callback)(int32_t stream_id,
|
||||
const uint8_t *data, uint32_t len, uint8_t flags);
|
||||
|
||||
typedef void (*on_user_stream_close_callback)(int32_t stream_id, uint32_t error_code);
|
||||
|
||||
typedef void (*on_user_frame_send_callback)(int32_t stream_id, int type, uint8_t flags);
|
||||
|
||||
typedef void (*on_user_frame_recv_callback)(int32_t stream_id, int type, uint8_t flags);
|
||||
|
||||
typedef struct {
|
||||
on_user_header_callback on_user_header_cb;
|
||||
on_user_chunk_recv_callback on_user_chunk_recv_cb;
|
||||
on_user_stream_close_callback on_user_stream_close_cb;
|
||||
on_user_frame_send_callback on_user_frame_send_cb;
|
||||
on_user_frame_recv_callback on_user_frame_recv_cb;
|
||||
} http2_user_cb_t;
|
||||
|
||||
typedef struct http2_connection {
|
||||
void *network; /* iot network ptr */
|
||||
void *session; /* http2 session */
|
||||
int flag; /* check the stream is end or not */
|
||||
int status;
|
||||
http2_user_cb_t *cbs;
|
||||
} http2_connection_t;
|
||||
|
||||
typedef struct http2_data_struct {
|
||||
http2_header *header; /* header data. */
|
||||
int header_count; /* the count of header data. */
|
||||
char *data; /* send data. */
|
||||
int len; /* send data length. */
|
||||
int stream_id; /* send data over specify stream */
|
||||
int flag; /* send data flag. */
|
||||
} http2_data;
|
||||
|
||||
typedef struct {
|
||||
http2_connection_t *http2_connect;
|
||||
void *mutex;
|
||||
void *semaphore;
|
||||
void *rw_thread;
|
||||
http2_list_t stream_list;
|
||||
int init_state;
|
||||
http2_stream_cb_t *cbs;
|
||||
uint8_t connect_state;
|
||||
uint8_t retry_cnt;
|
||||
} stream_handle_t;
|
||||
|
||||
#ifdef FS_ENABLED
|
||||
|
||||
typedef struct {
|
||||
char fs_upload_id[50];
|
||||
int fs_offset;
|
||||
} fs_rsp_header_val_t;
|
||||
|
||||
int IOT_HTTP2_FS_Close(void *hd, stream_data_info_t *info, header_ext_info_t *header);
|
||||
|
||||
#endif /* #ifdef FS_ENABLED */
|
||||
|
||||
/**
|
||||
* @brief the http2 client connect.
|
||||
* @param[in] pclient: http client. <struct httpclient_t>
|
||||
* @return http2 client connection handler.
|
||||
*/
|
||||
extern http2_connection_t *iotx_http2_client_connect(void *pclient, char *url, int port);
|
||||
|
||||
http2_connection_t *iotx_http2_client_connect_with_cb(void *pclient, char *url, int port, http2_user_cb_t *cb);
|
||||
/**
|
||||
* @brief the http2 client send data.
|
||||
* @param[in] handler: http2 client connection handler.
|
||||
* @param[in] data: send data.
|
||||
* @return The result. 0 is ok.
|
||||
*/
|
||||
extern int iotx_http2_client_send(http2_connection_t *conn, http2_data *h2_data);
|
||||
/**
|
||||
* @brief the http2 client receive data.
|
||||
* @param[in] handler: http2 client connection handler.
|
||||
* @param[in] data: receive data buffer.
|
||||
* @param[in] data_len: buffer length.
|
||||
* @param[in] len: receive data length.
|
||||
* @param[in] timeout: receive data timeout.
|
||||
* @return The result. 0 is ok.
|
||||
*/
|
||||
extern int iotx_http2_client_recv(http2_connection_t *conn, char *data, int data_len, int *len, int timeout);
|
||||
/**
|
||||
* @brief the http2 client connect.
|
||||
* @param[in] handler: http2 client connection handler.
|
||||
* @return The result. 0 is ok.
|
||||
*/
|
||||
extern int iotx_http2_client_disconnect(http2_connection_t *conn);
|
||||
/**
|
||||
* @brief the http2 client send ping to keep alive.
|
||||
* @param[in] handler: http2 client connection handler.
|
||||
* @return The result. 0 is ok.
|
||||
*/
|
||||
extern int iotx_http2_client_send_ping(http2_connection_t *conn);
|
||||
/**
|
||||
* @brief the http2 client get available windows size.
|
||||
* @param[in] handler: http2 client connection handler.
|
||||
* @return The window size.
|
||||
*/
|
||||
extern int iotx_http2_get_available_window_size(http2_connection_t *conn);
|
||||
/**
|
||||
* @brief the http2 client receive windows size packet to update window.
|
||||
* @param[in] handler: http2 client connection handler.
|
||||
* @return The result. 0 is ok.
|
||||
*/
|
||||
extern int iotx_http2_update_window_size(http2_connection_t *conn);
|
||||
/**
|
||||
* @brief the http2 client performs the network I/O.
|
||||
* @param[in] handler: http2 client connection handler.
|
||||
* @return The result. 0 is ok.
|
||||
*/
|
||||
extern int iotx_http2_exec_io(http2_connection_t *connection);
|
||||
|
||||
extern int iotx_http2_client_recv_ping(void);
|
||||
|
||||
int iotx_http2_reset_stream(http2_connection_t *connection, int32_t stream_id);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* IOT_EXPORT_HTTP2_H */
|
595
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.c
vendored
Normal file
595
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.c
vendored
Normal file
@@ -0,0 +1,595 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "infra_config.h"
|
||||
#ifdef FS_ENABLED
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "infra_defs.h"
|
||||
#include "infra_types.h"
|
||||
#include "infra_httpc.h"
|
||||
#include "infra_sha1.h"
|
||||
#include "infra_timer.h"
|
||||
#include "infra_list.h"
|
||||
#include "infra_log.h"
|
||||
|
||||
#include "http2_internal.h"
|
||||
#include "http2_api.h"
|
||||
#include "http2_upload_api.h"
|
||||
#include "http2_config.h"
|
||||
#include "http2_wrapper.h"
|
||||
|
||||
#include "wrappers_defs.h"
|
||||
|
||||
#define PACKET_LEN 16384
|
||||
#define HTTP2_FS_SERVICE_ID "c/iot/sys/thing/file/upload"
|
||||
|
||||
|
||||
typedef enum {
|
||||
FS_STATUS_WAITING,
|
||||
FS_STATUS_UPLOADING,
|
||||
FS_STATUS_BREAK,
|
||||
FS_STATUS_END,
|
||||
FS_STATUS_NUM
|
||||
} file_stream_status_t;
|
||||
|
||||
typedef enum {
|
||||
FS_TYPE_NORMAL,
|
||||
FS_TYPE_CONTINUE,
|
||||
FS_TYPE_OVERRIDE,
|
||||
} file_stream_type_t;
|
||||
|
||||
typedef struct {
|
||||
int idx;
|
||||
const char *file_path;
|
||||
char upload_id[40];
|
||||
uint32_t spec_len;
|
||||
uint32_t file_offset;
|
||||
uint32_t part_len;
|
||||
file_stream_type_t type;
|
||||
http2_upload_id_received_cb_t opened_cb;
|
||||
http2_upload_completed_cb_t end_cb;
|
||||
void *user_data;
|
||||
|
||||
uint8_t if_stop;
|
||||
|
||||
http2_list_t list;
|
||||
} http2_file_stream_t;
|
||||
|
||||
typedef struct {
|
||||
stream_handle_t *http2_handle;
|
||||
const char *service_id;
|
||||
http2_list_t file_list;
|
||||
void *list_mutex;
|
||||
void *file_thread;
|
||||
int upload_idx;
|
||||
} http2_file_stream_ctx_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *send_buffer;
|
||||
const char *upload_id;
|
||||
uint32_t file_offset;
|
||||
uint32_t part_len;
|
||||
} fs_send_ext_info_t;
|
||||
|
||||
|
||||
static http2_file_stream_ctx_t g_http2_fs_ctx = { 0 };
|
||||
static http2_stream_cb_t callback_func = { 0 };
|
||||
|
||||
|
||||
/* utils, get file sizef */
|
||||
static int http2_stream_get_file_size(const char *file_name)
|
||||
{
|
||||
void *fp = NULL;
|
||||
int size = 0;
|
||||
if ((fp = HAL_Fopen(file_name, "r")) == NULL) {
|
||||
h2_err("The file %s can not be opened.\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
HAL_Fseek(fp, 0L, HAL_SEEK_END);
|
||||
size = HAL_Ftell(fp);
|
||||
HAL_Fclose(fp);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* utils, get file name */
|
||||
static const char *_http2_fs_get_filename(const char *file_path)
|
||||
{
|
||||
const char *p_name = NULL;
|
||||
|
||||
if (file_path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p_name = file_path + strlen(file_path);
|
||||
|
||||
while (--p_name != file_path) {
|
||||
if (*p_name == '/') {
|
||||
p_name++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return p_name;
|
||||
}
|
||||
|
||||
/* utils, read file data */
|
||||
static int http2_stream_get_file_data(const char *file_name, char *data, int len, int offset)
|
||||
{
|
||||
void *fp = NULL;
|
||||
int ret = 0;
|
||||
if ((fp = HAL_Fopen(file_name, "r")) == NULL) {
|
||||
h2_err("The file %s can not be opened.\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
ret = HAL_Fseek(fp, offset, HAL_SEEK_SET);
|
||||
if (ret != 0) {
|
||||
HAL_Fclose(fp);
|
||||
h2_err("The file %s can not move offset.\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
ret = HAL_Fread(data, len, 1, fp);
|
||||
HAL_Fclose(fp);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* open http2 file upload channel */
|
||||
static int _http2_fs_open_channel(http2_file_stream_t *fs_node, stream_data_info_t *info)
|
||||
{
|
||||
stream_handle_t *h2_handle = g_http2_fs_ctx.http2_handle;
|
||||
header_ext_info_t ext_header;
|
||||
fs_rsp_header_val_t *open_rsp = (fs_rsp_header_val_t *)info->user_data;
|
||||
const char *filename = NULL;
|
||||
int ret = UPLOAD_ERROR_COMMON;
|
||||
|
||||
/* header for normal upload */
|
||||
http2_header header_filename[] = {
|
||||
MAKE_HEADER_CS("x-file-name", ""),
|
||||
};
|
||||
|
||||
/* header for override operation */
|
||||
http2_header header_overwrite[] = {
|
||||
MAKE_HEADER_CS("x-file-name", ""),
|
||||
MAKE_HEADER_CS("x-file-overwrite", "1"),
|
||||
};
|
||||
|
||||
/* header for continue operation */
|
||||
http2_header header_uploadid[] = {
|
||||
MAKE_HEADER("x-file-upload-id", ""),
|
||||
};
|
||||
|
||||
filename = _http2_fs_get_filename(fs_node->file_path);
|
||||
h2_info("filename = %s", filename);
|
||||
|
||||
header_filename[0].value = (char *)filename;
|
||||
header_filename[0].valuelen = strlen(filename);
|
||||
header_overwrite[0].value = (char *)filename;
|
||||
header_overwrite[0].valuelen = strlen(filename);
|
||||
|
||||
/* setup http2 ext_header */
|
||||
switch (fs_node->type) {
|
||||
case FS_TYPE_NORMAL: {
|
||||
ext_header.num = 1;
|
||||
ext_header.nva = header_filename;
|
||||
|
||||
} break;
|
||||
case FS_TYPE_OVERRIDE: {
|
||||
ext_header.num = 2;
|
||||
ext_header.nva = header_overwrite;
|
||||
|
||||
} break;
|
||||
case FS_TYPE_CONTINUE: {
|
||||
/* upload id must be exist */
|
||||
header_uploadid[0].value = fs_node->upload_id;
|
||||
header_uploadid[0].valuelen = strlen(fs_node->upload_id);
|
||||
ext_header.num = 1;
|
||||
ext_header.nva = header_uploadid;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
ret = IOT_HTTP2_Stream_Open(h2_handle, info, &ext_header);
|
||||
if (ret < 0 || open_rsp->fs_offset == -1 || open_rsp->fs_upload_id[0] == '\0') {
|
||||
h2_err("IOT_HTTP2_Stream_Open failed %d\n", ret);
|
||||
return UPLOAD_STREAM_OPEN_FAILED;
|
||||
}
|
||||
h2_info("fs channel open succeed");
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/* file part data send sync api */
|
||||
static int _http2_fs_part_send_sync(http2_file_stream_t *fs_node, stream_data_info_t *info, fs_send_ext_info_t *ext_info)
|
||||
{
|
||||
stream_handle_t *h2_handle = g_http2_fs_ctx.http2_handle;
|
||||
header_ext_info_t ext_header;
|
||||
int res;
|
||||
http2_header header_uploadid[] = {
|
||||
MAKE_HEADER_CS("x-file-upload-id", ext_info->upload_id),
|
||||
};
|
||||
|
||||
/* setup ext header */
|
||||
ext_header.num = 1;
|
||||
ext_header.nva = header_uploadid;
|
||||
|
||||
/* setup Stream_Send params */
|
||||
info->stream = ext_info->send_buffer;
|
||||
info->stream_len = ext_info->part_len;
|
||||
info->send_len = 0;
|
||||
info->packet_len = FS_UPLOAD_PACKET_LEN;
|
||||
|
||||
while (info->send_len < info->stream_len) {
|
||||
if (!h2_handle->init_state) {
|
||||
res = UPLOAD_ERROR_COMMON;
|
||||
break;
|
||||
}
|
||||
|
||||
res = http2_stream_get_file_data(fs_node->file_path, ext_info->send_buffer, FS_UPLOAD_PACKET_LEN, (info->send_len + ext_info->file_offset)); /* offset used */
|
||||
if (res <= 0) {
|
||||
res = UPLOAD_FILE_READ_FAILED;
|
||||
break;
|
||||
}
|
||||
info->packet_len = res;
|
||||
|
||||
/* adjust the packet len */
|
||||
if (info->stream_len - info->send_len < info->packet_len) {
|
||||
info->packet_len = info->stream_len - info->send_len;
|
||||
}
|
||||
|
||||
res = IOT_HTTP2_Stream_Send(h2_handle, info, &ext_header);
|
||||
if (res < 0) {
|
||||
res = UPLOAD_STREAM_SEND_FAILED;
|
||||
break;
|
||||
}
|
||||
h2_debug("send len = %d\n", info->send_len);
|
||||
|
||||
if (fs_node->if_stop) {
|
||||
res = UPLOAD_STOP_BY_IOCTL;
|
||||
break;
|
||||
}
|
||||
|
||||
res = SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void *_http2_fs_node_handle(http2_file_stream_t *fs_node)
|
||||
{
|
||||
stream_handle_t *h2_handle = g_http2_fs_ctx.http2_handle;
|
||||
int filesize = 0;
|
||||
int upload_len = 0;
|
||||
fs_rsp_header_val_t rsp_data;
|
||||
fs_send_ext_info_t send_ext_info;
|
||||
stream_data_info_t channel_info;
|
||||
uint32_t part_len = 0;
|
||||
int res = FAIL_RETURN;
|
||||
|
||||
/* params check */
|
||||
if (h2_handle == NULL) {
|
||||
/* TODO: handle */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get fileszie */
|
||||
filesize = http2_stream_get_file_size(fs_node->file_path);
|
||||
if (filesize <= 0) {
|
||||
if (fs_node->end_cb) {
|
||||
fs_node->end_cb(fs_node->file_path, UPLOAD_FILE_NOT_EXIST, fs_node->user_data);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
h2_info("filesize = %d", filesize);
|
||||
|
||||
/* open http2 file upload channel */
|
||||
memset(&rsp_data, 0, sizeof(fs_rsp_header_val_t));
|
||||
memset(&channel_info, 0, sizeof(stream_data_info_t));
|
||||
channel_info.identify = g_http2_fs_ctx.service_id;
|
||||
channel_info.user_data = (void *)&rsp_data;
|
||||
|
||||
res = _http2_fs_open_channel(fs_node, &channel_info);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
if (fs_node->end_cb) {
|
||||
fs_node->end_cb(fs_node->file_path, res, fs_node->user_data);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h2_info("upload_id = %s", rsp_data.fs_upload_id);
|
||||
h2_info("upload_offset = %d", rsp_data.fs_offset);
|
||||
if (fs_node->opened_cb) {
|
||||
fs_node->opened_cb(fs_node->file_path, rsp_data.fs_upload_id, fs_node->user_data);
|
||||
}
|
||||
|
||||
if (fs_node->spec_len && (fs_node->spec_len + rsp_data.fs_offset < filesize)) {
|
||||
upload_len = fs_node->spec_len + rsp_data.fs_offset;
|
||||
}
|
||||
else {
|
||||
upload_len = filesize;
|
||||
}
|
||||
|
||||
/* setup send part len */
|
||||
if ((fs_node->part_len < (1024 * 100)) || (fs_node->part_len > (1024 * 1024 * 100))) {
|
||||
part_len = FS_UPLOAD_PART_LEN;
|
||||
}
|
||||
else {
|
||||
part_len = fs_node->part_len;
|
||||
}
|
||||
|
||||
/* send http2 file upload data */
|
||||
send_ext_info.upload_id = rsp_data.fs_upload_id;
|
||||
send_ext_info.file_offset = rsp_data.fs_offset;
|
||||
send_ext_info.send_buffer = HTTP2_STREAM_MALLOC(FS_UPLOAD_PACKET_LEN);
|
||||
if (send_ext_info.send_buffer == NULL) {
|
||||
if (fs_node->end_cb) {
|
||||
fs_node->end_cb(fs_node->file_path, UPLOAD_MALLOC_FAILED, fs_node->user_data);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
/* setup the part len */
|
||||
send_ext_info.part_len = ((upload_len - send_ext_info.file_offset) < part_len)?
|
||||
(upload_len - send_ext_info.file_offset): part_len;
|
||||
|
||||
res = _http2_fs_part_send_sync(fs_node, &channel_info, &send_ext_info);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
h2_err("fs send return %d", res);
|
||||
break;
|
||||
}
|
||||
|
||||
send_ext_info.file_offset += send_ext_info.part_len;
|
||||
h2_info("file offset = %d now", send_ext_info.file_offset);
|
||||
} while (send_ext_info.file_offset < upload_len);
|
||||
|
||||
if (res < 0) {
|
||||
if (fs_node->end_cb) {
|
||||
fs_node->end_cb(fs_node->file_path, res, fs_node->user_data);
|
||||
}
|
||||
|
||||
HTTP2_STREAM_FREE(channel_info.channel_id);
|
||||
HTTP2_STREAM_FREE(send_ext_info.send_buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* close http2 file upload channel */
|
||||
IOT_HTTP2_FS_Close(h2_handle, &channel_info, NULL);
|
||||
|
||||
if (fs_node->end_cb) {
|
||||
fs_node->end_cb(fs_node->file_path, UPLOAD_SUCCESS, fs_node->user_data);
|
||||
}
|
||||
|
||||
HTTP2_STREAM_FREE(send_ext_info.send_buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *http_upload_file_func(void *fs_data)
|
||||
{
|
||||
http2_file_stream_ctx_t *fs_ctx = (http2_file_stream_ctx_t *)fs_data;
|
||||
http2_file_stream_t *node = NULL;
|
||||
if (fs_ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (fs_ctx->http2_handle->init_state) {
|
||||
HAL_MutexLock(fs_ctx->list_mutex);
|
||||
if (!list_empty((list_head_t *)&g_http2_fs_ctx.file_list)) {
|
||||
node = list_first_entry(&fs_ctx->file_list, http2_file_stream_t, list);
|
||||
HAL_MutexUnlock(fs_ctx->list_mutex);
|
||||
|
||||
/* execute upload routine */
|
||||
_http2_fs_node_handle((void *)node);
|
||||
|
||||
/* delete the completed node */
|
||||
HAL_MutexLock(fs_ctx->list_mutex);
|
||||
list_del((list_head_t *)&node->list);
|
||||
HTTP2_STREAM_FREE(node);
|
||||
HAL_MutexUnlock(fs_ctx->list_mutex);
|
||||
}
|
||||
else {
|
||||
HAL_MutexUnlock(fs_ctx->list_mutex);
|
||||
h2_debug("file list is empty, file upload thread exit\n");
|
||||
g_http2_fs_ctx.file_thread = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _http2_fs_list_insert(http2_file_stream_ctx_t *fs_ctx, http2_file_stream_t *node)
|
||||
{
|
||||
INIT_LIST_HEAD((list_head_t *)&node->list);
|
||||
HAL_MutexLock(fs_ctx->list_mutex);
|
||||
list_add_tail((list_head_t *)&node->list, (list_head_t *)&fs_ctx->file_list);
|
||||
HAL_MutexUnlock(fs_ctx->list_mutex);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
HTTP2_IOCTL_STOP_UPLOAD,
|
||||
HTTP2_IOCTL_COMMAND_NUM,
|
||||
} http2_file_upload_ioctl_command_t;
|
||||
|
||||
static int _http2_fs_list_search_by_idx(int idx, http2_file_stream_t **search_node)
|
||||
{
|
||||
http2_file_stream_t *node = NULL;
|
||||
|
||||
HAL_MutexLock(g_http2_fs_ctx.list_mutex);
|
||||
|
||||
list_for_each_entry(node, &g_http2_fs_ctx.file_list, list, http2_file_stream_t) {
|
||||
if (idx == node->idx) {
|
||||
*search_node = node;
|
||||
HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
|
||||
*search_node = NULL;
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
int IOT_HTTP2_Ioctl(int upload_idx, int command, void *data)
|
||||
{
|
||||
http2_file_stream_t *node = NULL;
|
||||
|
||||
if (g_http2_fs_ctx.http2_handle == NULL) {
|
||||
return UPLOAD_ERROR_COMMON;
|
||||
}
|
||||
|
||||
_http2_fs_list_search_by_idx(upload_idx, &node);
|
||||
if (node == NULL) {
|
||||
return UPLOAD_ERROR_COMMON;
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case HTTP2_IOCTL_STOP_UPLOAD: {
|
||||
if (g_http2_fs_ctx.http2_handle) {
|
||||
HAL_MutexLock(g_http2_fs_ctx.list_mutex);
|
||||
node->if_stop = 1;
|
||||
HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
else {
|
||||
return UPLOAD_ERROR_COMMON;
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
return UPLOAD_ERROR_COMMON;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void *IOT_HTTP2_UploadFile_Connect(http2_upload_conn_info_t *conn_info, http2_status_cb_t *cb)
|
||||
{
|
||||
void *handle;
|
||||
|
||||
memset(&callback_func, 0, sizeof(http2_stream_cb_t));
|
||||
|
||||
if (cb != NULL) {
|
||||
callback_func.on_reconnect_cb = cb->on_reconnect_cb;
|
||||
callback_func.on_disconnect_cb = cb->on_disconnect_cb;
|
||||
}
|
||||
|
||||
handle = IOT_HTTP2_Connect((device_conn_info_t *)conn_info, &callback_func);
|
||||
if (handle == NULL) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
g_http2_fs_ctx.list_mutex = HAL_MutexCreate();
|
||||
if (g_http2_fs_ctx.list_mutex == NULL) {
|
||||
h2_err("fs mutex create error\n");
|
||||
IOT_HTTP2_UploadFile_Disconnect(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD((list_head_t *)&(g_http2_fs_ctx.file_list));
|
||||
g_http2_fs_ctx.http2_handle = handle;
|
||||
g_http2_fs_ctx.service_id = HTTP2_FS_SERVICE_ID;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
int IOT_HTTP2_UploadFile_Request(void *http2_handle, http2_upload_params_t *params, http2_upload_result_cb_t *cb, void *user_data)
|
||||
{
|
||||
int ret;
|
||||
http2_file_stream_t *file_node = NULL;
|
||||
|
||||
if (http2_handle == NULL || params == NULL || cb == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (params->file_path == NULL) {
|
||||
return UPLOAD_FILE_PATH_IS_NULL;
|
||||
}
|
||||
|
||||
if ( (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_RESUME) && params->upload_id == NULL) {
|
||||
return UPLOAD_ID_IS_NULL;
|
||||
}
|
||||
|
||||
if ( (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN) && params->upload_len == 0) {
|
||||
return UPLOAD_LEN_IS_ZERO;
|
||||
}
|
||||
|
||||
file_node = (http2_file_stream_t *)HTTP2_STREAM_MALLOC(sizeof(http2_file_stream_t));
|
||||
if (file_node == NULL) {
|
||||
return UPLOAD_MALLOC_FAILED;
|
||||
}
|
||||
|
||||
memset(file_node, 0, sizeof(http2_file_stream_t));
|
||||
file_node->file_path = params->file_path;
|
||||
file_node->part_len = params->part_len;
|
||||
file_node->opened_cb = cb->upload_id_received_cb;
|
||||
file_node->end_cb = cb->upload_completed_cb;
|
||||
file_node->user_data = user_data;
|
||||
file_node->type = FS_TYPE_NORMAL;
|
||||
file_node->idx = g_http2_fs_ctx.upload_idx++;
|
||||
|
||||
if (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN) {
|
||||
file_node->spec_len = params->upload_len;
|
||||
}
|
||||
if (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_OVERWRITE) {
|
||||
file_node->type = FS_TYPE_OVERRIDE;
|
||||
}
|
||||
else if (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_RESUME) {
|
||||
file_node->type = FS_TYPE_CONTINUE;
|
||||
memcpy(file_node->upload_id, params->upload_id, sizeof(file_node->upload_id));
|
||||
}
|
||||
|
||||
/* inset http2_fs node */
|
||||
_http2_fs_list_insert(&g_http2_fs_ctx, file_node);
|
||||
|
||||
if (g_http2_fs_ctx.file_thread == NULL) {
|
||||
hal_os_thread_param_t thread_parms = {0};
|
||||
thread_parms.stack_size = 6144;
|
||||
thread_parms.name = "file_upload";
|
||||
ret = HAL_ThreadCreate(&g_http2_fs_ctx.file_thread, http_upload_file_func, (void *)&g_http2_fs_ctx, &thread_parms, NULL);
|
||||
if (ret != 0) {
|
||||
h2_err("file upload thread create error\n");
|
||||
return -1;
|
||||
}
|
||||
HAL_ThreadDetach(g_http2_fs_ctx.file_thread);
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int IOT_HTTP2_UploadFile_Disconnect(void *handle)
|
||||
{
|
||||
int res = FAIL_RETURN;
|
||||
|
||||
res = IOT_HTTP2_Disconnect(handle);
|
||||
|
||||
if (g_http2_fs_ctx.list_mutex == NULL) {
|
||||
memset(&g_http2_fs_ctx, 0, sizeof(g_http2_fs_ctx));
|
||||
}
|
||||
else {
|
||||
http2_file_stream_t *node, *next;
|
||||
HAL_MutexLock(g_http2_fs_ctx.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &g_http2_fs_ctx.file_list, list, http2_file_stream_t) {
|
||||
list_del((list_head_t *)&node->list);
|
||||
HTTP2_STREAM_FREE(node);
|
||||
break;
|
||||
}
|
||||
HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
|
||||
|
||||
HAL_MutexDestroy(g_http2_fs_ctx.list_mutex);
|
||||
memset(&g_http2_fs_ctx, 0, sizeof(g_http2_fs_ctx));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* #ifdef FS_ENABLED */
|
94
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.h
vendored
Normal file
94
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _HTTP2_UPLOAD_API_H_
|
||||
#define _HTTP2_UPLOAD_API_H_
|
||||
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* bit define of file override option */
|
||||
#define UPLOAD_FILE_OPT_BIT_OVERWRITE (0x00000001)
|
||||
#define UPLOAD_FILE_OPT_BIT_RESUME (0x00000002)
|
||||
#define UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN (0x00000004)
|
||||
|
||||
/* http2 connect information */
|
||||
typedef struct {
|
||||
char *product_key;
|
||||
char *device_name;
|
||||
char *device_secret;
|
||||
char *url;
|
||||
int port;
|
||||
} http2_upload_conn_info_t;
|
||||
|
||||
/* file upload option define */
|
||||
typedef struct {
|
||||
const char *file_path; /* file path, filename must be ASCII string and strlen < 2014 */
|
||||
uint32_t part_len; /* maximum content len of one http2 request, must be in range of 100KB ~ 100MB */
|
||||
const char *upload_id; /* a specific id used to indicate one upload session, only required when UPLOAD_FILE_OPT_BIT_RESUME option set */
|
||||
uint32_t upload_len; /* used to indicate the upload length, only required when UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN option set */
|
||||
uint32_t opt_bit_map; /* option bit map, support UPLOAD_FILE_OPT_BIT_OVERWRITE, UPLOAD_FILE_OPT_BIT_RESUME and UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN */
|
||||
} http2_upload_params_t;
|
||||
|
||||
/* error code for file upload */
|
||||
typedef enum {
|
||||
UPLOAD_STOP_BY_IOCTL = -14,
|
||||
UPLOAD_HTTP2_HANDLE_NULL = -13,
|
||||
UPLOAD_LEN_IS_ZERO = -12,
|
||||
UPLOAD_FILE_PATH_IS_NULL = -11,
|
||||
UPLOAD_ID_IS_NULL = -10,
|
||||
UPLOAD_FILE_NOT_EXIST = -9,
|
||||
UPLOAD_FILE_READ_FAILED = -8,
|
||||
UPLOAD_STREAM_OPEN_FAILED = -7,
|
||||
UPLOAD_STREAM_SEND_FAILED = -6,
|
||||
UPLOAD_MALLOC_FAILED = -5,
|
||||
UPLOAD_NULL_POINT = -2,
|
||||
UPLOAD_ERROR_COMMON = -1,
|
||||
UPLOAD_SUCCESS = 0,
|
||||
} http2_file_upload_result_t;
|
||||
|
||||
/* gerneral callback function, this callback will be invoke when http2 disconnected */
|
||||
typedef void (*http2_disconnect_cb_t)(void);
|
||||
|
||||
/* gerneral callback function, this callback will be invoke when http2 reconnected */
|
||||
typedef void (*http2_reconnect_cb_t)(void);
|
||||
|
||||
/* callback function type define, this callback will be invoke when upload completed */
|
||||
typedef void (*http2_upload_completed_cb_t)(const char *file_path, int result, void *user_data);
|
||||
|
||||
/* callback funciton type define, this callback will be invoke when upload_id received */
|
||||
typedef void (*http2_upload_id_received_cb_t)(const char *file_path, const char *upload_id, void *user_data);
|
||||
|
||||
/* http2 connect status callback define */
|
||||
typedef struct {
|
||||
http2_disconnect_cb_t on_disconnect_cb;
|
||||
http2_reconnect_cb_t on_reconnect_cb;
|
||||
} http2_status_cb_t;
|
||||
|
||||
/* http2 upload result callback define */
|
||||
typedef struct {
|
||||
http2_upload_id_received_cb_t upload_id_received_cb;
|
||||
http2_upload_completed_cb_t upload_completed_cb;
|
||||
} http2_upload_result_cb_t;
|
||||
|
||||
/* http2 uploadfile connect api, http2 handle returned */
|
||||
void *IOT_HTTP2_UploadFile_Connect(http2_upload_conn_info_t *conn_info, http2_status_cb_t *cb);
|
||||
|
||||
/* http2 uploadfile start api */
|
||||
int IOT_HTTP2_UploadFile_Request(void *http2_handle, http2_upload_params_t *params, http2_upload_result_cb_t *cb, void *user_data);
|
||||
|
||||
/* http2 uploadfile disconnect api */
|
||||
int IOT_HTTP2_UploadFile_Disconnect(void *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _HTTP2_UPLOAD_API_H_ */
|
||||
|
||||
|
54
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_wrapper.h
vendored
Normal file
54
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_wrapper.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __HTTP2_WRAPPER_H__
|
||||
#define __HTTP2_WRAPPER_H__
|
||||
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "wrappers_defs.h"
|
||||
|
||||
extern void HAL_Printf(const char *fmt, ...);
|
||||
extern void HAL_SleepMs(uint32_t ms);
|
||||
|
||||
extern void *HAL_Malloc(uint32_t size);
|
||||
extern void *HAL_Realloc(void *ptr, uint32_t size);
|
||||
extern void HAL_Free(void *ptr);
|
||||
|
||||
extern void *HAL_MutexCreate(void);
|
||||
extern void HAL_MutexDestroy(void *mutex);
|
||||
extern void HAL_MutexLock(void *mutex);
|
||||
extern void HAL_MutexUnlock(void *mutex);
|
||||
|
||||
extern void *HAL_SemaphoreCreate(void);
|
||||
extern void HAL_SemaphoreDestroy(void *sem);
|
||||
extern void HAL_SemaphorePost(void *sem);
|
||||
extern int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
|
||||
|
||||
extern int HAL_ThreadCreate(
|
||||
void **thread_handle,
|
||||
void *(*work_routine)(void *),
|
||||
void *arg,
|
||||
hal_os_thread_param_t *hal_os_thread_param,
|
||||
int *stack_used);
|
||||
extern void HAL_ThreadDetach(void *thread_handle);
|
||||
extern void HAL_ThreadDelete(void *thread_handle);
|
||||
|
||||
#ifdef FS_ENABLED
|
||||
typedef enum {
|
||||
HAL_SEEK_SET,
|
||||
HAL_SEEK_CUR,
|
||||
HAL_SEEK_END
|
||||
} hal_fs_seek_type_t;
|
||||
|
||||
extern void *HAL_Fopen(const char *path, const char *mode);
|
||||
extern uint32_t HAL_Fread(void *buff, uint32_t size, uint32_t count, void *stream);
|
||||
extern uint32_t HAL_Fwrite(const void *ptr, uint32_t size, uint32_t count, void *stream);
|
||||
extern int HAL_Fseek(void *stream, long offset, int framewhere);
|
||||
extern int HAL_Fclose(void *stream);
|
||||
extern long HAL_Ftell(void *stream);
|
||||
#endif /* #ifdef FS_ENABLED */
|
||||
|
||||
#endif /* #ifndef __HTTP2_WRAPPER_H__ */
|
||||
|
16
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iot.mk
vendored
Normal file
16
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iot.mk
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
LIBA_TARGET := libiot_http2.a
|
||||
|
||||
HDR_REFS += src/infra
|
||||
|
||||
DEPENDS += wrappers external_libs/nghttp2
|
||||
LDFLAGS += -liot_sdk -liot_hal -liot_tls -liot_nghttp2
|
||||
|
||||
LIB_SRCS_EXCLUDE := examples/http2_example_stream.c examples/http2_example_uploadfile.c examples/http2_example_break_resume.c
|
||||
|
||||
SRCS_http2-example-stream += examples/http2_example_stream.c
|
||||
SRCS_http2-example-uploadfile += examples/http2_example_uploadfile.c
|
||||
SRCS_http2-example-break-resume += examples/http2_example_break_resume.c
|
||||
|
||||
$(call Append_Conditional, TARGET, http2-example-stream, HTTP2_COMM_ENABLED)
|
||||
$(call Append_Conditional, TARGET, http2-example-uploadfile http2-example-break-resume, HTTP2_COMM_ENABLED FS_ENABLED)
|
||||
|
841
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iotx_http2.c
vendored
Normal file
841
components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iotx_http2.c
vendored
Normal file
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nghttp2.h"
|
||||
#include "nghttp2_session.h"
|
||||
#include "infra_httpc.h"
|
||||
#include "http2_internal.h"
|
||||
#include "http2_wrapper.h"
|
||||
|
||||
|
||||
#define MAX_HTTP2_HOST_LEN (128)
|
||||
#define NGHTTP2_DBG h2_info
|
||||
|
||||
typedef enum {
|
||||
PING_IDLE,
|
||||
PING_SENDING,
|
||||
PING_SENT,
|
||||
PING_RECVED,
|
||||
} http2_ping_state_t;
|
||||
|
||||
|
||||
enum { IO_NONE, WANT_READ, WANT_WRITE };
|
||||
|
||||
typedef struct _http2_request_struct_ {
|
||||
/* Stream ID for this request. */
|
||||
int32_t stream_id;
|
||||
} http2_request;
|
||||
|
||||
|
||||
extern const char *iotx_ca_get(void);
|
||||
extern int httpclient_connect(httpclient_t *client);
|
||||
static int http2_nv_copy_nghttp2_nv(nghttp2_nv *nva, int start, http2_header *nva_copy, int end);
|
||||
/*static int http2_parse_host(char *url, char *host, size_t maxHostLen);*/
|
||||
|
||||
static http2_ping_state_t ping_state = PING_IDLE;
|
||||
|
||||
int g_recv_timeout = 10;
|
||||
|
||||
int set_http2_recv_timeout(int timeout)
|
||||
{
|
||||
g_recv_timeout = timeout;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data)
|
||||
{
|
||||
http2_connection_t *connection;
|
||||
httpclient_t *client;
|
||||
int rv;
|
||||
|
||||
connection = (http2_connection_t *)user_data;
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NGHTTP2_DBG("send_callback data len %d, session->remote_window_size=%d!\r\n", (int)length,
|
||||
session->remote_window_size);
|
||||
if (session->remote_window_size < length * 2) {
|
||||
HAL_SleepMs(50);
|
||||
NGHTTP2_DBG("wait a munite ....");
|
||||
}
|
||||
/*if(length < 50)
|
||||
LITE_hexdump("data:", data, length);*/
|
||||
client = (httpclient_t *)connection->network;
|
||||
rv = client->net.write(&client->net, (char *)data, length, 5000);
|
||||
NGHTTP2_DBG("send_callback data ends len = %d!\r\n", rv);
|
||||
if (rv < 0 || rv < length) {
|
||||
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The implementation of nghttp2_recv_callback type. Here we read |data| from the network
|
||||
* and write them in |buf|. The capacity of |buf| is |length| bytes. Returns the number of
|
||||
* bytes stored in |buf|. See the documentation of nghttp2_recv_callback for the details.
|
||||
* To set this callback to :type:`nghttp2_session_callbacks`, use
|
||||
* `nghttp2_session_callbacks_set_on_frame_send_callback()`.
|
||||
* @param[in] session: nghttp2 session.
|
||||
* @param[in] buf: receive data buffer.
|
||||
* @param[in] length: data length.
|
||||
* @param[in] flags: no using.
|
||||
* @param[in] user_data: user data.
|
||||
* @return Received data length.
|
||||
*/
|
||||
static ssize_t recv_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t length, int flags, void *user_data)
|
||||
{
|
||||
http2_connection_t *connection;
|
||||
int rv;
|
||||
httpclient_t *client;
|
||||
|
||||
connection = (http2_connection_t *)user_data;
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
client = (httpclient_t *)connection->network;
|
||||
|
||||
rv = client->net.read(&client->net, (char *)buf, length, g_recv_timeout);
|
||||
/* NGHTTP2_DBG("recv_callback len= %d\r\n", rv); */
|
||||
if (rv < 0) {
|
||||
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
} else if (rv == 0) {
|
||||
rv = 0;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
/**
|
||||
* @brief Callback function invoked after the frame |frame| is sent.
|
||||
* To set this callback to :type:`nghttp2_session_callbacks`, use
|
||||
* `nghttp2_session_callbacks_set_on_frame_send_callback()`.
|
||||
* @param[in] session: nghttp2 session.
|
||||
* @param[in] frame: nghttp2 frame.
|
||||
* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
|
||||
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
|
||||
* @return The implementation of this function must return 0 if it succeeds.
|
||||
* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
|
||||
* and `nghttp2_session_mem_send()` functions immediately return :enum:
|
||||
* `NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||
*/
|
||||
static int on_frame_send_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *user_data)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
http2_connection_t *connection = (http2_connection_t *)user_data;
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (frame->hd.type) {
|
||||
case NGHTTP2_HEADERS: {
|
||||
const nghttp2_nv *nva = frame->headers.nva;
|
||||
NGHTTP2_DBG("[INFO] C ---------> S (HEADERS) stream_id [%d]\n", frame->hd.stream_id);
|
||||
for (i = 0; i < frame->headers.nvlen; ++i) {
|
||||
NGHTTP2_DBG("> %s: %s\n", nva[i].name, nva[i].value);
|
||||
}
|
||||
(void)nva;
|
||||
} break;
|
||||
case NGHTTP2_RST_STREAM: {
|
||||
NGHTTP2_DBG("[INFO] C ---------> S (RST_STREAM)\n");
|
||||
} break;
|
||||
case NGHTTP2_GOAWAY: {
|
||||
NGHTTP2_DBG("[INFO] C ---------> S (GOAWAY) code = %d\n",frame->goaway.error_code);
|
||||
} break;
|
||||
case NGHTTP2_PING: {
|
||||
NGHTTP2_DBG("[INFO] C ---------> S (PING)\n");
|
||||
ping_state = PING_SENDING;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (connection->cbs && connection->cbs->on_user_frame_send_cb) {
|
||||
connection->cbs->on_user_frame_send_cb(frame->hd.stream_id, frame->hd.type, frame->hd.flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function invoked by `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` when a frame is received.
|
||||
* If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``member of their data structure are always
|
||||
* ``NULL`` and 0 respectively. The header name/value pairs are emitted via:type:`nghttp2_on_header_callback`
|
||||
* To set this callback to :type:`nghttp2_session_callbacks`, use`nghttp2_session_callbacks_set_on_frame_send_callback()`.
|
||||
* For HEADERS, PUSH_PROMISE and DATA frames, this callback may be called after stream is closed (see:type:
|
||||
* `nghttp2_on_stream_close_callback`). The application should check that stream is still alive using its own stream
|
||||
* management or :func:`nghttp2_session_get_stream_user_data()`.
|
||||
* Only HEADERS and DATA frame can signal the end of incoming data. If ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM``
|
||||
* is nonzero, the|frame| is the last frame from the remote peer in this stream.
|
||||
* This callback won't be called for CONTINUATION frames.
|
||||
* HEADERS/PUSH_PROMISE + CONTINUATIONs are treated as single frame.
|
||||
* @param[in] session: nghttp2 session.
|
||||
* @param[in] frame: nghttp2 frame.
|
||||
* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
|
||||
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
|
||||
* @return The implementation of this function must return 0 if it succeeds.
|
||||
* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
|
||||
* and `nghttp2_session_mem_send()` functions immediately return :enum:
|
||||
* `NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||
*/
|
||||
static int on_frame_recv_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *user_data)
|
||||
{
|
||||
http2_connection_t *connection = (http2_connection_t *)user_data;
|
||||
http2_request *req;
|
||||
NGHTTP2_DBG("on_frame_recv_callback, type = %d\n", frame->hd.type);
|
||||
NGHTTP2_DBG("on_frame_recv_callback, stream_id = %d\n", frame->hd.stream_id);
|
||||
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
req = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
|
||||
if (req == NULL) {
|
||||
NGHTTP2_DBG("stream user data is not exist\n");
|
||||
}
|
||||
|
||||
switch (frame->hd.type) {
|
||||
case NGHTTP2_HEADERS: {
|
||||
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
|
||||
|
||||
}
|
||||
} break;
|
||||
case NGHTTP2_RST_STREAM: {
|
||||
connection->status = 0;
|
||||
NGHTTP2_DBG("[INFO] C <--------- S (RST_STREAM)\n");
|
||||
} break;
|
||||
case NGHTTP2_GOAWAY: {
|
||||
connection->status = 0;
|
||||
NGHTTP2_DBG("[INFO] C <--------- S (GOAWAY) code = %d\n",frame->goaway.error_code);
|
||||
} break;
|
||||
case NGHTTP2_DATA: {
|
||||
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
||||
NGHTTP2_DBG("end stream flag\r\n");
|
||||
}
|
||||
} break;
|
||||
case NGHTTP2_PING: {
|
||||
NGHTTP2_DBG("[INFO] C <--------- S (PING)\n");
|
||||
ping_state = PING_RECVED;
|
||||
} break;
|
||||
}
|
||||
|
||||
if (connection->cbs && connection->cbs->on_user_frame_recv_cb) {
|
||||
connection->cbs->on_user_frame_recv_cb(frame->hd.stream_id, frame->hd.type, frame->hd.flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function invoked when the stream |stream_id| is closed.
|
||||
* We use this function to know if the response is fully received. Since we just fetch 1 resource in this program, after
|
||||
* the response is received, we submit GOAWAY and close the session.
|
||||
* @param[in] session: nghttp2 session.
|
||||
* @param[in] stream_id: stream id.
|
||||
* @param[in] error_code: The reason of closure.
|
||||
* Usually one of :enum:`nghttp2_error_code`, but that is not guaranteed. The stream_user_data, which was specified in
|
||||
* `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still available in this function.
|
||||
* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
|
||||
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
|
||||
* @return The implementation of this function must return 0 if it succeeds.
|
||||
* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
|
||||
* and `nghttp2_session_mem_send()` functions immediately return :enum:
|
||||
* `NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||
*/
|
||||
static int on_h2_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code,
|
||||
void *user_data)
|
||||
{
|
||||
http2_request *req;
|
||||
http2_connection_t *connection = (http2_connection_t *)user_data;
|
||||
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
req = nghttp2_session_get_stream_user_data(session, stream_id);
|
||||
if (req) {
|
||||
int rv;
|
||||
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
|
||||
|
||||
if (rv != 0) {
|
||||
NGHTTP2_DBG("stream close nghttp2_session_terminate_session\r\n");
|
||||
}
|
||||
}
|
||||
if (connection->cbs && connection->cbs->on_user_stream_close_cb) {
|
||||
connection->cbs->on_user_stream_close_cb(stream_id, error_code);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function invoked when a chunk of data in DATA frame is received.
|
||||
* The implementation of nghttp2_on_data_chunk_recv_callback type. We use this function to print the received response body.
|
||||
* @param[in] session: nghttp2 session.
|
||||
* @param[in] flags: no using.
|
||||
* @param[in] stream_id: the stream ID this DATA frame belongs to.
|
||||
* @param[in] data: receive data.
|
||||
* @param[in] len: data length.
|
||||
* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
|
||||
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
|
||||
* @return The implementation of this function must return 0 if it succeeds.
|
||||
* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
|
||||
* and `nghttp2_session_mem_send()` functions immediately return :enum:
|
||||
* `NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||
*/
|
||||
static int on_data_chunk_recv_callback(nghttp2_session *session,
|
||||
uint8_t flags, int32_t stream_id,
|
||||
const uint8_t *data, size_t len,
|
||||
void *user_data)
|
||||
{
|
||||
http2_request *req;
|
||||
http2_connection_t *connection = (http2_connection_t *)user_data;
|
||||
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
req = nghttp2_session_get_stream_user_data(session, stream_id);
|
||||
if (req) {
|
||||
NGHTTP2_DBG("stream user data is not exist\n");
|
||||
}
|
||||
NGHTTP2_DBG("[INFO] C <----------- S (DATA chunk) stream_id [%d] :: %lu bytes\n", stream_id, (unsigned long int)len);
|
||||
|
||||
if (connection->cbs && connection->cbs->on_user_chunk_recv_cb) {
|
||||
connection->cbs->on_user_chunk_recv_cb(stream_id, data, len, flags);
|
||||
}
|
||||
|
||||
nghttp2_session_consume_connection(session, len);
|
||||
nghttp2_session_consume(session, stream_id, len);
|
||||
nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, len);
|
||||
nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, stream_id, len);
|
||||
nghttp2_session_send(session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function invoked when a header name/value pair is received.
|
||||
* The implementation of nghttp2_on_data_chunk_recv_callback type. We use this function to print the received response body.
|
||||
* @param[in] session: nghttp2 session.
|
||||
* @param[in] frame: nghttp2 frame.
|
||||
* @param[in] name: header name.
|
||||
* @param[in] namelen: length of header name.
|
||||
* @param[in] value: header value.
|
||||
* @param[in] valuelen: length of header value.
|
||||
* @param[in] flags: no using.
|
||||
* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
|
||||
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
|
||||
* @return The implementation of this function must return 0 if it succeeds.
|
||||
* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
|
||||
* and `nghttp2_session_mem_send()` functions immediately return :enum:
|
||||
* `NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||
*/
|
||||
|
||||
|
||||
static int on_header_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame, const uint8_t *name,
|
||||
size_t namelen, const uint8_t *value,
|
||||
size_t valuelen, uint8_t flags,
|
||||
void *user_data)
|
||||
{
|
||||
http2_connection_t *connection = (http2_connection_t *)user_data;
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
switch (frame->hd.type) {
|
||||
case NGHTTP2_HEADERS:
|
||||
|
||||
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
|
||||
http2_connection_t *connection = (http2_connection_t *)user_data;
|
||||
/* Print response headers for the initiated request. */
|
||||
NGHTTP2_DBG("< %s: %s\n", name, value);
|
||||
|
||||
if (connection->cbs && connection->cbs->on_user_header_cb) {
|
||||
connection->cbs->on_user_header_cb(frame->hd.stream_id, (int)frame->headers.cat, name, namelen, value, valuelen, flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when nghttp2 library gets started to receive header block.
|
||||
* @param[in] session: nghttp2 session.
|
||||
* @param[in] frame: nghttp2 frame.
|
||||
* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
|
||||
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
|
||||
* @return The implementation of this function must return 0 if it succeeds.
|
||||
* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
|
||||
* and `nghttp2_session_mem_send()` functions immediately return :enum:
|
||||
* `NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||
*/
|
||||
static int on_begin_headers_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *user_data)
|
||||
{
|
||||
switch (frame->hd.type) {
|
||||
case NGHTTP2_HEADERS:
|
||||
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
|
||||
NGHTTP2_DBG("[INFO] C <--------- S (HEADERS) stream_id [%d]\n", (int)frame->hd.stream_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Setup callback functions.
|
||||
* nghttp2 API offers many callback functions, but most of them are optional. The send_callback is always required.
|
||||
* Since we use nghttp2_session_recv(), the recv_callback is also required.
|
||||
* @param[in|out] callbacks: nghttp2 callbacks.
|
||||
* @return None.
|
||||
*/
|
||||
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
|
||||
{
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
||||
on_frame_send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback(
|
||||
callbacks, on_h2_stream_close_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||
callbacks, on_data_chunk_recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_header_callback(callbacks,
|
||||
on_header_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
callbacks, on_begin_headers_callback);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static ssize_t data_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length,
|
||||
uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data)
|
||||
{
|
||||
int len = 0;
|
||||
http2_connection_t *connection = (http2_connection_t *)user_data;
|
||||
if (connection == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (source->ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (connection != NULL && connection->flag != NGHTTP2_FLAG_END_STREAM) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
|
||||
connection->flag = NGHTTP2_FLAG_NONE;
|
||||
}
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
|
||||
/*len = strlen((char *)source->ptr);*/
|
||||
len = source->len;
|
||||
|
||||
if (length < len) {
|
||||
len = length;
|
||||
}
|
||||
memcpy(buf, source->ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int http2_nv_copy_nghttp2_nv(nghttp2_nv *nva, int start, http2_header *nva_copy, int end)
|
||||
{
|
||||
int i, j;
|
||||
for (i = start, j = 0; j < end; i++, j++) {
|
||||
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
|
||||
nva[i].name = (uint8_t *)nva_copy[j].name;
|
||||
nva[i].value = (uint8_t *)nva_copy[j].value;
|
||||
nva[i].namelen = nva_copy[j].namelen;
|
||||
nva[i].valuelen = nva_copy[j].valuelen;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Connect the SSL client.
|
||||
* @param[in] pclient: http client.
|
||||
* @param[in] url. destination url.
|
||||
* @param[in] port. destination port.
|
||||
* @param[in] ssl_config: custome config.
|
||||
* @return The result. 0 is ok.
|
||||
*/
|
||||
static int http2_client_conn(httpclient_t *pclient, char *url, int port)
|
||||
{
|
||||
int ret = 0;
|
||||
/*char host[MAX_HTTP2_HOST_LEN] = { 0 };*/
|
||||
|
||||
/*http2_parse_host(url, host, sizeof(host));*/
|
||||
if (0 == pclient->net.handle) {
|
||||
/* Establish connection if no. */
|
||||
extern const char *iotx_ca_crt;
|
||||
|
||||
ret = iotx_net_init(&pclient->net, url, port, iotx_ca_crt);
|
||||
|
||||
if (0 != ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = httpclient_connect(pclient);
|
||||
if (0 != ret) {
|
||||
h2_err("http2client_connect is error, ret = %d", ret);
|
||||
httpclient_close(pclient);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iotx_http2_client_send(http2_connection_t *conn, http2_data *h2_data)
|
||||
{
|
||||
int send_flag = 0;
|
||||
int rv = 0;
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_nv *nva = NULL;
|
||||
int nva_size = 0;
|
||||
http2_header *header = h2_data->header;
|
||||
int header_count = h2_data->header_count;
|
||||
char *data = h2_data->data;
|
||||
int len = h2_data->len;
|
||||
int stream_id = h2_data->stream_id;
|
||||
int flags = h2_data->flag;
|
||||
|
||||
if (conn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (header != NULL && header_count != 0) {
|
||||
nva = (nghttp2_nv *)HTTP2_STREAM_MALLOC(sizeof(nghttp2_nv) * header_count);
|
||||
if (nva == NULL) {
|
||||
return -1;
|
||||
}
|
||||
nva_size = http2_nv_copy_nghttp2_nv(nva, nva_size, header, header_count);
|
||||
}
|
||||
/*upload to server*/
|
||||
if (data != NULL && len != 0) {
|
||||
data_prd.source.ptr = data;
|
||||
data_prd.source.len = len;
|
||||
data_prd.read_callback = data_read_callback;
|
||||
if (nva_size != 0) {
|
||||
rv = nghttp2_submit_request(conn->session, NULL, nva, nva_size, &data_prd, NULL);
|
||||
h2_data->stream_id = rv;
|
||||
} else {
|
||||
rv = nghttp2_submit_data(conn->session, flags, stream_id, &data_prd);
|
||||
}
|
||||
} else {
|
||||
rv = nghttp2_submit_request(conn->session, NULL, nva, nva_size, NULL, NULL);
|
||||
h2_data->stream_id = rv;
|
||||
}
|
||||
HTTP2_STREAM_FREE(nva);
|
||||
|
||||
if (rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
send_flag = nghttp2_session_want_write(conn->session);
|
||||
if (send_flag) {
|
||||
rv = nghttp2_session_send(conn->session);
|
||||
NGHTTP2_DBG("nghttp2_session_send %d\r\n", rv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int iotx_http2_client_recv(http2_connection_t *conn, char *data, int data_len, int *len, int timeout)
|
||||
{
|
||||
int rv = 0;
|
||||
int read_flag = 0;
|
||||
|
||||
if (conn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_http2_recv_timeout(timeout);
|
||||
read_flag = nghttp2_session_want_read(conn->session);
|
||||
if (read_flag) {
|
||||
rv = nghttp2_session_recv(conn->session);
|
||||
NGHTTP2_DBG("nghttp2_client_recv %d\r\n", rv);
|
||||
if (rv < 0) {
|
||||
read_flag = 0;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief the http2 client connect.
|
||||
* @param[in] pclient: http client.
|
||||
* @return http2 client connection handler.
|
||||
*/
|
||||
http2_connection_t *iotx_http2_client_connect(void *pclient, char *url, int port)
|
||||
{
|
||||
http2_connection_t *connection;
|
||||
nghttp2_session_callbacks *callbacks;
|
||||
int rv;
|
||||
int ret = 0;
|
||||
|
||||
connection = HTTP2_STREAM_MALLOC(sizeof(http2_connection_t));
|
||||
if (connection == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(connection, 0, sizeof(http2_connection_t));
|
||||
|
||||
if (0 != (ret = http2_client_conn((httpclient_t *)pclient, url, port))) {
|
||||
NGHTTP2_DBG("https_client_conn failed %d\r\n", ret);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
connection->network = pclient;
|
||||
|
||||
rv = nghttp2_session_callbacks_new(&callbacks);
|
||||
if (rv != 0) {
|
||||
NGHTTP2_DBG("nghttp2_session_callbacks_new1 %d", rv);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
setup_nghttp2_callbacks(callbacks);
|
||||
rv = nghttp2_session_client_new((nghttp2_session **)&connection->session, callbacks, connection);
|
||||
if (rv != 0) {
|
||||
NGHTTP2_DBG("nghttp2_session_client_new3 %d", rv);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
nghttp2_session_callbacks_del(callbacks);
|
||||
|
||||
nghttp2_submit_settings(connection->session, NGHTTP2_FLAG_NONE, NULL, 0);
|
||||
#if 0
|
||||
|
||||
parse_uri(&uri, url);
|
||||
request_init(&req, &uri);
|
||||
/* Submit the HTTP request to the outbound queue. */
|
||||
submit_request(connection, &req);
|
||||
#endif
|
||||
|
||||
rv = nghttp2_session_send(connection->session);
|
||||
/*request_free(&req);*/
|
||||
if (rv < 0) {
|
||||
NGHTTP2_DBG("nghttp2_session_send fail %d", rv);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
connection->status = 1;
|
||||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief the http2 client connect.
|
||||
* @param[in] pclient: http client.
|
||||
* @return http2 client connection handler.
|
||||
*/
|
||||
http2_connection_t *iotx_http2_client_connect_with_cb(void *pclient, char *url, int port, http2_user_cb_t *cb)
|
||||
{
|
||||
http2_connection_t *connection;
|
||||
nghttp2_session_callbacks *callbacks;
|
||||
int rv;
|
||||
int ret = 0;
|
||||
|
||||
connection = HTTP2_STREAM_MALLOC(sizeof(http2_connection_t));
|
||||
if (connection == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(connection, 0, sizeof(http2_connection_t));
|
||||
|
||||
if (0 != (ret = http2_client_conn((httpclient_t *)pclient, url, port))) {
|
||||
NGHTTP2_DBG("https_client_conn failed %d\r\n", ret);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
connection->network = pclient;
|
||||
|
||||
rv = nghttp2_session_callbacks_new(&callbacks);
|
||||
if (rv != 0) {
|
||||
NGHTTP2_DBG("nghttp2_session_callbacks_new1 %d", rv);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
connection->cbs = cb;
|
||||
setup_nghttp2_callbacks(callbacks);
|
||||
|
||||
rv = nghttp2_session_client_new((nghttp2_session **)&connection->session, callbacks, connection);
|
||||
if (rv != 0) {
|
||||
NGHTTP2_DBG("nghttp2_session_client_new3 %d", rv);
|
||||
nghttp2_session_callbacks_del(callbacks);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
nghttp2_session_callbacks_del(callbacks);
|
||||
|
||||
nghttp2_submit_settings(connection->session, NGHTTP2_FLAG_NONE, NULL, 0);
|
||||
#if 0
|
||||
|
||||
parse_uri(&uri, url);
|
||||
request_init(&req, &uri);
|
||||
/* Submit the HTTP request to the outbound queue. */
|
||||
submit_request(connection, &req);
|
||||
#endif
|
||||
|
||||
rv = nghttp2_session_send(connection->session);
|
||||
/*request_free(&req);*/
|
||||
if (rv < 0) {
|
||||
nghttp2_session_del(connection->session);
|
||||
NGHTTP2_DBG("nghttp2_session_send fail %d", rv);
|
||||
HTTP2_STREAM_FREE(connection);
|
||||
return NULL;
|
||||
}
|
||||
connection->status = 1;
|
||||
return connection;
|
||||
}
|
||||
|
||||
int iotx_http2_client_disconnect(http2_connection_t *conn)
|
||||
{
|
||||
/* Resource cleanup */
|
||||
if (conn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
httpclient_close((httpclient_t *)conn->network);
|
||||
nghttp2_session_del(conn->session);
|
||||
HTTP2_STREAM_FREE(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iotx_http2_client_send_ping(http2_connection_t *conn)
|
||||
{
|
||||
int rv = 0;
|
||||
int send_flag;
|
||||
|
||||
ping_state = PING_IDLE;
|
||||
|
||||
if (conn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
rv = nghttp2_submit_ping(conn->session, NGHTTP2_FLAG_NONE, NULL);
|
||||
if (rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
send_flag = nghttp2_session_want_write(conn->session);
|
||||
if (send_flag) {
|
||||
rv = nghttp2_session_send(conn->session);
|
||||
NGHTTP2_DBG("nghttp2_session_send %d\r\n", rv);
|
||||
if (rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
ping_state = PING_SENDING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iotx_http2_client_recv_ping(void)
|
||||
{
|
||||
if (ping_state == PING_RECVED || ping_state == PING_IDLE) {
|
||||
NGHTTP2_DBG("ping recv secceed\r\n");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
NGHTTP2_DBG("ping recv timeout");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int iotx_http2_get_available_window_size(http2_connection_t *conn)
|
||||
{
|
||||
int windows_size = 0;
|
||||
|
||||
if (conn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
windows_size = nghttp2_session_get_remote_window_size(conn->session);
|
||||
return windows_size;
|
||||
}
|
||||
|
||||
|
||||
int iotx_http2_update_window_size(http2_connection_t *conn)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (conn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = nghttp2_session_recv(conn->session);
|
||||
if (rv < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs the network I/O.
|
||||
*/
|
||||
int iotx_http2_exec_io(http2_connection_t *connection)
|
||||
{
|
||||
if (connection == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nghttp2_session_want_read(connection->session) /*||
|
||||
nghttp2_session_want_write(connection->session)*/) {
|
||||
|
||||
int rv;
|
||||
rv = nghttp2_session_recv(connection->session);
|
||||
if (rv < 0) {
|
||||
NGHTTP2_DBG("nghttp2_session_recv error");
|
||||
return -1;
|
||||
}
|
||||
/* rv = nghttp2_session_send(connection->session); */
|
||||
/* if (rv < 0) { */
|
||||
/* NGHTTP2_DBG("nghttp2_session_send error"); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iotx_http2_reset_stream(http2_connection_t *connection, int32_t stream_id)
|
||||
{
|
||||
int rv = 0;
|
||||
if(connection == NULL){
|
||||
return -1;
|
||||
}
|
||||
if(!nghttp2_session_get_stream_local_close(connection->session,stream_id)) {
|
||||
rv = nghttp2_submit_rst_stream(connection->session,0, stream_id, NGHTTP2_NO_ERROR);
|
||||
}
|
||||
if (rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = nghttp2_session_want_write(connection->session);
|
||||
if (rv) {
|
||||
rv = nghttp2_session_send(connection->session);
|
||||
NGHTTP2_DBG("nghttp2_session_send %d\r\n", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
Reference in New Issue
Block a user