3131 * The server will start the connection by sending a setting frame, which will
3232 * specify a zero-length dynamic dictionary for QPACK.
3333 */
34+ #include <stdio.h>
3435#include <string.h>
3536#include <stdlib.h>
3637#include <stdint.h>
@@ -478,6 +479,16 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
478479 decoded_length , & parts -> path , & parts -> path_length );
479480 }
480481 break ;
482+ case http_pseudo_header_authority :
483+ if (parts -> authority != NULL ) {
484+ /* Duplicate authority! */
485+ bytes = 0 ;
486+ }
487+ else {
488+ bytes = h3zero_parse_qpack_header_value_string (bytes , decoded ,
489+ decoded_length , & parts -> authority , & parts -> authority_length );
490+ }
491+ break ;
481492 case http_header_range :
482493 if (parts -> range != NULL ) {
483494 /* Duplicate content type! */
@@ -517,7 +528,16 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
517528 }
518529 else {
519530 bytes = h3zero_parse_qpack_header_value_string (bytes , decoded ,
520- decoded_length , & parts -> wt_protocol , & parts -> wt_available_protocols_length );
531+ decoded_length , & parts -> wt_protocol , & parts -> wt_protocol_length );
532+ /* WT-Protocol is a Structured Header String — strip surrounding quotes */
533+ if (parts -> wt_protocol != NULL && parts -> wt_protocol_length >= 2 &&
534+ parts -> wt_protocol [0 ] == '"' &&
535+ parts -> wt_protocol [parts -> wt_protocol_length - 1 ] == '"' ) {
536+ uint8_t * p = (uint8_t * )parts -> wt_protocol ;
537+ parts -> wt_protocol_length -= 2 ;
538+ memmove (p , p + 1 , parts -> wt_protocol_length );
539+ p [parts -> wt_protocol_length ] = 0 ;
540+ }
521541 }
522542 break ;
523543
@@ -537,11 +557,12 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
537557int h3zero_get_interesting_header_type (uint8_t * name , size_t name_length , int is_huffman )
538558{
539559 char const * interesting_header_name [] = {
540- ":method" , ":path" , ":status" , "content-type" , ":protocol" , "origin" , "range" ,
560+ ":method" , ":path" , ":authority" , ": status" , "content-type" , ":protocol" , "origin" , "range" ,
541561 H3ZERO_WT_AVAILABLE_PROTOCOLS , H3ZERO_WT_PROTOCOL ,
542562 NULL };
543563 const http_header_enum_t interesting_header [] = {
544564 http_pseudo_header_method , http_pseudo_header_path ,
565+ http_pseudo_header_authority ,
545566 http_pseudo_header_status , http_header_content_type ,
546567 http_pseudo_header_protocol , http_header_origin ,
547568 http_header_range , http_header_wt_available_protocols , http_header_wt_protocol
@@ -998,9 +1019,12 @@ uint8_t * h3zero_create_response_header_frame_ex(uint8_t * bytes, uint8_t * byte
9981019 }
9991020
10001021 if (wt_protocol != NULL ) {
1022+ /* WT-Protocol is a Structured Header String and must be quoted per spec */
1023+ char quoted [258 ];
1024+ int quoted_len = snprintf (quoted , sizeof (quoted ), "\"%s\"" , wt_protocol );
10011025 bytes = h3zero_qpack_literal_plus_name_encode (bytes , bytes_max ,
10021026 (uint8_t * )H3ZERO_WT_PROTOCOL , strlen (H3ZERO_WT_PROTOCOL ),
1003- (uint8_t * )wt_protocol , strlen ( wt_protocol ) );
1027+ (uint8_t * )quoted , ( size_t ) quoted_len );
10041028 }
10051029
10061030 return bytes ;
@@ -1113,6 +1137,11 @@ void h3zero_release_header_parts(h3zero_header_parts_t* header)
11131137 * ((uint8_t * * )& header -> path ) = NULL ;
11141138 header -> path_length = 0 ;
11151139 }
1140+ if (header -> authority != NULL ) {
1141+ free ((uint8_t * )header -> authority );
1142+ * ((uint8_t * * )& header -> authority ) = NULL ;
1143+ header -> authority_length = 0 ;
1144+ }
11161145 if (header -> range != NULL ) {
11171146 free ((uint8_t * )header -> range );
11181147 * ((uint8_t * * )& header -> range ) = NULL ;
0 commit comments