From 6ff604c95472ad28e9d329b26030b8bd68493ecc Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Thu, 10 Jun 2021 16:29:20 +0800 Subject: [PATCH] [update] shard download, add HEAD request function. --- inc/webclient.h | 6 +- samples/webclient_shard_download_sample.c | 9 +- src/webclient.c | 119 +++++++++++++++++----- 3 files changed, 105 insertions(+), 29 deletions(-) diff --git a/inc/webclient.h b/inc/webclient.h index 0477be1..6bd4f1f 100644 --- a/inc/webclient.h +++ b/inc/webclient.h @@ -109,8 +109,12 @@ struct webclient_session *webclient_session_create(size_t header_sz); /* send HTTP GET request */ int webclient_get(struct webclient_session *session, const char *URI); -int webclient_shard_position_function(struct webclient_session *session, const char *URI, int size); +/* send HTTP HEAD request */ +int webclient_shard_head_function(struct webclient_session *session, const char *URI, int *length); + +/* send HTTP Range parameter, shard download */ +int webclient_shard_position_function(struct webclient_session *session, const char *URI, int start, int length, int mem_size); char *webclient_register_shard_position_function(struct webclient_session *session, int (*handle_function)(char *buffer, int size)); /* send HTTP POST request */ diff --git a/samples/webclient_shard_download_sample.c b/samples/webclient_shard_download_sample.c index bceff39..5a6d2e2 100644 --- a/samples/webclient_shard_download_sample.c +++ b/samples/webclient_shard_download_sample.c @@ -22,7 +22,6 @@ static int shard_download_handle(char *buffer, int length) int boundary; /* print the receive data */ - rt_kprintf("\nReceive, len[%04d]:\n", length); for (outindex = 0; outindex < length; outindex = outindex + inindex) { char print_buffer[CHARACTER_LENGTH + 1] = {0}; @@ -45,7 +44,6 @@ static int shard_download_handle(char *buffer, int length) *point = 0; rt_kprintf("%04d - %04d: %s\n", outindex, outindex + boundary - 1, print_buffer); } - rt_kprintf("Total: [%04d]Bytes\n", length); /* release this buffer if we have handled data */ web_free(buffer); @@ -59,7 +57,7 @@ int webclient_shard_download_test(int argc, char **argv) struct webclient_session* session = RT_NULL; rt_err_t result = RT_EOK; char *uri = RT_NULL; - int size = 0; + int length, size = 0; int usage_flag = 0; @@ -108,11 +106,14 @@ int webclient_shard_download_test(int argc, char **argv) goto __exit; } + /* get the real data length */ + webclient_shard_head_function(session, uri, &length); + /* register the handle function, you can handle data in the function */ webclient_register_shard_position_function(session, shard_download_handle); /* the "memory size" that you can provide in the project and uri */ - webclient_shard_position_function(session, uri, size); + webclient_shard_position_function(session, uri, 0, length, size); /* clear the handle function */ webclient_register_shard_position_function(session, RT_NULL); diff --git a/src/webclient.c b/src/webclient.c index 6747bd6..cb9b46b 100644 --- a/src/webclient.c +++ b/src/webclient.c @@ -990,23 +990,27 @@ char *webclient_register_shard_position_function(struct webclient_session *sessi * @return <0: send GET request failed * >0: response http status code */ -int webclient_shard_position_function(struct webclient_session *session, const char *URI, int size) +int webclient_shard_head_function(struct webclient_session *session, const char *URI, int *length) { - int rc = WEBCLIENT_OK; - int resp_status = 0; - int real_total_len = 0; - int start_position, end_position = 0; - char *buffer = RT_NULL; - RT_ASSERT(session); RT_ASSERT(URI); - rc = webclient_connect(session, URI); - if (rc != WEBCLIENT_OK) + int rc = WEBCLIENT_OK; + int resp_status = 0; + + if(session->socket == -1) { - return rc; + rc = webclient_connect(session, URI); + if (rc != WEBCLIENT_OK) + { + return rc; + } } + /* clean header buffer and size */ + rt_memset(session->header->buffer, 0x00, session->header->size); + session->header->length = 0; + rc = webclient_send_header(session, WEBCLIENT_HEAD); if (rc != WEBCLIENT_OK) { @@ -1017,27 +1021,57 @@ int webclient_shard_position_function(struct webclient_session *session, const c resp_status = webclient_handle_response(session); if(resp_status >= 0) { - real_total_len = webclient_content_length_get(session); - LOG_D("The length[%04d] of real data of URI.", real_total_len); + *length = webclient_content_length_get(session); + LOG_D("The length[%04d] of real data of URI.", *length); } + return rc; +} + +/** + * http breakpoint resume and shard download. + * + * @param session webclient session + * @param URI input server URI address + * @param start the position of you want to receive + * @param length the length of data length from "webclient_shard_head_function" + * @param mem_size the buffer size that you alloc + * + * @return <0: send GET request failed + * >0: response http status code + */ +int webclient_shard_position_function(struct webclient_session *session, const char *URI, int start, int length, int mem_size) +{ + int rc = WEBCLIENT_OK; + int resp_status = 0; + char *buffer = RT_NULL; + int start_position, end_position = 0; + int total_len = 0; + + RT_ASSERT(session); + RT_ASSERT(URI); + + /* set the offset of "Range" and "total_len" */ + end_position = start; + total_len = start + length; + /* clean header buffer and size */ rt_memset(session->header->buffer, 0x00, session->header->size); session->header->length = 0; - for(start_position = end_position; end_position < real_total_len; start_position = end_position + 1) + for(start_position = end_position; total_len != end_position + 1;) { - RT_ASSERT(start_position < real_total_len); + RT_ASSERT(start_position <= total_len); int data_len = 0; - end_position = start_position + size - 1; - if(end_position >= real_total_len) + end_position = start_position + mem_size - 1; + if(end_position >= total_len) { - end_position = real_total_len; + end_position = total_len - 1; } /* splice header and send header */ - LOG_I("Range: [%04d -> %04d]", start_position, end_position); + LOG_D("Range: [%04d -> %04d]", start_position, end_position); webclient_header_fields_add(session, "Range: bytes=%d-%d\r\n", start_position, end_position); rc = webclient_send_header(session, WEBCLIENT_GET); if (rc != WEBCLIENT_OK) @@ -1047,9 +1081,12 @@ int webclient_shard_position_function(struct webclient_session *session, const c /* handle the response header of webclient server */ resp_status = webclient_handle_response(session); - LOG_D("get position handle response(%d).", resp_status); - if (resp_status > 0) + if (resp_status == 206) + { + /* normal resp_status */ + } + else if(resp_status > 0) { const char *location = webclient_header_fields_get(session, "Location"); @@ -1070,23 +1107,57 @@ int webclient_shard_position_function(struct webclient_session *session, const c session->header->length = 0; rt_memset(session->header->buffer, 0, session->header->size); - rc = webclient_shard_position_function(session, new_url, size); + rc = webclient_shard_position_function(session, new_url, start, length, mem_size); web_free(new_url); return rc; } } + else + { + if(resp_status == -WEBCLIENT_ERROR) + { + if(session->socket == -WEBCLIENT_ERROR) + { + /* clean webclient session */ + webclient_clean(session); + if(webclient_connect(session, URI) == WEBCLIENT_OK) + { + LOG_D("webclient reconnect success, retry at [%06d]", end_position); + continue; + } + else + { + LOG_E("webclient reconnect failed. Please retry by yourself."); + return -WEBCLIENT_ERROR; + } + } + } + } /* receive the incoming data */ - data_len = webclient_response(session, &buffer, RT_NULL); - session->handle_function(buffer, data_len); + data_len = webclient_response(session, &buffer, (size_t *)RT_NULL); + if(data_len > 0) + { + start_position += mem_size; + session->handle_function(buffer, data_len); + } + else + { + /* clean webclient session */ + webclient_clean(session); + if(session->socket == -WEBCLIENT_ERROR) + { + webclient_connect(session, URI); + } + } /* clean header buffer and size */ rt_memset(session->header->buffer, 0x00, session->header->size); session->header->length = 0; } - return resp_status; + return rc; } /**