Skip to content

Commit 0077d3d

Browse files
authoredFeb 2, 2024
fix: stream flow control insufficient size before ack (#746)
* fix: stream flow control insufficient size before ack * test: client sending data before initial settings ack
1 parent 4ce5955 commit 0077d3d

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed
 

‎src/proto/connection.rs

-4
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,6 @@ where
106106
pub fn new(codec: Codec<T, Prioritized<B>>, config: Config) -> Connection<T, P, B> {
107107
fn streams_config(config: &Config) -> streams::Config {
108108
streams::Config {
109-
local_init_window_sz: config
110-
.settings
111-
.initial_window_size()
112-
.unwrap_or(DEFAULT_INITIAL_WINDOW_SIZE),
113109
initial_max_send_streams: config.initial_max_send_streams,
114110
local_max_buffer_size: config.max_send_buffer_size,
115111
local_next_stream_id: config.next_stream_id,

‎src/proto/streams/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ use std::time::Duration;
3333

3434
#[derive(Debug)]
3535
pub struct Config {
36-
/// Initial window size of locally initiated streams
37-
pub local_init_window_sz: WindowSize,
38-
3936
/// Initial maximum number of locally initiated streams.
4037
/// After receiving a Settings frame from the remote peer,
4138
/// the connection will overwrite this value with the

‎src/proto/streams/recv.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl Recv {
9393
flow.assign_capacity(DEFAULT_INITIAL_WINDOW_SIZE).unwrap();
9494

9595
Recv {
96-
init_window_sz: config.local_init_window_sz,
96+
init_window_sz: DEFAULT_INITIAL_WINDOW_SIZE,
9797
flow,
9898
in_flight_data: 0 as WindowSize,
9999
next_stream_id: Ok(next_stream_id.into()),

‎tests/h2-tests/tests/server.rs

+45
Original file line numberDiff line numberDiff line change
@@ -1453,3 +1453,48 @@ async fn client_drop_connection_without_close_notify() {
14531453

14541454
join(client, h2).await;
14551455
}
1456+
1457+
#[tokio::test]
1458+
async fn init_window_size_smaller_than_default_should_use_default_before_ack() {
1459+
h2_support::trace_init!();
1460+
1461+
let (io, mut client) = mock::new();
1462+
let client = async move {
1463+
// Client can send in some data before ACK;
1464+
// Server needs to make sure the Recv stream has default window size
1465+
// as per https://datatracker.ietf.org/doc/html/rfc9113#name-initial-flow-control-window
1466+
client.write_preface().await;
1467+
client
1468+
.send(frame::Settings::default().into())
1469+
.await
1470+
.unwrap();
1471+
client.next().await.expect("unexpected EOF").unwrap();
1472+
client
1473+
.send_frame(frames::headers(1).request("GET", "https://example.com/"))
1474+
.await;
1475+
client.send_frame(frames::data(1, &b"hello"[..])).await;
1476+
client.send(frame::Settings::ack().into()).await.unwrap();
1477+
client.next().await;
1478+
client
1479+
.recv_frame(frames::headers(1).response(200).eos())
1480+
.await;
1481+
};
1482+
1483+
let mut builder = server::Builder::new();
1484+
builder.max_concurrent_streams(1);
1485+
builder.initial_window_size(1);
1486+
let h2 = async move {
1487+
let mut srv = builder.handshake::<_, Bytes>(io).await.expect("handshake");
1488+
let (req, mut stream) = srv.next().await.unwrap().unwrap();
1489+
1490+
assert_eq!(req.method(), &http::Method::GET);
1491+
1492+
let rsp = http::Response::builder().status(200).body(()).unwrap();
1493+
stream.send_response(rsp, true).unwrap();
1494+
1495+
// Drive the state forward
1496+
let _ = poll_fn(|cx| srv.poll_closed(cx)).await.unwrap();
1497+
};
1498+
1499+
join(client, h2).await;
1500+
}

0 commit comments

Comments
 (0)