LCOV - code coverage report
Current view: top level - waltz/h2 - fd_hpack_wr.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 47 86 54.7 %
Date: 2026-08-18 04:36:42 Functions: 8 20 40.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_h2_fd_hpack_wr_h
       2             : #define HEADER_fd_src_waltz_h2_fd_hpack_wr_h
       3             : 
       4             : /* fd_hpack_wr.h provides simple APIs to generate HPACK header entries.
       5             :    Generates somewhat wasteful serializations, but is quite simple. */
       6             : 
       7             : #include "fd_h2_base.h"
       8             : #include "fd_h2_rbuf.h"
       9             : 
      10          18 : #define FD_HPACK_INDEXED_SHORT( val ) ((uchar)( 0x80|(val) ))
      11             : 
      12             : #if FD_HAS_X86
      13             : #if defined(__GNUC__) && !defined(__clang__)
      14             : #include <x86gprintrin.h>
      15             : #else
      16             : #include <immintrin.h>
      17             : #endif
      18             : #endif
      19             : 
      20             : FD_PROTOTYPES_BEGIN
      21             : 
      22             : static inline ulong
      23             : fd_hpack_wr_varint(
      24             :     uchar code[9],
      25             :     uint  prefix,
      26             :     uint  addend,
      27             :     ulong number /* in [0,2^56) */
      28          18 : ) {
      29          18 :   ulong sz;
      30          18 :   if( number<addend ) {
      31          18 :     code[0] = (uchar)( prefix|number );
      32          18 :     sz = 1UL;
      33          18 :   } else {
      34           0 :     code[0] = (uchar)( prefix|addend );
      35           0 :     ulong tail = number-addend;
      36           0 : #if FD_HAS_X86 && defined(__BMI2__)
      37           0 :     ulong enc = _pdep_u64( tail, 0x7f7f7f7f7f7f7f7fUL );
      38             : #else
      39             :     ulong enc =
      40             :       ( ( tail<<0 )&0x000000000000007fUL ) |
      41             :       ( ( tail<<1 )&0x0000000000007f00UL ) |
      42             :       ( ( tail<<2 )&0x00000000007f0000UL ) |
      43             :       ( ( tail<<3 )&0x000000007f000000UL ) |
      44             :       ( ( tail<<4 )&0x0000007f00000000UL ) |
      45             :       ( ( tail<<5 )&0x00007f0000000000UL ) |
      46             :       ( ( tail<<6 )&0x007f000000000000UL ) |
      47             :       ( ( tail<<7 )&0x7f00000000000000UL );
      48             : #endif
      49           0 :     int   msb   = fd_ulong_find_msb_w_default( enc, 0 );
      50           0 :     int   shift = 64-(msb&0x38);
      51           0 :     ulong mask  = shift==64 ? 0UL : 0x8080808080808080UL>>shift;
      52           0 :     FD_STORE( ulong, code+1, enc|mask );
      53           0 :     sz = 2 + (ulong)( msb>>3 );
      54           0 :   }
      55          18 :   return sz;
      56          18 : }
      57             : 
      58             : static inline int
      59             : fd_hpack_wr_private_indexed( fd_h2_rbuf_t * rbuf_tx,
      60          18 :                              ulong          idx ) {
      61          18 :   if( FD_UNLIKELY( !fd_h2_rbuf_free_sz( rbuf_tx ) ) ) return 0;
      62          18 :   uchar code[1] = { FD_HPACK_INDEXED_SHORT( idx ) };
      63          18 :   fd_h2_rbuf_push( rbuf_tx, code, 1 );
      64          18 :   return 1;
      65          18 : }
      66             : 
      67             : static inline int
      68             : fd_hpack_wr_private_name_indexed_0(
      69             :     fd_h2_rbuf_t * rbuf_tx,
      70             :     ulong          key,
      71             :     ulong          value_len  /* in [0,128) */
      72          18 : ) {
      73          18 :   uchar prefix[10] = { (uchar)key };
      74          18 :   if( FD_UNLIKELY( fd_h2_rbuf_free_sz( rbuf_tx ) < sizeof(prefix)+value_len ) ) return 0;
      75          18 :   ulong prefix_len = 1+fd_hpack_wr_varint( prefix+1, 0x00, 0x7f, value_len );
      76          18 :   fd_h2_rbuf_push( rbuf_tx, prefix, prefix_len );
      77          18 :   return 1;
      78          18 : }
      79             : 
      80             : static inline int
      81           9 : fd_hpack_wr_method_post( fd_h2_rbuf_t * rbuf_tx ) {
      82           9 :   return fd_hpack_wr_private_indexed( rbuf_tx, 0x03 );
      83           9 : }
      84             : 
      85             : static inline int
      86             : fd_hpack_wr_scheme( fd_h2_rbuf_t * rbuf_tx,
      87           9 :                     int            is_https ) {
      88           9 :   if( is_https ) {
      89           9 :     return fd_hpack_wr_private_indexed( rbuf_tx, 0x07 );
      90           9 :   } else {
      91           0 :     return fd_hpack_wr_private_indexed( rbuf_tx, 0x06 );
      92           0 :   }
      93           9 : }
      94             : 
      95             : /* fd_hpack_wr_path writes a ':path: ...' header.  path_len must be in
      96             :    [0,128). */
      97             : 
      98             : static inline int
      99             : fd_hpack_wr_path( fd_h2_rbuf_t * rbuf_tx,
     100             :                   char const *   path,
     101           9 :                   ulong          path_len ) {
     102           9 :   if( FD_UNLIKELY( !fd_hpack_wr_private_name_indexed_0( rbuf_tx, 0x04, path_len ) ) ) return 0;
     103           9 :   fd_h2_rbuf_push( rbuf_tx, path, path_len );
     104           9 :   return 1;
     105           9 : }
     106             : 
     107             : /* fd_hpack_wr_trailers writes the 'te: trailers' header. */
     108             : 
     109             : static inline int
     110           9 : fd_hpack_wr_trailers( fd_h2_rbuf_t * rbuf_tx ) {
     111           9 :   static char const code[] =
     112           9 :     "\x00"
     113           9 :     "\x02" "te"
     114           9 :     "\x08" "trailers";
     115           9 :   if( FD_UNLIKELY( fd_h2_rbuf_free_sz( rbuf_tx )<sizeof(code)-1 ) ) return 0;
     116           9 :   fd_h2_rbuf_push( rbuf_tx, code, sizeof(code)-1 );
     117           9 :   return 1;
     118           9 : }
     119             : 
     120             : /* fd_hpack_wr_user_agent writes a 'user-agent' header.
     121             :    user_agent_len is in [0,128). */
     122             : 
     123             : static inline int
     124             : fd_hpack_wr_user_agent( fd_h2_rbuf_t * rbuf_tx,
     125           9 :                         ulong          user_agent_len ) {
     126           9 :   return fd_hpack_wr_private_name_indexed_0( rbuf_tx, 0x7a, user_agent_len );
     127           9 : }
     128             : 
     129             : /* fd_hpack_wr_auth_bearer writes an 'authorization: Bearer xxx' header.
     130             :    Uses a never-indexed literal to prevent compression attacks. */
     131             : 
     132             : static inline int
     133             : fd_hpack_wr_auth_bearer( fd_h2_rbuf_t * rbuf_tx,
     134             :                          char const *   auth_token,
     135           0 :                          ulong          auth_token_len ) {
     136           0 :   uchar prefix[11] = { 0x1f, 0x08 };
     137           0 :   ulong value_len = 7UL+auth_token_len;
     138           0 :   if( FD_UNLIKELY( fd_h2_rbuf_free_sz( rbuf_tx ) < sizeof(prefix)+value_len ) ) return 0;
     139           0 :   ulong prefix_len = 2+fd_hpack_wr_varint( prefix+2, 0x00, 0x7f, value_len );
     140           0 :   fd_h2_rbuf_push( rbuf_tx, prefix,     prefix_len     );
     141           0 :   fd_h2_rbuf_push( rbuf_tx, "Bearer ",  7              );
     142           0 :   fd_h2_rbuf_push( rbuf_tx, auth_token, auth_token_len );
     143           0 :   return 1;
     144           0 : }
     145             : 
     146             : /* fd_hpack_wr_authority writes an ':authority: host[:port]' header.
     147             :    Port is only specified if it is non-zero. */
     148             : 
     149             : static inline int
     150             : fd_hpack_wr_authority( fd_h2_rbuf_t * rbuf_tx,
     151             :                        char const *   host,
     152             :                        ulong          host_len,
     153           0 :                        ushort         port ) {
     154           0 :   char suffix_cstr[ 7 ];
     155           0 :   ulong port_cstr_len = fd_ushort_base10_dig_cnt( port );
     156           0 :   char * p = fd_cstr_init( suffix_cstr );
     157           0 :   p = fd_cstr_append_char( p, ':' );
     158           0 :   p = fd_cstr_append_ushort_as_text( p, 0, 0, port, port_cstr_len );
     159           0 :   ulong suffix_len = (ulong)p - (ulong)suffix_cstr;
     160           0 :   fd_cstr_fini( p );
     161             : 
     162             :   //if( !port ) suffix_len = 0;
     163           0 :   ulong value_len  = host_len+suffix_len;
     164             : 
     165           0 :   uchar prefix[10] = { (uchar)0x01 };
     166           0 :   if( FD_UNLIKELY( fd_h2_rbuf_free_sz( rbuf_tx ) < sizeof(prefix)+value_len ) ) return 0;
     167           0 :   ulong prefix_len = 1+fd_hpack_wr_varint( prefix+1, 0x00, 0x7f, value_len );
     168           0 :   fd_h2_rbuf_push( rbuf_tx, prefix,      prefix_len );
     169           0 :   fd_h2_rbuf_push( rbuf_tx, host,        host_len   );
     170           0 :   fd_h2_rbuf_push( rbuf_tx, suffix_cstr, suffix_len );
     171           0 :   return 1;
     172           0 : }
     173             : 
     174             : FD_PROTOTYPES_END
     175             : 
     176             : #endif /* HEADER_fd_src_waltz_h2_fd_hpack_wr_h */

Generated by: LCOV version 1.14