@@ -736,7 +736,7 @@ ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos,
736736 return ngx_http_v2_state_head (h2c , pos + sizeof (preface ) - 1 , end );
737737}
738738
739-
739+ //ngx_http_v2_read_handler读取到HTTP2客户端数据后调用该函数执行
740740static u_char *
741741ngx_http_v2_state_head (ngx_http_v2_connection_t * h2c , u_char * pos , u_char * end )
742742{
@@ -780,6 +780,7 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
780780 ngx_http_v2_node_t * node ;
781781 ngx_http_v2_stream_t * stream ;
782782
783+ /* 跳过pad数据部分 */
783784 if (h2c -> state .flags & NGX_HTTP_V2_PADDED_FLAG ) {
784785
785786 if (h2c -> state .length == 0 ) {
@@ -814,6 +815,7 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
814815 ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , h2c -> connection -> log , 0 ,
815816 "http2 DATA frame" );
816817
818+ /* 如果对端发送过来的数据大于本端接收窗口,直接报错 */
817819 if (h2c -> state .length > h2c -> recv_window ) {
818820 ngx_log_error (NGX_LOG_INFO , h2c -> connection -> log , 0 ,
819821 "client violated connection flow control: "
@@ -823,10 +825,14 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
823825 return ngx_http_v2_connection_error (h2c , NGX_HTTP_V2_FLOW_CTRL_ERROR );
824826 }
825827
828+ /* 接收到DATA帧数据后,调整接收窗口大小 */
826829 h2c -> recv_window -= h2c -> state .length ;
827830
828- if (h2c -> recv_window < NGX_HTTP_V2_MAX_WINDOW / 4 ) {
829-
831+ /* 当本端收到DATA帧的时候,如果发现该连接上的recv_window大小已经小于NGX_HTTP_V2_MAX_WINDOW / 4了,
832+ 则通知本发送端把h2c->send_window调整为NGX_HTTP_V2_MAX_WINDOW,同时本端也把连接的接收recv_window恢复到该MAX值 */
833+ if (h2c -> recv_window < NGX_HTTP_V2_MAX_WINDOW / 4 ) {
834+ //这里为什么是NGX_HTTP_V2_MAX_WINDOW?因为整个连接的recv_window(即h2c->recv_window)初始值就为NGX_HTTP_V2_MAX_WINDOW,
835+ //而且不会变化,也就是协议规定HTTP2 一个连接对应的recv_window为NGX_HTTP_V2_MAX_WINDOW
830836 if (ngx_http_v2_send_window_update (h2c , 0 , NGX_HTTP_V2_MAX_WINDOW
831837 - h2c -> recv_window )
832838 == NGX_ERROR )
@@ -835,7 +841,7 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
835841 NGX_HTTP_V2_INTERNAL_ERROR );
836842 }
837843
838- h2c -> recv_window = NGX_HTTP_V2_MAX_WINDOW ;
844+ h2c -> recv_window = NGX_HTTP_V2_MAX_WINDOW ; //
839845 }
840846
841847 node = ngx_http_v2_get_node_by_id (h2c , h2c -> state .sid , 0 );
@@ -867,9 +873,12 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
867873 }
868874
869875 stream -> recv_window -= h2c -> state .length ;
870-
876+
877+ //流的recv_window小于NGX_HTTP_V2_MAX_WINDOW / 4后,恢复本流recv_window为NGX_HTTP_V2_MAX_WINDOW,同时发送
878+ //更新帧个会对端使其也更新为NGX_HTTP_V2_MAX_WINDOW,从而保持同步
871879 if (stream -> recv_window < NGX_HTTP_V2_MAX_WINDOW / 4 ) {
872-
880+ //为什么这里是和NGX_HTTP_V2_MAX_WINDOW比较? 因为nginx通过ngx_http_v2_send_settings发送的setting帧
881+ //把init_window设置为NGX_HTTP_V2_MAX_WINDOW对端收到后就会把自己的strem->send_window设置为NGX_HTTP_V2_MAX_WINDOW
873882 if (ngx_http_v2_send_window_update (h2c , node -> id ,
874883 NGX_HTTP_V2_MAX_WINDOW
875884 - stream -> recv_window )
@@ -904,6 +913,7 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
904913}
905914
906915
916+ //接收到数据帧后在ngx_http_v2_state_data调用该函数读取数据帧中的真实数据
907917static u_char *
908918ngx_http_v2_state_read_data (ngx_http_v2_connection_t * h2c , u_char * pos ,
909919 u_char * end )
@@ -1936,6 +1946,7 @@ ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos,
19361946 return ngx_http_v2_state_complete (h2c , pos , end );
19371947}
19381948
1949+ //接收到RST_STREAM帧,需要关闭对应流,因此流也要处于关闭状态。 - 接收者不能够在此流上发送任何帧
19391950//见ngx_http_v2_frame_states
19401951static u_char *
19411952ngx_http_v2_state_rst_stream (ngx_http_v2_connection_t * h2c , u_char * pos ,
@@ -2051,7 +2062,8 @@ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
20512062 return ngx_http_v2_state_settings_params (h2c , pos , end );
20522063}
20532064
2054-
2065+ //setting帧决定接收到HEAD帧后创建流的时候,确定发送窗口的大小。同时决定在通过write chain发送frame帧的时候,决定没个数据块的大小
2066+ //例如一个frame帧为10K,但是对端指定其接收数据的frame_size=5K,则该frame会被拆成两个frame_size大小的包体发送
20552067static u_char *
20562068ngx_http_v2_state_settings_params (ngx_http_v2_connection_t * h2c , u_char * pos ,
20572069 u_char * end )
@@ -2091,6 +2103,7 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
20912103 NGX_HTTP_V2_INTERNAL_ERROR );
20922104 }
20932105
2106+ //决定流的发送窗口大小
20942107 h2c -> init_window = value ;
20952108 break ;
20962109
@@ -2106,6 +2119,7 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
21062119 NGX_HTTP_V2_PROTOCOL_ERROR );
21072120 }
21082121
2122+ //决定发送FRAME帧的时候,每帧数据大小不超过该值
21092123 h2c -> frame_size = value ;
21102124 break ;
21112125
@@ -2152,10 +2166,11 @@ ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
21522166 ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , h2c -> connection -> log , 0 ,
21532167 "http2 PING frame, flags: %ui" , h2c -> state .flags );
21542168
2155- if (h2c -> state .flags & NGX_HTTP_V2_ACK_FLAG ) {
2169+ if (h2c -> state .flags & NGX_HTTP_V2_ACK_FLAG ) { //ping帧的ACK信息
21562170 return ngx_http_v2_state_skip (h2c , pos , end );
21572171 }
21582172
2173+ //发送PING帧的ACK帧
21592174 frame = ngx_http_v2_get_frame (h2c , NGX_HTTP_V2_PING_SIZE ,
21602175 NGX_HTTP_V2_PING_FRAME ,
21612176 NGX_HTTP_V2_ACK_FLAG , 0 );
@@ -2165,14 +2180,16 @@ ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
21652180
21662181 buf = frame -> first -> buf ;
21672182
2183+ //PING帧带有8字节负载,8个字节负载,值随意填写。
21682184 buf -> last = ngx_cpymem (buf -> last , pos , NGX_HTTP_V2_PING_SIZE );
21692185
21702186 ngx_http_v2_queue_blocked_frame (h2c , frame );
21712187
21722188 return ngx_http_v2_state_complete (h2c , pos + NGX_HTTP_V2_PING_SIZE , end );
21732189}
21742190
2175- //见ngx_http_v2_frame_states
2191+ //见ngx_http_v2_frame_states
2192+ //GOAWAY帧直接跳过的,啥也没处理
21762193static u_char *
21772194ngx_http_v2_state_goaway (ngx_http_v2_connection_t * h2c , u_char * pos ,
21782195 u_char * end )
@@ -2233,15 +2250,15 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos,
22332250 ngx_http_v2_state_window_update );
22342251 }
22352252
2236- window = ngx_http_v2_parse_window (pos );
2253+ window = ngx_http_v2_parse_window (pos ); //获取对方发送过来的更新窗口大小
22372254
22382255 pos += NGX_HTTP_V2_WINDOW_UPDATE_SIZE ;
22392256
22402257 ngx_log_debug2 (NGX_LOG_DEBUG_HTTP , h2c -> connection -> log , 0 ,
22412258 "http2 WINDOW_UPDATE frame sid:%ui window:%uz" ,
22422259 h2c -> state .sid , window );
22432260
2244- if (h2c -> state .sid ) {
2261+ if (h2c -> state .sid ) { //是针对某个流进行窗口更新,则把该流的发送窗口增加window大小
22452262 node = ngx_http_v2_get_node_by_id (h2c , h2c -> state .sid , 0 );
22462263
22472264 if (node == NULL || node -> stream == NULL ) {
@@ -2253,6 +2270,7 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos,
22532270
22542271 stream = node -> stream ;
22552272
2273+ /* 对端告诉本端我们可以把发送窗口调大window大小,但是本端发送窗口调大window后会超过NGX_HTTP_V2_MAX_WINDOW限制,这是不规范的 */
22562274 if (window > (size_t ) (NGX_HTTP_V2_MAX_WINDOW - stream -> send_window )) {
22572275
22582276 ngx_log_error (NGX_LOG_INFO , h2c -> connection -> log , 0 ,
@@ -2289,6 +2307,8 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos,
22892307 return ngx_http_v2_state_complete (h2c , pos , end );
22902308 }
22912309
2310+ /* 说明是针对整个连接的发送窗口更新,对整个连接的发送窗口增加window大小 */
2311+
22922312 if (window > NGX_HTTP_V2_MAX_WINDOW - h2c -> send_window ) {
22932313 ngx_log_error (NGX_LOG_INFO , h2c -> connection -> log , 0 ,
22942314 "client violated connection flow control: "
@@ -2704,7 +2724,7 @@ ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t sid,
27042724 return NGX_OK ;
27052725}
27062726
2707-
2727+ //http2处理完成后,在ngx_http_v2_finalize_connection中调用该函数和对端说拜拜
27082728static ngx_int_t
27092729ngx_http_v2_send_goaway (ngx_http_v2_connection_t * h2c , ngx_uint_t status )
27102730{
@@ -4014,9 +4034,9 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
40144034 ngx_http_close_connection (c );
40154035}
40164036
4017-
4037+ //调整连接h2c上的所有流的发送窗口大小,增加delta,如果加上delta后超过了阈值,则直接发送RST复位帧
40184038static ngx_int_t
4019- ngx_http_v2_adjust_windows (ngx_http_v2_connection_t * h2c , ssize_t delta )
4039+ ngx_http_v2_adjust_windows (ngx_http_v2_connection_t * h2c , ssize_t delta ) //delta为流的发送窗口增加量
40204040{
40214041 ngx_uint_t i , size ;
40224042 ngx_event_t * wev ;
@@ -4038,6 +4058,7 @@ ngx_http_v2_adjust_windows(ngx_http_v2_connection_t *h2c, ssize_t delta)
40384058 continue ;
40394059 }
40404060
4061+ /* 如果流的发送窗口加上delta后超过了NGX_HTTP_V2_MAX_WINDOW最大限制,则发送RST帧 */
40414062 if (delta > 0
40424063 && stream -> send_window
40434064 > (ssize_t ) (NGX_HTTP_V2_MAX_WINDOW - delta ))
0 commit comments