Skip to content

Commit

Permalink
API to query http server listener endpoint (#463)
Browse files Browse the repository at this point in the history
Co-authored-by: Bret Ambrose <[email protected]>
  • Loading branch information
bretambrose and Bret Ambrose authored Feb 13, 2024
1 parent 425e5da commit 98ec73a
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
6 changes: 6 additions & 0 deletions include/aws/http/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ int aws_http_connection_configure_server(
AWS_HTTP_API
bool aws_http_connection_is_server(const struct aws_http_connection *connection);

/**
* Returns the local listener endpoint of the HTTP server. Only valid as long as the server remains valid.
*/
AWS_HTTP_API
const struct aws_socket_endpoint *aws_http_server_get_listener_endpoint(const struct aws_http_server *server);

AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL

Expand Down
6 changes: 6 additions & 0 deletions source/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,12 @@ void aws_http_server_release(struct aws_http_server *server) {
* clean up will be called from eventloop */
}

const struct aws_socket_endpoint *aws_http_server_get_listener_endpoint(const struct aws_http_server *server) {
AWS_FATAL_ASSERT(server);

return &server->socket->local_endpoint;
}

/* At this point, the channel bootstrapper has established a connection to the server and set up a channel.
* Now we need to create the aws_http_connection and insert it into the channel as a channel-handler. */
static void s_client_bootstrap_on_channel_setup(
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ add_test_case(h2_client_manual_data_write_no_data)
add_test_case(h2_client_manual_data_write_connection_close)

add_test_case(server_new_destroy)
add_test_case(server_new_destroy_tcp)
add_test_case(connection_setup_shutdown)
add_test_case(connection_setup_shutdown_tls)
add_test_case(connection_setup_shutdown_proxy_setting_on_ev_not_found)
Expand Down
40 changes: 32 additions & 8 deletions tests/test_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct tester_options {
char *client_alpn_list;
bool no_connection; /* don't connect server to client */
bool pin_event_loop;
bool use_tcp; /* otherwise uses domain sockets */
};

/* Singleton used by tests in this file */
Expand Down Expand Up @@ -336,22 +337,23 @@ static int s_tester_init(struct tester *tester, const struct tester_options *opt

struct aws_socket_options socket_options = {
.type = AWS_SOCKET_STREAM,
.domain = AWS_SOCKET_LOCAL,
.domain = options->use_tcp ? AWS_SOCKET_IPV4 : AWS_SOCKET_LOCAL,
.connect_timeout_ms =
(uint32_t)aws_timestamp_convert(TESTER_TIMEOUT_SEC, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_MILLIS, NULL),
};
tester->socket_options = socket_options;
/* Generate random address for endpoint */
struct aws_uuid uuid;
ASSERT_SUCCESS(aws_uuid_init(&uuid));
char uuid_str[AWS_UUID_STR_LEN];
struct aws_byte_buf uuid_buf = aws_byte_buf_from_empty_array(uuid_str, sizeof(uuid_str));
ASSERT_SUCCESS(aws_uuid_to_str(&uuid, &uuid_buf));

struct aws_socket_endpoint endpoint;
AWS_ZERO_STRUCT(endpoint);

snprintf(endpoint.address, sizeof(endpoint.address), LOCAL_SOCK_TEST_FORMAT, uuid_str);
if (options->use_tcp) {
snprintf(endpoint.address, sizeof(endpoint.address), "127.0.0.1");
} else {
aws_socket_endpoint_init_local_address_for_test(&endpoint);
}

tester->endpoint = endpoint;

/* Create server (listening socket) */
struct aws_http_server_options server_options = AWS_HTTP_SERVER_OPTIONS_INIT;
server_options.allocator = tester->alloc;
Expand All @@ -370,6 +372,14 @@ static int s_tester_init(struct tester *tester, const struct tester_options *opt
tester->server = aws_http_server_new(&server_options);
ASSERT_NOT_NULL(tester->server);

/*
* localhost server binds to any port, so let's get the final listener endpoint whether or not we're making
* connections to it.
*/
if (options->use_tcp) {
tester->endpoint = *aws_http_server_get_listener_endpoint(tester->server);
}

/* If test doesn't need a connection, we're done setting up. */
if (options->no_connection) {
return AWS_OP_SUCCESS;
Expand Down Expand Up @@ -448,6 +458,20 @@ static int s_test_server_new_destroy(struct aws_allocator *allocator, void *ctx)
}
AWS_TEST_CASE(server_new_destroy, s_test_server_new_destroy);

static int s_test_server_new_destroy_tcp(struct aws_allocator *allocator, void *ctx) {
(void)ctx;
struct tester_options options = {.alloc = allocator, .no_connection = true, .use_tcp = true};
struct tester tester;
ASSERT_SUCCESS(s_tester_init(&tester, &options));

const struct aws_socket_endpoint *listener_endpoint = aws_http_server_get_listener_endpoint(tester.server);
ASSERT_TRUE(listener_endpoint->port > 0);

ASSERT_SUCCESS(s_tester_clean_up(&tester));
return AWS_OP_SUCCESS;
}
AWS_TEST_CASE(server_new_destroy_tcp, s_test_server_new_destroy_tcp);

void release_all_client_connections(struct tester *tester) {
for (int i = 0; i < tester->client_connection_num; i++) {
aws_http_connection_release(tester->client_connections[i]);
Expand Down

0 comments on commit 98ec73a

Please sign in to comment.