123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- /*
- * Tencent is pleased to support the open source community by making IoT Hub
- available.
- * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
- * Licensed under the MIT License (the "License"); you may not use this file
- except in
- * compliance with the License. You may obtain a copy of the License at
- * http://opensource.org/licenses/MIT
- * Unless required by applicable law or agreed to in writing, software
- distributed under the License is
- * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND,
- * either express or implied. See the License for the specific language
- governing permissions and
- * limitations under the License.
- *
- */
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "utils_httpc.h"
- #include <ctype.h>
- #include <string.h>
- #include "qcloud_iot_ca.h"
- #include "qcloud_iot_common.h"
- #include "qcloud_iot_export.h"
- #include "qcloud_iot_import.h"
- #include "utils_timer.h"
- #define HTTP_CLIENT_MIN(x, y) (((x) < (y)) ? (x) : (y))
- #define HTTP_CLIENT_MAX(x, y) (((x) > (y)) ? (x) : (y))
- #define HTTP_CLIENT_AUTHB_SIZE 128
- #define HTTP_CLIENT_CHUNK_SIZE 1025
- #define HTTP_CLIENT_SEND_BUF_SIZE 1024
- #define HTTP_CLIENT_MAX_HOST_LEN 64
- #define HTTP_CLIENT_MAX_URL_LEN 1024
- #define HTTP_RETRIEVE_MORE_DATA (1)
- #if defined(MBEDTLS_DEBUG_C)
- #define DEBUG_LEVEL 2
- #endif
- static void _http_client_base64enc(char *out, const char *in)
- {
- const char code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
- int i = 0, x = 0, l = 0;
- for (; *in; in++) {
- x = x << 8 | *in;
- for (l += 8; l >= 6; l -= 6) {
- out[i++] = code[(x >> (l - 6)) & 0x3f];
- }
- }
- if (l > 0) {
- x <<= 6 - l;
- out[i++] = code[x & 0x3f];
- }
- for (; i % 4;) {
- out[i++] = '=';
- }
- out[i] = '\0';
- }
- static int _http_client_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host,
- uint32_t maxhost_len, int *port, char *path, uint32_t max_path_len)
- {
- char * scheme_ptr = (char *)url;
- char * host_ptr = (char *)strstr(url, "://");
- uint32_t host_len = 0;
- uint32_t path_len;
- char *path_ptr;
- char *fragment_ptr;
- if (host_ptr == NULL) {
- Log_e("Could not find host");
- return QCLOUD_ERR_HTTP_PARSE;
- }
- if (max_scheme_len < host_ptr - scheme_ptr + 1) {
- Log_e("Scheme str is too small (%u >= %u)", max_scheme_len, (uint32_t)(host_ptr - scheme_ptr + 1));
- return QCLOUD_ERR_HTTP_PARSE;
- }
- memcpy(scheme, scheme_ptr, host_ptr - scheme_ptr);
- scheme[host_ptr - scheme_ptr] = '\0';
- host_ptr += 3;
- *port = 0;
- path_ptr = strchr(host_ptr, '/');
- if (NULL == path_ptr) {
- path_ptr = scheme_ptr + (int)strlen(url);
- host_len = path_ptr - host_ptr;
- memcpy(host, host_ptr, host_len);
- host[host_len] = '\0';
- memcpy(path, "/", 1);
- path[1] = '\0';
- return QCLOUD_RET_SUCCESS;
- }
- if (host_len == 0) {
- host_len = path_ptr - host_ptr;
- }
- if (maxhost_len < host_len + 1) {
- Log_e("Host str is too long (host_len(%d) >= max_len(%d))", host_len + 1, maxhost_len);
- return QCLOUD_ERR_HTTP_PARSE;
- }
- memcpy(host, host_ptr, host_len);
- host[host_len] = '\0';
- fragment_ptr = strchr(host_ptr, '#');
- if (fragment_ptr != NULL) {
- path_len = fragment_ptr - path_ptr;
- } else {
- path_len = strlen(path_ptr);
- }
- if (max_path_len < path_len + 1) {
- Log_e("Path str is too small (%d >= %d)", max_path_len, path_len + 1);
- return QCLOUD_ERR_HTTP_PARSE;
- }
- memcpy(path, path_ptr, path_len);
- path[path_len] = '\0';
- return QCLOUD_RET_SUCCESS;
- }
- static int _http_client_parse_host(const char *url, char *host, uint32_t host_max_len)
- {
- const char *host_ptr = (const char *)strstr(url, "://");
- uint32_t host_len = 0;
- char * path_ptr;
- if (host_ptr == NULL) {
- Log_e("Could not find host");
- return QCLOUD_ERR_HTTP_PARSE;
- }
- host_ptr += 3;
- uint32_t pro_len = 0;
- pro_len = host_ptr - url;
- path_ptr = strchr(host_ptr, '/');
- if (path_ptr != NULL)
- host_len = path_ptr - host_ptr;
- else
- host_len = strlen(url) - pro_len;
- if (host_max_len < host_len + 1) {
- Log_e("Host str is too small (%d >= %d)", host_max_len, host_len + 1);
- return QCLOUD_ERR_HTTP_PARSE;
- }
- memcpy(host, host_ptr, host_len);
- host[host_len] = '\0';
- return QCLOUD_RET_SUCCESS;
- }
- static int _http_client_get_info(HTTPClient *client, unsigned char *send_buf, int *send_idx, char *buf, uint32_t len)
- {
- int rc = QCLOUD_RET_SUCCESS;
- int cp_len;
- int idx = *send_idx;
- if (len == 0) {
- len = strlen(buf);
- }
- do {
- if ((HTTP_CLIENT_SEND_BUF_SIZE - idx) >= len) {
- cp_len = len;
- } else {
- cp_len = HTTP_CLIENT_SEND_BUF_SIZE - idx;
- }
- memcpy(send_buf + idx, buf, cp_len);
- idx += cp_len;
- len -= cp_len;
- if (idx == HTTP_CLIENT_SEND_BUF_SIZE) {
- size_t byte_written_len = 0;
- rc = client->network_stack.write(&(client->network_stack), send_buf, HTTP_CLIENT_SEND_BUF_SIZE, 5000,
- &byte_written_len);
- if (byte_written_len) {
- return (byte_written_len);
- }
- }
- } while (len);
- *send_idx = idx;
- return rc;
- }
- static int _http_client_send_auth(HTTPClient *client, unsigned char *send_buf, int *send_idx)
- {
- char b_auth[(int)((HTTP_CLIENT_AUTHB_SIZE + 3) * 4 / 3 + 1)];
- char base64buff[HTTP_CLIENT_AUTHB_SIZE + 3];
- _http_client_get_info(client, send_buf, send_idx, "Authorization: Basic ", 0);
- HAL_Snprintf(base64buff, sizeof(base64buff), "%s:%s", client->auth_user, client->auth_password);
- _http_client_base64enc(b_auth, base64buff);
- b_auth[strlen(b_auth) + 1] = '\0';
- b_auth[strlen(b_auth)] = '\n';
- _http_client_get_info(client, send_buf, send_idx, b_auth, 0);
- return QCLOUD_RET_SUCCESS;
- }
- static int _http_client_send_header(HTTPClient *client, const char *url, HttpMethod method, HTTPClientData *client_data)
- {
- char scheme[8] = {0};
- char host[HTTP_CLIENT_MAX_HOST_LEN] = {0};
- char path[HTTP_CLIENT_MAX_URL_LEN] = {0};
- int len;
- unsigned char send_buf[HTTP_CLIENT_SEND_BUF_SIZE] = {0};
- char buf[HTTP_CLIENT_SEND_BUF_SIZE] = {0};
- char * meth = (method == HTTP_GET)
- ? "GET"
- : (method == HTTP_POST)
- ? "POST"
- : (method == HTTP_PUT)
- ? "PUT"
- : (method == HTTP_DELETE) ? "DELETE" : (method == HTTP_HEAD) ? "HEAD" : "";
- int rc;
- int port;
- int res = _http_client_parse_url(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
- if (res != QCLOUD_RET_SUCCESS) {
- Log_e("httpclient_parse_url returned %d", res);
- return res;
- }
- if (strcmp(scheme, "http") == 0) {
- } else if (strcmp(scheme, "https") == 0) {
- }
- memset(send_buf, 0, HTTP_CLIENT_SEND_BUF_SIZE);
- len = 0;
- HAL_Snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host);
- rc = _http_client_get_info(client, send_buf, &len, buf, strlen(buf));
- if (rc) {
- Log_e("Could not write request");
- return QCLOUD_ERR_HTTP_CONN;
- }
- if (client->auth_user) {
- _http_client_send_auth(client, send_buf, &len);
- }
- if (client->header) {
- _http_client_get_info(client, send_buf, &len, (char *)client->header, strlen(client->header));
- }
- if (client_data->post_buf != NULL) {
- HAL_Snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", client_data->post_buf_len);
- _http_client_get_info(client, send_buf, &len, buf, strlen(buf));
- if (client_data->post_content_type != NULL) {
- HAL_Snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", client_data->post_content_type);
- _http_client_get_info(client, send_buf, &len, buf, strlen(buf));
- }
- }
- _http_client_get_info(client, send_buf, &len, "\r\n", 0);
- // Log_d("REQUEST:\n%s", send_buf);
- size_t written_len = 0;
- rc = client->network_stack.write(&client->network_stack, send_buf, len, 5000, &written_len);
- if (written_len > 0) {
- // Log_d("Written %lu bytes", written_len);
- } else if (written_len == 0) {
- Log_e("written_len == 0,Connection was closed by server");
- return QCLOUD_ERR_HTTP_CLOSED; /* Connection was closed by server */
- } else {
- Log_e("Connection error (send returned %d)", rc);
- return QCLOUD_ERR_HTTP_CONN;
- }
- return QCLOUD_RET_SUCCESS;
- }
- static int _http_client_send_userdata(HTTPClient *client, HTTPClientData *client_data)
- {
- if (client_data->post_buf && client_data->post_buf_len) {
- // Log_d("client_data->post_buf: %s", client_data->post_buf);
- {
- size_t written_len = 0;
- int rc = client->network_stack.write(&client->network_stack, (unsigned char *)client_data->post_buf,
- client_data->post_buf_len, 5000, &written_len);
- if (written_len > 0) {
- // Log_d("Written %d bytes", written_len);
- } else if (written_len == 0) {
- Log_e("written_len == 0,Connection was closed by server");
- return QCLOUD_ERR_HTTP_CLOSED;
- } else {
- Log_e("Connection error (send returned %d)", rc);
- return QCLOUD_ERR_HTTP_CONN;
- }
- }
- }
- return QCLOUD_RET_SUCCESS;
- }
- static int _http_client_recv(HTTPClient *client, char *buf, int min_len, int max_len, int *p_read_len,
- uint32_t timeout_ms, HTTPClientData *client_data)
- {
- IOT_FUNC_ENTRY;
- int rc = 0;
- Timer timer;
- size_t recv_size = 0;
- InitTimer(&timer);
- countdown_ms(&timer, (unsigned int)timeout_ms);
- *p_read_len = 0;
- rc = client->network_stack.read(&client->network_stack, (unsigned char *)buf, max_len, (uint32_t)left_ms(&timer),
- &recv_size);
- *p_read_len = (int)recv_size;
- if (rc == QCLOUD_ERR_SSL_NOTHING_TO_READ || rc == QCLOUD_ERR_TCP_NOTHING_TO_READ) {
- Log_d("HTTP read nothing and timeout");
- rc = QCLOUD_RET_SUCCESS;
- } else if (rc == QCLOUD_ERR_SSL_READ_TIMEOUT || rc == QCLOUD_ERR_TCP_READ_TIMEOUT) {
- if (*p_read_len == client_data->retrieve_len || client_data->retrieve_len == 0)
- rc = QCLOUD_RET_SUCCESS;
- else
- Log_e("network_stack read timeout");
- } else if (rc == QCLOUD_ERR_TCP_PEER_SHUTDOWN && *p_read_len > 0) {
- /* HTTP server give response and close this connection */
- client->network_stack.disconnect(&client->network_stack);
- rc = QCLOUD_RET_SUCCESS;
- } else if (rc != QCLOUD_RET_SUCCESS) {
- Log_e("Connection error rc = %d (recv returned %d)", rc, *p_read_len);
- IOT_FUNC_EXIT_RC(rc);
- }
- IOT_FUNC_EXIT_RC(rc);
- }
- static int _http_client_retrieve_content(HTTPClient *client, char *data, int len, uint32_t timeout_ms,
- HTTPClientData *client_data)
- {
- IOT_FUNC_ENTRY;
- int count = 0;
- int templen = 0;
- int crlf_pos;
- Timer timer;
- InitTimer(&timer);
- countdown_ms(&timer, (unsigned int)timeout_ms);
- client_data->is_more = IOT_TRUE;
- if (client_data->response_content_len == -1 && client_data->is_chunked == IOT_FALSE) {
- while (1) {
- int rc, max_len;
- if (count + len < client_data->response_buf_len - 1) {
- memcpy(client_data->response_buf + count, data, len);
- count += len;
- client_data->response_buf[count] = '\0';
- } else {
- memcpy(client_data->response_buf + count, data, client_data->response_buf_len - 1 - count);
- client_data->response_buf[client_data->response_buf_len - 1] = '\0';
- return HTTP_RETRIEVE_MORE_DATA;
- }
- max_len = HTTP_CLIENT_MIN(HTTP_CLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count);
- rc = _http_client_recv(client, data, 1, max_len, &len, (uint32_t)left_ms(&timer), client_data);
- /* Receive data */
- // Log_d("data len: %d %d", len, count);
- if (rc != QCLOUD_RET_SUCCESS) {
- IOT_FUNC_EXIT_RC(rc);
- }
- if (0 == left_ms(&timer)) {
- Log_e("HTTP read timeout!");
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_TIMEOUT);
- }
- if (len == 0) {
- /* read no more data */
- Log_d("no more data, len == 0");
- client_data->is_more = IOT_FALSE;
- IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
- }
- }
- }
- while (1) {
- uint32_t readLen = 0;
- if (client_data->is_chunked && client_data->retrieve_len <= 0) {
- /* Read chunk header */
- bool foundCrlf;
- int n;
- do {
- foundCrlf = IOT_FALSE;
- crlf_pos = 0;
- data[len] = 0;
- if (len >= 2) {
- for (; crlf_pos < len - 2; crlf_pos++) {
- if (data[crlf_pos] == '\r' && data[crlf_pos + 1] == '\n') {
- foundCrlf = IOT_TRUE;
- break;
- }
- }
- }
- if (!foundCrlf) {
- /* Try to read more */
- if (len < HTTP_CLIENT_CHUNK_SIZE) {
- int new_trf_len, rc;
- rc = _http_client_recv(client, data + len, 0, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len,
- left_ms(&timer), client_data);
- len += new_trf_len;
- if (rc != QCLOUD_RET_SUCCESS) {
- IOT_FUNC_EXIT_RC(rc);
- } else {
- continue;
- }
- } else {
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP);
- }
- }
- } while (!foundCrlf);
- data[crlf_pos] = '\0';
- // n = sscanf(data, "%x", &readLen);/* chunk length */
- readLen = strtoul(data, NULL, 16);
- n = (0 == readLen) ? 0 : 1;
- client_data->retrieve_len = readLen;
- client_data->response_content_len += client_data->retrieve_len;
- if (readLen == 0) {
- client_data->is_more = IOT_FALSE;
- Log_d("no more (last chunk)");
- }
- if (n != 1) {
- Log_e("Could not read chunk length");
- return QCLOUD_ERR_HTTP_UNRESOLVED_DNS;
- }
- memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2));
- len -= (crlf_pos + 2);
- } else {
- readLen = client_data->retrieve_len;
- }
- do {
- templen = HTTP_CLIENT_MIN(len, readLen);
- if (count + templen < client_data->response_buf_len - 1) {
- memcpy(client_data->response_buf + count, data, templen);
- count += templen;
- client_data->response_buf[count] = '\0';
- client_data->retrieve_len -= templen;
- } else {
- memcpy(client_data->response_buf + count, data, client_data->response_buf_len - 1 - count);
- client_data->response_buf[client_data->response_buf_len - 1] = '\0';
- client_data->retrieve_len -= (client_data->response_buf_len - 1 - count);
- IOT_FUNC_EXIT_RC(HTTP_RETRIEVE_MORE_DATA);
- }
- if (len > readLen) {
- Log_d("memmove %d %d %d\n", readLen, len, client_data->retrieve_len);
- memmove(data, &data[readLen], len - readLen); /* chunk case, read between two chunks */
- len -= readLen;
- readLen = 0;
- client_data->retrieve_len = 0;
- } else {
- readLen -= len;
- }
- if (readLen) {
- int rc;
- int max_len = HTTP_CLIENT_MIN(HTTP_CLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count);
- max_len = HTTP_CLIENT_MIN(max_len, readLen);
- rc = _http_client_recv(client, data, 1, max_len, &len, left_ms(&timer), client_data);
- if (rc != QCLOUD_RET_SUCCESS) {
- IOT_FUNC_EXIT_RC(rc);
- }
- if (left_ms(&timer) == 0) {
- Log_e("HTTP read timeout!");
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_TIMEOUT);
- }
- }
- } while (readLen);
- if (client_data->is_chunked) {
- if (len < 2) {
- int new_trf_len, rc;
- /* Read missing chars to find end of chunk */
- rc = _http_client_recv(client, data + len, 2 - len, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len,
- left_ms(&timer), client_data);
- if ((rc != QCLOUD_RET_SUCCESS) || (0 == left_ms(&timer))) {
- IOT_FUNC_EXIT_RC(rc);
- }
- len += new_trf_len;
- }
- if ((data[0] != '\r') || (data[1] != '\n')) {
- Log_e("Format error, %s", data); /* after memmove, the beginning of next chunk */
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_UNRESOLVED_DNS);
- }
- memmove(data, &data[2], len - 2); /* remove the \r\n */
- len -= 2;
- } else {
- // Log_d("no more (content-length)");
- client_data->is_more = IOT_FALSE;
- break;
- }
- }
- IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
- }
- static int _http_client_response_parse(HTTPClient *client, char *data, int len, uint32_t timeout_ms,
- HTTPClientData *client_data)
- {
- IOT_FUNC_ENTRY;
- int crlf_pos;
- Timer timer;
- char *tmp_ptr, *ptr_body_end;
- InitTimer(&timer);
- countdown_ms(&timer, timeout_ms);
- client_data->response_content_len = -1;
- char *crlf_ptr = strstr(data, "\r\n");
- if (crlf_ptr == NULL) {
- Log_e("\\r\\n not found");
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_UNRESOLVED_DNS);
- }
- crlf_pos = crlf_ptr - data;
- data[crlf_pos] = '\0';
- #if 0
- if (sscanf(data, "HTTP/%*d.%*d %d %*[^\r\n]", &(client->response_code)) != 1) {
- Log_e("Not a correct HTTP answer : %s\n", data);
- return QCLOUD_ERR_HTTP_UNRESOLVED_DNS;
- }
- #endif
- client->response_code = atoi(data + 9);
- if ((client->response_code < 200) || (client->response_code >= 400)) {
- Log_w("Response code %d", client->response_code);
- if (client->response_code == 403)
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_AUTH);
- if (client->response_code == 404)
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_NOT_FOUND);
- }
- // Log_d("Reading headers : %s", data);
- // remove null character
- memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2) + 1);
- len -= (crlf_pos + 2);
- client_data->is_chunked = IOT_FALSE;
- if (NULL == (ptr_body_end = strstr(data, "\r\n\r\n"))) {
- int new_trf_len, rc;
- rc = _http_client_recv(client, data + len, 1, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len, left_ms(&timer),
- client_data);
- if (rc != QCLOUD_RET_SUCCESS) {
- IOT_FUNC_EXIT_RC(rc);
- }
- len += new_trf_len;
- data[len] = '\0';
- if (NULL == (ptr_body_end = strstr(data, "\r\n\r\n"))) {
- Log_e("parse error: no end of the request body");
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
- }
- }
- if (NULL != (tmp_ptr = strstr(data, "Content-Length"))) {
- client_data->response_content_len = atoi(tmp_ptr + strlen("Content-Length: "));
- client_data->retrieve_len = client_data->response_content_len;
- } else if (NULL != (tmp_ptr = strstr(data, "Transfer-Encoding"))) {
- int len_chunk = strlen("Chunked");
- char *chunk_value = data + strlen("Transfer-Encoding: ");
- if ((!memcmp(chunk_value, "Chunked", len_chunk)) || (!memcmp(chunk_value, "chunked", len_chunk))) {
- client_data->is_chunked = IOT_TRUE;
- client_data->response_content_len = 0;
- client_data->retrieve_len = 0;
- }
- } else {
- Log_e("Could not parse header");
- IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP);
- }
- len = len - (ptr_body_end + 4 - data);
- memmove(data, ptr_body_end + 4, len + 1);
- int rc = _http_client_retrieve_content(client, data, len, left_ms(&timer), client_data);
- IOT_FUNC_EXIT_RC(rc);
- }
- static int _http_client_connect(HTTPClient *client)
- {
- if (QCLOUD_RET_SUCCESS != client->network_stack.connect(&client->network_stack)) {
- return QCLOUD_ERR_HTTP_CONN;
- }
- return QCLOUD_RET_SUCCESS;
- }
- static int _http_client_send_request(HTTPClient *client, const char *url, HttpMethod method,
- HTTPClientData *client_data)
- {
- int rc;
- rc = _http_client_send_header(client, url, method, client_data);
- if (rc != 0) {
- Log_e("httpclient_send_header is error, rc = %d", rc);
- return rc;
- }
- if (method == HTTP_POST || method == HTTP_PUT) {
- rc = _http_client_send_userdata(client, client_data);
- }
- return rc;
- }
- static int _http_client_recv_response(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data)
- {
- IOT_FUNC_ENTRY;
- int reclen = 0, rc = QCLOUD_ERR_HTTP_CONN;
- char buf[HTTP_CLIENT_CHUNK_SIZE] = {0};
- Timer timer;
- InitTimer(&timer);
- countdown_ms(&timer, timeout_ms);
- if (0 == client->network_stack.handle) {
- Log_e("Connection has not been established");
- IOT_FUNC_EXIT_RC(rc);
- }
- if (client_data->is_more) {
- client_data->response_buf[0] = '\0';
- rc = _http_client_retrieve_content(client, buf, reclen, left_ms(&timer), client_data);
- } else {
- client_data->is_more = IOT_TRUE;
- rc = _http_client_recv(client, buf, 1, HTTP_CLIENT_CHUNK_SIZE - 1, &reclen, left_ms(&timer), client_data);
- if (rc != QCLOUD_RET_SUCCESS) {
- IOT_FUNC_EXIT_RC(rc);
- }
- // else if(0 == left_ms(&timer)){
- // IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_TIMEOUT);
- //}
- buf[reclen] = '\0';
- if (reclen) {
- // HAL_Printf("RESPONSE:\n%s", buf);
- rc = _http_client_response_parse(client, buf, reclen, left_ms(&timer), client_data);
- }
- }
- IOT_FUNC_EXIT_RC(rc);
- }
- static int _http_network_init(unsigned char profile_idx, qcloud_Network *pNetwork, const char *host, int port, const char *ca_crt_dir)
- {
- int rc = QCLOUD_RET_SUCCESS;
- if (pNetwork == NULL) {
- return QCLOUD_ERR_INVAL;
- }
- pNetwork->type = NETWORK_TCP;
- #ifndef AUTH_WITH_NOTLS
- if (ca_crt_dir != NULL) {
- pNetwork->ssl_connect_params.ca_crt = ca_crt_dir;
- pNetwork->ssl_connect_params.ca_crt_len = strlen(pNetwork->ssl_connect_params.ca_crt);
- pNetwork->ssl_connect_params.timeout_ms = 10000;
- pNetwork->type = NETWORK_TLS;
- }
- #endif
- pNetwork->host = host;
- pNetwork->port = port;
- pNetwork->profile_idx = profile_idx;
- rc = network_init(pNetwork);
- return rc;
- }
- int qcloud_http_client_connect(HTTPClient *client, const char *url, int port, const char *ca_crt)
- {
- if (client->network_stack.handle != 0) {
- Log_e("http client has connected to host!");
- return QCLOUD_ERR_HTTP_CONN;
- }
- int rc;
- char host[HTTP_CLIENT_MAX_HOST_LEN] = {0};
- rc = _http_client_parse_host(url, host, sizeof(host));
- if (rc != QCLOUD_RET_SUCCESS)
- return rc;
- rc = _http_network_init(client->profile_idx, &client->network_stack, host, port, ca_crt);
- if (rc != QCLOUD_RET_SUCCESS)
- return rc;
- rc = _http_client_connect(client);
- if (rc != QCLOUD_RET_SUCCESS) {
- Log_e("http_client_connect is error,rc = %d", rc);
- qcloud_http_client_close(client);
- } else {
- /* reduce log print due to frequent log server connect/disconnect */
- if (0 == strcmp(url, LOG_UPLOAD_SERVER_URL))
- UPLOAD_DBG("http client connect success");
- else
- Log_d("http client connect success");
- }
- return rc;
- }
- void qcloud_http_client_close(HTTPClient *client)
- {
- if (client->network_stack.handle != 0) {
- client->network_stack.disconnect(&client->network_stack);
- }
- }
- int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method,
- HTTPClientData *client_data)
- {
- int rc;
- if (client->network_stack.handle == 0) {
- rc = qcloud_http_client_connect(client, url, port, ca_crt);
- if (rc != QCLOUD_RET_SUCCESS)
- return rc;
- }
- rc = _http_client_send_request(client, url, method, client_data);
- if (rc != QCLOUD_RET_SUCCESS) {
- Log_e("http_client_send_request is error,rc = %d", rc);
- qcloud_http_client_close(client);
- return rc;
- }
- return QCLOUD_RET_SUCCESS;
- }
- int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data)
- {
- IOT_FUNC_ENTRY;
- int rc = QCLOUD_RET_SUCCESS;
- Timer timer;
- InitTimer(&timer);
- countdown_ms(&timer, (unsigned int)timeout_ms);
- if ((NULL != client_data->response_buf) && (0 != client_data->response_buf_len)) {
- rc = _http_client_recv_response(client, left_ms(&timer), client_data);
- if (rc < 0) {
- Log_e("http_client_recv_response is error,rc = %d", rc);
- qcloud_http_client_close(client);
- IOT_FUNC_EXIT_RC(rc);
- }
- }
- IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
- }
- #ifdef __cplusplus
- }
- #endif
|