LCOV - code coverage report
Current view: top level - waltz/h2 - fd_hpack.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 12 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 60 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_h2_fd_hpack_h
       2             : #define HEADER_fd_src_waltz_h2_fd_hpack_h
       3             : 
       4             : /* fd_hpack.h provides APIs for HPACK compression and decompression.
       5             : 
       6             :    Supports the static table and Huffman string coding.  Does not use
       7             :    the dynamic table while encoding.  Assumes that the endpoint used
       8             :    HTTP/2 SETTINGS to force the peer's dynamic table size to zero. */
       9             : 
      10             : #include "fd_h2_base.h"
      11             : 
      12             : /* fd_h2_hdr_t points to an HTTP/2 header name:value pair.
      13             : 
      14             :    {name,value} point to decoded header values stored either in the
      15             :    hardcoded HPACK static table, the binary frame, or a scratch buffer.
      16             :    It is not guaranteed that these are valid ASCII.  These are NOT
      17             :    null-terminated.
      18             : 
      19             :    (hint&FD_H2_HDR_HINT_INDEXED) indicates that the HPACK coding of the
      20             :    header referenced a static table entry.  The index of the entry is
      21             :    in the low 6 bits.
      22             : 
      23             :    (hint&FD_H2_HDR_HINT_HUFFMAN) is internal and can be safely ignored,
      24             :    as fd_hpack_rd_next takes care of Huffman coding. */
      25             : 
      26             : struct fd_h2_hdr {
      27             :   char const * name;
      28             :   char const * value;
      29             :   ushort       name_len;
      30             :   ushort       hint;
      31             :   uint         value_len;
      32             : };
      33             : 
      34             : typedef struct fd_h2_hdr fd_h2_hdr_t;
      35             : 
      36           0 : #define FD_H2_HDR_HINT_NAME_HUFFMAN  ((ushort)0x8000) /* name is huffman coded */
      37           0 : #define FD_H2_HDR_HINT_VALUE_HUFFMAN ((ushort)0x4000) /* value is huffman coded */
      38           0 : #define FD_H2_HDR_HINT_HUFFMAN ((ushort)(FD_H2_HDR_HINT_NAME_HUFFMAN|FD_H2_HDR_HINT_VALUE_HUFFMAN))
      39           0 : #define FD_H2_HDR_HINT_NAME_INDEXED  ((ushort)0x2000) /* name was indexed from table */
      40           0 : #define FD_H2_HDR_HINT_VALUE_INDEXED ((ushort)0x1000) /* value was indexed from table */
      41             : #define FD_H2_HDR_HINT_INDEXED ((ushort)(FD_H2_HDR_HINT_NAME_INDEXED|FD_H2_HDR_HINT_VALUE_INDEXED))
      42           0 : #define FD_H2_HDR_HINT_GET_INDEX(hint) ((uchar)((hint)&0xFF))
      43             : 
      44             : /* An fd_hpack_rd_t object reads a block of HPACK-encoded HTTP/2
      45             :    headers.  For example usage, see test_hpack. */
      46             : 
      47             : struct fd_hpack_rd {
      48             :   uchar const * src;
      49             :   uchar const * src_end;
      50             : };
      51             : 
      52             : typedef struct fd_hpack_rd fd_hpack_rd_t;
      53             : 
      54             : /* fd_hpack_skip_t incrementally decodes a field block whose fields are
      55             :    discarded.  It retains no input or decoded strings, so both records
      56             :    and Huffman strings may cross fragment boundaries.  Like fd_hpack_rd,
      57             :    it assumes the peer's dynamic table size has been forced to zero. */
      58             : 
      59             : struct fd_hpack_skip {
      60             :   ulong  integer;     /* current integer, or encoded string bytes remaining */
      61             :   ushort huff_state;  /* 0 for raw strings, otherwise Huffman decoder state */
      62             :   uchar  phase;
      63             :   uchar  int_shift;   /* 0, or 7 plus the shift of the next continuation octet */
      64             :   uchar  field_seen;  /* table size updates are only allowed before fields */
      65             : };
      66             : 
      67             : typedef struct fd_hpack_skip fd_hpack_skip_t;
      68             : 
      69             : FD_PROTOTYPES_BEGIN
      70             : 
      71             : /* Start a new field block. */
      72             : 
      73             : static inline void
      74           0 : fd_hpack_skip_init( fd_hpack_skip_t * skip ) {
      75           0 :   *skip = (fd_hpack_skip_t){0};
      76           0 : }
      77             : 
      78             : /* Decode a fragment without retaining its fields.  fin marks the end of
      79             :    the field block, not the end of a string or an individual frame.
      80             :    Returns FD_H2_SUCCESS for a valid complete block or an incomplete
      81             :    prefix when !fin.  Returns FD_H2_ERR_COMPRESSION for invalid HPACK,
      82             :    integers with more than eight continuation octets, or an unfinished
      83             :    record when fin.  Errors remain sticky until fd_hpack_skip_init. */
      84             : 
      85             : uint
      86             : fd_hpack_skip_feed( fd_hpack_skip_t * skip,
      87             :                     uchar const *     src,
      88             :                     ulong             srcsz,
      89             :                     int               fin );
      90             : 
      91             : /* fd_hpack_rd_init initializes a hpack_rd for reading of the header
      92             :    block in src.  hpack_rd has a read interest in src for its entire
      93             :    lifetime. */
      94             : 
      95             : fd_hpack_rd_t *
      96             : fd_hpack_rd_init( fd_hpack_rd_t * rd,
      97             :                   uchar const *   src,
      98             :                   ulong           srcsz );
      99             : 
     100             : /* fd_hpack_rd_done returns 1 if all header entries were read from
     101             :    hpack_rd.  Returns 0 if fd_hpack_rd_next should be called again. */
     102             : 
     103             : static inline int
     104           0 : fd_hpack_rd_done( fd_hpack_rd_t const * rd ) {
     105           0 :   return rd->src >= rd->src_end;
     106           0 : }
     107             : 
     108             : /* fd_hpack_rd_next reads the next header from hpack_rd.  hdr is
     109             :    populated with pointers to the decoded data.  These pointers either
     110             :    point into hpack_rd->src or *scratch.
     111             : 
     112             :    *scratch is assumed to point to the next free byte in a scratch
     113             :    buffer.  scratch_end points one past the last byte of the scratch
     114             :    buffer.
     115             : 
     116             :    Returns FD_H2_SUCCESS, populates header, and updates *scratch on
     117             :    success.  On failure, returns FD_H2_ERR_COMPRESSION and leaves
     118             :    *scratch intact.  Reasons for failure include HPACK parse error,
     119             :    out-of-bounds table index, use of the dynamic table, Huffman coding
     120             :    error, or out of scratch space.  The caller should assume that *hdr
     121             :    and **scratch (the free bytes in the scratch buffer, not the pointer
     122             :    itself) are invalidated/filled with garbage on failure. */
     123             : 
     124             : uint
     125             : fd_hpack_rd_next( fd_hpack_rd_t * hpack_rd,
     126             :                   fd_h2_hdr_t *   hdr,
     127             :                   uchar **        scratch,
     128             :                   uchar *         scratch_end );
     129             : 
     130             : FD_PROTOTYPES_END
     131             : 
     132             : #endif /* HEADER_fd_src_waltz_h2_fd_hpack_h */

Generated by: LCOV version 1.14