Skip to content

Commit ad8fb54

Browse files
committed
Respect peer MAX_FRAME_SIZE
Signed-off-by: Eloi DEMOLIS <eloi.demolis@clever-cloud.com>
1 parent e1cc9c0 commit ad8fb54

File tree

2 files changed

+54
-26
lines changed

2 files changed

+54
-26
lines changed

lib/src/protocol/mux/converter.rs

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::cmp::min;
2+
13
use kawa::{
24
AsBuffer, Block, BlockConverter, Chunk, Flags, Kawa, Pair, ParsingErrorKind, ParsingPhase,
35
StatusLine, Store,
@@ -13,6 +15,7 @@ use crate::protocol::{
1315
};
1416

1517
pub struct H2BlockConverter<'a> {
18+
pub max_frame_size: usize,
1619
pub window: i32,
1720
pub stream_id: StreamId,
1821
pub encoder: &'a mut hpack::Encoder<'static>,
@@ -121,19 +124,25 @@ impl<'a, T: AsBuffer> BlockConverter<T> for H2BlockConverter<'a> {
121124
Block::Chunk(Chunk { data }) => {
122125
let mut header = [0; 9];
123126
let payload_len = data.len();
124-
let (data, payload_len, can_continue) = if self.window >= payload_len as i32 {
125-
// the window is wide enought to send the entire chunk
126-
(data, payload_len as u32, true)
127-
} else if self.window > 0 {
128-
// we split the chunk to fit in the window
129-
let (before, after) = data.split(self.window as usize);
130-
kawa.blocks.push_front(Block::Chunk(Chunk { data: after }));
131-
(before, self.window as u32, false)
132-
} else {
133-
// the window can't take any more bytes, return the chunk to the blocks
134-
kawa.blocks.push_front(Block::Chunk(Chunk { data }));
135-
return false;
136-
};
127+
let (data, payload_len, can_continue) =
128+
if self.window >= payload_len as i32 && self.max_frame_size >= payload_len {
129+
// the window is wide enought to send the entire chunk
130+
(data, payload_len as u32, true)
131+
} else if self.window > 0 {
132+
// we split the chunk to fit in the window
133+
let payload_len = min(self.max_frame_size, self.window as usize);
134+
let (before, after) = data.split(payload_len);
135+
kawa.blocks.push_front(Block::Chunk(Chunk { data: after }));
136+
(
137+
before,
138+
payload_len as u32,
139+
self.max_frame_size < self.window as usize,
140+
)
141+
} else {
142+
// the window can't take any more bytes, return the chunk to the blocks
143+
kawa.blocks.push_front(Block::Chunk(Chunk { data }));
144+
return false;
145+
};
137146
self.window -= payload_len as i32;
138147
gen_frame_header(
139148
&mut header,
@@ -158,19 +167,37 @@ impl<'a, T: AsBuffer> BlockConverter<T> for H2BlockConverter<'a> {
158167
if end_header {
159168
let payload = std::mem::take(&mut self.out);
160169
let mut header = [0; 9];
161-
let flags = if end_stream { 1 } else { 0 } | if end_header { 4 } else { 0 };
162-
gen_frame_header(
163-
&mut header,
164-
&FrameHeader {
165-
payload_len: payload.len() as u32,
166-
frame_type: FrameType::Headers,
167-
flags,
168-
stream_id: self.stream_id,
169-
},
170-
)
171-
.unwrap();
172-
kawa.push_out(Store::from_slice(&header));
173-
kawa.push_out(Store::Alloc(payload.into_boxed_slice(), 0));
170+
let chunks = payload.chunks(self.max_frame_size);
171+
let n_chunks = chunks.len();
172+
for (i, chunk) in chunks.enumerate() {
173+
let flags = if i == 0 && end_stream { 1 } else { 0 }
174+
| if i + 1 == n_chunks { 4 } else { 0 };
175+
if i == 0 {
176+
gen_frame_header(
177+
&mut header,
178+
&FrameHeader {
179+
payload_len: chunk.len() as u32,
180+
frame_type: FrameType::Headers,
181+
flags,
182+
stream_id: self.stream_id,
183+
},
184+
)
185+
.unwrap();
186+
} else {
187+
gen_frame_header(
188+
&mut header,
189+
&FrameHeader {
190+
payload_len: chunk.len() as u32,
191+
frame_type: FrameType::Continuation,
192+
flags,
193+
stream_id: self.stream_id,
194+
},
195+
)
196+
.unwrap();
197+
}
198+
kawa.push_out(Store::from_slice(&header));
199+
kawa.push_out(Store::from_slice(chunk));
200+
}
174201
} else if end_stream {
175202
let mut header = [0; 9];
176203
gen_frame_header(

lib/src/protocol/mux/h2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ impl<Front: SocketHandler> ConnectionH2<Front> {
595595
}
596596

597597
let mut converter = converter::H2BlockConverter {
598+
max_frame_size: self.peer_settings.settings_max_frame_size as usize,
598599
window: 0,
599600
stream_id: 0,
600601
encoder: &mut self.encoder,

0 commit comments

Comments
 (0)