Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_http2.c File Reference

HTTP/2 (RFC 7540) wire framing and HPACK (RFC 7541) header compression. More...

#include "nilorea/n_http2.h"
#include <stdlib.h>
#include <string.h>
+ Include dependency graph for n_http2.c:

Go to the source code of this file.

Data Structures

struct  H2_DYN_ENTRY
 one HPACK dynamic table entry (owned strings and its accounted size) More...
 
struct  N_H2_HPACK
 HPACK codec context: the dynamic table (index 0 = most recently added) More...
 

Functions

static int hpack_dyn_add (N_H2_HPACK *ctx, const char *name, const char *value)
 insert (name, value) at the front of the dynamic table, evicting as needed; both strings are copied.
 
static void hpack_evict (N_H2_HPACK *ctx)
 drop the oldest dynamic entries until the table fits max_size
 
static int hpack_huff_decode (const unsigned char *s, size_t len, char **out)
 decode a Huffman-coded string of len bytes into a fresh C string
 
static int hpack_huff_lookup (uint32_t code, int nbits)
 find the Huffman symbol for an accumulated code of nbits bits, or -1
 
static int hpack_int_decode (const unsigned char *buf, size_t len, size_t *pos, int prefix_bits, uint64_t *out)
 decode an HPACK integer with an N-bit prefix; advances *pos
 
static size_t hpack_int_encode (unsigned char *out, size_t cap, int prefix_bits, unsigned char flags, uint64_t value)
 encode an HPACK integer with an N-bit prefix and high-bit flags
 
static int hpack_lookup (const N_H2_HPACK *ctx, uint64_t idx, const char **name, const char **value)
 resolve a table index to its name/value (const, not owned).
 
static int hpack_str_decode (const unsigned char *buf, size_t len, size_t *pos, char **out)
 decode an HPACK string (Huffman or literal); allocates *out
 
static size_t hpack_str_encode (unsigned char *out, size_t cap, const char *s)
 encode a literal (non-Huffman) string with its 7-bit length prefix
 
size_t n_http2_frame_build_header (unsigned char *out, size_t out_cap, uint32_t length, int type, int flags, uint32_t stream_id)
 write a 9-byte HTTP/2 frame header into out.
 
int n_http2_frame_parse (const unsigned char *buf, size_t len, N_H2_FRAME *frame, size_t *consumed)
 parse one HTTP/2 frame from a byte buffer (stateless).
 
int n_http2_hpack_decode (N_H2_HPACK *ctx, const unsigned char *block, size_t len, N_H2_HEADER *out, size_t max_out, size_t *count)
 decode an HPACK header block into out[] (owned name/value strings).
 
size_t n_http2_hpack_encode (const N_H2_HEADER *headers, size_t n, unsigned char *out, size_t out_cap)
 encode a header list into a block using literal representations without indexing and without Huffman (a valid, interoperable, self-contained encoding that needs no dynamic-table state).
 
void n_http2_hpack_free (N_H2_HPACK **pctx)
 free an HPACK codec context and NULL the caller's pointer
 
void n_http2_hpack_headers_free (N_H2_HEADER *headers, size_t n)
 free the owned name/value strings of a decoded header array (does not free the array itself)
 
N_H2_HPACKn_http2_hpack_new (size_t max_table_size)
 create an HPACK codec context with the given dynamic table size limit (0 uses N_H2_HPACK_DEFAULT_TABLE_SIZE).
 
void n_http2_hpack_set_max_size (N_H2_HPACK *ctx, size_t max_table_size)
 change the dynamic table size limit (a SETTINGS_HEADER_TABLE_SIZE change), evicting entries as needed so the table fits.
 
int n_http2_settings_parse (const unsigned char *payload, size_t len, N_H2_SETTING *out, size_t max, size_t *count)
 parse a SETTINGS frame payload (6-byte id/value entries) into out.
 

Variables

static const uint32_t hpack_huff_code [256]
 HPACK Huffman codes (RFC 7541 Appendix B), index = byte value 0..255.
 
static const uint8_t hpack_huff_len [256]
 HPACK Huffman code lengths in bits (RFC 7541 Appendix B)
 
static const char *const hpack_static_name [61]
 HPACK static table names (RFC 7541 Appendix A, index 1..61)
 
static const char *const hpack_static_value [61]
 HPACK static table values (empty where the entry has no value)
 

Detailed Description

HTTP/2 (RFC 7540) wire framing and HPACK (RFC 7541) header compression.

Author
Castagnier Mickael
Version
1.0

Definition in file n_http2.c.


Data Structure Documentation

◆ H2_DYN_ENTRY

struct H2_DYN_ENTRY

one HPACK dynamic table entry (owned strings and its accounted size)

Definition at line 175 of file n_http2.c.

+ Collaboration diagram for H2_DYN_ENTRY:
Data Fields
char * name
size_t size
char * value

◆ N_H2_HPACK

struct N_H2_HPACK

HPACK codec context: the dynamic table (index 0 = most recently added)

opaque HPACK codec context holding one direction's dynamic table (RFC 7541)

Examples
ex_http2.c.

Definition at line 182 of file n_http2.c.

+ Collaboration diagram for N_H2_HPACK:
Data Fields
size_t cap
size_t cur_size
H2_DYN_ENTRY * ents
size_t limit
size_t max_size
size_t nents

Function Documentation

◆ hpack_dyn_add()

static int hpack_dyn_add ( N_H2_HPACK ctx,
const char *  name,
const char *  value 
)
static

insert (name, value) at the front of the dynamic table, evicting as needed; both strings are copied.

An entry larger than max_size empties the table without being stored (RFC 7541 4.4).

Definition at line 402 of file n_http2.c.

References N_H2_HPACK::cap, N_H2_HPACK::cur_size, N_H2_HPACK::ents, hpack_evict(), N_H2_HPACK::max_size, H2_DYN_ENTRY::name, N_H2_HPACK::nents, H2_DYN_ENTRY::size, and H2_DYN_ENTRY::value.

Referenced by n_http2_hpack_decode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hpack_evict()

static void hpack_evict ( N_H2_HPACK ctx)
static

drop the oldest dynamic entries until the table fits max_size

Definition at line 365 of file n_http2.c.

References N_H2_HPACK::cur_size, N_H2_HPACK::ents, N_H2_HPACK::max_size, H2_DYN_ENTRY::name, N_H2_HPACK::nents, H2_DYN_ENTRY::size, and H2_DYN_ENTRY::value.

Referenced by hpack_dyn_add(), n_http2_hpack_decode(), and n_http2_hpack_set_max_size().

+ Here is the caller graph for this function:

◆ hpack_huff_decode()

static int hpack_huff_decode ( const unsigned char *  s,
size_t  len,
char **  out 
)
static

decode a Huffman-coded string of len bytes into a fresh C string

Definition at line 202 of file n_http2.c.

References hpack_huff_lookup().

Referenced by hpack_str_decode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hpack_huff_lookup()

static int hpack_huff_lookup ( uint32_t  code,
int  nbits 
)
static

find the Huffman symbol for an accumulated code of nbits bits, or -1

Definition at line 192 of file n_http2.c.

References hpack_huff_code, and hpack_huff_len.

Referenced by hpack_huff_decode().

+ Here is the caller graph for this function:

◆ hpack_int_decode()

static int hpack_int_decode ( const unsigned char *  buf,
size_t  len,
size_t *  pos,
int  prefix_bits,
uint64_t *  out 
)
static

decode an HPACK integer with an N-bit prefix; advances *pos

Definition at line 257 of file n_http2.c.

Referenced by hpack_str_decode(), and n_http2_hpack_decode().

+ Here is the caller graph for this function:

◆ hpack_int_encode()

static size_t hpack_int_encode ( unsigned char *  out,
size_t  cap,
int  prefix_bits,
unsigned char  flags,
uint64_t  value 
)
static

encode an HPACK integer with an N-bit prefix and high-bit flags

Definition at line 315 of file n_http2.c.

Referenced by hpack_str_encode().

+ Here is the caller graph for this function:

◆ hpack_lookup()

static int hpack_lookup ( const N_H2_HPACK ctx,
uint64_t  idx,
const char **  name,
const char **  value 
)
static

resolve a table index to its name/value (const, not owned).

Returns 0 on success, -1 when the index is out of range.

Definition at line 444 of file n_http2.c.

References N_H2_HPACK::ents, hpack_static_name, hpack_static_value, H2_DYN_ENTRY::name, N_H2_HPACK::nents, and H2_DYN_ENTRY::value.

Referenced by n_http2_hpack_decode().

+ Here is the caller graph for this function:

◆ hpack_str_decode()

static int hpack_str_decode ( const unsigned char *  buf,
size_t  len,
size_t *  pos,
char **  out 
)
static

decode an HPACK string (Huffman or literal); allocates *out

Definition at line 287 of file n_http2.c.

References hpack_huff_decode(), and hpack_int_decode().

Referenced by n_http2_hpack_decode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hpack_str_encode()

static size_t hpack_str_encode ( unsigned char *  out,
size_t  cap,
const char *  s 
)
static

encode a literal (non-Huffman) string with its 7-bit length prefix

Definition at line 341 of file n_http2.c.

References hpack_int_encode().

Referenced by n_http2_hpack_encode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ n_http2_frame_build_header()

size_t n_http2_frame_build_header ( unsigned char *  out,
size_t  out_cap,
uint32_t  length,
int  type,
int  flags,
uint32_t  stream_id 
)

write a 9-byte HTTP/2 frame header into out.

Returns N_H2_FRAME_HEADER_LEN, or 0 when out_cap is too small or length exceeds 24 bits.

Examples
ex_http2.c.

Definition at line 52 of file n_http2.c.

References N_H2_FRAME_HEADER_LEN.

Referenced by test_boundaries(), and test_roundtrip().

+ Here is the caller graph for this function:

◆ n_http2_frame_parse()

int n_http2_frame_parse ( const unsigned char *  buf,
size_t  len,
N_H2_FRAME frame,
size_t *  consumed 
)

parse one HTTP/2 frame from a byte buffer (stateless).

Returns 1 and fills frame + *consumed (header + payload) on a complete frame, 0 when more bytes are needed, -1 when the payload exceeds N_H2_MAX_FRAME_PAYLOAD.

Examples
ex_http2.c.

Definition at line 32 of file n_http2.c.

References N_H2_FRAME::flags, N_H2_FRAME::length, N_H2_FRAME_HEADER_LEN, N_H2_MAX_FRAME_PAYLOAD, N_H2_FRAME::payload, N_H2_FRAME::stream_id, and N_H2_FRAME::type.

Referenced by test_boundaries(), and test_roundtrip().

+ Here is the caller graph for this function:

◆ n_http2_hpack_decode()

int n_http2_hpack_decode ( N_H2_HPACK ctx,
const unsigned char *  block,
size_t  len,
N_H2_HEADER out,
size_t  max_out,
size_t *  count 
)

decode an HPACK header block into out[] (owned name/value strings).

Handles indexed fields (static and dynamic table), the three literal forms (with/without/never indexing), Huffman-coded and literal strings, and dynamic table size updates. On success *count holds the number of headers written (<= max_out) and the dynamic table is updated. Returns 0 on success, -1 on a malformed block or when more than max_out headers are produced. Free the decoded headers with n_http2_hpack_headers_free.

Parameters
ctxcodec context (its dynamic table is read and updated)
blockthe header block fragment bytes
lenlength of block
outarray receiving the decoded headers
max_outcapacity of out
countreceives the number of headers decoded
Returns
0 on success, -1 on error
Examples
ex_http2.c.

Definition at line 472 of file n_http2.c.

References hpack_dyn_add(), hpack_evict(), hpack_int_decode(), hpack_lookup(), hpack_str_decode(), N_H2_HPACK::limit, N_H2_HPACK::max_size, n_http2_hpack_headers_free(), N_H2_HEADER::name, and N_H2_HEADER::value.

Referenced by test_hpack_guards(), test_hpack_overflow(), test_hpack_rfc_huffman(), test_hpack_rfc_requests(), and test_hpack_roundtrip().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ n_http2_hpack_encode()

size_t n_http2_hpack_encode ( const N_H2_HEADER headers,
size_t  n,
unsigned char *  out,
size_t  out_cap 
)

encode a header list into a block using literal representations without indexing and without Huffman (a valid, interoperable, self-contained encoding that needs no dynamic-table state).

Returns the number of bytes written, or 0 when out_cap is too small or an argument is invalid.

Parameters
headersthe header fields to encode (name/value C strings)
nnumber of headers
outdestination buffer
out_capcapacity of out
Returns
bytes written, or 0 on error
Examples
ex_http2.c.

Definition at line 554 of file n_http2.c.

References hpack_str_encode().

Referenced by test_hpack_roundtrip().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ n_http2_hpack_free()

void n_http2_hpack_free ( N_H2_HPACK **  pctx)

free an HPACK codec context and NULL the caller's pointer

Examples
ex_http2.c.

Definition at line 375 of file n_http2.c.

References N_H2_HPACK::ents, H2_DYN_ENTRY::name, N_H2_HPACK::nents, and H2_DYN_ENTRY::value.

Referenced by test_hpack_guards(), test_hpack_overflow(), test_hpack_rfc_huffman(), test_hpack_rfc_requests(), and test_hpack_roundtrip().

+ Here is the caller graph for this function:

◆ n_http2_hpack_headers_free()

void n_http2_hpack_headers_free ( N_H2_HEADER headers,
size_t  n 
)

free the owned name/value strings of a decoded header array (does not free the array itself)

Examples
ex_http2.c.

Definition at line 460 of file n_http2.c.

References N_H2_HEADER::name, and N_H2_HEADER::value.

Referenced by n_http2_hpack_decode(), test_hpack_rfc_huffman(), test_hpack_rfc_requests(), and test_hpack_roundtrip().

+ Here is the caller graph for this function:

◆ n_http2_hpack_new()

N_H2_HPACK * n_http2_hpack_new ( size_t  max_table_size)

create an HPACK codec context with the given dynamic table size limit (0 uses N_H2_HPACK_DEFAULT_TABLE_SIZE).

Returns NULL on allocation failure.

Examples
ex_http2.c.

Definition at line 353 of file n_http2.c.

References N_H2_HPACK::limit, N_H2_HPACK::max_size, and N_H2_HPACK_DEFAULT_TABLE_SIZE.

Referenced by test_hpack_guards(), test_hpack_overflow(), test_hpack_rfc_huffman(), test_hpack_rfc_requests(), and test_hpack_roundtrip().

+ Here is the caller graph for this function:

◆ n_http2_hpack_set_max_size()

void n_http2_hpack_set_max_size ( N_H2_HPACK ctx,
size_t  max_table_size 
)

change the dynamic table size limit (a SETTINGS_HEADER_TABLE_SIZE change), evicting entries as needed so the table fits.

Definition at line 390 of file n_http2.c.

References hpack_evict(), N_H2_HPACK::limit, and N_H2_HPACK::max_size.

+ Here is the call graph for this function:

◆ n_http2_settings_parse()

int n_http2_settings_parse ( const unsigned char *  payload,
size_t  len,
N_H2_SETTING out,
size_t  max,
size_t *  count 
)

parse a SETTINGS frame payload (6-byte id/value entries) into out.

Returns 0 on success (*count set, <= max), -1 when the payload length is not a multiple of 6.

Examples
ex_http2.c.

Definition at line 70 of file n_http2.c.

References N_H2_SETTING::id, and N_H2_SETTING::value.

Referenced by test_settings().

+ Here is the caller graph for this function:

Variable Documentation

◆ hpack_huff_code

const uint32_t hpack_huff_code[256]
static
Initial value:
= {
0x1ff8, 0x7fffd8, 0xfffffe2, 0xfffffe3, 0xfffffe4, 0xfffffe5, 0xfffffe6, 0xfffffe7,
0xfffffe8, 0xffffea, 0x3ffffffc, 0xfffffe9, 0xfffffea, 0x3ffffffd, 0xfffffeb, 0xfffffec,
0xfffffed, 0xfffffee, 0xfffffef, 0xffffff0, 0xffffff1, 0xffffff2, 0x3ffffffe, 0xffffff3,
0xffffff4, 0xffffff5, 0xffffff6, 0xffffff7, 0xffffff8, 0xffffff9, 0xffffffa, 0xffffffb,
0x14, 0x3f8, 0x3f9, 0xffa, 0x1ff9, 0x15, 0xf8, 0x7fa,
0x3fa, 0x3fb, 0xf9, 0x7fb, 0xfa, 0x16, 0x17, 0x18,
0x0, 0x1, 0x2, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0x1e, 0x1f, 0x5c, 0xfb, 0x7ffc, 0x20, 0xffb, 0x3fc,
0x1ffa, 0x21, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
0xfc, 0x73, 0xfd, 0x1ffb, 0x7fff0, 0x1ffc, 0x3ffc, 0x22,
0x7ffd, 0x3, 0x23, 0x4, 0x24, 0x5, 0x25, 0x26,
0x27, 0x6, 0x74, 0x75, 0x28, 0x29, 0x2a, 0x7,
0x2b, 0x76, 0x2c, 0x8, 0x9, 0x2d, 0x77, 0x78,
0x79, 0x7a, 0x7b, 0x7ffe, 0x7fc, 0x3ffd, 0x1ffd, 0xffffffc,
0xfffe6, 0x3fffd2, 0xfffe7, 0xfffe8, 0x3fffd3, 0x3fffd4, 0x3fffd5, 0x7fffd9,
0x3fffd6, 0x7fffda, 0x7fffdb, 0x7fffdc, 0x7fffdd, 0x7fffde, 0xffffeb, 0x7fffdf,
0xffffec, 0xffffed, 0x3fffd7, 0x7fffe0, 0xffffee, 0x7fffe1, 0x7fffe2, 0x7fffe3,
0x7fffe4, 0x1fffdc, 0x3fffd8, 0x7fffe5, 0x3fffd9, 0x7fffe6, 0x7fffe7, 0xffffef,
0x3fffda, 0x1fffdd, 0xfffe9, 0x3fffdb, 0x3fffdc, 0x7fffe8, 0x7fffe9, 0x1fffde,
0x7fffea, 0x3fffdd, 0x3fffde, 0xfffff0, 0x1fffdf, 0x3fffdf, 0x7fffeb, 0x7fffec,
0x1fffe0, 0x1fffe1, 0x3fffe0, 0x1fffe2, 0x7fffed, 0x3fffe1, 0x7fffee, 0x7fffef,
0xfffea, 0x3fffe2, 0x3fffe3, 0x3fffe4, 0x7ffff0, 0x3fffe5, 0x3fffe6, 0x7ffff1,
0x3ffffe0, 0x3ffffe1, 0xfffeb, 0x7fff1, 0x3fffe7, 0x7ffff2, 0x3fffe8, 0x1ffffec,
0x3ffffe2, 0x3ffffe3, 0x3ffffe4, 0x7ffffde, 0x7ffffdf, 0x3ffffe5, 0xfffff1, 0x1ffffed,
0x7fff2, 0x1fffe3, 0x3ffffe6, 0x7ffffe0, 0x7ffffe1, 0x3ffffe7, 0x7ffffe2, 0xfffff2,
0x1fffe4, 0x1fffe5, 0x3ffffe8, 0x3ffffe9, 0xffffffd, 0x7ffffe3, 0x7ffffe4, 0x7ffffe5,
0xfffec, 0xfffff3, 0xfffed, 0x1fffe6, 0x3fffe9, 0x1fffe7, 0x1fffe8, 0x7ffff3,
0x3fffea, 0x3fffeb, 0x1ffffee, 0x1ffffef, 0xfffff4, 0xfffff5, 0x3ffffea, 0x7ffff4,
0x3ffffeb, 0x7ffffe6, 0x3ffffec, 0x3ffffed, 0x7ffffe7, 0x7ffffe8, 0x7ffffe9, 0x7ffffea,
0x7ffffeb, 0xffffffe, 0x7ffffec, 0x7ffffed, 0x7ffffee, 0x7ffffef, 0x7fffff0, 0x3ffffee}

HPACK Huffman codes (RFC 7541 Appendix B), index = byte value 0..255.

Definition at line 121 of file n_http2.c.

Referenced by hpack_huff_lookup().

◆ hpack_huff_len

const uint8_t hpack_huff_len[256]
static
Initial value:
= {
13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26}

HPACK Huffman code lengths in bits (RFC 7541 Appendix B)

Definition at line 156 of file n_http2.c.

Referenced by hpack_huff_lookup().

◆ hpack_static_name

const char* const hpack_static_name[61]
static
Initial value:
= {
":authority", ":method", ":method", ":path", ":path", ":scheme", ":scheme",
":status", ":status", ":status", ":status", ":status", ":status", ":status",
"accept-charset", "accept-encoding", "accept-language", "accept-ranges", "accept",
"access-control-allow-origin", "age", "allow", "authorization", "cache-control",
"content-disposition", "content-encoding", "content-language", "content-length",
"content-location", "content-range", "content-type", "cookie", "date", "etag",
"expect", "expires", "from", "host", "if-match", "if-modified-since", "if-none-match",
"if-range", "if-unmodified-since", "last-modified", "link", "location", "max-forwards",
"proxy-authenticate", "proxy-authorization", "range", "referer", "refresh", "retry-after",
"server", "set-cookie", "strict-transport-security", "transfer-encoding", "user-agent",
"vary", "via", "www-authenticate"}

HPACK static table names (RFC 7541 Appendix A, index 1..61)

Definition at line 93 of file n_http2.c.

Referenced by hpack_lookup().

◆ hpack_static_value

const char* const hpack_static_value[61]
static
Initial value:
= {
"", "GET", "POST", "/", "/index.html", "http", "https",
"200", "204", "206", "304", "400", "404", "500",
"", "gzip, deflate", "", "", "",
"", "", "", "", "",
"", "", "", "",
"", "", "", "", "", "",
"", "", "", "", "", "", "",
"", "", "", "", "", "",
"", "", "", "", "", "",
"", "", "", "", "",
"", "", ""}

HPACK static table values (empty where the entry has no value)

Definition at line 107 of file n_http2.c.

Referenced by hpack_lookup().