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+
624641struct 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