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

HTTP/2 (RFC 7540) server-side connection and stream state machine. More...

#include "n_http2.h"
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
Include dependency graph for n_http2_server.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  N_H2_REQUEST
 one complete request received on a stream; every pointer is owned by the server and valid only for the duration of the request callback More...

Macros

#define N_H2_SRV_MAX_BODY   (16 * 1024 * 1024)
 largest request body accumulated for one stream
#define N_H2_SRV_MAX_HEADERS   128
 largest number of header fields decoded from one request
#define N_H2_SRV_MAX_STREAMS   128
 largest number of streams tracked at once on one connection
#define N_H2_SRV_READ_CHUNK   16384
 bytes pulled from the read callback per call
HTTP/2 error codes (RFC 7540 7)
#define N_H2_ERR_CANCEL   0x8
 stream cancelled
#define N_H2_ERR_COMPRESSION_ERROR   0x9
 HPACK compression state not updated.
#define N_H2_ERR_CONNECT_ERROR   0xa
 TCP connection error for CONNECT.
#define N_H2_ERR_ENHANCE_YOUR_CALM   0xb
 processing capacity exceeded
#define N_H2_ERR_FLOW_CONTROL_ERROR   0x3
 flow-control limits exceeded
#define N_H2_ERR_FRAME_SIZE_ERROR   0x6
 frame size incorrect
#define N_H2_ERR_HTTP_1_1_REQUIRED   0xd
 use HTTP/1.1 for the request
#define N_H2_ERR_INADEQUATE_SECURITY   0xc
 negotiated TLS parameters not acceptable
#define N_H2_ERR_INTERNAL_ERROR   0x2
 implementation fault
#define N_H2_ERR_NO_ERROR   0x0
 graceful shutdown
#define N_H2_ERR_PROTOCOL_ERROR   0x1
 unspecific protocol error
#define N_H2_ERR_REFUSED_STREAM   0x7
 stream not processed
#define N_H2_ERR_SETTINGS_TIMEOUT   0x4
 settings not acknowledged
#define N_H2_ERR_STREAM_CLOSED   0x5
 frame received for a closed stream

Typedefs

typedef ssize_t(* n_h2_srv_read_fn) (void *io, void *buf, size_t len)
 read up to len bytes into buf: returns the bytes read (>0), 0 on a clean end of stream, or -1 on error (a timeout included)
typedef int(* n_h2_srv_request_cb) (void *user_data, N_H2_SERVER *srv, const N_H2_REQUEST *req)
 called with each complete request; answer it with n_http2_server_respond() (or n_http2_server_rst_stream()).
typedef ssize_t(* n_h2_srv_write_fn) (void *io, const void *buf, size_t len)
 write exactly len bytes from buf: returns len on success, -1 on error

Functions

const char * n_http2_server_error (const N_H2_SERVER *srv)
 the reason the connection failed, or NULL when none was recorded
void n_http2_server_free (N_H2_SERVER **srv)
 free a server connection and NULL the caller's pointer
int n_http2_server_goaway (N_H2_SERVER *srv, uint32_t error_code)
 send GOAWAY, naming the last stream we processed
int n_http2_server_handshake (N_H2_SERVER *srv)
 read and validate the client connection preface, then send ours
N_H2_SERVER * n_http2_server_new (void *io, n_h2_srv_read_fn rd, n_h2_srv_write_fn wr)
 create a server connection over the given I/O callbacks
size_t n_http2_server_request_count (const N_H2_SERVER *srv)
 the number of requests delivered to the callback so far
int n_http2_server_respond (N_H2_SERVER *srv, uint32_t stream_id, const N_H2_HEADER *headers, size_t nheaders, const unsigned char *body, size_t body_len)
 write a complete response on a stream (HEADERS then DATA, END_STREAM)
int n_http2_server_rst_stream (N_H2_SERVER *srv, uint32_t stream_id, uint32_t error_code)
 abort one stream with RST_STREAM
int n_http2_server_run (N_H2_SERVER *srv, n_h2_srv_request_cb cb, void *user_data)
 serve the connection until it ends

Detailed Description

HTTP/2 (RFC 7540) server-side connection and stream state machine.

Author
Castagnier Mickael
Version
1.0
Date
2026

The server half of HTTP/2, built on the framing and HPACK codec of n_http2.h: it validates the client connection preface, exchanges SETTINGS, reassembles HEADERS plus CONTINUATION per stream, accumulates DATA until END_STREAM, hands each complete request to a callback, and writes responses back as HEADERS plus DATA. It answers PING, honours RST_STREAM, and closes with GOAWAY.

Both directions are flow controlled at the connection AND the stream level: the receive windows are replenished as request bodies are consumed, and a response body is never written past the peer's advertised window (when a window is exhausted the server pumps incoming frames until a WINDOW_UPDATE reopens it). A server that skips this works against small responses and deadlocks against large ones.

Byte I/O goes through injected read/write callbacks rather than a socket, so the same core runs over a plain connection (h2c prior knowledge, and the tests against a scripted peer) or a TLS connection that negotiated ALPN "h2"; the callbacks own the timeouts and the TLS.

Requests are delivered one at a time: the callback for a stream returns before the next stream's request is delivered, so a handler may block. Streams are still multiplexed on the wire (the client may open many at once, and their frames keep being read and buffered), they are simply served in the order they complete.

Definition in file n_http2_server.h.


Data Structure Documentation

◆ N_H2_REQUEST

struct N_H2_REQUEST

one complete request received on a stream; every pointer is owned by the server and valid only for the duration of the request callback

Examples
ex_http2_server.c, and ex_network_alpn.c.

Definition at line 104 of file n_http2_server.h.

Collaboration diagram for N_H2_REQUEST:
Data Fields
const char * authority the :authority pseudo-header, or NULL when absent
const unsigned char * body the request body, or NULL when there is none
size_t body_len the body length in bytes
N_H2_HEADER * headers the decoded header fields, pseudo-headers included
const char * method the :method pseudo-header, or NULL when absent
size_t nheaders number of header fields
const char * path the :path pseudo-header, or NULL when absent
const char * scheme the :scheme pseudo-header, or NULL when absent
uint32_t stream_id the stream the request arrived on

Macro Definition Documentation

◆ N_H2_ERR_CANCEL

#define N_H2_ERR_CANCEL   0x8

stream cancelled

Examples
ex_http2_server.c.

Definition at line 84 of file n_http2_server.h.

Referenced by test_rst_stream().

◆ N_H2_ERR_COMPRESSION_ERROR

#define N_H2_ERR_COMPRESSION_ERROR   0x9

HPACK compression state not updated.

Definition at line 85 of file n_http2_server.h.

◆ N_H2_ERR_CONNECT_ERROR

#define N_H2_ERR_CONNECT_ERROR   0xa

TCP connection error for CONNECT.

Definition at line 86 of file n_http2_server.h.

◆ N_H2_ERR_ENHANCE_YOUR_CALM

#define N_H2_ERR_ENHANCE_YOUR_CALM   0xb

processing capacity exceeded

Definition at line 87 of file n_http2_server.h.

Referenced by srv_apply_data().

◆ N_H2_ERR_FLOW_CONTROL_ERROR

#define N_H2_ERR_FLOW_CONTROL_ERROR   0x3

flow-control limits exceeded

Definition at line 79 of file n_http2_server.h.

◆ N_H2_ERR_FRAME_SIZE_ERROR

#define N_H2_ERR_FRAME_SIZE_ERROR   0x6

frame size incorrect

Definition at line 82 of file n_http2_server.h.

◆ N_H2_ERR_HTTP_1_1_REQUIRED

#define N_H2_ERR_HTTP_1_1_REQUIRED   0xd

use HTTP/1.1 for the request

Definition at line 89 of file n_http2_server.h.

◆ N_H2_ERR_INADEQUATE_SECURITY

#define N_H2_ERR_INADEQUATE_SECURITY   0xc

negotiated TLS parameters not acceptable

Definition at line 88 of file n_http2_server.h.

◆ N_H2_ERR_INTERNAL_ERROR

#define N_H2_ERR_INTERNAL_ERROR   0x2

implementation fault

Definition at line 78 of file n_http2_server.h.

◆ N_H2_ERR_NO_ERROR

#define N_H2_ERR_NO_ERROR   0x0

graceful shutdown

Definition at line 76 of file n_http2_server.h.

Referenced by n_http2_server_run().

◆ N_H2_ERR_PROTOCOL_ERROR

#define N_H2_ERR_PROTOCOL_ERROR   0x1

unspecific protocol error

Definition at line 77 of file n_http2_server.h.

◆ N_H2_ERR_REFUSED_STREAM

#define N_H2_ERR_REFUSED_STREAM   0x7

stream not processed

Definition at line 83 of file n_http2_server.h.

Referenced by srv_apply_headers().

◆ N_H2_ERR_SETTINGS_TIMEOUT

#define N_H2_ERR_SETTINGS_TIMEOUT   0x4

settings not acknowledged

Definition at line 80 of file n_http2_server.h.

◆ N_H2_ERR_STREAM_CLOSED

#define N_H2_ERR_STREAM_CLOSED   0x5

frame received for a closed stream

Definition at line 81 of file n_http2_server.h.

◆ N_H2_SRV_MAX_BODY

#define N_H2_SRV_MAX_BODY   (16 * 1024 * 1024)

largest request body accumulated for one stream

Definition at line 68 of file n_http2_server.h.

Referenced by srv_apply_data().

◆ N_H2_SRV_MAX_HEADERS

#define N_H2_SRV_MAX_HEADERS   128

largest number of header fields decoded from one request

Definition at line 66 of file n_http2_server.h.

Referenced by srv_finish_headers().

◆ N_H2_SRV_MAX_STREAMS

#define N_H2_SRV_MAX_STREAMS   128

largest number of streams tracked at once on one connection

Definition at line 70 of file n_http2_server.h.

Referenced by n_http2_server_free(), n_http2_server_handshake(), n_http2_server_run(), srv_apply_settings(), srv_next_ready(), srv_stream_find(), and srv_stream_open().

◆ N_H2_SRV_READ_CHUNK

#define N_H2_SRV_READ_CHUNK   16384

bytes pulled from the read callback per call

Definition at line 72 of file n_http2_server.h.

Referenced by srv_fill().

Typedef Documentation

◆ n_h2_srv_read_fn

typedef ssize_t(* n_h2_srv_read_fn) (void *io, void *buf, size_t len)

read up to len bytes into buf: returns the bytes read (>0), 0 on a clean end of stream, or -1 on error (a timeout included)

Definition at line 94 of file n_http2_server.h.

◆ n_h2_srv_request_cb

typedef int(* n_h2_srv_request_cb) (void *user_data, N_H2_SERVER *srv, const N_H2_REQUEST *req)

called with each complete request; answer it with n_http2_server_respond() (or n_http2_server_rst_stream()).

Return 0 to keep serving the connection, -1 to stop n_http2_server_run().

Definition at line 119 of file n_http2_server.h.

◆ n_h2_srv_write_fn

typedef ssize_t(* n_h2_srv_write_fn) (void *io, const void *buf, size_t len)

write exactly len bytes from buf: returns len on success, -1 on error

Definition at line 97 of file n_http2_server.h.

Function Documentation

◆ n_http2_server_error()

const char * n_http2_server_error ( const N_H2_SERVER * srv)

the reason the connection failed, or NULL when none was recorded

Definition at line 833 of file n_http2_server.c.

References N_H2_SERVER::err.

Referenced by server_fn(), test_continuation(), test_guards(), test_handshake_errors(), and test_send_window_stall().

Here is the caller graph for this function:

◆ n_http2_server_free()

void n_http2_server_free ( N_H2_SERVER ** srv)

◆ n_http2_server_goaway()

int n_http2_server_goaway ( N_H2_SERVER * srv,
uint32_t error_code )

send GOAWAY, naming the last stream we processed

Parameters
srvthe server connection, not NULL
error_codean N_H2_ERR_* code
Returns
0 on success, -1 on error

< GOAWAY

Definition at line 817 of file n_http2_server.c.

References __n_assert, N_H2_SERVER::io_failed, N_H2_SERVER::last_stream_id, N_H2_GOAWAY, and srv_send().

Referenced by n_http2_server_run().

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

◆ n_http2_server_handshake()

int n_http2_server_handshake ( N_H2_SERVER * srv)

read and validate the client connection preface, then send ours

Reads the 24-byte preface, requires the client's first frame to be SETTINGS (RFC 7540 3.5), acknowledges it, and sends our own SETTINGS plus the connection-level WINDOW_UPDATE that opens our receive window.

Parameters
srvthe server connection, not NULL
Returns
0 on success, -1 on a bad preface, a protocol error, or an I/O error

< SETTINGS

< SETTINGS

< SETTINGS/PING: acknowledgement

Definition at line 617 of file n_http2_server.c.

References __n_assert, H2BUF::data, N_H2_SERVER::err, N_H2_FRAME::flags, H2_DEFAULT_WINDOW, H2_SRV_RECV_WINDOW, h2buf_shift(), N_H2_FLAG_ACK, N_H2_PREFACE, N_H2_SETTINGS, N_H2_SETTINGS_ENABLE_PUSH, N_H2_SETTINGS_INITIAL_WINDOW_SIZE, N_H2_SETTINGS_MAX_CONCURRENT_STREAMS, N_H2_SRV_MAX_STREAMS, N_H2_SERVER::rb, srv_handle_frame(), srv_need(), srv_next_frame(), srv_put_setting(), srv_send(), srv_window_update(), N_H2_FRAME::stream_id, and N_H2_FRAME::type.

Referenced by server_fn(), test_callback_stop(), test_continuation(), test_dribbled_reads(), test_get(), test_guards(), test_handshake(), test_handshake_errors(), test_multiplex(), test_ping_goaway(), test_post_body(), test_rst_stream(), test_send_flow_control(), and test_send_window_stall().

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

◆ n_http2_server_new()

N_H2_SERVER * n_http2_server_new ( void * io,
n_h2_srv_read_fn rd,
n_h2_srv_write_fn wr )

create a server connection over the given I/O callbacks

Parameters
ioopaque handle handed to the callbacks
rdread callback, not NULL
wrwrite callback, not NULL
Returns
the new server, or NULL on a bad argument or an allocation failure

Definition at line 579 of file n_http2_server.c.

References __n_assert, N_H2_SERVER::dec, H2_DEFAULT_MAX_FRAME, H2_DEFAULT_WINDOW, N_H2_SERVER::io, LOG_ERR, n_http2_hpack_new(), n_log, N_H2_SERVER::peer_initial_win, N_H2_SERVER::peer_max_frame, N_H2_SERVER::rd, N_H2_SERVER::send_win_conn, and N_H2_SERVER::wr.

Referenced by server_fn(), test_callback_stop(), test_continuation(), test_dribbled_reads(), test_get(), test_guards(), test_handshake(), test_handshake_errors(), test_multiplex(), test_ping_goaway(), test_post_body(), test_rst_stream(), test_send_flow_control(), and test_send_window_stall().

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

◆ n_http2_server_request_count()

size_t n_http2_server_request_count ( const N_H2_SERVER * srv)

the number of requests delivered to the callback so far

Definition at line 837 of file n_http2_server.c.

References N_H2_SERVER::nrequests.

Referenced by test_get(), and test_guards().

Here is the caller graph for this function:

◆ n_http2_server_respond()

int n_http2_server_respond ( N_H2_SERVER * srv,
uint32_t stream_id,
const N_H2_HEADER * headers,
size_t nheaders,
const unsigned char * body,
size_t body_len )

write a complete response on a stream (HEADERS then DATA, END_STREAM)

headers must start with the :status pseudo-header and hold no connection-specific field (RFC 7540 8.1.2.2 forbids them). The body is split into DATA frames at the peer's SETTINGS_MAX_FRAME_SIZE and paced by the stream and connection send windows, pumping incoming frames whenever a window is exhausted.

Parameters
srvthe server connection, not NULL
stream_idthe stream to answer
headersthe response header fields, :status first, not NULL
nheadersnumber of header fields
bodythe response body, or NULL for none
body_lenthe body length
Returns
0 on success, -1 on a bad argument, a closed stream, or an I/O error

< HEADERS/PUSH_PROMISE/CONTINUATION: header block complete

< DATA/HEADERS: last frame of the stream

< HEADERS

< CONTINUATION

< DATA

< DATA/HEADERS: last frame of the stream

Definition at line 725 of file n_http2_server.c.

References __n_assert, N_H2_SERVER::err, N_H2_CONTINUATION, N_H2_DATA, N_H2_FLAG_END_HEADERS, N_H2_FLAG_END_STREAM, N_H2_HEADERS, n_http2_hpack_encode(), N_H2_SERVER::peer_max_frame, H2_STREAM::reset, H2_STREAM::send_win, N_H2_SERVER::send_win_conn, srv_pump_one(), srv_send(), srv_stream_find(), and N_H2_HEADER::value.

Referenced by h2_on_request(), and on_request().

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

◆ n_http2_server_rst_stream()

int n_http2_server_rst_stream ( N_H2_SERVER * srv,
uint32_t stream_id,
uint32_t error_code )

abort one stream with RST_STREAM

Parameters
srvthe server connection, not NULL
stream_idthe stream to reset
error_codean N_H2_ERR_* code
Returns
0 on success, -1 on error

< RST_STREAM

Definition at line 807 of file n_http2_server.c.

References __n_assert, N_H2_RST_STREAM, and srv_send().

Referenced by srv_apply_data(), and srv_apply_headers().

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

◆ n_http2_server_run()

int n_http2_server_run ( N_H2_SERVER * srv,
n_h2_srv_request_cb cb,
void * user_data )

serve the connection until it ends

Reads frames, reassembles requests, and calls cb once per complete request. Returns when the peer closes or sends GOAWAY, when the callback returns -1, or on an error.

Parameters
srvthe handshaked server connection, not NULL
cbthe request callback, not NULL
user_dataopaque pointer handed to the callback
Returns
0 when the connection ended cleanly (peer close, GOAWAY, or a callback stop), -1 on a protocol or I/O error

< graceful shutdown

< graceful shutdown

Definition at line 661 of file n_http2_server.c.

References __n_assert, N_H2_REQUEST::authority, H2_STREAM::body, N_H2_REQUEST::body, N_H2_REQUEST::body_len, H2BUF::data, H2_STREAM::delivered, N_H2_SERVER::eof, N_H2_SERVER::goaway_recv, H2_STREAM::hdrs, N_H2_REQUEST::headers, H2_STREAM::id, H2_STREAM::in_use, N_H2_SERVER::io_failed, H2BUF::len, N_H2_REQUEST::method, N_H2_ERR_NO_ERROR, N_H2_SRV_MAX_STREAMS, n_http2_server_goaway(), N_H2_HEADER::name, H2_STREAM::nhdrs, N_H2_REQUEST::nheaders, N_H2_SERVER::nrequests, N_H2_REQUEST::path, H2_STREAM::reset, N_H2_REQUEST::scheme, srv_next_ready(), srv_pump_one(), srv_stream_close(), srv_stream_find(), stop(), N_H2_REQUEST::stream_id, N_H2_SERVER::streams, and N_H2_HEADER::value.

Referenced by server_fn(), test_callback_stop(), test_continuation(), test_dribbled_reads(), test_get(), test_guards(), test_multiplex(), test_ping_goaway(), test_post_body(), test_rst_stream(), test_send_flow_control(), and test_send_window_stall().

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