Skip to content

Commit fbb9e0f

Browse files
committed
Fix window size decrement of send-closed streams
Send-closed streams should be skipped when decreasing window size, as they are skipped when increasing it.
1 parent d7c56f4 commit fbb9e0f

File tree

3 files changed

+17
-13
lines changed

3 files changed

+17
-13
lines changed

src/proto/streams/flow_control.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,16 @@ impl FlowControl {
136136
///
137137
/// This is called after receiving a SETTINGS frame with a lower
138138
/// INITIAL_WINDOW_SIZE value.
139-
pub fn dec_send_window(&mut self, sz: WindowSize) -> Result<(), Reason> {
139+
pub fn dec_send_window(&mut self, sz: WindowSize) {
140140
tracing::trace!(
141141
"dec_window; sz={}; window={}, available={}",
142142
sz,
143143
self.window_size,
144144
self.available
145145
);
146-
// ~~This should not be able to overflow `window_size` from the bottom.~~ wrong. it can.
147-
self.window_size.decrease_by(sz)?;
148-
Ok(())
146+
self.window_size
147+
.decrease_by(sz)
148+
.expect("window_size should be greater than decrement");
149149
}
150150

151151
/// Decrement the recv-side window size.

src/proto/streams/send.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -466,18 +466,24 @@ impl Send {
466466
store.try_for_each(|mut stream| {
467467
let stream = &mut *stream;
468468

469+
if stream.state.is_send_closed() && stream.buffered_send_data == 0 {
470+
tracing::trace!(
471+
"skipping send-closed stream; id={:?}; flow={:?}",
472+
stream.id,
473+
stream.send_flow
474+
);
475+
476+
return Ok(());
477+
}
478+
469479
tracing::trace!(
470480
"decrementing stream window; id={:?}; decr={}; flow={:?}",
471481
stream.id,
472482
dec,
473483
stream.send_flow
474484
);
475485

476-
// TODO: this decrement can underflow based on received frames!
477-
stream
478-
.send_flow
479-
.dec_send_window(dec)
480-
.map_err(proto::Error::library_go_away)?;
486+
stream.send_flow.dec_send_window(dec);
481487

482488
// It's possible that decreasing the window causes
483489
// `window_size` (the stream-specific window) to fall below

tests/h2-tests/tests/flow_control.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,7 @@ async fn poll_capacity_wakeup_after_window_update() {
18591859
}
18601860

18611861
#[tokio::test]
1862-
async fn window_size_decremented_past_zero() {
1862+
async fn window_size_does_not_underflow() {
18631863
h2_support::trace_init!();
18641864
let (io, mut client) = mock::new();
18651865

@@ -1891,9 +1891,7 @@ async fn window_size_decremented_past_zero() {
18911891
let builder = server::Builder::new();
18921892
let mut srv = builder.handshake::<_, Bytes>(io).await.expect("handshake");
18931893

1894-
// just keep it open
1895-
let res = poll_fn(move |cx| srv.poll_closed(cx)).await;
1896-
tracing::debug!("{:?}", res);
1894+
poll_fn(move |cx| srv.poll_closed(cx)).await.unwrap();
18971895
};
18981896

18991897
join(client, srv).await;

0 commit comments

Comments
 (0)