44using System ;
55using System . Collections . Generic ;
66using System . Diagnostics ;
7- using System . Net . Http . HPack ;
87using System . Net . Http . QPack ;
98
109namespace Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Http3
1110{
1211 internal static class QPackHeaderWriter
1312 {
14- public static bool BeginEncode ( IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , out int length )
13+ public static bool BeginEncode ( IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
1514 {
1615 bool hasValue = enumerator . MoveNext ( ) ;
1716 Debug . Assert ( hasValue == true ) ;
1817
1918 buffer [ 0 ] = 0 ;
2019 buffer [ 1 ] = 0 ;
2120
22- bool doneEncode = Encode ( enumerator , buffer . Slice ( 2 ) , out length ) ;
21+ bool doneEncode = Encode ( enumerator , buffer . Slice ( 2 ) , ref totalHeaderSize , out length ) ;
2322
2423 // Add two for the first two bytes.
2524 length += 2 ;
2625 return doneEncode ;
2726 }
2827
29- public static bool BeginEncode ( int statusCode , IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , out int length )
28+ public static bool BeginEncode ( int statusCode , IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
3029 {
3130 bool hasValue = enumerator . MoveNext ( ) ;
3231 Debug . Assert ( hasValue == true ) ;
@@ -36,24 +35,28 @@ public static bool BeginEncode(int statusCode, IEnumerator<KeyValuePair<string,
3635 buffer [ 1 ] = 0 ;
3736
3837 int statusCodeLength = EncodeStatusCode ( statusCode , buffer . Slice ( 2 ) ) ;
39- bool done = Encode ( enumerator , buffer . Slice ( statusCodeLength + 2 ) , throwIfNoneEncoded : false , out int headersLength ) ;
38+ totalHeaderSize += 42 ; // name (:status) + value (xxx) + overhead (32)
39+
40+ bool done = Encode ( enumerator , buffer . Slice ( statusCodeLength + 2 ) , throwIfNoneEncoded : false , ref totalHeaderSize , out int headersLength ) ;
4041 length = statusCodeLength + headersLength + 2 ;
4142
4243 return done ;
4344 }
4445
45- public static bool Encode ( IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , out int length )
46+ public static bool Encode ( IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
4647 {
47- return Encode ( enumerator , buffer , throwIfNoneEncoded : true , out length ) ;
48+ return Encode ( enumerator , buffer , throwIfNoneEncoded : true , ref totalHeaderSize , out length ) ;
4849 }
4950
50- private static bool Encode ( IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , bool throwIfNoneEncoded , out int length )
51+ private static bool Encode ( IEnumerator < KeyValuePair < string , string > > enumerator , Span < byte > buffer , bool throwIfNoneEncoded , ref int totalHeaderSize , out int length )
5152 {
5253 length = 0 ;
5354
5455 do
5556 {
56- if ( ! QPackEncoder . EncodeLiteralHeaderFieldWithoutNameReference ( enumerator . Current . Key , enumerator . Current . Value , buffer . Slice ( length ) , out int headerLength ) )
57+ var current = enumerator . Current ;
58+
59+ if ( ! QPackEncoder . EncodeLiteralHeaderFieldWithoutNameReference ( current . Key , current . Value , buffer . Slice ( length ) , out int headerLength ) )
5760 {
5861 if ( length == 0 && throwIfNoneEncoded )
5962 {
@@ -62,6 +65,8 @@ private static bool Encode(IEnumerator<KeyValuePair<string, string>> enumerator,
6265 return false ;
6366 }
6467
68+ // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-4.1.1.3
69+ totalHeaderSize += HeaderField . GetLength ( current . Key . Length , current . Value . Length ) ;
6570 length += headerLength ;
6671 } while ( enumerator . MoveNext ( ) ) ;
6772
@@ -87,7 +92,7 @@ private static int EncodeStatusCode(int statusCode, Span<byte> buffer)
8792 buffer [ 0 ] = 0b01011111 ;
8893 buffer [ 1 ] = 0b00110000 ;
8994
90- ReadOnlySpan < byte > statusBytes = StatusCodes . ToStatusBytes ( statusCode ) ;
95+ ReadOnlySpan < byte > statusBytes = System . Net . Http . HPack . StatusCodes . ToStatusBytes ( statusCode ) ;
9196 buffer [ 2 ] = ( byte ) statusBytes . Length ;
9297 statusBytes . CopyTo ( buffer . Slice ( 3 ) ) ;
9398
0 commit comments