1
+ use std:: cmp:: min;
2
+
1
3
use kawa:: {
2
4
AsBuffer , Block , BlockConverter , Chunk , Flags , Kawa , Pair , ParsingErrorKind , ParsingPhase ,
3
5
StatusLine , Store ,
@@ -13,6 +15,7 @@ use crate::protocol::{
13
15
} ;
14
16
15
17
pub struct H2BlockConverter < ' a > {
18
+ pub max_frame_size : usize ,
16
19
pub window : i32 ,
17
20
pub stream_id : StreamId ,
18
21
pub encoder : & ' a mut hpack:: Encoder < ' static > ,
@@ -121,19 +124,25 @@ impl<'a, T: AsBuffer> BlockConverter<T> for H2BlockConverter<'a> {
121
124
Block :: Chunk ( Chunk { data } ) => {
122
125
let mut header = [ 0 ; 9 ] ;
123
126
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
+ } ;
137
146
self . window -= payload_len as i32 ;
138
147
gen_frame_header (
139
148
& mut header,
@@ -158,19 +167,37 @@ impl<'a, T: AsBuffer> BlockConverter<T> for H2BlockConverter<'a> {
158
167
if end_header {
159
168
let payload = std:: mem:: take ( & mut self . out ) ;
160
169
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
+ }
174
201
} else if end_stream {
175
202
let mut header = [ 0 ; 9 ] ;
176
203
gen_frame_header (
0 commit comments