in source/channel_bootstrap.c [725:877]
int aws_client_bootstrap_new_socket_channel(struct aws_socket_channel_bootstrap_options *options) {
struct aws_client_bootstrap *bootstrap = options->bootstrap;
AWS_FATAL_ASSERT(options->setup_callback);
AWS_FATAL_ASSERT(options->shutdown_callback);
AWS_FATAL_ASSERT(bootstrap);
const struct aws_socket_options *socket_options = options->socket_options;
AWS_FATAL_ASSERT(socket_options != NULL);
const struct aws_tls_connection_options *tls_options = options->tls_options;
AWS_FATAL_ASSERT(tls_options == NULL || socket_options->type == AWS_SOCKET_STREAM);
aws_io_fatal_assert_library_initialized();
if (options->requested_event_loop != NULL) {
/* If we're asking for a specific event loop, verify it belongs to the bootstrap's event loop group */
if (!(s_does_event_loop_belong_to_event_loop_group(
options->requested_event_loop, bootstrap->event_loop_group))) {
return aws_raise_error(AWS_ERROR_IO_PINNED_EVENT_LOOP_MISMATCH);
}
}
struct client_connection_args *client_connection_args =
aws_mem_calloc(bootstrap->allocator, 1, sizeof(struct client_connection_args));
if (!client_connection_args) {
return AWS_OP_ERR;
}
const char *host_name = options->host_name;
uint16_t port = options->port;
AWS_LOGF_TRACE(
AWS_LS_IO_CHANNEL_BOOTSTRAP,
"id=%p: attempting to initialize a new client channel to %s:%d",
(void *)bootstrap,
host_name,
(int)port);
aws_ref_count_init(
&client_connection_args->ref_count,
client_connection_args,
(aws_simple_completion_callback *)s_client_connection_args_destroy);
client_connection_args->user_data = options->user_data;
client_connection_args->bootstrap = aws_client_bootstrap_acquire(bootstrap);
client_connection_args->creation_callback = options->creation_callback;
client_connection_args->setup_callback = options->setup_callback;
client_connection_args->shutdown_callback = options->shutdown_callback;
client_connection_args->outgoing_options = *socket_options;
client_connection_args->outgoing_port = port;
client_connection_args->enable_read_back_pressure = options->enable_read_back_pressure;
client_connection_args->requested_event_loop = options->requested_event_loop;
if (tls_options) {
if (aws_tls_connection_options_copy(&client_connection_args->channel_data.tls_options, tls_options)) {
goto error;
}
client_connection_args->channel_data.use_tls = true;
client_connection_args->channel_data.on_protocol_negotiated = bootstrap->on_protocol_negotiated;
client_connection_args->channel_data.tls_user_data = tls_options->user_data;
/* in order to honor any callbacks a user may have installed on their tls_connection_options,
* we need to wrap them if they were set.*/
if (bootstrap->on_protocol_negotiated) {
client_connection_args->channel_data.tls_options.advertise_alpn_message = true;
}
if (tls_options->on_data_read) {
client_connection_args->channel_data.user_on_data_read = tls_options->on_data_read;
client_connection_args->channel_data.tls_options.on_data_read = s_tls_client_on_data_read;
}
if (tls_options->on_error) {
client_connection_args->channel_data.user_on_error = tls_options->on_error;
client_connection_args->channel_data.tls_options.on_error = s_tls_client_on_error;
}
if (tls_options->on_negotiation_result) {
client_connection_args->channel_data.user_on_negotiation_result = tls_options->on_negotiation_result;
}
client_connection_args->channel_data.tls_options.on_negotiation_result = s_tls_client_on_negotiation_result;
client_connection_args->channel_data.tls_options.user_data = client_connection_args;
}
if (s_aws_socket_domain_uses_dns(socket_options->domain)) {
client_connection_args->host_name = aws_string_new_from_c_str(bootstrap->allocator, host_name);
if (!client_connection_args->host_name) {
goto error;
}
if (aws_host_resolver_resolve_host(
bootstrap->host_resolver,
client_connection_args->host_name,
s_on_host_resolved,
&bootstrap->host_resolver_config,
client_connection_args)) {
goto error;
}
} else {
/* ensure that the pipe/domain socket name will fit in the endpoint address */
const size_t host_name_len = strlen(host_name);
if (host_name_len >= AWS_ADDRESS_MAX_LEN) {
aws_raise_error(AWS_IO_SOCKET_INVALID_ADDRESS);
goto error;
}
struct aws_socket_endpoint endpoint;
AWS_ZERO_STRUCT(endpoint);
memcpy(endpoint.address, host_name, host_name_len);
if (socket_options->domain == AWS_SOCKET_VSOCK) {
endpoint.port = port;
} else {
endpoint.port = 0;
}
struct aws_socket *outgoing_socket = aws_mem_acquire(bootstrap->allocator, sizeof(struct aws_socket));
if (!outgoing_socket) {
goto error;
}
if (aws_socket_init(outgoing_socket, bootstrap->allocator, socket_options)) {
aws_mem_release(bootstrap->allocator, outgoing_socket);
goto error;
}
client_connection_args->addresses_count = 1;
struct aws_event_loop *connect_loop = s_get_connection_event_loop(client_connection_args);
s_client_connection_args_acquire(client_connection_args);
if (aws_socket_connect(
outgoing_socket, &endpoint, connect_loop, s_on_client_connection_established, client_connection_args)) {
aws_socket_clean_up(outgoing_socket);
aws_mem_release(client_connection_args->bootstrap->allocator, outgoing_socket);
s_client_connection_args_release(client_connection_args);
goto error;
}
}
return AWS_OP_SUCCESS;
error:
if (client_connection_args) {
/* tls opt will also be freed when we clean up the connection arg */
s_client_connection_args_release(client_connection_args);
}
return AWS_OP_ERR;
}