Skip to content

Commit 98ec73a

Browse files
bretambroseBret Ambrose
andauthored
API to query http server listener endpoint (#463)
Co-authored-by: Bret Ambrose <[email protected]>
1 parent 425e5da commit 98ec73a

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

include/aws/http/server.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ int aws_http_connection_configure_server(
195195
AWS_HTTP_API
196196
bool aws_http_connection_is_server(const struct aws_http_connection *connection);
197197

198+
/**
199+
* Returns the local listener endpoint of the HTTP server. Only valid as long as the server remains valid.
200+
*/
201+
AWS_HTTP_API
202+
const struct aws_socket_endpoint *aws_http_server_get_listener_endpoint(const struct aws_http_server *server);
203+
198204
AWS_EXTERN_C_END
199205
AWS_POP_SANE_WARNING_LEVEL
200206

source/connection.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,12 @@ void aws_http_server_release(struct aws_http_server *server) {
762762
* clean up will be called from eventloop */
763763
}
764764

765+
const struct aws_socket_endpoint *aws_http_server_get_listener_endpoint(const struct aws_http_server *server) {
766+
AWS_FATAL_ASSERT(server);
767+
768+
return &server->socket->local_endpoint;
769+
}
770+
765771
/* At this point, the channel bootstrapper has established a connection to the server and set up a channel.
766772
* Now we need to create the aws_http_connection and insert it into the channel as a channel-handler. */
767773
static void s_client_bootstrap_on_channel_setup(

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ add_test_case(h2_client_manual_data_write_no_data)
498498
add_test_case(h2_client_manual_data_write_connection_close)
499499

500500
add_test_case(server_new_destroy)
501+
add_test_case(server_new_destroy_tcp)
501502
add_test_case(connection_setup_shutdown)
502503
add_test_case(connection_setup_shutdown_tls)
503504
add_test_case(connection_setup_shutdown_proxy_setting_on_ev_not_found)

tests/test_connection.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct tester_options {
4444
char *client_alpn_list;
4545
bool no_connection; /* don't connect server to client */
4646
bool pin_event_loop;
47+
bool use_tcp; /* otherwise uses domain sockets */
4748
};
4849

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

337338
struct aws_socket_options socket_options = {
338339
.type = AWS_SOCKET_STREAM,
339-
.domain = AWS_SOCKET_LOCAL,
340+
.domain = options->use_tcp ? AWS_SOCKET_IPV4 : AWS_SOCKET_LOCAL,
340341
.connect_timeout_ms =
341342
(uint32_t)aws_timestamp_convert(TESTER_TIMEOUT_SEC, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_MILLIS, NULL),
342343
};
343344
tester->socket_options = socket_options;
344-
/* Generate random address for endpoint */
345-
struct aws_uuid uuid;
346-
ASSERT_SUCCESS(aws_uuid_init(&uuid));
347-
char uuid_str[AWS_UUID_STR_LEN];
348-
struct aws_byte_buf uuid_buf = aws_byte_buf_from_empty_array(uuid_str, sizeof(uuid_str));
349-
ASSERT_SUCCESS(aws_uuid_to_str(&uuid, &uuid_buf));
345+
350346
struct aws_socket_endpoint endpoint;
351347
AWS_ZERO_STRUCT(endpoint);
352348

353-
snprintf(endpoint.address, sizeof(endpoint.address), LOCAL_SOCK_TEST_FORMAT, uuid_str);
349+
if (options->use_tcp) {
350+
snprintf(endpoint.address, sizeof(endpoint.address), "127.0.0.1");
351+
} else {
352+
aws_socket_endpoint_init_local_address_for_test(&endpoint);
353+
}
354+
354355
tester->endpoint = endpoint;
356+
355357
/* Create server (listening socket) */
356358
struct aws_http_server_options server_options = AWS_HTTP_SERVER_OPTIONS_INIT;
357359
server_options.allocator = tester->alloc;
@@ -370,6 +372,14 @@ static int s_tester_init(struct tester *tester, const struct tester_options *opt
370372
tester->server = aws_http_server_new(&server_options);
371373
ASSERT_NOT_NULL(tester->server);
372374

375+
/*
376+
* localhost server binds to any port, so let's get the final listener endpoint whether or not we're making
377+
* connections to it.
378+
*/
379+
if (options->use_tcp) {
380+
tester->endpoint = *aws_http_server_get_listener_endpoint(tester->server);
381+
}
382+
373383
/* If test doesn't need a connection, we're done setting up. */
374384
if (options->no_connection) {
375385
return AWS_OP_SUCCESS;
@@ -448,6 +458,20 @@ static int s_test_server_new_destroy(struct aws_allocator *allocator, void *ctx)
448458
}
449459
AWS_TEST_CASE(server_new_destroy, s_test_server_new_destroy);
450460

461+
static int s_test_server_new_destroy_tcp(struct aws_allocator *allocator, void *ctx) {
462+
(void)ctx;
463+
struct tester_options options = {.alloc = allocator, .no_connection = true, .use_tcp = true};
464+
struct tester tester;
465+
ASSERT_SUCCESS(s_tester_init(&tester, &options));
466+
467+
const struct aws_socket_endpoint *listener_endpoint = aws_http_server_get_listener_endpoint(tester.server);
468+
ASSERT_TRUE(listener_endpoint->port > 0);
469+
470+
ASSERT_SUCCESS(s_tester_clean_up(&tester));
471+
return AWS_OP_SUCCESS;
472+
}
473+
AWS_TEST_CASE(server_new_destroy_tcp, s_test_server_new_destroy_tcp);
474+
451475
void release_all_client_connections(struct tester *tester) {
452476
for (int i = 0; i < tester->client_connection_num; i++) {
453477
aws_http_connection_release(tester->client_connections[i]);

0 commit comments

Comments
 (0)