16
16
#include <aws/common/string.h>
17
17
#include <aws/http/request_response.h>
18
18
#include <aws/io/channel_bootstrap.h>
19
+ #include <aws/io/future.h>
19
20
#include <aws/io/logging.h>
20
21
#include <aws/io/socket.h>
21
22
#include <aws/io/socket_channel_handler.h>
@@ -58,6 +59,7 @@ struct aws_http_server {
58
59
aws_http_server_on_incoming_connection_fn * on_incoming_connection ;
59
60
aws_http_server_on_destroy_fn * on_destroy_complete ;
60
61
struct aws_socket * socket ;
62
+ struct aws_future_void * setup_future ;
61
63
62
64
/* Any thread may touch this data, but the lock must be held */
63
65
struct {
@@ -576,6 +578,7 @@ static void s_http_server_clean_up(struct aws_http_server *server) {
576
578
}
577
579
aws_hash_table_clean_up (& server -> synced_data .channel_to_connection_map );
578
580
aws_mutex_clean_up (& server -> synced_data .lock );
581
+ aws_future_void_release (server -> setup_future );
579
582
aws_mem_release (server -> alloc , server );
580
583
}
581
584
@@ -621,6 +624,20 @@ static void s_server_bootstrap_on_server_listener_destroy(struct aws_server_boot
621
624
s_http_server_clean_up (server );
622
625
}
623
626
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
+
624
641
struct aws_http_server * aws_http_server_new (const struct aws_http_server_options * options ) {
625
642
aws_http_fatal_assert_library_initialized ();
626
643
@@ -654,7 +671,7 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
654
671
if (err ) {
655
672
AWS_LOGF_ERROR (
656
673
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 ;
658
675
}
659
676
err = aws_hash_table_init (
660
677
& 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
664
681
"static: Cannot create server, error %d (%s)." ,
665
682
aws_last_error (),
666
683
aws_error_name (aws_last_error ()));
667
- goto hash_table_error ;
684
+ goto server_error ;
668
685
}
669
686
/* Protect against callbacks firing before server->socket is set */
670
687
s_server_lock_synced_data (server );
671
688
if (options -> tls_options ) {
672
689
server -> is_using_tls = true;
673
690
}
674
691
692
+ server -> setup_future = aws_future_void_new (options -> allocator );
693
+
675
694
struct aws_server_socket_channel_bootstrap_options bootstrap_options = {
676
695
.enable_read_back_pressure = options -> manual_window_management ,
677
696
.tls_options = options -> tls_options ,
@@ -680,23 +699,38 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
680
699
.incoming_callback = s_server_bootstrap_on_accept_channel_setup ,
681
700
.shutdown_callback = s_server_bootstrap_on_accept_channel_shutdown ,
682
701
.destroy_callback = s_server_bootstrap_on_server_listener_destroy ,
702
+ .setup_callback = s_server_bootstrap_on_server_listener_setup ,
683
703
.host_name = options -> endpoint -> address ,
684
704
.port = options -> endpoint -> port ,
685
705
.user_data = server ,
686
706
};
687
707
688
- server -> socket = aws_server_bootstrap_new_socket_listener ( & bootstrap_options ) ;
708
+ int listen_error = AWS_OP_SUCCESS ;
689
709
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
+ }
690
723
s_server_unlock_synced_data (server );
691
724
692
- if (! server -> socket ) {
725
+ if (listen_error ) {
693
726
AWS_LOGF_ERROR (
694
727
AWS_LS_HTTP_SERVER ,
695
728
"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 ));
698
731
699
- goto socket_error ;
732
+ aws_raise_error (listen_error );
733
+ goto server_error ;
700
734
}
701
735
702
736
AWS_LOGF_INFO (
@@ -708,12 +742,8 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
708
742
709
743
return server ;
710
744
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 );
717
747
return NULL ;
718
748
}
719
749
0 commit comments