Skip to content

Commit 7c837e1

Browse files
committed
feat(h2): implement flow control for h2 bodies
This is implemented sligntly differently than what the TODO comment said, but matches with tower-h2's implementation. h2 already handles the buffering of the pending chunk and capacity management for it, so we just want to make sure there's some capacity available (i.e. the previous chunk has been fully written out). Closes hyperium#1548
1 parent 386fc0d commit 7c837e1

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

Diff for: src/proto/h2/mod.rs

+16-14
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,21 @@ where
103103
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
104104
loop {
105105
if !self.data_done {
106-
// TODO: make use of flow control on SendStream
107-
// If you're looking at this and thinking of trying to fix this TODO,
108-
// you may want to look at:
109-
// https://docs.rs/h2/0.1.*/h2/struct.SendStream.html
110-
//
111-
// With that doc open, we'd want to do these things:
112-
// - check self.body_tx.capacity() to see if we can send *any* data
113-
// - if > 0:
114-
// - poll self.stream
115-
// - reserve chunk.len() more capacity (because its about to be used)?
116-
// - send the chunk
117-
// - else:
118-
// - try reserve a smallish amount of capacity
119-
// - call self.body_tx.poll_capacity(), return if NotReady
106+
if self.body_tx.capacity() == 0 {
107+
// we don't have the next chunk of data yet, so just reserve 1 byte to make
108+
// sure there's some capacity available. h2 will handle the capacity management
109+
// for the actual body chunk.
110+
self.body_tx.reserve_capacity(1);
111+
112+
loop {
113+
match try_ready!(self.body_tx.poll_capacity().map_err(::Error::new_h2)) {
114+
Some(0) => {}
115+
Some(_) => break,
116+
None => return Err(::Error::new_canceled(None::<::Error>)),
117+
}
118+
}
119+
}
120+
120121
match try_ready!(self.stream.poll_data().map_err(|e| self.on_err(e))) {
121122
Some(chunk) => {
122123
let is_eos = self.stream.is_end_stream();
@@ -136,6 +137,7 @@ where
136137
}
137138
}
138139
None => {
140+
self.body_tx.reserve_capacity(0);
139141
let is_eos = self.stream.is_end_stream();
140142
if is_eos {
141143
return self.send_eos_frame().map(Async::Ready);

0 commit comments

Comments
 (0)