1+ use std:: cmp:: min;
2+
13use kawa:: {
24 AsBuffer , Block , BlockConverter , Chunk , Flags , Kawa , Pair , ParsingErrorKind , ParsingPhase ,
35 StatusLine , Store ,
@@ -13,6 +15,7 @@ use crate::protocol::{
1315} ;
1416
1517pub 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 (
0 commit comments