reduce available window capacity when settings lowers window size
This commit is contained in:
		| @@ -126,8 +126,10 @@ impl FlowControl { | |||||||
|     /// This is called after receiving a SETTINGS frame with a lower |     /// This is called after receiving a SETTINGS frame with a lower | ||||||
|     /// INITIAL_WINDOW_SIZE value. |     /// INITIAL_WINDOW_SIZE value. | ||||||
|     pub fn dec_window(&mut self, sz: WindowSize) { |     pub fn dec_window(&mut self, sz: WindowSize) { | ||||||
|  |         trace!("dec_window; sz={}; window={}, available={}", sz, self.window_size, self.available); | ||||||
|         // This should not be able to overflow `window_size` from the bottom. |         // This should not be able to overflow `window_size` from the bottom. | ||||||
|         self.window_size -= sz as i32; |         self.window_size -= sz as i32; | ||||||
|  |         self.available = self.available.saturating_sub(sz); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Decrements the window reflecting data has actually been sent. The caller |     /// Decrements the window reflecting data has actually been sent. The caller | ||||||
|   | |||||||
| @@ -532,17 +532,16 @@ fn recv_window_update_on_stream_closed_by_data_frame() { | |||||||
|             // Send a data frame, this will also close the connection |             // Send a data frame, this will also close the connection | ||||||
|             stream.send_data("hello".into(), true).unwrap(); |             stream.send_data("hello".into(), true).unwrap(); | ||||||
|  |  | ||||||
|  |             // keep `stream` from being dropped in order to prevent | ||||||
|  |             // it from sending an RST_STREAM frame. | ||||||
|  |             // | ||||||
|  |             // i know this is kind of evil, but it's necessary to | ||||||
|  |             // ensure that the stream is closed by the EOS frame, | ||||||
|  |             // and not by the RST_STREAM. | ||||||
|  |             std::mem::forget(stream); | ||||||
|  |  | ||||||
|             // Wait for the connection to close |             // Wait for the connection to close | ||||||
|             h2.map(|h2| { |             h2.unwrap() | ||||||
|                 // keep `stream` from being dropped in order to prevent |  | ||||||
|                 // it from sending an RST_STREAM frame. |  | ||||||
|                 std::mem::forget(stream); |  | ||||||
|                 // i know this is kind of evil, but it's necessary to |  | ||||||
|                 // ensure that the stream is closed by the EOS frame, |  | ||||||
|                 // and not by the RST_STREAM. |  | ||||||
|                 h2 |  | ||||||
|             }) |  | ||||||
|                 .unwrap() |  | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|     let srv = srv.assert_client_handshake() |     let srv = srv.assert_client_handshake() | ||||||
| @@ -744,3 +743,60 @@ fn connection_notified_on_released_capacity() { | |||||||
|     // implicitly released before. |     // implicitly released before. | ||||||
|     drop(b); |     drop(b); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[test] | ||||||
|  | fn recv_settings_removes_available_capacity() { | ||||||
|  |     let _ = ::env_logger::init(); | ||||||
|  |     let (io, srv) = mock::new(); | ||||||
|  |  | ||||||
|  |     let mut settings = frame::Settings::default(); | ||||||
|  |     settings.set_initial_window_size(Some(0)); | ||||||
|  |  | ||||||
|  |     let srv = srv.assert_client_handshake_with_settings(settings).unwrap() | ||||||
|  |         .recv_settings() | ||||||
|  |         .recv_frame( | ||||||
|  |             frames::headers(1) | ||||||
|  |                 .request("POST", "https://http2.akamai.com/") | ||||||
|  |         ) | ||||||
|  |         .idle_ms(100) | ||||||
|  |         .send_frame(frames::window_update(0, 11)) | ||||||
|  |         .send_frame(frames::window_update(1, 11)) | ||||||
|  |         .recv_frame(frames::data(1, "hello world").eos()) | ||||||
|  |         .send_frame( | ||||||
|  |             frames::headers(1) | ||||||
|  |                 .response(204) | ||||||
|  |                 .eos() | ||||||
|  |         ) | ||||||
|  |         .close(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     let h2 = Client::handshake(io).unwrap() | ||||||
|  |         .and_then(|(mut client, h2)| { | ||||||
|  |             let request = Request::builder() | ||||||
|  |                 .method(Method::POST) | ||||||
|  |                 .uri("https://http2.akamai.com/") | ||||||
|  |                 .body(()).unwrap(); | ||||||
|  |  | ||||||
|  |             let mut stream = client.send_request(request, false).unwrap(); | ||||||
|  |  | ||||||
|  |             stream.reserve_capacity(11); | ||||||
|  |  | ||||||
|  |             h2.drive(util::wait_for_capacity(stream, 11)) | ||||||
|  |         }) | ||||||
|  |         .and_then(|(h2, mut stream)| { | ||||||
|  |             assert_eq!(stream.capacity(), 11); | ||||||
|  |  | ||||||
|  |             stream.send_data("hello world".into(), true).unwrap(); | ||||||
|  |  | ||||||
|  |             h2.drive(GetResponse { stream: Some(stream) }) | ||||||
|  |         }) | ||||||
|  |         .and_then(|(h2, (response, _))| { | ||||||
|  |             assert_eq!(response.status(), StatusCode::NO_CONTENT); | ||||||
|  |  | ||||||
|  |             // Wait for the connection to close | ||||||
|  |             h2.unwrap() | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |     let _ = h2.join(srv) | ||||||
|  |         .wait().unwrap(); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user