@@ -60,6 +60,8 @@ typedef struct {
60
60
static void ngx_http_v2_read_handler (ngx_event_t * rev );
61
61
static void ngx_http_v2_write_handler (ngx_event_t * wev );
62
62
static void ngx_http_v2_handle_connection (ngx_http_v2_connection_t * h2c );
63
+ static void ngx_http_v2_lingering_close (ngx_http_v2_connection_t * h2c );
64
+ static void ngx_http_v2_lingering_close_handler (ngx_event_t * rev );
63
65
64
66
static u_char * ngx_http_v2_state_proxy_protocol (ngx_http_v2_connection_t * h2c ,
65
67
u_char * pos , u_char * end );
@@ -661,7 +663,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
661
663
}
662
664
663
665
if (h2c -> goaway ) {
664
- ngx_http_close_connection ( c );
666
+ ngx_http_v2_lingering_close ( h2c );
665
667
return ;
666
668
}
667
669
@@ -699,6 +701,113 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
699
701
}
700
702
701
703
704
+ static void
705
+ ngx_http_v2_lingering_close (ngx_http_v2_connection_t * h2c )
706
+ {
707
+ ngx_event_t * rev , * wev ;
708
+ ngx_connection_t * c ;
709
+ ngx_http_core_loc_conf_t * clcf ;
710
+
711
+ c = h2c -> connection ;
712
+
713
+ clcf = ngx_http_get_module_loc_conf (h2c -> http_connection -> conf_ctx ,
714
+ ngx_http_core_module );
715
+
716
+ if (clcf -> lingering_close == NGX_HTTP_LINGERING_OFF ) {
717
+ ngx_http_close_connection (c );
718
+ return ;
719
+ }
720
+
721
+ rev = c -> read ;
722
+ rev -> handler = ngx_http_v2_lingering_close_handler ;
723
+
724
+ h2c -> lingering_time = ngx_time () + (time_t ) (clcf -> lingering_time / 1000 );
725
+ ngx_add_timer (rev , clcf -> lingering_timeout );
726
+
727
+ if (ngx_handle_read_event (rev , 0 ) != NGX_OK ) {
728
+ ngx_http_close_connection (c );
729
+ return ;
730
+ }
731
+
732
+ wev = c -> write ;
733
+ wev -> handler = ngx_http_empty_handler ;
734
+
735
+ if (wev -> active && (ngx_event_flags & NGX_USE_LEVEL_EVENT )) {
736
+ if (ngx_del_event (wev , NGX_WRITE_EVENT , 0 ) != NGX_OK ) {
737
+ ngx_http_close_connection (c );
738
+ return ;
739
+ }
740
+ }
741
+
742
+ if (ngx_shutdown_socket (c -> fd , NGX_WRITE_SHUTDOWN ) == -1 ) {
743
+ ngx_connection_error (c , ngx_socket_errno ,
744
+ ngx_shutdown_socket_n " failed" );
745
+ ngx_http_close_connection (c );
746
+ return ;
747
+ }
748
+
749
+ if (rev -> ready ) {
750
+ ngx_http_v2_lingering_close_handler (rev );
751
+ }
752
+ }
753
+
754
+
755
+ static void
756
+ ngx_http_v2_lingering_close_handler (ngx_event_t * rev )
757
+ {
758
+ ssize_t n ;
759
+ ngx_msec_t timer ;
760
+ ngx_connection_t * c ;
761
+ ngx_http_core_loc_conf_t * clcf ;
762
+ ngx_http_v2_connection_t * h2c ;
763
+ u_char buffer [NGX_HTTP_LINGERING_BUFFER_SIZE ];
764
+
765
+ c = rev -> data ;
766
+ h2c = c -> data ;
767
+
768
+ ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , c -> log , 0 ,
769
+ "http2 lingering close handler" );
770
+
771
+ if (rev -> timedout ) {
772
+ ngx_http_close_connection (c );
773
+ return ;
774
+ }
775
+
776
+ timer = (ngx_msec_t ) h2c -> lingering_time - (ngx_msec_t ) ngx_time ();
777
+ if ((ngx_msec_int_t ) timer <= 0 ) {
778
+ ngx_http_close_connection (c );
779
+ return ;
780
+ }
781
+
782
+ do {
783
+ n = c -> recv (c , buffer , NGX_HTTP_LINGERING_BUFFER_SIZE );
784
+
785
+ ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , c -> log , 0 , "lingering read: %z" , n );
786
+
787
+ if (n == NGX_ERROR || n == 0 ) {
788
+ ngx_http_close_connection (c );
789
+ return ;
790
+ }
791
+
792
+ } while (rev -> ready );
793
+
794
+ if (ngx_handle_read_event (rev , 0 ) != NGX_OK ) {
795
+ ngx_http_close_connection (c );
796
+ return ;
797
+ }
798
+
799
+ clcf = ngx_http_get_module_loc_conf (h2c -> http_connection -> conf_ctx ,
800
+ ngx_http_core_module );
801
+ timer *= 1000 ;
802
+
803
+ if (timer > clcf -> lingering_timeout ) {
804
+ timer = clcf -> lingering_timeout ;
805
+ }
806
+
807
+ ngx_add_timer (rev , timer );
808
+ }
809
+
810
+
702
811
static u_char *
703
812
ngx_http_v2_state_proxy_protocol (ngx_http_v2_connection_t * h2c , u_char * pos ,
704
813
u_char * end )
@@ -4541,16 +4650,15 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
4541
4650
h2c -> blocked = 1 ;
4542
4651
4543
4652
if (!c -> error && !h2c -> goaway ) {
4653
+ h2c -> goaway = 1 ;
4654
+
4544
4655
if (ngx_http_v2_send_goaway (h2c , status ) != NGX_ERROR ) {
4545
4656
(void ) ngx_http_v2_send_output_queue (h2c );
4546
4657
}
4547
4658
}
4548
4659
4549
- c -> error = 1 ;
4550
-
4551
4660
if (!h2c -> processing && !h2c -> pushing ) {
4552
- ngx_http_close_connection (c );
4553
- return ;
4661
+ goto done ;
4554
4662
}
4555
4663
4556
4664
c -> read -> handler = ngx_http_empty_handler ;
@@ -4598,10 +4706,18 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
4598
4706
h2c -> blocked = 0 ;
4599
4707
4600
4708
if (h2c -> processing || h2c -> pushing ) {
4709
+ c -> error = 1 ;
4710
+ return ;
4711
+ }
4712
+
4713
+ done :
4714
+
4715
+ if (c -> error ) {
4716
+ ngx_http_close_connection (c );
4601
4717
return ;
4602
4718
}
4603
4719
4604
- ngx_http_close_connection ( c );
4720
+ ngx_http_v2_lingering_close ( h2c );
4605
4721
}
4606
4722
4607
4723
0 commit comments