@@ -117,6 +117,84 @@ async fn release_capacity_sends_window_update() {
117117 join ( mock, h2) . await ;
118118}
119119
120+ #[ tokio:: test]
121+ async fn window_updates_include_padded_length ( ) {
122+ h2_support:: trace_init!( ) ;
123+
124+ // Our manual way of sending padding frames, not supported publicly
125+ const PAYLOAD_LEN : usize = 16_378 ; // 16_384; does padding + payload count for max frame size?
126+ let mut payload = Vec :: with_capacity ( PAYLOAD_LEN + 6 ) ;
127+ payload. push ( 5 ) ;
128+ payload. extend_from_slice ( & [ b'z' ; PAYLOAD_LEN ] [ ..] ) ;
129+ payload. extend_from_slice ( & [ b'0' ; 5 ] [ ..] ) ;
130+
131+ let ( io, mut srv) = mock:: new ( ) ;
132+
133+ let mock = async move {
134+ let settings = srv. assert_client_handshake ( ) . await ;
135+ assert_default_settings ! ( settings) ;
136+ srv. recv_frame (
137+ frames:: headers ( 1 )
138+ . request ( "GET" , "https://http2.akamai.com/" )
139+ . eos ( ) ,
140+ )
141+ . await ;
142+ srv. send_frame ( frames:: headers ( 1 ) . response ( 200 ) ) . await ;
143+ srv. send_frame ( frames:: data ( 1 , & payload[ ..] ) . padded ( ) ) . await ;
144+ srv. send_frame ( frames:: data ( 1 , & payload[ ..] ) . padded ( ) ) . await ;
145+ srv. send_frame ( frames:: data ( 1 , & payload[ ..] ) . padded ( ) ) . await ;
146+ // the other 6 was auto-released earlier
147+ srv. recv_frame ( frames:: window_update ( 0 , 32_774 ) ) . await ;
148+ srv. recv_frame ( frames:: window_update ( 1 , 32_774 ) ) . await ;
149+ srv. send_frame ( frames:: data ( 1 , & payload[ ..] ) . padded ( ) . eos ( ) )
150+ . await ;
151+ // but not double released here
152+ srv. recv_frame ( frames:: window_update ( 0 , 32_762 ) ) . await ;
153+ // and no one cares about closed stream window
154+ } ;
155+
156+ let h2 = async move {
157+ let ( mut client, h2) = client:: handshake ( io) . await . unwrap ( ) ;
158+ let request = Request :: builder ( )
159+ . method ( Method :: GET )
160+ . uri ( "https://http2.akamai.com/" )
161+ . body ( ( ) )
162+ . unwrap ( ) ;
163+
164+ let req = async move {
165+ let resp = client. send_request ( request, true ) . unwrap ( ) . 0 . await . unwrap ( ) ;
166+ // Get the response
167+ assert_eq ! ( resp. status( ) , StatusCode :: OK ) ;
168+ let mut body = resp. into_parts ( ) . 1 ;
169+
170+ // read some body to use up window size to below half
171+ let buf = body. data ( ) . await . unwrap ( ) . unwrap ( ) ;
172+ assert_eq ! ( buf. len( ) , PAYLOAD_LEN ) ;
173+
174+ let buf = body. data ( ) . await . unwrap ( ) . unwrap ( ) ;
175+ assert_eq ! ( buf. len( ) , PAYLOAD_LEN ) ;
176+
177+ let buf = body. data ( ) . await . unwrap ( ) . unwrap ( ) ;
178+ assert_eq ! ( buf. len( ) , PAYLOAD_LEN ) ;
179+ body. flow_control ( ) . release_capacity ( buf. len ( ) * 2 ) . unwrap ( ) ;
180+
181+ let buf = body. data ( ) . await . unwrap ( ) . unwrap ( ) ;
182+ assert_eq ! ( buf. len( ) , PAYLOAD_LEN ) ;
183+ drop ( body) ;
184+ idle_ms ( 20 ) . await ;
185+ } ;
186+
187+ join (
188+ async move {
189+ h2. await . unwrap ( ) ;
190+ } ,
191+ req,
192+ )
193+ . await
194+ } ;
195+ join ( mock, h2) . await ;
196+ }
197+
120198#[ tokio:: test]
121199async fn release_capacity_of_small_amount_does_not_send_window_update ( ) {
122200 h2_support:: trace_init!( ) ;
0 commit comments