diff --git a/quinn-proto/src/connection/streams/recv.rs b/quinn-proto/src/connection/streams/recv.rs index e180a852a..2a820b4d0 100644 --- a/quinn-proto/src/connection/streams/recv.rs +++ b/quinn-proto/src/connection/streams/recv.rs @@ -107,8 +107,7 @@ impl Recv { // smaller than `stream_receive_window` in order to make sure the stream // does not get stuck. let diff = max_stream_data - self.sent_max_stream_data; - let transmit = - self.final_offset_unknown() && !self.stopped && diff >= (stream_receive_window / 8); + let transmit = self.can_send_flow_control() && diff >= (stream_receive_window / 8); (max_stream_data, ShouldTransmit(transmit)) } @@ -134,6 +133,13 @@ impl Recv { matches!(self.state, RecvState::Recv { size: None }) } + /// Whether stream-level flow control updates should be sent for this stream + pub(super) fn can_send_flow_control(&self) -> bool { + // Stream-level flow control is redundant if the sender has already sent the whole stream, + // and moot if we no longer want data on this stream. + self.final_offset_unknown() && !self.stopped + } + /// Whether data is still being accepted from the peer pub(super) fn is_receiving(&self) -> bool { matches!(self.state, RecvState::Recv { .. }) diff --git a/quinn-proto/src/connection/streams/state.rs b/quinn-proto/src/connection/streams/state.rs index 339efa112..57c0c5036 100644 --- a/quinn-proto/src/connection/streams/state.rs +++ b/quinn-proto/src/connection/streams/state.rs @@ -358,7 +358,7 @@ impl StreamsState { self.recv .get(&id) .and_then(|s| s.as_ref()) - .map_or(false, |s| s.final_offset_unknown() && !s.stopped) + .map_or(false, |s| s.can_send_flow_control()) } pub(in crate::connection) fn write_control_frames( @@ -446,7 +446,7 @@ impl StreamsState { Some(x) => x, None => continue, }; - if !rs.final_offset_unknown() || rs.stopped { + if !rs.can_send_flow_control() { continue; } retransmits.get_or_create().max_stream_data.insert(id);