44using System ;
55using System . Diagnostics ;
66using System . Net . Http . QPack ;
7+ using System . Text ;
78
89namespace Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Http3 ;
910
1011internal static class QPackHeaderWriter
1112{
12- public static bool BeginEncode ( Http3HeadersEnumerator enumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
13+ public static bool BeginEncodeHeaders ( Http3HeadersEnumerator enumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
1314 {
1415 bool hasValue = enumerator . MoveNext ( ) ;
1516 Debug . Assert ( hasValue == true ) ;
@@ -24,40 +25,47 @@ public static bool BeginEncode(Http3HeadersEnumerator enumerator, Span<byte> buf
2425 return doneEncode ;
2526 }
2627
27- public static bool BeginEncode ( int statusCode , Http3HeadersEnumerator enumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
28+ public static bool BeginEncodeHeaders ( int statusCode , Http3HeadersEnumerator headersEnumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
2829 {
29- bool hasValue = enumerator . MoveNext ( ) ;
30- Debug . Assert ( hasValue == true ) ;
30+ length = 0 ;
3131
3232 // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#header-prefix
3333 buffer [ 0 ] = 0 ;
3434 buffer [ 1 ] = 0 ;
3535
3636 int statusCodeLength = EncodeStatusCode ( statusCode , buffer . Slice ( 2 ) ) ;
3737 totalHeaderSize += 42 ; // name (:status) + value (xxx) + overhead (32)
38+ length += statusCodeLength + 2 ;
3839
39- bool done = Encode ( enumerator , buffer . Slice ( statusCodeLength + 2 ) , throwIfNoneEncoded : false , ref totalHeaderSize , out int headersLength ) ;
40- length = statusCodeLength + headersLength + 2 ;
40+ if ( ! headersEnumerator . MoveNext ( ) )
41+ {
42+ return true ;
43+ }
44+
45+ bool done = Encode ( headersEnumerator , buffer . Slice ( statusCodeLength + 2 ) , throwIfNoneEncoded : false , ref totalHeaderSize , out int headersLength ) ;
46+ length += headersLength ;
4147
4248 return done ;
4349 }
4450
45- public static bool Encode ( Http3HeadersEnumerator enumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
51+ public static bool Encode ( Http3HeadersEnumerator headersEnumerator , Span < byte > buffer , ref int totalHeaderSize , out int length )
4652 {
47- return Encode ( enumerator , buffer , throwIfNoneEncoded : true , ref totalHeaderSize , out length ) ;
53+ return Encode ( headersEnumerator , buffer , throwIfNoneEncoded : true , ref totalHeaderSize , out length ) ;
4854 }
4955
50- private static bool Encode ( Http3HeadersEnumerator enumerator , Span < byte > buffer , bool throwIfNoneEncoded , ref int totalHeaderSize , out int length )
56+ private static bool Encode ( Http3HeadersEnumerator headersEnumerator , Span < byte > buffer , bool throwIfNoneEncoded , ref int totalHeaderSize , out int length )
5157 {
5258 length = 0 ;
5359
5460 do
5561 {
56- var current = enumerator . Current ;
57- var valueEncoding = ReferenceEquals ( enumerator . EncodingSelector , KestrelServerOptions . DefaultHeaderEncodingSelector )
58- ? null : enumerator . EncodingSelector ( current . Key ) ;
62+ var staticTableId = headersEnumerator . QPackStaticTableId ;
63+ var name = headersEnumerator . Current . Key ;
64+ var value = headersEnumerator . Current . Value ;
65+ var valueEncoding = ReferenceEquals ( headersEnumerator . EncodingSelector , KestrelServerOptions . DefaultHeaderEncodingSelector )
66+ ? null : headersEnumerator . EncodingSelector ( name ) ;
5967
60- if ( ! QPackEncoder . EncodeLiteralHeaderFieldWithoutNameReference ( current . Key , current . Value , valueEncoding , buffer . Slice ( length ) , out int headerLength ) )
68+ if ( ! EncodeHeader ( buffer . Slice ( length ) , staticTableId , name , value , valueEncoding , out var headerLength ) )
6169 {
6270 if ( length == 0 && throwIfNoneEncoded )
6371 {
@@ -67,13 +75,20 @@ private static bool Encode(Http3HeadersEnumerator enumerator, Span<byte> buffer,
6775 }
6876
6977 // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-4.1.1.3
70- totalHeaderSize += HeaderField . GetLength ( current . Key . Length , current . Value . Length ) ;
78+ totalHeaderSize += HeaderField . GetLength ( name . Length , value . Length ) ;
7179 length += headerLength ;
72- } while ( enumerator . MoveNext ( ) ) ;
80+ } while ( headersEnumerator . MoveNext ( ) ) ;
7381
7482 return true ;
7583 }
7684
85+ private static bool EncodeHeader ( Span < byte > buffer , int staticTableId , string name , string value , Encoding ? valueEncoding , out int headerLength )
86+ {
87+ return staticTableId == - 1
88+ ? QPackEncoder . EncodeLiteralHeaderFieldWithoutNameReference ( name , value , valueEncoding , buffer , out headerLength )
89+ : QPackEncoder . EncodeLiteralHeaderFieldWithStaticNameReference ( staticTableId , value , valueEncoding , buffer , out headerLength ) ;
90+ }
91+
7792 private static int EncodeStatusCode ( int statusCode , Span < byte > buffer )
7893 {
7994 switch ( statusCode )
0 commit comments