Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions include/aws/io/channel_bootstrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ struct aws_tls_connection_options;

struct aws_event_loop_group;

/**
* Called after client bootstrap has been completely cleaned up, after its last refcount is released.
*/
typedef void aws_client_bootstrap_shutdown_complete_fn(void *user_data);

/**
* aws_client_bootstrap handles creation and setup of channels that communicate via socket with a specific endpoint.
*/
Expand All @@ -78,6 +83,31 @@ struct aws_client_bootstrap {
struct aws_host_resolution_config host_resolver_config;
aws_channel_on_protocol_negotiated_fn *on_protocol_negotiated;
struct aws_atomic_var ref_count;
aws_client_bootstrap_shutdown_complete_fn *on_shutdown_complete;
void *user_data;
};

/**
* aws_client_bootstrap creation options.
*/
struct aws_client_bootstrap_options {

/* Required. Must outlive the client bootstrap. */
struct aws_event_loop_group *event_loop_group;

/* Required. Must outlive the client bootstrap. */
struct aws_host_resolver *host_resolver;

/* Optional. If none is provided then default settings are used.
* This object is deep-copied by bootstrap.
* */
struct aws_host_resolution_config *host_resolution_config;

/* Optional. If provided, callback is invoked when client bootstrap has completely shut down. */
aws_client_bootstrap_shutdown_complete_fn *on_shutdown_complete;

/* Optional. Passed to callbacks */
void *user_data;
};

struct aws_server_bootstrap;
Expand Down Expand Up @@ -140,15 +170,11 @@ struct aws_server_bootstrap {
AWS_EXTERN_C_BEGIN

/**
* Initializes the client bootstrap with `allocator` and `el_group`. This object manages client connections and
* channels. host_resolver will be used for resolving host names.
* If host_resolution_config is NULL, the default will be used, host_resolution_config will be copied.
* Create the client bootstrap.
*/
AWS_IO_API struct aws_client_bootstrap *aws_client_bootstrap_new(
struct aws_allocator *allocator,
struct aws_event_loop_group *el_group,
struct aws_host_resolver *host_resolver,
struct aws_host_resolution_config *host_resolution_config);
const struct aws_client_bootstrap_options *options);

/**
* Cleans up the bootstrap's resources. Does not clean up any of your channels. You must shutdown your channels before
Expand Down
31 changes: 21 additions & 10 deletions source/channel_bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@
void s_client_bootstrap_destroy_impl(struct aws_client_bootstrap *bootstrap) {
AWS_ASSERT(bootstrap);
AWS_LOGF_DEBUG(AWS_LS_IO_CHANNEL_BOOTSTRAP, "id=%p: destroying", (void *)bootstrap);
aws_client_bootstrap_shutdown_complete_fn *on_shutdown_complete = bootstrap->on_shutdown_complete;
void *user_data = bootstrap->user_data;
aws_mem_release(bootstrap->allocator, bootstrap);

if (on_shutdown_complete) {
on_shutdown_complete(user_data);
}
}

void s_client_bootstrap_acquire(struct aws_client_bootstrap *bootstrap) {
Expand All @@ -54,12 +60,11 @@ void s_client_bootstrap_release(struct aws_client_bootstrap *bootstrap) {

struct aws_client_bootstrap *aws_client_bootstrap_new(
struct aws_allocator *allocator,
struct aws_event_loop_group *el_group,
struct aws_host_resolver *host_resolver,
struct aws_host_resolution_config *host_resolution_config) {
const struct aws_client_bootstrap_options *options) {
AWS_ASSERT(allocator);
AWS_ASSERT(el_group);
AWS_ASSERT(host_resolver);
AWS_ASSERT(options);
AWS_ASSERT(options->event_loop_group);
AWS_ASSERT(options->host_resolver);

struct aws_client_bootstrap *bootstrap = aws_mem_calloc(allocator, 1, sizeof(struct aws_client_bootstrap));
if (!bootstrap) {
Expand All @@ -70,16 +75,18 @@ struct aws_client_bootstrap *aws_client_bootstrap_new(
AWS_LS_IO_CHANNEL_BOOTSTRAP,
"id=%p: Initializing client bootstrap with event-loop group %p",
(void *)bootstrap,
(void *)el_group);
(void *)options->event_loop_group);

bootstrap->allocator = allocator;
bootstrap->event_loop_group = el_group;
bootstrap->event_loop_group = options->event_loop_group;
bootstrap->on_protocol_negotiated = NULL;
aws_atomic_init_int(&bootstrap->ref_count, 1);
bootstrap->host_resolver = host_resolver;
bootstrap->host_resolver = options->host_resolver;
bootstrap->on_shutdown_complete = options->on_shutdown_complete;
bootstrap->user_data = options->user_data;

if (host_resolution_config) {
bootstrap->host_resolver_config = *host_resolution_config;
if (options->host_resolution_config) {
bootstrap->host_resolver_config = *options->host_resolution_config;
} else {
bootstrap->host_resolver_config = (struct aws_host_resolution_config){
.impl = aws_default_dns_resolve,
Expand All @@ -102,6 +109,10 @@ int aws_client_bootstrap_set_alpn_callback(
}

void aws_client_bootstrap_release(struct aws_client_bootstrap *bootstrap) {
if (!bootstrap) {
return;
}

AWS_LOGF_DEBUG(AWS_LS_IO_CHANNEL_BOOTSTRAP, "id=%p: releasing bootstrap reference", (void *)bootstrap);
s_client_bootstrap_release(bootstrap);
}
Expand Down
9 changes: 7 additions & 2 deletions tests/channel_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,8 +914,13 @@ static int s_test_channel_connect_some_hosts_timeout(struct aws_allocator *alloc
struct aws_host_resolver resolver;
ASSERT_SUCCESS(aws_host_resolver_init_default(&resolver, allocator, 8, &event_loop_group));

struct aws_client_bootstrap *bootstrap =
aws_client_bootstrap_new(allocator, &event_loop_group, &resolver, &mock_resolver_config);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &event_loop_group,
.host_resolver = &resolver,
.host_resolution_config = &mock_resolver_config,
};

struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
ASSERT_NOT_NULL(bootstrap);

struct aws_socket_options options;
Expand Down
14 changes: 10 additions & 4 deletions tests/socket_handler_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,11 @@ static int s_socket_echo_and_backpressure_test(struct aws_allocator *allocator,
/* this should never get used for this case. */
struct aws_host_resolver dummy_resolver;
AWS_ZERO_STRUCT(dummy_resolver);
struct aws_client_bootstrap *client_bootstrap =
aws_client_bootstrap_new(allocator, &c_tester.el_group, &dummy_resolver, NULL);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &c_tester.el_group,
.host_resolver = &dummy_resolver,
};
struct aws_client_bootstrap *client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
ASSERT_NOT_NULL(client_bootstrap);

ASSERT_SUCCESS(aws_mutex_lock(&c_tester.mutex));
Expand Down Expand Up @@ -480,8 +483,11 @@ static int s_socket_close_test(struct aws_allocator *allocator, void *ctx) {
/* this should not get used for a unix domain socket. */
struct aws_host_resolver dummy_resolver;
AWS_ZERO_STRUCT(dummy_resolver);
struct aws_client_bootstrap *client_bootstrap =
aws_client_bootstrap_new(allocator, &c_tester.el_group, &dummy_resolver, NULL);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &c_tester.el_group,
.host_resolver = &dummy_resolver,
};
struct aws_client_bootstrap *client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
ASSERT_NOT_NULL(client_bootstrap);

ASSERT_SUCCESS(aws_mutex_lock(&c_tester.mutex));
Expand Down
35 changes: 25 additions & 10 deletions tests/tls_handler_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,11 @@ static int s_tls_channel_echo_and_backpressure_test_fn(struct aws_allocator *all
aws_tls_connection_options_set_callbacks(
&client_tls_opt_tester.opt, s_tls_on_negotiated, NULL, NULL, &outgoing_args);

struct aws_client_bootstrap *client_bootstrap =
aws_client_bootstrap_new(allocator, &c_tester.el_group, &c_tester.resolver, NULL);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &c_tester.el_group,
.host_resolver = &c_tester.resolver,
};
struct aws_client_bootstrap *client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);

ASSERT_SUCCESS(aws_mutex_lock(&c_tester.mutex));

Expand Down Expand Up @@ -604,8 +607,11 @@ static int s_verify_negotiation_fails(struct aws_allocator *allocator, const str

aws_mutex_lock(&c_tester.mutex);

struct aws_client_bootstrap *client_bootstrap =
aws_client_bootstrap_new(allocator, &c_tester.el_group, &c_tester.resolver, NULL);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &c_tester.el_group,
.host_resolver = &c_tester.resolver,
};
struct aws_client_bootstrap *client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
ASSERT_NOT_NULL(client_bootstrap);

ASSERT_SUCCESS(aws_client_bootstrap_new_tls_socket_channel(
Expand Down Expand Up @@ -745,8 +751,11 @@ static int s_tls_client_channel_negotiation_error_socket_closed_fn(struct aws_al

aws_mutex_lock(&c_tester.mutex);

struct aws_client_bootstrap *client_bootstrap =
aws_client_bootstrap_new(allocator, &c_tester.el_group, &c_tester.resolver, NULL);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &c_tester.el_group,
.host_resolver = &c_tester.resolver,
};
struct aws_client_bootstrap *client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
ASSERT_NOT_NULL(client_bootstrap);

ASSERT_SUCCESS(aws_client_bootstrap_new_tls_socket_channel(
Expand Down Expand Up @@ -824,8 +833,11 @@ static int s_verify_good_host(struct aws_allocator *allocator, const struct aws_

aws_mutex_lock(&c_tester.mutex);

struct aws_client_bootstrap *client_bootstrap =
aws_client_bootstrap_new(allocator, &c_tester.el_group, &c_tester.resolver, NULL);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &c_tester.el_group,
.host_resolver = &c_tester.resolver,
};
struct aws_client_bootstrap *client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
ASSERT_NOT_NULL(client_bootstrap);

ASSERT_SUCCESS(aws_client_bootstrap_new_tls_socket_channel(
Expand Down Expand Up @@ -918,8 +930,11 @@ static int s_tls_server_multiple_connections_fn(struct aws_allocator *allocator,
aws_tls_connection_options_set_callbacks(
&client_tls_opt_tester.opt, s_tls_on_negotiated, NULL, NULL, &outgoing_args);

struct aws_client_bootstrap *client_bootstrap =
aws_client_bootstrap_new(allocator, &c_tester.el_group, &c_tester.resolver, NULL);
struct aws_client_bootstrap_options bootstrap_options = {
.event_loop_group = &c_tester.el_group,
.host_resolver = &c_tester.resolver,
};
struct aws_client_bootstrap *client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);

ASSERT_SUCCESS(aws_mutex_lock(&c_tester.mutex));

Expand Down