Skip to content

Commit e526ac3

Browse files
xiazhveragraebm
andauthored
Apple Network Framework Support (#502)
Co-authored-by: Michael Graeb <[email protected]>
1 parent 2fa08d5 commit e526ac3

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

.github/workflows/ci.yml

+13-5
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,11 @@ jobs:
204204
python .\aws-c-http\build\deps\aws-c-common\scripts\appverifier_ctest.py --build_directory .\aws-c-http\build\aws-c-http
205205
206206
macos:
207-
runs-on: macos-14 # latest
207+
runs-on: macos-14
208+
strategy:
209+
fail-fast: false
210+
matrix:
211+
eventloop: ["kqueue", "dispatch_queue"]
208212
steps:
209213
- uses: aws-actions/configure-aws-credentials@v4
210214
with:
@@ -214,10 +218,10 @@ jobs:
214218
run: |
215219
python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')"
216220
chmod a+x builder
217-
./builder build -p ${{ env.PACKAGE_NAME }}
221+
./builder build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DAWS_USE_APPLE_NETWORK_FRAMEWORK=${{ matrix.eventloop == 'dispatch_queue' && 'ON' || 'OFF' }}
218222
219223
macos-x64:
220-
runs-on: macos-14-large # latest
224+
runs-on: macos-14-large
221225
steps:
222226
- uses: aws-actions/configure-aws-credentials@v4
223227
with:
@@ -244,7 +248,11 @@ jobs:
244248
python3 builder.pyz build -p aws-c-http --cmake-extra=-DENABLE_LOCALHOST_INTEGRATION_TESTS=ON --config Debug
245249
246250
localhost-test-macos:
247-
runs-on: macos-14 # latest
251+
runs-on: macos-14
252+
strategy:
253+
fail-fast: false
254+
matrix:
255+
eventloop: ["kqueue", "dispatch_queue"]
248256
steps:
249257
- uses: aws-actions/configure-aws-credentials@v4
250258
with:
@@ -257,7 +265,7 @@ jobs:
257265
python3 -m venv .venv
258266
source .venv/bin/activate
259267
python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')"
260-
python3 builder.pyz build -p aws-c-http --cmake-extra=-DENABLE_LOCALHOST_INTEGRATION_TESTS=ON --config Debug
268+
python3 builder.pyz build -p aws-c-http --cmake-extra=-DENABLE_LOCALHOST_INTEGRATION_TESTS=ON --cmake-extra=-DAWS_USE_APPLE_NETWORK_FRAMEWORK=${{ matrix.eventloop == 'dispatch_queue' && 'ON' || 'OFF' }} --config Debug
261269
262270
localhost-test-win:
263271
runs-on: windows-2022 # latest

source/connection.c

+43-13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <aws/common/string.h>
1717
#include <aws/http/request_response.h>
1818
#include <aws/io/channel_bootstrap.h>
19+
#include <aws/io/future.h>
1920
#include <aws/io/logging.h>
2021
#include <aws/io/socket.h>
2122
#include <aws/io/socket_channel_handler.h>
@@ -58,6 +59,7 @@ struct aws_http_server {
5859
aws_http_server_on_incoming_connection_fn *on_incoming_connection;
5960
aws_http_server_on_destroy_fn *on_destroy_complete;
6061
struct aws_socket *socket;
62+
struct aws_future_void *setup_future;
6163

6264
/* Any thread may touch this data, but the lock must be held */
6365
struct {
@@ -576,6 +578,7 @@ static void s_http_server_clean_up(struct aws_http_server *server) {
576578
}
577579
aws_hash_table_clean_up(&server->synced_data.channel_to_connection_map);
578580
aws_mutex_clean_up(&server->synced_data.lock);
581+
aws_future_void_release(server->setup_future);
579582
aws_mem_release(server->alloc, server);
580583
}
581584

@@ -621,6 +624,20 @@ static void s_server_bootstrap_on_server_listener_destroy(struct aws_server_boot
621624
s_http_server_clean_up(server);
622625
}
623626

627+
/* the server listener has finished setup. We released the socket if error_code is not 0. */
628+
static void s_server_bootstrap_on_server_listener_setup(
629+
struct aws_server_bootstrap *bootstrap,
630+
int error_code,
631+
void *user_data) {
632+
(void)bootstrap;
633+
struct aws_http_server *server = user_data;
634+
if (error_code) {
635+
aws_future_void_set_error(server->setup_future, error_code);
636+
} else {
637+
aws_future_void_set_result(server->setup_future);
638+
}
639+
}
640+
624641
struct aws_http_server *aws_http_server_new(const struct aws_http_server_options *options) {
625642
aws_http_fatal_assert_library_initialized();
626643

@@ -654,7 +671,7 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
654671
if (err) {
655672
AWS_LOGF_ERROR(
656673
AWS_LS_HTTP_SERVER, "static: Failed to initialize mutex, error %d (%s).", err, aws_error_name(err));
657-
goto mutex_error;
674+
goto server_error;
658675
}
659676
err = aws_hash_table_init(
660677
&server->synced_data.channel_to_connection_map, server->alloc, 16, aws_hash_ptr, aws_ptr_eq, NULL, NULL);
@@ -664,14 +681,16 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
664681
"static: Cannot create server, error %d (%s).",
665682
aws_last_error(),
666683
aws_error_name(aws_last_error()));
667-
goto hash_table_error;
684+
goto server_error;
668685
}
669686
/* Protect against callbacks firing before server->socket is set */
670687
s_server_lock_synced_data(server);
671688
if (options->tls_options) {
672689
server->is_using_tls = true;
673690
}
674691

692+
server->setup_future = aws_future_void_new(options->allocator);
693+
675694
struct aws_server_socket_channel_bootstrap_options bootstrap_options = {
676695
.enable_read_back_pressure = options->manual_window_management,
677696
.tls_options = options->tls_options,
@@ -680,23 +699,38 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
680699
.incoming_callback = s_server_bootstrap_on_accept_channel_setup,
681700
.shutdown_callback = s_server_bootstrap_on_accept_channel_shutdown,
682701
.destroy_callback = s_server_bootstrap_on_server_listener_destroy,
702+
.setup_callback = s_server_bootstrap_on_server_listener_setup,
683703
.host_name = options->endpoint->address,
684704
.port = options->endpoint->port,
685705
.user_data = server,
686706
};
687707

688-
server->socket = aws_server_bootstrap_new_socket_listener(&bootstrap_options);
708+
int listen_error = AWS_OP_SUCCESS;
689709

710+
/*
711+
* WARNING & TODO!!!!
712+
* aws_server_bootstrap_new_socket_listener has async callback, we would block here waiting for
713+
* setup complete. aws-c-http library need to be updated with a proper async API.
714+
*/
715+
server->socket = aws_server_bootstrap_new_socket_listener(&bootstrap_options);
716+
// if server setup properly, waiting for setup callback
717+
if (server->socket) {
718+
aws_future_void_wait(server->setup_future, UINT64_MAX /*timeout*/);
719+
listen_error = aws_future_void_get_error(server->setup_future);
720+
} else {
721+
listen_error = aws_last_error();
722+
}
690723
s_server_unlock_synced_data(server);
691724

692-
if (!server->socket) {
725+
if (listen_error) {
693726
AWS_LOGF_ERROR(
694727
AWS_LS_HTTP_SERVER,
695728
"static: Failed creating new socket listener, error %d (%s). Cannot create server.",
696-
aws_last_error(),
697-
aws_error_name(aws_last_error()));
729+
listen_error,
730+
aws_error_name(listen_error));
698731

699-
goto socket_error;
732+
aws_raise_error(listen_error);
733+
goto server_error;
700734
}
701735

702736
AWS_LOGF_INFO(
@@ -708,12 +742,8 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
708742

709743
return server;
710744

711-
socket_error:
712-
aws_hash_table_clean_up(&server->synced_data.channel_to_connection_map);
713-
hash_table_error:
714-
aws_mutex_clean_up(&server->synced_data.lock);
715-
mutex_error:
716-
aws_mem_release(server->alloc, server);
745+
server_error:
746+
s_http_server_clean_up(server);
717747
return NULL;
718748
}
719749

0 commit comments

Comments
 (0)