15 static const char crlf[] =
"\r\n";
26 #define TLS_DEFAULT_PORT 443 27 #define HTTP_CALLBACK_BUFFER_SIZE 1024 28 #define HTTP_PARSE_BUFFER_SIZE 2048 29 #define SIZE_OF_STRING(x) (sizeof(x) - MCL_NULL_CHAR_SIZE) 31 #define TO_STRING_HELPER(x) (#x) 32 #define TO_STRING(x) TO_STRING_HELPER(x) 34 #define PORT_STRING_BUFFER_SIZE 6 35 #define CRLF_SIZE (sizeof(crlf) - MCL_NULL_CHAR_SIZE) 36 #define HTTPS_PREFIX_SIZE (sizeof(https_prefix) - MCL_NULL_CHAR_SIZE) 37 #define GET_STRING_SIZE (sizeof(get_string) - MCL_NULL_CHAR_SIZE) 38 #define PUT_STRING_SIZE (sizeof(put_string) - MCL_NULL_CHAR_SIZE) 39 #define POST_STRING_SIZE (sizeof(post_string) - MCL_NULL_CHAR_SIZE) 40 #define HTTP_STRING_SIZE (sizeof(http_string) - MCL_NULL_CHAR_SIZE) 41 #define CONTENT_LENGTH_BUFFER_SIZE (sizeof(TO_STRING(SIZE_MAX))) 42 #define CONTENT_LENGTH_SIZE (sizeof(content_length_header) - MCL_NULL_CHAR_SIZE) 43 #define TRANSFER_ENCODING_SIZE (sizeof(transfer_encoding_header) - MCL_NULL_CHAR_SIZE) 44 #define CHUNK_LENGTH_IN_HEX_BUFFER_SIZE (sizeof(TO_STRING(HTTP_CALLBACK_BUFFER_SIZE)) + CRLF_SIZE) 54 static mcl_error_t send_header(mcl_tls_socket_handle tls_socket,
const char *header_name,
const char *header_value);
62 MCL_DEBUG_ENTRY(
"mcl_http_client_configuration_t *configuration = <%p>, mcl_http_client_t **http_client = <%p>", configuration, http_client);
86 (*http_client)->user_agent = configuration->
user_agent;
88 (*http_client)->port = configuration->
port;
113 MCL_DEBUG_ENTRY(
"mcl_http_client_t *http_client = <%p>, const char *certificate = <%p>, mcl_bool_t certificate_is_file = <%u>", http_client, certificate, is_file);
128 mcl_tls_socket_handle tls_socket;
172 code =
start_http(tls_socket, http_client, http_request);
241 MCL_DEBUG_ENTRY(
"mcl_http_client_t **http_client = <%p>", http_client);
259 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, mcl_http_client_t *http_client = <%p>, mcl_http_request_t *http_request = <%p>", tls_socket, http_client, http_request);
263 for (hostname_length = 0; hostname_length < uri_length; ++hostname_length)
290 switch(http_request->
method)
327 code =
send_buffer(tls_socket, hostname, hostname_length);
363 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, mcl_list_t *header_list = <%p>", tls_socket, header_list);
367 for (index = 0; (
MCL_OK == code) && (index < header_list->count); ++index)
375 const char *header = (
const char *) header_node->
data;
394 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, const char *header_name = <%p>, const char *header_value = <%p>", tls_socket, header_name, header_value);
422 MCL_VERBOSE_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, const void *buffer = <%p>, mcl_size_t size = <%lu>", tls_socket, buffer, (
long unsigned) size);
424 while ((
MCL_OK == code) && (size > sent_already))
426 mcl_size_t in_requested_out_sent = size - sent_already;
430 sent_already += in_requested_out_sent;
443 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, mcl_http_payload_callback callback = <%p>, void *stream_data = <%p>, mcl_size_t payload_size = <%lu>", tls_socket, callback, stream_data, payload_size);
455 MCL_ERROR_STRING(
"HTTP payload callback cannot return greater value than HTTP_CALLBACK_BUFFER_SIZE.");
458 else if (
MCL_TRUE == using_transfer_encoding)
470 else if (size > remaining_size)
477 remaining_size -= size;
480 if ((
MCL_OK == code) && (0 != size))
482 code =
send_buffer(tls_socket, callback_buffer, size);
491 }
while((
MCL_OK == code) && (0 != size));
493 if ((
MCL_OK == code) && (0 != remaining_size))
515 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, mcl_http_response_t **http_response = <%p>", tls_socket, http_response);
519 code =
receive_until_lf(tls_socket, parse_buffer, &in_requested_out_received);
525 if (1 == sscanf(parse_buffer,
"HTTP/1.1 %u", &status))
545 code =
receive_until_lf(tls_socket, parse_buffer, &in_requested_out_received);
547 if (
CRLF_SIZE >= in_requested_out_received)
576 if (1 == sscanf(parse_buffer,
"Content-Length: %lu", (
unsigned long *) &body_size))
579 MCL_DEBUG(
"Received Content-Length header: %lu.", (
unsigned long *) body_size);
591 if (
MCL_TRUE == using_transfer_encoding)
595 else if (
MCL_TRUE == found_content_length)
630 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, char **response_body = <%p>, mcl_size_t *body_size = <%p>", tls_socket, response_body, body_size);
638 code =
receive_until_lf(tls_socket, chunk_string, &in_requested_out_received);
642 if (1 == sscanf(chunk_string,
"%x\r\n", (
unsigned int *) &chunk_size))
644 MCL_DEBUG(
"Chunk size: %lu.", (
unsigned long) chunk_size);
653 if ((
MCL_OK == code) && (0 != chunk_size))
661 *response_body =
MCL_RESIZE(*response_body, *body_size + chunk_size);
673 *body_size += chunk_size;
700 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, char **response_body = <%p>, mcl_size_t body_size = <%lu>", tls_socket, response_body, (
long unsigned) body_size);
727 MCL_VERBOSE_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, void *buffer = <%p>, mcl_size_t size = <%lu>", tls_socket, buffer, (
long unsigned) size);
729 while ((
MCL_OK == code) && (size > received_already))
731 mcl_size_t in_requested_out_received = size - received_already;
735 received_already += in_requested_out_received;
748 MCL_DEBUG_ENTRY(
"mcl_tls_socket_handle tls_socket = <%p>, void *buffer = <%p>, mcl_size_t *size = <%p>", tls_socket, buffer, size);
759 ((
char *) buffer)[*size] = received_char;
762 if (
'\n' == received_char)
static mcl_error_t receive_until_lf(mcl_tls_socket_handle tls_socket, void *buffer, mcl_size_t *size)
#define MCL_FUNCTION_LEAVE_LABEL
static void header_list_destroy_callback(void **item)
mcl_error_t mcl_tls_socket_send(mcl_tls_socket_handle tls_socket_handle, const mcl_uint8_t *buffer, mcl_size_t *size)
char * uri
Uri of http request.
void mcl_http_client_destroy(mcl_http_client_t **http_client)
Received parameter is null.
#define HTTP_PARSE_BUFFER_SIZE
mcl_error_t mcl_http_client_initialize(mcl_http_client_configuration_t *configuration, mcl_http_client_t **http_client)
MCL_CORE_EXPORT mcl_error_t mcl_http_response_initialize(mcl_list_t *header, mcl_uint8_t *payload, mcl_size_t payload_size, E_MCL_HTTP_STATUS_CODE status_code, mcl_http_response_t **http_response)
static const char content_length_header[]
static const char get_string[]
#define MCL_DEBUG_ENTRY(...)
mcl_tls_ca_chain_handle certificate_chain
mcl_size_t payload_size
Payload size of http request.
void * stream_data
Stream data.
static const char http_string[]
mcl_error_t mcl_http_client_add_certificate(mcl_http_client_t *http_client, const char *certificate, mcl_bool_t is_file)
const char * user_agent
User agent.
Requested operation is not supported.
MCL_CORE_EXPORT mcl_size_t mcl_string_util_strlen(const char *buffer)
MCL_CORE_EXPORT mcl_error_t mcl_list_next(mcl_list_t *list, mcl_list_node_t **node)
static mcl_error_t send_with_callback(mcl_tls_socket_handle tls_socket, mcl_http_payload_callback callback, void *stream_data, mcl_size_t payload_size)
#define MCL_ERROR_STRING(string)
mcl_bool_t certificate_is_file
Flag to check if certificate is given as file or string.
List module interface header file.
static mcl_error_t send_header_list(mcl_tls_socket_handle tls_socket, mcl_list_t *header_list)
#define TRANSFER_ENCODING_SIZE
#define MCL_VERBOSE_LEAVE(...)
static mcl_error_t receive_to_buffer(mcl_tls_socket_handle tls_socket, void *buffer, mcl_size_t size)
mcl_error_t mcl_tls_socket_connect(mcl_tls_socket_handle tls_socket_handle, const char *host, mcl_uint16_t port)
static mcl_error_t send_buffer(mcl_tls_socket_handle tls_socket, const void *buffer, mcl_size_t size)
const char * certificate
Certificate. If it is NULL, default CA certificate store will be used (if available).
MCL_CORE_EXPORT mcl_error_t mcl_list_add(mcl_list_t *list, void *data)
mcl_error_t mcl_tls_ca_chain_add_certificate(mcl_tls_ca_chain_handle tls_ca_chain_handle, const char *certificate, mcl_bool_t is_file)
static mcl_error_t get_chunked_response(mcl_tls_socket_handle tls_socket, char **response_body, mcl_size_t *body_size)
mcl_error_t mcl_tls_socket_set_parameter(mcl_tls_socket_handle tls_socket_handle, E_MCL_TLS_SOCKET_PARAMETER parameter, const void *value)
#define CHUNK_LENGTH_IN_HEX_BUFFER_SIZE
#define MCL_RESIZE(p, bytes)
E_MCL_HTTP_METHOD method
Http method of http request.
MCL_CORE_EXPORT void mcl_list_destroy_with_content(mcl_list_t **list, mcl_list_item_destroy_callback callback)
static mcl_error_t start_http(mcl_tls_socket_handle tls_socket, mcl_http_client_t *http_client, mcl_http_request_t *request)
#define MCL_ASSERT_NOT_NULL(argument, return_variable)
#define HTTP_CALLBACK_BUFFER_SIZE
MCL_CORE_EXPORT void mcl_string_util_memcpy(void *destination, const void *source, mcl_size_t count)
mcl_error_t mcl_http_client_send(mcl_http_client_t *http_client, mcl_http_request_t *http_request, mcl_http_response_t **http_response)
mcl_error_t mcl_tls_ca_chain_init(mcl_tls_ca_chain_handle *tls_ca_chain_handle)
static const char https_prefix[]
MCL_CORE_EXPORT mcl_bool_t mcl_string_util_find_case_insensitive(const char *source, const char *target, mcl_size_t *start_index)
MCL_CORE_EXPORT mcl_error_t mcl_string_util_snprintf(char *string, mcl_size_t length, const char *format,...)
MCL_CORE_EXPORT void mcl_list_reset(mcl_list_t *list)
mcl_error_t mcl_tls_socket_receive(mcl_tls_socket_handle tls_socket_handle, mcl_uint8_t *buffer, mcl_size_t *size)
mcl_uint32_t http_request_timeout
Timeout value (in seconds) for HTTP requests. Default timeout is 300 seconds.
static mcl_error_t send_header(mcl_tls_socket_handle tls_socket, const char *header_name, const char *header_value)
#define PORT_STRING_BUFFER_SIZE
static mcl_error_t get_response(mcl_tls_socket_handle tls_socket, mcl_http_response_t **http_response)
mcl_size_t(* mcl_http_payload_callback)(char *buffer, mcl_size_t size, mcl_size_t count, void *user_context)
mcl_http_payload_callback stream_callback
Callback to be used with chunked Transfer-Encoding. If not used, it must be NULL. ...
mcl_uint16_t port
Port number.
String utility module interface header file.
mcl_uint8_t * payload
Payload of http request.
void mcl_tls_ca_chain_destroy(mcl_tls_ca_chain_handle *tls_ca_chain_handle)
#define CONTENT_LENGTH_BUFFER_SIZE
static mcl_error_t get_content_length_response(mcl_tls_socket_handle tls_socket, char **response_body, mcl_size_t body_size)
static const char transfer_encoding_header[]
Basic HTTP client module header file.
MCL_CORE_EXPORT mcl_error_t mcl_list_initialize(mcl_list_t **list)
#define MCL_NULL_CHAR_SIZE
#define MCL_MALLOC(bytes)
mcl_error_t mcl_tls_socket_open(mcl_tls_socket_handle tls_socket_handle)
static const char put_string[]
General invalid parameter fail.
const char * proxy_hostname
Proxy hostname. Optional.
void mcl_tls_socket_destroy(mcl_tls_socket_handle *tls_socket_handle)
#define MCL_DEBUG_LEAVE(...)
#define SIZE_OF_STRING(x)
#define MCL_VERBOSE_ENTRY(...)
mcl_list_t * header
Header of http request.
mcl_error_t mcl_tls_socket_init(mcl_tls_socket_handle *tls_socket_handle)
void * data
Data of the node.
MCL_CORE_EXPORT mcl_error_t mcl_string_util_strncmp(const char *string_1, const char *string_2, mcl_size_t count)
#define HTTPS_PREFIX_SIZE
static const char post_string[]
Memory module interface header file.