|
cwist
Modern C web framework with libttak runtime
|
HTTP/3 (QUIC-based) Protocol Definitions for CWIST. More...
#include <cwist/net/http/http.h>#include <cwist/sys/err/cwist_err.h>#include <openssl/ssl.h>#include <stdbool.h>#include <stdint.h>#include <pthread.h>

Go to the source code of this file.
Classes | |
| struct | cwist_http3_context |
| HTTP/3 server context encapsulating lsquic/BoringSSL settings. More... | |
Typedefs | |
| typedef struct cwist_http3_context | cwist_http3_context |
| typedef void(* | cwist_webtransport_handler_func) (cwist_http_request *req, cwist_http_response *res, void *stream) |
| Callback function type for handling WebTransport sessions over HTTP/3. | |
| typedef void(* | cwist_http3_request_handler_func) (void *user_ctx, cwist_http_request *req, cwist_http_response *res) |
| Callback function type for handling HTTP/3 requests. | |
Functions | |
| cwist_error_t | cwist_http3_init_context (cwist_http3_context **ctx, const char *cert_path, const char *key_path) |
| Callback function type for handling WebTransport sessions over HTTP/3. | |
| cwist_error_t | cwist_http3_init_context_ephemeral (cwist_http3_context **ctx) |
| Initialize an HTTP/3 context with an ephemeral self-signed certificate. | |
| void | cwist_http3_destroy_context (cwist_http3_context *ctx) |
| Destroy an HTTP/3 context. | |
| cwist_error_t | cwist_http3_reload_context (cwist_http3_context *ctx, const char *cert_path, const char *key_path) |
| Hot-reload the certificate chain and key of a live HTTP/3 context. | |
| cwist_error_t | cwist_http3_server_loop (int udp_fd, cwist_http3_context *ctx, cwist_http3_request_handler_func handler, void *user_ctx) |
| Run the HTTP/3 server event loop. | |
| void | cwist_http3_set_early_data (cwist_http3_context *ctx, bool enabled) |
| Enable or disable server-side 0-RTT early data on the given context. | |
| void | cwist_http3_set_early_data_guard (cwist_http3_context *ctx, int enabled) |
| Enable or disable the 0-RTT replay guard (default ON when early data is enabled). | |
| void | cwist_http3_set_push_enabled (cwist_http3_context *ctx, int enabled) |
| Enable or disable HTTP/3 server push on the given context. | |
| int | cwist_http3_push_resource (cwist_http_request *req, const char *path, const char *content_type) |
| Push a resource to the client. | |
| int | cwist_http3_set_stream_priority (cwist_http_request *req, unsigned priority) |
| Set stream priority for the current response. | |
| void | cwist_http3_set_datagram_enabled (cwist_http3_context *ctx, int enabled) |
| Enable or disable QUIC datagram extension on the given context. | |
| void | cwist_http3_set_datagram_callback (cwist_http3_context *ctx, void(*cb)(const void *data, size_t len, void *user_ctx), void *user_ctx) |
| Register a callback for incoming QUIC datagrams. | |
| int | cwist_http3_send_datagram (void *conn, const void *data, size_t len) |
| Send an unreliable datagram over the given QUIC connection. | |
| void | cwist_http3_set_webtransport_handler (cwist_http3_context *ctx, cwist_webtransport_handler_func handler) |
| Register a WebTransport session handler on the given HTTP/3 context. | |
| void | cwist_http3_set_idle_timeout (cwist_http3_context *ctx, int ms) |
| Set the idle timeout for QUIC connections. | |
| void | cwist_http3_set_handshake_timeout (cwist_http3_context *ctx, int ms) |
| Set the handshake timeout. | |
| void | cwist_http3_set_ping_period (cwist_http3_context *ctx, int ms) |
| Set the keep-alive PING period. | |
| void | cwist_http3_set_noprogress_timeout (cwist_http3_context *ctx, int ms) |
| Set the no-progress timeout. | |
WebTransport I/O | |
| ssize_t | cwist_webtransport_read (void *stream, void *buf, size_t len) |
| Read data from a WebTransport stream. | |
| ssize_t | cwist_webtransport_write (void *stream, const void *data, size_t len) |
| Write data to a WebTransport stream. | |
| int | cwist_webtransport_flush (void *stream) |
| Flush any buffered data on a WebTransport stream. | |
| int | cwist_webtransport_close_stream (void *stream) |
| Close a WebTransport stream. | |
| void | cwist_webtransport_set_new_stream_handler (cwist_http3_context *ctx, void(*handler)(void *stream, void *user_ctx), void *user_ctx) |
| Register a callback for newly created WebTransport data streams. | |
| int | cwist_webtransport_open_bidi_stream (void *session) |
| Request a new server-initiated bidirectional WebTransport stream. | |
| int | cwist_webtransport_open_uni_stream (void *session) |
| Request a new server-initiated unidirectional WebTransport stream. | |
| ssize_t | cwist_webtransport_send_datagram (void *session, const void *data, size_t len) |
| Send an unreliable WebTransport datagram in session context. | |
| size_t | cwist_webtransport_max_datagram_size (void *session) |
| Return the current maximum WebTransport datagram payload size. | |
| int | cwist_webtransport_close_session (void *session, uint64_t code, const char *reason) |
| Close a WebTransport session with an application error code. | |
HTTP/3 (QUIC-based) Protocol Definitions for CWIST.
Definition in file http3.h.
| typedef void(* cwist_http3_request_handler_func) (void *user_ctx, cwist_http_request *req, cwist_http_response *res) |
| typedef void(* cwist_webtransport_handler_func) (cwist_http_request *req, cwist_http_response *res, void *stream) |
Callback function type for handling WebTransport sessions over HTTP/3.
| req | Parsed HTTP request object (CONNECT with :protocol=webtransport). |
| res | HTTP response object to be populated (e.g., 200 OK to accept). |
| stream | Opaque CWIST WebTransport session handle. |
| void cwist_http3_destroy_context | ( | cwist_http3_context * | ctx | ) |
Destroy an HTTP/3 context.
Destroy an HTTP/3 context.
| ctx | Context from cwist_http3_init_context*(); may be NULL (no-op). |
Releases the process-wide lsquic reference taken at init. Must not be called concurrently with cwist_http3_server_loop() on the same context.
Definition at line 2848 of file http3.c.
References cap, cwist_free(), cwist_http3_context::engine, cwist_http3_context::ssl_ctx, SSL_CTX_free, cwist_http3_context::ssl_ctx_handout, cwist_http3_context::ssl_ctx_lock, and cwist_http3_context::ticket_key.
Referenced by cwist_app_destroy().
| cwist_error_t cwist_http3_init_context | ( | cwist_http3_context ** | ctx, |
| const char * | cert_path, | ||
| const char * | key_path | ||
| ) |
Callback function type for handling WebTransport sessions over HTTP/3.
| req | Parsed HTTP request object (CONNECT with :protocol=webtransport). |
| res | HTTP response object to be populated (e.g., 200 OK to accept). |
| stream | Opaque CWIST WebTransport session handle. — API Functions — |
Initialize an HTTP/3 context with a certificate.
Callback function type for handling WebTransport sessions over HTTP/3.
| ctx | Receives the new context. |
| cert_path | PEM file with the certificate chain. |
| key_path | PEM file with the private key. |
Takes a process-wide lsquic reference (released by cwist_http3_destroy_context()).
Definition at line 2673 of file http3.c.
References cap, cwist_alloc(), CWIST_ERR_INT16, make_error(), and SSL_CTX_free.
| cwist_error_t cwist_http3_init_context_ephemeral | ( | cwist_http3_context ** | ctx | ) |
Initialize an HTTP/3 context with an ephemeral self-signed certificate.
Initialize an HTTP/3 context with an ephemeral self-signed certificate.
| ctx | Receives the new context. |
Intended for tests and local deployments where provisioning a real certificate is impractical. Takes a process-wide lsquic reference (released by cwist_http3_destroy_context()).
Definition at line 2721 of file http3.c.
References cap, cwist_alloc(), CWIST_ERR_INT16, EVP_sha256, make_error(), SSL_CTX_free, and SSL_CTX_new.
| int cwist_http3_push_resource | ( | cwist_http_request * | req, |
| const char * | path, | ||
| const char * | content_type | ||
| ) |
Push a resource to the client.
This should be called from inside the request handler callback. The push is associated with the current request stream.
| req | The current request (used to find the underlying stream). |
| path | Resource path to push (e.g. "/style.css"). |
| content_type | Optional Content-Type header value (may be NULL). |
Push a resource to the client.
| req | Request whose stream anchors the push (must carry the lsquic stream in private_data). |
| path | Request path for the pushed resource. |
| content_type | Ignored; a response field, not valid in a push request set. |
| 0 | Push stream created. |
| -1 | Bad arguments, no connection, or push not negotiated. |
Builds a request header set (:method GET, :scheme https, :path from path, :authority copied from the original request's Host or "localhost").
Definition at line 3469 of file http3.c.
References h3_hdr_out::arr, cap, cwist_http_header_get(), cwist_http_request::headers, and cwist_http_request::private_data.
| cwist_error_t cwist_http3_reload_context | ( | cwist_http3_context * | ctx, |
| const char * | cert_path, | ||
| const char * | key_path | ||
| ) |
Hot-reload the certificate chain and key of a live HTTP/3 context.
Builds and fully validates a new SSL_CTX, then swaps it into ctx under its lock: lsquic's per-connection SSL_CTX lookup picks up the new certificate for new handshakes, while established QUIC connections keep their own SSL reference and finish on the old one. The shared session-ticket key is carried over, so QUIC session resumption (and 0-RTT, when enabled) survives the reload.
Safe to call from any thread while cwist_http3_server_loop() is running on ctx.
| ctx | HTTP/3 context created by cwist_http3_init_context(). |
| cert_path | Path to the new PEM certificate chain. |
| key_path | Path to the new PEM private key. |
Hot-reload the certificate chain and key of a live HTTP/3 context.
Definition at line 2879 of file http3.c.
References cap, CWIST_ERR_INT16, cwist_http3_context::early_data_enabled, make_error(), cwist_http3_context::ssl_ctx, SSL_CTX_free, cwist_http3_context::ssl_ctx_lock, and cwist_http3_context::ticket_key.
Referenced by cwist_app_reload_tls().
Send an unreliable datagram over the given QUIC connection.
This is non-blocking; the datagram is queued and flushed by the engine.
| conn | Target QUIC connection. |
| data | Datagram payload. |
| len | Payload length in bytes. |
Send an unreliable datagram over the given QUIC connection.
| conn | lsquic connection (as seen in cwist_http_request::private_data chains); used to find the per-connection queue. |
| data | Payload to copy. |
| len | Payload length. |
| 0 | Datagram queued; lsquic is signaled to drain it via the on_dg_write callback. |
| -1 | Bad arguments, no per-connection ctx, or OOM (nothing queued). |
Thread-safe: the payload is copied and appended to the connection's own mutex-guarded queue, so concurrent sends on different connections never share state and concurrent sends on one connection queue instead of clobbering each other.
Definition at line 3823 of file http3.c.
References cap.
| cwist_error_t cwist_http3_server_loop | ( | int | udp_fd, |
| cwist_http3_context * | ctx, | ||
| cwist_http3_request_handler_func | handler, | ||
| void * | user_ctx | ||
| ) |
Run the HTTP/3 server event loop.
Run the HTTP/3 server event loop.
| udp_fd | Bound UDP socket; forced non-blocking here (idempotent). |
| ctx | Context with an initialized SSL_CTX. |
| handler | Request handler invoked per request (required). |
| user_ctx | Passed through to handler. |
Configures lsquic engine settings from the context's knobs (push, WebTransport, datagrams, flow-control windows, timeout set), then polls the socket (epoll on Linux, poll elsewhere; recvmmsg batching when available), feeds packets to the engine, and processes connections until shutdown. Linux receive batches and the packet buffer are heap-allocated so the loop does not require an oversized thread stack. On exit the engine is gracefully stopped and destroyed. CWIST_H3_DEBUG=1 routes lsquic's logger to stderr.
Definition at line 2932 of file http3.c.
References cwist_http3_context::allow_migration, cap, CWIST_ERR_INT16, cwist_http3_context::datagram_enabled, cwist_http3_context::engine, g_cwist_running, cwist_http3_context::handler, cwist_http3_context::handshake_timeout_ms, cwist_http3_context::idle_timeout_ms, make_error(), MSG_DONTWAIT, cwist_http3_context::noprogress_timeout_ms, cwist_http3_context::ping_period_ms, cwist_http3_context::push_enabled, cwist_http3_context::running, cwist_http3_context::udp_fd, cwist_http3_context::user_ctx, and cwist_http3_context::wt_handler.
| void cwist_http3_set_datagram_callback | ( | cwist_http3_context * | ctx, |
| void(*)(const void *data, size_t len, void *user_ctx) | cb, | ||
| void * | user_ctx | ||
| ) |
Register a callback for incoming QUIC datagrams.
| ctx | HTTP/3 context. |
| cb | Callback invoked for each received datagram. |
| user_ctx | Opaque pointer forwarded to cb. |
Register a callback for incoming QUIC datagrams.
| user_ctx | Passed through as the last argument of cb. |
Definition at line 3799 of file http3.c.
References cwist_http3_context::datagram_cb, and cwist_http3_context::datagram_user_ctx.
| void cwist_http3_set_datagram_enabled | ( | cwist_http3_context * | ctx, |
| int | enabled | ||
| ) |
Enable or disable QUIC datagram extension on the given context.
— Datagram API —
Datagram is disabled by default. When enabled, the application can send and receive unreliable datagrams over QUIC.
Enable or disable QUIC datagram extension on the given context.
Note: enabling WebTransport forces the datagram engine settings on regardless of this knob.
Definition at line 3791 of file http3.c.
References cwist_http3_context::datagram_enabled.
| void cwist_http3_set_early_data | ( | cwist_http3_context * | ctx, |
| bool | enabled | ||
| ) |
Enable or disable server-side 0-RTT early data on the given context.
— Advanced Features —
Early data is disabled by default because 0-RTT payloads are replayable: BoringSSL does not provide replay suppression for QUIC early data, so an attacker can re-send captured 0-RTT packets. Only opt in when the application can tolerate replays (or relies on the built-in idempotent method guard, see cwist_http3_set_early_data_guard()).
The flag is applied immediately to the context's SSL_CTX and stored so the server loop can enforce the replay guard. Works for both cwist_http3_init_context() and cwist_http3_init_context_ephemeral().
Note: enabling early data also requires session resumption; the H3 SSL_CTX is configured with a server session cache and a shared ticket key at context creation so tickets (and thus 0-RTT) work across prefork workers.
| ctx | HTTP/3 context. |
| enabled | true to accept 0-RTT early data, false to reject it. |
Enable or disable server-side 0-RTT early data on the given context.
Enabling also arms the replay guard (only idempotent methods are accepted as early data) unless the application overrides it with cwist_http3_set_early_data_guard().
Definition at line 3416 of file http3.c.
References cap, cwist_http3_context::early_data_enabled, cwist_http3_context::early_data_guard, cwist_http3_context::ssl_ctx, and cwist_http3_context::ssl_ctx_lock.
| void cwist_http3_set_early_data_guard | ( | cwist_http3_context * | ctx, |
| int | enabled | ||
| ) |
Enable or disable the 0-RTT replay guard (default ON when early data is enabled).
When the guard is active, a request that arrived as early data (i.e. while the QUIC handshake is still in progress) is only passed to the application handler if its method is idempotent (GET/HEAD/PUT/DELETE/OPTIONS/TRACE); other methods are answered with 425 Too Early so the client retries after the handshake completes.
| ctx | HTTP/3 context. |
| enabled | Non-zero to keep the guard, 0 to disable it (replay risk). |
Enable or disable the 0-RTT replay guard (default ON when early data is enabled).
While armed, requests received while the QUIC handshake is still in progress are refused with 425 unless their method is idempotent (RFC 8470).
Definition at line 3438 of file http3.c.
References cwist_http3_context::early_data_guard.
| void cwist_http3_set_handshake_timeout | ( | cwist_http3_context * | ctx, |
| int | ms | ||
| ) |
Set the handshake timeout.
Connections that do not complete the handshake within this time are dropped. Increase this on high-latency mobile networks.
| ctx | HTTP/3 context. |
| ms | Timeout in milliseconds, or 0 for default. |
Set the handshake timeout.
Definition at line 3761 of file http3.c.
References cap, and cwist_http3_context::handshake_timeout_ms.
| void cwist_http3_set_idle_timeout | ( | cwist_http3_context * | ctx, |
| int | ms | ||
| ) |
Set the idle timeout for QUIC connections.
— Unstable-network resilience knobs —
If the connection is idle for longer than this, it is closed. Default is 0 (lsquic default, typically 30s).
| ctx | HTTP/3 context. |
| ms | Timeout in milliseconds, or 0 for default. |
Set the idle timeout for QUIC connections.
Definition at line 3753 of file http3.c.
References cap, and cwist_http3_context::idle_timeout_ms.
| void cwist_http3_set_noprogress_timeout | ( | cwist_http3_context * | ctx, |
| int | ms | ||
| ) |
Set the no-progress timeout.
Connections that make no forward progress (no acks, no data) for this long are terminated. Default is 0 (lsquic default, typically 60s on server).
| ctx | HTTP/3 context. |
| ms | Timeout in milliseconds, or 0 for default. |
Set the no-progress timeout.
Definition at line 3777 of file http3.c.
References cap, and cwist_http3_context::noprogress_timeout_ms.
| void cwist_http3_set_ping_period | ( | cwist_http3_context * | ctx, |
| int | ms | ||
| ) |
Set the keep-alive PING period.
When non-zero, the server sends PING frames at this interval to keep NAT bindings alive and detect dead peers early. Recommended 10000-15000 ms for mobile clients behind aggressive NATs.
| ctx | HTTP/3 context. |
| ms | Interval in milliseconds, or 0 to disable. |
Set the keep-alive PING period.
Definition at line 3769 of file http3.c.
References cap, and cwist_http3_context::ping_period_ms.
| void cwist_http3_set_push_enabled | ( | cwist_http3_context * | ctx, |
| int | enabled | ||
| ) |
Enable or disable HTTP/3 server push on the given context.
Push is disabled by default. When enabled, the handler can push resources by calling cwist_http3_push_resource().
Enable or disable HTTP/3 server push on the given context.
Definition at line 3405 of file http3.c.
References cwist_http3_context::push_enabled.
| int cwist_http3_set_stream_priority | ( | cwist_http_request * | req, |
| unsigned | priority | ||
| ) |
Set stream priority for the current response.
Priority response header (RFC 9218) instead.This function is kept for ABI compatibility but currently always refuses: it logs a warning and returns -1 without touching the stream.
Valid priority values are 1 through 256, inclusive. Lower value means higher priority.
Set stream priority for the current response.
lsquic_stream_set_priority() on a request stream emits a PRIORITY_UPDATE frame on the control stream, which violates RFC 9218 (PRIORITY_UPDATE may only reference client-opened streams). Strict stacks (Firefox/neqo) then kill the connection with H3_FRAME_UNEXPECTED. Use the RFC 9218 Priority header instead. See the deprecation note in include/cwist/net/http/http3.h.
Definition at line 3508 of file http3.c.
References cap, and CWIST_LOG_WARN.
| void cwist_http3_set_webtransport_handler | ( | cwist_http3_context * | ctx, |
| cwist_webtransport_handler_func | handler | ||
| ) |
Register a WebTransport session handler on the given HTTP/3 context.
When an HTTP/3 CONNECT request with :protocol=webtransport is received, the regular request handler is bypassed and handler is invoked instead.
| ctx | HTTP/3 context. |
| handler | WebTransport session handler. |
Register a WebTransport session handler on the given HTTP/3 context.
When set, the server loop enables the lsquic WebTransport settings and extended-CONNECT requests with :protocol "webtransport" are handed to this handler via cwist_h3_wt_on_session_open().
Definition at line 3527 of file http3.c.
References cwist_http3_context::wt_handler.
Referenced by cwist_app_use_webtransport().
Request a new server-initiated bidirectional WebTransport stream.
The actual stream is delivered asynchronously via the new-stream handler.
| session | Opaque CWIST WebTransport session handle. |
Request a new server-initiated bidirectional WebTransport stream.
Definition at line 3730 of file http3.c.
References cap.
Request a new server-initiated unidirectional WebTransport stream.
The actual stream is delivered asynchronously via the new-stream handler.
| session | Opaque CWIST WebTransport session handle. |
Request a new server-initiated unidirectional WebTransport stream.
Definition at line 3738 of file http3.c.
References cap.
Read data from a WebTransport stream.
Non-blocking. Returns number of bytes read, 0 if no data is currently available, or -1 on error.
| stream | Opaque CWIST WebTransport stream handle. |
| buf | Destination buffer. |
| len | Buffer capacity in bytes. |
Read data from a WebTransport stream.
Definition at line 3694 of file http3.c.
References cap.
Send an unreliable WebTransport datagram in session context.
| session | Opaque CWIST WebTransport session handle. |
| data | Datagram payload. |
| len | Payload length in bytes. |
Send an unreliable WebTransport datagram in session context.
Definition at line 3978 of file http3.c.
References cap.
| void cwist_webtransport_set_new_stream_handler | ( | cwist_http3_context * | ctx, |
| void(*)(void *stream, void *user_ctx) | handler, | ||
| void * | user_ctx | ||
| ) |
Register a callback for newly created WebTransport data streams.
Invoked for both server-initiated and client-initiated streams.
| ctx | HTTP/3 context. |
| handler | Callback invoked for each new data stream. |
| user_ctx | Opaque pointer forwarded to handler. |
Register a callback for newly created WebTransport data streams.
| user_ctx | Passed through as the second argument of handler. |
Definition at line 3536 of file http3.c.
References cwist_http3_context::wt_new_stream_ctx, and cwist_http3_context::wt_new_stream_handler.
Write data to a WebTransport stream.
Returns number of bytes accepted into the send buffer, or -1 on error.
| stream | Opaque CWIST WebTransport stream handle. |
| data | Payload to write. |
| len | Payload length in bytes. |
Write data to a WebTransport stream.
Definition at line 3704 of file http3.c.
References cap.