in source/connection.c [980:1115]
int aws_http_client_connect_internal(
const struct aws_http_client_connection_options *orig_options,
aws_http_proxy_request_transform_fn *proxy_request_transform) {
if (!orig_options) {
AWS_LOGF_ERROR(AWS_LS_HTTP_CONNECTION, "static: http connection options are null.");
return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
}
struct aws_http_client_bootstrap *http_bootstrap = NULL;
struct aws_string *host_name = NULL;
int err = 0;
/* make copy of options, and add defaults for missing optional structs */
struct aws_http_client_connection_options options = *orig_options;
if (options.prior_knowledge_http2 && options.tls_options) {
AWS_LOGF_ERROR(AWS_LS_HTTP_CONNECTION, "static: HTTP/2 prior knowledge only works with cleartext TCP.");
return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
}
struct aws_http1_connection_options default_http1_options;
AWS_ZERO_STRUCT(default_http1_options);
if (options.http1_options == NULL) {
options.http1_options = &default_http1_options;
}
struct aws_http2_connection_options default_http2_options;
AWS_ZERO_STRUCT(default_http2_options);
if (options.http2_options == NULL) {
options.http2_options = &default_http2_options;
}
/* validate options */
if (s_validate_http_client_connection_options(&options)) {
goto error;
}
AWS_FATAL_ASSERT(options.proxy_options == NULL);
/* bootstrap_new() functions requires a null-terminated c-str */
host_name = aws_string_new_from_cursor(options.allocator, &options.host_name);
if (!host_name) {
goto error;
}
struct aws_http2_setting *setting_array = NULL;
struct aws_hash_table *alpn_string_map = NULL;
if (!aws_mem_acquire_many(
options.allocator,
3,
&http_bootstrap,
sizeof(struct aws_http_client_bootstrap),
&setting_array,
options.http2_options->num_initial_settings * sizeof(struct aws_http2_setting),
&alpn_string_map,
sizeof(struct aws_hash_table))) {
goto error;
}
AWS_ZERO_STRUCT(*http_bootstrap);
http_bootstrap->alloc = options.allocator;
http_bootstrap->is_using_tls = options.tls_options != NULL;
http_bootstrap->stream_manual_window_management = options.manual_window_management;
http_bootstrap->prior_knowledge_http2 = options.prior_knowledge_http2;
http_bootstrap->initial_window_size = options.initial_window_size;
http_bootstrap->user_data = options.user_data;
http_bootstrap->on_setup = options.on_setup;
http_bootstrap->on_shutdown = options.on_shutdown;
http_bootstrap->proxy_request_transform = proxy_request_transform;
http_bootstrap->http1_options = *options.http1_options;
http_bootstrap->http2_options = *options.http2_options;
/* keep a copy of the settings array if it's not NULL */
if (options.http2_options->num_initial_settings > 0) {
memcpy(
setting_array,
options.http2_options->initial_settings_array,
options.http2_options->num_initial_settings * sizeof(struct aws_http2_setting));
http_bootstrap->http2_options.initial_settings_array = setting_array;
}
if (options.alpn_string_map) {
if (aws_http_alpn_map_init_copy(options.allocator, alpn_string_map, options.alpn_string_map)) {
goto error;
}
http_bootstrap->alpn_string_map = alpn_string_map;
}
if (options.monitoring_options) {
http_bootstrap->monitoring_options = *options.monitoring_options;
}
AWS_LOGF_TRACE(
AWS_LS_HTTP_CONNECTION,
"static: attempting to initialize a new client channel to %s:%d",
aws_string_c_str(host_name),
(int)options.port);
struct aws_socket_channel_bootstrap_options channel_options = {
.bootstrap = options.bootstrap,
.host_name = aws_string_c_str(host_name),
.port = options.port,
.socket_options = options.socket_options,
.tls_options = options.tls_options,
.setup_callback = s_client_bootstrap_on_channel_setup,
.shutdown_callback = s_client_bootstrap_on_channel_shutdown,
.enable_read_back_pressure = options.manual_window_management,
.user_data = http_bootstrap,
};
err = s_system_vtable_ptr->new_socket_channel(&channel_options);
if (err) {
AWS_LOGF_ERROR(
AWS_LS_HTTP_CONNECTION,
"static: Failed to initiate socket channel for new client connection, error %d (%s).",
aws_last_error(),
aws_error_name(aws_last_error()));
goto error;
}
aws_string_destroy(host_name);
return AWS_OP_SUCCESS;
error:
if (http_bootstrap) {
aws_http_client_bootstrap_destroy(http_bootstrap);
}
if (host_name) {
aws_string_destroy(host_name);
}
return AWS_OP_ERR;
}