ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
h3_conn.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 h3_conn.h
6 * @brief HTTP/3 application engine over QUIC streams (RFC 9114).
7 *
8 * Sits on top of the QUIC transport engine (::QuicConn) and speaks HTTP/3: on the handshake
9 * completing it opens the server's unidirectional control stream (sending SETTINGS) and the two
10 * QPACK encoder / decoder streams, reads the client's control stream, and on each client-initiated
11 * bidirectional request stream reassembles the HTTP/3 frames - QPACK-decoding the HEADERS field
12 * section into a request (method / path / authority + a small header set) and collecting the DATA
13 * body - then hands the finished request to the application through a callback.
14 * @ref H3ConnNs::respond serializes a response (HEADERS + DATA) back onto the request stream and
15 * finishes it.
16 *
17 * QPACK is static-table only (we advertise QPACK_MAX_TABLE_CAPACITY = 0), so no dynamic-table state
18 * is needed and the encoder / decoder streams carry only their stream-type byte. Fixed storage, no
19 * heap; host-testable by feeding it decoded stream bytes through the ::QuicConn callback seam.
20 *
21 * @author Douglas Quigg (dstroy0)
22 * @date 2026
23 */
24
25#ifndef PROTOCORE_H3_CONN_H
26#define PROTOCORE_H3_CONN_H
27
28#include "protocore_config.h" // the entry point: the enable gate below, and the widths
29
30#if PROTOCORE_ENABLE_HTTP3
31
33
34// PROTOCORE_H3_CONN_BORROW - the bytes one connection runs out of - is stated in
35// protocore_config.h, which sums it into the plaintext arena. The connection carries no key
36// material, so its context leads that one span rather than taking a secure one of its own. A caller
37// takes the span once and binds it; how it is carved is this module's and is never named here.
38
39/**
40 * @brief A completed request delivered to the application.
41 * @param body / body_len the request body (may be empty); valid only during the call.
42 */
43typedef void (*H3RequestFn)(void *app, uint8_t *h3, uint64_t stream_id, const char *method, const char *path,
44 const char *authority, const uint8_t *body, size_t body_len);
45
46/** @brief The QUIC transport under this connection. The connection's own storage is the borrow. */
47typedef struct
48{
49 uint8_t *qc; ///< the QUIC connection's context span (::QuicConnNs::bind, member ctx)
50} H3ConnBind;
51
52/** @brief What the application is told about, and the opaque it is told with. */
53typedef struct
54{
55 H3RequestFn on_request; ///< invoked for each completed request
56 void *app; ///< opaque, passed back to the callback
57} H3ConnAppArgs;
58
59/** @brief One response, serialized onto a request stream. */
60typedef struct
61{
62 uint64_t stream_id; ///< the request stream it answers
63 int status; ///< HTTP status code
64 const char *content_type; ///< optional; NULL omits the field
65 const uint8_t *body; ///< the body (may be empty)
66 size_t body_len; ///< its length
67} H3ConnRespondArgs;
68
69/**
70 * @brief HTTP/3 server connection (RFC 9114).
71 *
72 * The connection's storage is the CALLER's: it arrives as the entry's borrow, and this file lays
73 * its context and per-stream buffers out at compile-time offsets inside it. A caller binds the QUIC
74 * connection under it, sets the members a call takes, invokes it through ::H3Conn with those bytes,
75 * and reads the outcome off the same handle.
76 *
77 * H3Conn.bind.qc = quic_ctx_span;
78 * H3Conn.app_args.on_request = on_request;
79 * H3Conn.app_args.app = app;
80 * H3Conn.init(byte_span);
81 * H3Conn.respond_args.stream_id = id;
82 * H3Conn.respond_args.status = 200;
83 * H3Conn.respond(byte_span);
84 *
85 * @var H3ConnNs::bind the QUIC connection under this one; the storage is the borrow
86 * @var H3ConnNs::app_args what the application is told about
87 * @var H3ConnNs::respond_args one response, serialized onto a request stream
88 * @var H3ConnNs::ok a call's true/false outcome
89 * @var H3ConnNs::init open the connection and install its hooks on the bound QUIC connection
90 * @var H3ConnNs::respond serialize HEADERS + DATA onto a request stream and finish it
91 *
92 * @ref H3ConnNs::init overwrites the bound QUIC connection's callbacks with this engine's hooks, so
93 * the application callback goes in @ref H3ConnNs::app_args rather than on the transport.
94 *
95 * The bound span is the CALLER's, at an address it knows. The caller releases it, and the pool wipes
96 * on release; this module neither takes it, holds it past the connection, nor releases it. The span
97 * IS the connection, so two connections are two spans and never collide.
98 *
99 * No storage member: a caller binds, sets operands and reads @ref H3ConnNs::ok, and that is all the
100 * surface there is.
101 */
102typedef struct
103{
104 H3ConnBind bind;
105 H3ConnAppArgs app_args;
106 H3ConnRespondArgs respond_args;
107 proto_bool ok;
108} H3ConnVars;
109
110/** @brief The operands and the outcome. */
111extern H3ConnVars H3ConnV;
112
113/** @brief The entries. */
114typedef struct
115{
116 void (*const init)(uint8_t *work);
117 void (*const respond)(uint8_t *work);
118} H3ConnNs;
119
120// What the table binds, defined once in the .c and taking one parameter each: everything
121// else an entry needs is an operand in H3ConnV or a region of the borrow at a fixed offset.
122void protocore_h3_conn_init(uint8_t *work);
123void protocore_h3_conn_respond(uint8_t *work);
124
125// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
126// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
127// `H3Conn.init(work)` resolves to a named function and becomes a DIRECT call. An extern table
128// leaves the call indirect and the symbol live at every level, -O2 -flto included.
129static const H3ConnNs H3Conn __attribute__((unused)) = {
130 .init = protocore_h3_conn_init,
131 .respond = protocore_h3_conn_respond,
132};
133
135
136#endif // PROTOCORE_ENABLE_HTTP3
137
138#endif // PROTOCORE_H3_CONN_H
#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