wired
libc-free QUIC/HTTP3 SDK in C for x86_64-linux
Loading...
Searching...
No Matches
srvboot.h File Reference

RFC 9000 17.2 / RFC 9001 5 / RFC 8446 4.4: cold-start a server connection from a client Initial datagram. More...

Go to the source code of this file.

Data Structures

struct  wired_srvboot_id
 The fixed server identity a bootstrap needs: the X25519 handshake key pair, the ECDSA P-256 signing scalar the server builds its end-entity certificate from, the server's source connection id (written in every reply), and the ServerHello random. More...
struct  wired_srvboot_conn
 The server orchestrator and its HTTP/3 loop, freshly cold-started by wired_srvboot_accept and driven together thereafter (wired_srvloop_step takes the same pair). More...
struct  wired_srvboot_in
 The fixed server identity to boot with and the client's Initial datagram to recover the ClientHello from. More...
struct  wired_srvboot_out
 The sealed reply datagrams of a bootstrap. More...
struct  wired_srvboot_acc
 One nascent connection's ClientHello reassembly across Initial datagrams: a ClientHello too big for one Initial (a post-quantum hybrid key share pushes it near 1.7KB) arrives as CRYPTO chunks spread over several packets (RFC 9000 19.6), and the server may not build its flight until the whole message is contiguous. More...

Macros

#define WIRED_SRVBOOT_FLIGHT_MAX   12
 Most Handshake flight datagrams a bootstrap seals: sized past quic-interop-runner's deliberately inflated 9-cert amplificationlimit chain (~10KB TLS flight, ~10 chunks at the per-datagram CRYPTO chunk size) with headroom.
#define WIRED_SRVBOOT_ZERORTT_MAX   32
 Datagrams a boot's accumulator holds verbatim while waiting for 0-RTT keys (wired_srvboot_acc.zerortt_dg): comfortably past a real quic-go 0-RTT burst (26 single-packet datagrams observed live).
#define WIRED_SRVBOOT_ZERORTT_DG_MAX   1500
 Byte capacity of one buffered 0-RTT datagram: past RFC 9000 14.1's 1200-byte Initial floor and a real Ethernet MTU's ~1500-byte payload, the range every 0-RTT datagram observed live falls within.

Functions

int wired_srvboot_is_initial (const u8 *dg, usz len)
 RFC 9000 17.2: 1 if dg is a long-header Initial datagram (a Handshake or short-header packet is the live connection continuing, not a new Initial).
int wired_srvboot_is_zerortt (const u8 *dg, usz len)
 RFC 9000 17.2.3: 1 if dg is a long-header 0-RTT datagram.
int wired_srvboot_accept (const wired_srvboot_conn *conn, const wired_srvboot_in *in, wired_srvboot_out *out)
 Recover the ClientHello from the protected Initial datagram, initialize the server and its HTTP/3 loop with in->id, build the server flight, and seal it: a server Initial (ServerHello, acknowledging the client Initial) into out->initial, and the Handshake flight (Certificate/CertificateVerify/ Finished) into out->flight as one Handshake packet datagram per CRYPTO chunk (RFC 9000 19.6), recording each datagram's length in out->dgram_len and the count in out->dgram_count.
usz wired_srvboot_vneg (quic_span dg, u8 *out, usz cap)
 Answer a long-header datagram of an unsupported version with a Version Negotiation packet offering this server's supported versions – v2 then v1 (RFC 9368 5), connection ids swapped (RFC 9000 5.2.2 / RFC 8999 6).
void wired_srvboot_acc_reset (wired_srvboot_acc *a)
 Empty the accumulator for a fresh connection attempt.
int wired_srvboot_acc_feed (wired_srvboot_acc *a, quic_mspan dg)
 Absorb one Initial datagram: every coalesced Initial packet in it is opened with the bound ODCID's keys and its CRYPTO chunks land at their stream offsets (duplicates and any arrival order are fine).
usz wired_srvboot_acc_zerortt_count (const wired_srvboot_acc *a)
quic_span wired_srvboot_acc_zerortt_take (const wired_srvboot_acc *a, usz i)
 The i'th buffered 0-RTT datagram, verbatim as received.
void wired_srvboot_acc_allow (wired_srvboot_acc *a, quic_span dcid)
 Admit dcid alongside the bound one: after the server's first packet the client switches its DCID to the server's scid (RFC 9000 7.2), and its remaining ClientHello pieces arrive under that new DCID.
usz wired_srvboot_partial_ack (wired_srvboot_acc *a, quic_span scid, u8 *out, usz cap)
 Seal an ACK-only server Initial acknowledging the highest Initial opened so far (RFC 9000 13.2.1) — sent while the ClientHello is still incomplete, so a client whose missing piece keeps getting dropped still hears the server is alive instead of timing out.
int wired_srvboot_acc_complete (const wired_srvboot_acc *a)
int wired_srvboot_accept_acc (const wired_srvboot_conn *conn, const wired_srvboot_id *id, wired_srvboot_acc *a, wired_srvboot_out *out)
 Cold-start the connection from a completed accumulator: initialize the server and loop from the bound header, fold the reassembled ClientHello, and seal the flight, acknowledging the highest Initial packet number received (out fields as in wired_srvboot_accept).
usz wired_srvboot_refusal (const wired_srvboot_acc *a, quic_span scid, u64 error_code, u8 *out, usz cap)
 Refuse an authenticated but unservable connection attempt: an Initial CONNECTION_CLOSE acknowledging the highest received packet number so the peer stops retransmitting and fails fast (RFC 9000 10.2).

Detailed Description

RFC 9000 17.2 / RFC 9001 5 / RFC 8446 4.4: cold-start a server connection from a client Initial datagram.

The symmetric partner of wired_srvloop_step: srvloop_step drives the live connection, this bootstraps it. Both are socket-free (buffer in, sealed replies out) so the SDK core stays kernel-free; the caller does the UDP send.

Function Documentation

◆ wired_srvboot_acc_allow()

void wired_srvboot_acc_allow ( wired_srvboot_acc * a,
quic_span dcid )

Admit dcid alongside the bound one: after the server's first packet the client switches its DCID to the server's scid (RFC 9000 7.2), and its remaining ClientHello pieces arrive under that new DCID.

Keys stay the bound ODCID's (RFC 9001 5.2).

Parameters
athe accumulator
dcidthe additional DCID to admit (the server's own scid)

◆ wired_srvboot_acc_complete()

int wired_srvboot_acc_complete ( const wired_srvboot_acc * a)
Parameters
athe accumulator
Returns
1 once the buffered CRYPTO prefix folds a complete ClientHello.

◆ wired_srvboot_acc_feed()

int wired_srvboot_acc_feed ( wired_srvboot_acc * a,
quic_mspan dg )

Absorb one Initial datagram: every coalesced Initial packet in it is opened with the bound ODCID's keys and its CRYPTO chunks land at their stream offsets (duplicates and any arrival order are fine).

The first datagram binds the accumulator; later ones must repeat its DCID. RFC 9001 4.6.1: a datagram whose leading packet is 0-RTT instead (no Initial keys exist to open it with yet) is held verbatim in a's zerortt_dg buffer rather than refused, for wired_srvboot_acc_zerortt_take to open once wired_srvboot_accept_acc succeeds.

Parameters
athe accumulator
dgthe received datagram (opened in place)
Returns
1 if at least one Initial packet in the datagram authenticated and was absorbed, or the datagram was buffered as 0-RTT; 0 if it was refused outright (unparseable, a foreign DCID, or nothing in it opened under the bound keys).

◆ wired_srvboot_acc_reset()

void wired_srvboot_acc_reset ( wired_srvboot_acc * a)

Empty the accumulator for a fresh connection attempt.

Parameters
athe accumulator to reset

◆ wired_srvboot_acc_zerortt_count()

usz wired_srvboot_acc_zerortt_count ( const wired_srvboot_acc * a)
Parameters
athe accumulator
Returns
the number of whole 0-RTT datagrams buffered in a (wired_srvboot_acc_zerortt_take indexes 0..this).

◆ wired_srvboot_acc_zerortt_take()

quic_span wired_srvboot_acc_zerortt_take ( const wired_srvboot_acc * a,
usz i )

The i'th buffered 0-RTT datagram, verbatim as received.

Parameters
athe accumulator
iindex, 0 <= i < wired_srvboot_acc_zerortt_count(a)
Returns
the datagram's bytes as a view into a's own storage.

◆ wired_srvboot_accept()

int wired_srvboot_accept ( const wired_srvboot_conn * conn,
const wired_srvboot_in * in,
wired_srvboot_out * out )

Recover the ClientHello from the protected Initial datagram, initialize the server and its HTTP/3 loop with in->id, build the server flight, and seal it: a server Initial (ServerHello, acknowledging the client Initial) into out->initial, and the Handshake flight (Certificate/CertificateVerify/ Finished) into out->flight as one Handshake packet datagram per CRYPTO chunk (RFC 9000 19.6), recording each datagram's length in out->dgram_len and the count in out->dgram_count.

Sets both obufs' len. The caller registers its request handler on conn->l via wired_srvloop_set_handler.

Parameters
connthe orchestrator/loop pair to cold-start
inthe fixed server identity and the client's Initial datagram
outreceives the sealed server Initial and Handshake datagrams
Returns
1 on success, 0 if the datagram is not a valid Initial, the open/reassembly fails, or the flight cannot be built or does not fit.

◆ wired_srvboot_accept_acc()

int wired_srvboot_accept_acc ( const wired_srvboot_conn * conn,
const wired_srvboot_id * id,
wired_srvboot_acc * a,
wired_srvboot_out * out )

Cold-start the connection from a completed accumulator: initialize the server and loop from the bound header, fold the reassembled ClientHello, and seal the flight, acknowledging the highest Initial packet number received (out fields as in wired_srvboot_accept).

Parameters
connthe orchestrator/loop pair to cold-start
idthe fixed server identity
aa complete accumulator (wired_srvboot_acc_complete)
outreceives the sealed flight and the acknowledged packet number
Returns
1, or 0 when the accumulator is incomplete or the boot fails.

◆ wired_srvboot_is_initial()

int wired_srvboot_is_initial ( const u8 * dg,
usz len )

RFC 9000 17.2: 1 if dg is a long-header Initial datagram (a Handshake or short-header packet is the live connection continuing, not a new Initial).

Parameters
dgthe datagram bytes as received from the socket
lenlength of dg in octets
Returns
1 if dg is a long-header Initial datagram, 0 otherwise

◆ wired_srvboot_is_zerortt()

int wired_srvboot_is_zerortt ( const u8 * dg,
usz len )

RFC 9000 17.2.3: 1 if dg is a long-header 0-RTT datagram.

Read before any key exists to open it with – only the type bits are needed, same scope as wired_srvboot_is_initial's own byte0-vs-version read.

Parameters
dgthe datagram bytes as received from the socket
lenlength of dg in octets
Returns
1 if dg is a long-header 0-RTT datagram, 0 otherwise

◆ wired_srvboot_partial_ack()

usz wired_srvboot_partial_ack ( wired_srvboot_acc * a,
quic_span scid,
u8 * out,
usz cap )

Seal an ACK-only server Initial acknowledging the highest Initial opened so far (RFC 9000 13.2.1) — sent while the ClientHello is still incomplete, so a client whose missing piece keeps getting dropped still hears the server is alive instead of timing out.

No-op before anything authenticated (nothing may be reflected to an unproven address, RFC 9000 8.1).

Parameters
athe accumulator (its ack_pn advances on success)
scidthe server's own connection id for the header
outreceives the sealed datagram
capbytes available at out
Returns
bytes written, or 0 when nothing was opened yet or sealing failed.

◆ wired_srvboot_refusal()

usz wired_srvboot_refusal ( const wired_srvboot_acc * a,
quic_span scid,
u64 error_code,
u8 * out,
usz cap )

Refuse an authenticated but unservable connection attempt: an Initial CONNECTION_CLOSE acknowledging the highest received packet number so the peer stops retransmitting and fails fast (RFC 9000 10.2).

Parameters
athe bound accumulator of the refused attempt
scidthe server connection id to answer with
error_codeRFC 9001 8.2 CRYPTO_ERROR (0x0100 | TLS alert) to report, e.g. quic_sdrv_last_error's value – 0 falls back to the generic TLS handshake_failure code (0x128, RFC 9001 4.8) when the caller has no more specific cause on hand.
outreceives the sealed Initial datagram
capbytes available at out
Returns
bytes written, or 0 on overflow.

◆ wired_srvboot_vneg()

usz wired_srvboot_vneg ( quic_span dg,
u8 * out,
usz cap )

Answer a long-header datagram of an unsupported version with a Version Negotiation packet offering this server's supported versions – v2 then v1 (RFC 9368 5), connection ids swapped (RFC 9000 5.2.2 / RFC 8999 6).

No response for: a datagram under 1200 bytes (amplification guard, RFC 9000 6), version 0 (never answer a Version Negotiation packet with another, RFC 9000 6.1), a supported version (v1 or v2), a short header, or an unparseable header.

Parameters
dgthe received datagram
outreceives the Version Negotiation packet
capbytes available at out
Returns
bytes written, or 0 when no response is owed.