6 n__http2_8h
gullradriel edited this page 2026-10-09 00:55:18 +02:00

include/nilorea/n_http2.h

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

Structures

Name
struct N_H2_SETTING
one SETTINGS parameter (identifier and value)
struct N_H2_HEADER
one HPACK header field; after a decode both strings are owned (heap)
struct N_H2_FRAME
a parsed HTTP/2 frame; payload aliases the input buffer

Functions

Name
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.
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.
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).
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)
void n_http2_hpack_free(N_H2_HPACK ** ctx)
free an HPACK codec context and NULL the caller's pointer
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).
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).
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).
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.

Defines

Name
N_H2_WINDOW_UPDATE
WINDOW_UPDATE.
N_H2_SETTINGS_MAX_HEADER_LIST_SIZE
N_H2_SETTINGS_MAX_FRAME_SIZE
N_H2_SETTINGS_MAX_CONCURRENT_STREAMS
N_H2_SETTINGS_INITIAL_WINDOW_SIZE
N_H2_SETTINGS_HEADER_TABLE_SIZE
N_H2_SETTINGS_ENABLE_PUSH
N_H2_SETTINGS
SETTINGS.
N_H2_RST_STREAM
RST_STREAM.
N_H2_PUSH_PROMISE
PUSH_PROMISE.
N_H2_PRIORITY
PRIORITY.
N_H2_PREFACE
the client connection preface sent before any HTTP/2 frame (RFC 7540 3.5)
N_H2_PING
PING.
N_H2_MAX_FRAME_PAYLOAD
largest frame payload the parser accepts (the default SETTINGS_MAX_FRAME_SIZE)
N_H2_HPACK_DEFAULT_TABLE_SIZE
the default HPACK dynamic table size (SETTINGS_HEADER_TABLE_SIZE default)
N_H2_HEADERS
HEADERS.
N_H2_GOAWAY
GOAWAY.
N_H2_FRAME_HEADER_LEN
length of the fixed frame header in bytes
N_H2_FLAG_PRIORITY
HEADERS: priority fields are present.
N_H2_FLAG_PADDED
DATA/HEADERS/PUSH_PROMISE: a pad-length prefix is present.
N_H2_FLAG_END_STREAM
DATA/HEADERS: last frame of the stream.
N_H2_FLAG_END_HEADERS
HEADERS/PUSH_PROMISE/CONTINUATION: header block complete.
N_H2_FLAG_ACK
SETTINGS/PING: acknowledgement.
N_H2_DATA
DATA.
N_H2_CONTINUATION
CONTINUATION.

Detailed Description

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

Author: Castagnier Mickael

Version: 1.0

Date: 2026

The framing layer of HTTP/2: the client connection preface, the frame-type and flag constants, a 9-byte frame-header parse/build, and a SETTINGS payload reader. The frame codec is stateless and does no allocation, so a caller drives its own reassembly buffer.

On top of the framing sits HPACK (RFC 7541): an N_H2_HPACK codec context with a per-direction dynamic table, a full decoder (indexed and literal fields, the static and dynamic tables, Huffman-coded and literal strings, and dynamic table size updates), and a self-contained encoder (literal fields without indexing, no Huffman) that needs no shared state. The stream/connection state machine builds on these two layers.

Functions Documentation

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.

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.

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.

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)

function n_http2_hpack_free

void n_http2_hpack_free(
    N_H2_HPACK ** ctx
)

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

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).

Parameters:

  • headers the header fields to encode (name/value C strings)
  • n number of headers
  • out destination buffer
  • out_cap capacity of out

Return: bytes written, or 0 on error

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

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).

Parameters:

  • ctx codec context (its dynamic table is read and updated)
  • block the header block fragment bytes
  • len length of block
  • out array receiving the decoded headers
  • max_out capacity of out
  • count receives the number of headers decoded

Return: 0 on success, -1 on error

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.

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.

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.

Macros Documentation

define N_H2_WINDOW_UPDATE

#define N_H2_WINDOW_UPDATE 0x8

WINDOW_UPDATE.

define N_H2_SETTINGS_MAX_HEADER_LIST_SIZE

#define N_H2_SETTINGS_MAX_HEADER_LIST_SIZE 0x6

define N_H2_SETTINGS_MAX_FRAME_SIZE

#define N_H2_SETTINGS_MAX_FRAME_SIZE 0x5

define N_H2_SETTINGS_MAX_CONCURRENT_STREAMS

#define N_H2_SETTINGS_MAX_CONCURRENT_STREAMS 0x3

define N_H2_SETTINGS_INITIAL_WINDOW_SIZE

#define N_H2_SETTINGS_INITIAL_WINDOW_SIZE 0x4

define N_H2_SETTINGS_HEADER_TABLE_SIZE

#define N_H2_SETTINGS_HEADER_TABLE_SIZE 0x1

define N_H2_SETTINGS_ENABLE_PUSH

#define N_H2_SETTINGS_ENABLE_PUSH 0x2

define N_H2_SETTINGS

#define N_H2_SETTINGS 0x4

SETTINGS.

define N_H2_RST_STREAM

#define N_H2_RST_STREAM 0x3

RST_STREAM.

define N_H2_PUSH_PROMISE

#define N_H2_PUSH_PROMISE 0x5

PUSH_PROMISE.

define N_H2_PRIORITY

#define N_H2_PRIORITY 0x2

PRIORITY.

define N_H2_PREFACE

#define N_H2_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"

the client connection preface sent before any HTTP/2 frame (RFC 7540 3.5)

define N_H2_PING

#define N_H2_PING 0x6

PING.

define N_H2_MAX_FRAME_PAYLOAD

#define N_H2_MAX_FRAME_PAYLOAD 16384

largest frame payload the parser accepts (the default SETTINGS_MAX_FRAME_SIZE)

define N_H2_HPACK_DEFAULT_TABLE_SIZE

#define N_H2_HPACK_DEFAULT_TABLE_SIZE 4096

the default HPACK dynamic table size (SETTINGS_HEADER_TABLE_SIZE default)

define N_H2_HEADERS

#define N_H2_HEADERS 0x1

HEADERS.

define N_H2_GOAWAY

#define N_H2_GOAWAY 0x7

GOAWAY.

define N_H2_FRAME_HEADER_LEN

#define N_H2_FRAME_HEADER_LEN 9

length of the fixed frame header in bytes

define N_H2_FLAG_PRIORITY

#define N_H2_FLAG_PRIORITY 0x20

HEADERS: priority fields are present.

define N_H2_FLAG_PADDED

#define N_H2_FLAG_PADDED 0x8

DATA/HEADERS/PUSH_PROMISE: a pad-length prefix is present.

define N_H2_FLAG_END_STREAM

#define N_H2_FLAG_END_STREAM 0x1

DATA/HEADERS: last frame of the stream.

define N_H2_FLAG_END_HEADERS

#define N_H2_FLAG_END_HEADERS 0x4

HEADERS/PUSH_PROMISE/CONTINUATION: header block complete.

define N_H2_FLAG_ACK

#define N_H2_FLAG_ACK 0x1

SETTINGS/PING: acknowledgement.

define N_H2_DATA

#define N_H2_DATA 0x0

DATA.

define N_H2_CONTINUATION

#define N_H2_CONTINUATION 0x9

CONTINUATION.

Source code

/*
 * Nilorea Library
 * Copyright (C) 2005-2026 Castagnier Mickael
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#ifndef __NILOREA_HTTP2_HEADER
#define __NILOREA_HTTP2_HEADER

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>
#include <stdint.h>

#define N_H2_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
#define N_H2_FRAME_HEADER_LEN 9
#define N_H2_MAX_FRAME_PAYLOAD 16384

#define N_H2_DATA 0x0          
#define N_H2_HEADERS 0x1       
#define N_H2_PRIORITY 0x2      
#define N_H2_RST_STREAM 0x3    
#define N_H2_SETTINGS 0x4      
#define N_H2_PUSH_PROMISE 0x5  
#define N_H2_PING 0x6          
#define N_H2_GOAWAY 0x7        
#define N_H2_WINDOW_UPDATE 0x8 
#define N_H2_CONTINUATION 0x9  

#define N_H2_FLAG_END_STREAM 0x1  
#define N_H2_FLAG_ACK 0x1         
#define N_H2_FLAG_END_HEADERS 0x4 
#define N_H2_FLAG_PADDED 0x8      
#define N_H2_FLAG_PRIORITY 0x20   

#define N_H2_SETTINGS_HEADER_TABLE_SIZE 0x1
#define N_H2_SETTINGS_ENABLE_PUSH 0x2
#define N_H2_SETTINGS_MAX_CONCURRENT_STREAMS 0x3
#define N_H2_SETTINGS_INITIAL_WINDOW_SIZE 0x4
#define N_H2_SETTINGS_MAX_FRAME_SIZE 0x5
#define N_H2_SETTINGS_MAX_HEADER_LIST_SIZE 0x6

typedef struct N_H2_FRAME {
    uint32_t length;              
    int type;                     
    int flags;                    
    uint32_t stream_id;           
    const unsigned char* payload; 
} N_H2_FRAME;

typedef struct N_H2_SETTING {
    uint16_t id;    
    uint32_t value; 
} N_H2_SETTING;

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

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);

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

#define N_H2_HPACK_DEFAULT_TABLE_SIZE 4096

typedef struct N_H2_HEADER {
    char* name;  
    char* value; 
} N_H2_HEADER;

typedef struct N_H2_HPACK N_H2_HPACK;

N_H2_HPACK* n_http2_hpack_new(size_t max_table_size);

void n_http2_hpack_free(N_H2_HPACK** ctx);

void n_http2_hpack_set_max_size(N_H2_HPACK* ctx, size_t max_table_size);

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);

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

void n_http2_hpack_headers_free(N_H2_HEADER* headers, size_t n);

#ifdef __cplusplus
}
#endif

#endif /* __NILOREA_HTTP2_HEADER */