ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
quic_server.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file protocore_quic_server.h
6 * @brief HTTP/3 server glue - binds UDP to a pool of QUIC + HTTP/3 connections (RFC 9000/9114).
7 *
8 * The last piece of the HTTP/3 stack: it owns a fixed pool of QuicConn + H3Conn engines, binds the
9 * HTTP/3 UDP port through the transport layer (protocore_udp), routes each inbound datagram to the right
10 * connection by its Destination Connection ID (a new client Initial opens a pool slot), drives the
11 * handshake + streams, and pulls the outbound datagrams back onto the wire. A completed HTTP/3
12 * request is surfaced through a single callback; the application answers with protocore_quic_server_respond().
13 *
14 * Threading (ESP32): protocore_udp delivers datagrams on the lwIP thread, but requests must be dispatched
15 * on the server's worker/main loop, so the UDP handler only copies each datagram into a lock-free
16 * ingest ring; protocore_quic_server_poll() (called from the loop) drains the ring, runs the engines, and
17 * sends replies. The engines therefore only ever run in one context.
18 *
19 * The pool (QuicConn + H3Conn per slot + the ingest ring) is large, so like HTTP/2 it is a
20 * PSRAM-class feature. No heap; fixed storage. This module has no PC dependency - the
21 * request/response seam is a plain callback - so the route-dispatch bridge lives in the server.
22 *
23 * @author Douglas Quigg (dstroy0)
24 * @date 2026
25 */
26
27#ifndef PROTOCORE_QUIC_SERVER_H
28#define PROTOCORE_QUIC_SERVER_H
29
30#include "protocore_config.h" // the entry point: the enable gate below, and the widths
31
32#if PROTOCORE_ENABLE_HTTP3
33
35
38
39#ifndef PROTOCORE_HTTP3_PORT
40#define PROTOCORE_HTTP3_PORT 443 ///< default UDP port the HTTP/3 server binds (QUIC)
41#endif
42#ifndef PROTOCORE_QUIC_SCID_LEN
43#define PROTOCORE_QUIC_SCID_LEN 8 ///< length of the connection ID the server chooses for itself
44#endif
45#ifndef PROTOCORE_QUIC_IDLE_MS
46#define PROTOCORE_QUIC_IDLE_MS 30000 ///< reclaim a connection idle this long (also advertised as max_idle_timeout)
47#endif
48
49/**
50 * @brief A completed HTTP/3 request handed to the application on the poll thread.
51 *
52 * Reply synchronously with protocore_quic_server_respond(@p conn_id, @p stream_id, ...) (typically from inside
53 * this call). @p body / @p body_len are valid only during the call.
54 */
55typedef void (*QuicServerRequestFn)(void *app, uint32_t conn_id, uint64_t stream_id, const char *method,
56 const char *path, const char *authority, const uint8_t *body, size_t body_len);
57
58/** @brief Server configuration: the Ed25519 leaf certificate + its key, and a randomness source. */
59typedef struct
60{
61 const uint8_t *cert_der; ///< DER X.509 leaf certificate (Ed25519 public key)
62 size_t cert_len;
63 uint8_t ed25519_seed[32]; ///< Ed25519 private seed matching the certificate
64 void (*rng)(uint8_t *out, size_t len); ///< fills @p out with @p len random bytes (ephemeral keys, SCIDs)
65} QuicServerConfig;
66
67/** @brief What binding the server takes: the port, its keys, and where requests go. */
68typedef struct
69{
70 uint16_t port; ///< the UDP port a begin binds
71 const QuicServerConfig *cfg; ///< the certificate, its key, and the randomness source
72 QuicServerRequestFn on_request; ///< what a completed request is delivered to, on the poll thread
73 void *app; ///< the opaque pointer that callback is given back
74} QuicBeginArgs;
75
76/** @brief RFC 9000 sec 2.1: the connection and stream a response is written on. */
77typedef struct
78{
79 uint32_t conn_id; ///< the connection a response routes back on
80 uint64_t stream_id; ///< the stream it finishes
81} QuicStreamRef;
82
83/** @brief What one response carries. */
84typedef struct
85{
86 int status; ///< the status that response carries
87 const char *content_type; ///< its media type
88 const uint8_t *body; ///< its body bytes
89 size_t body_len; ///< how many
90} QuicRespArgs;
91
92/**
93 * @brief The HTTP/3 server: a QUIC connection pool over one bound UDP port.
94 *
95 * A caller sets the members a call takes, invokes it through ::QuicServer, and reads the outcome off
96 * the same handle.
97 *
98 * @var QuicServerNs::begin_args what binding the server takes
99 * @var QuicServerNs::now_ms the caller's monotonic clock, so this module stays platform-agnostic
100 * @var QuicServerNs::stream the connection and stream a response names
101 * @var QuicServerNs::resp what that response carries
102 * @var QuicServerNs::ok a call's true/false outcome
103 * @var QuicServerNs::u8 the pool slots currently in use
104 * @var QuicServerNs::begin install begin_args.cfg, bind its port over UDP, route datagrams into the pool
105 * @var QuicServerNs::poll drive the server once: drain, run the engines, flush; closed or
106 * idle (PROTOCORE_QUIC_IDLE_MS) connections are reaped here
107 * @var QuicServerNs::respond send HEADERS + DATA, finishing the stream; call from within the
108 * request callback
109 * @var QuicServerNs::active_conns open connections, for diagnostics and tests
110 * @var QuicServerNs::stop close the UDP binding and release every pool slot
111 */
112typedef struct
113{
114 uint32_t now_ms; ///< the caller's monotonic clock, so this module stays platform-agnostic
115
116 QuicBeginArgs begin_args; ///< what binding the server takes
117 QuicStreamRef stream; ///< the connection and stream a response names
118 QuicRespArgs resp; ///< what that response carries
119
120 proto_bool ok;
121 uint8_t u8;
122
123 void (*const begin)(uint8_t *work);
124 void (*const poll)(uint8_t *work);
125 void (*const respond)(uint8_t *work);
126 void (*const active_conns)(uint8_t *work);
127 void (*const stop)(uint8_t *work);
128
129} QuicServerNs;
130
131/** @brief The one symbol this module exports. */
132extern QuicServerNs QuicServer;
133
134/**
135 * @brief The PROTOCORE_QUIC_SERVER_BORROW bytes this server runs out of.
136 *
137 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
138 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
139 * walks, so the server lasts the life of the program.
140 *
141 * @return the span.
142 */
143uint8_t *protocore_quic_server_span(void);
144/**
145 * @brief The response sink the HTTP/3 bridge installs; its shape is the seam's, not this module's.
146 */
147proto_bool protocore_quic_server_respond(uint32_t conn_id, uint64_t stream_id, int status, const char *content_type,
148 const uint8_t *body, size_t body_len);
149
151
152#endif // PROTOCORE_ENABLE_HTTP3
153
154#endif // PROTOCORE_QUIC_SERVER_H
HTTP/3 application engine over QUIC streams (RFC 9114).
Stateful QUIC v1 server connection engine (RFC 9000 / RFC 9001).
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97