Line data Source code
1 : #ifndef HEADER_fd_src_waltz_quic_fd_quic_h
2 : #define HEADER_fd_src_waltz_quic_fd_quic_h
3 :
4 : /* fd_quic_t is a partial implementation of QUIC -- an encrypted,
5 : multiplexing transport layer network protocol.
6 :
7 : For now, IPv4 over Ethernet (EN10MB) flows are supported.
8 :
9 : This API is non-blocking and single-threaded. Any requests to the
10 : peer (such as "open a connection") are queued and processed on RX
11 : or service call. The user is notified of events via callbacks.
12 : The user must further ensure that RX (via fd_aio_t) is dispatched
13 : only from the thread with the active join to the target fd_quic_t.
14 :
15 : Scaling is achieved via fd_quic_t instances and steering of RX flows.
16 : For example, incoming RX that exceeds the throughput of one fd_quic_t
17 : may be load balanced based on QUIC dest conn ID, or UDP src flow ID.
18 :
19 : This implementation aims to be compliant to RFC 9000 and RFC 9001:
20 : - https://datatracker.ietf.org/doc/html/rfc9000
21 : - https://datatracker.ietf.org/doc/html/rfc9001
22 :
23 : ### Memory Management
24 :
25 : fd_quic is entirely pre-allocated. Currently, a QUIC object reserves
26 : space for a number of connection slots, with uniform stream,
27 : reassembly, and ACK buffers.
28 :
29 : ### Memory Layout
30 :
31 : fd_quic_t is the publicly exported memory layout of a QUIC object.
32 : The private memory region of a QUIC object extends beyond the end of
33 : this struct. fd_quic_t is not intended to be allocated directly,
34 : refer to the below for details.
35 :
36 : ### Lifecycle
37 :
38 : The below state diagram shows the lifecycle of an fd_quic_t.
39 :
40 : ┌───────────┐ new ┌───────────┐ join ┌──────────┐
41 : │ ├───────►│ ├──────►│ │
42 : │ allocated │ │ formatted │ │ joined │
43 : │ │◄───────┤ │◄──────┤ │
44 : └───────────┘ delete └───────────┘ leave └───▲───┬──┘
45 : │ │ set config
46 : │ │ set callbacks
47 : fini │ │ init
48 : ┌──┴───▼──┐
49 : ┌───│ │
50 : service │ │ ready │
51 : └──►│ │
52 : └─────────┘
53 :
54 : ### Lifecycle: Allocation & Formatting
55 :
56 : A QUIC object resides in a contiguous pre-allocated memory region.
57 : (Usually, in a Firedancer workspace) The footprint and internal
58 : layout depends on the pre-configured fd_quic_limits_t parameters.
59 : These limits are constant throughout the lifetime of an fd_quic_t.
60 :
61 : Use fd_quic_{align,footprint} to determine size and alignment of the
62 : memory region to be used. Use fd_quic_new to format such a memory
63 : region and to obtain an opaque handle. In the formatted state, the
64 : fd_quic_t is position-independent (may be mapped at different virtual
65 : addresses). This is useful for separating allocation and runtime use
66 : into different steps.
67 :
68 : ### Lifecycle: Joining
69 :
70 : Given an opaque handle, fd_quic_join runs basic coherence checks and
71 : returns a typed pointer to the object. The object is not modified
72 : by this operation. Each object may have multiple active joins, but
73 : only one of them may write. (Typically, a single join is used for
74 : service, and secondary joins for read-only monitoring)
75 :
76 : ### Lifecycle: Usage
77 :
78 : fd_quic_init initializes an fd_quic_t for use. On success, the QUIC
79 : becomes ready to serve from the thread that init was called from (it
80 : is invalid to service QUIC from another thread). */
81 :
82 : /* TODO provide fd_quic on non-hosted targets */
83 :
84 : #include "fd_quic_common.h"
85 : #include "fd_quic_enum.h"
86 :
87 : #include "../aio/fd_aio.h"
88 : #include "../tls/fd_tls.h"
89 : #include "../../util/hist/fd_histf.h"
90 :
91 : /* FD_QUIC_API marks public API declarations. No-op for now. */
92 : #define FD_QUIC_API
93 :
94 : /* Forward declarations */
95 :
96 : struct fd_quic_conn;
97 : typedef struct fd_quic_conn fd_quic_conn_t;
98 :
99 : struct fd_quic_stream;
100 : typedef struct fd_quic_stream fd_quic_stream_t;
101 :
102 : struct fd_quic_state_private;
103 : typedef struct fd_quic_state_private fd_quic_state_t;
104 :
105 : /* fd_quic_limits_t defines the memory layout of an fd_quic_t object.
106 : Limits are immutable and valid for the lifetime of an fd_quic_t
107 : (i.e. outlasts joins, until fd_quic_delete) */
108 :
109 : struct __attribute__((aligned(16UL))) fd_quic_limits {
110 : ulong conn_cnt; /* instance-wide, max concurrent conn count */
111 : ulong handshake_cnt; /* instance-wide, max concurrent handshake count */
112 : ulong log_depth; /* instance-wide, depth of shm log cache */
113 :
114 : ulong conn_id_cnt; /* per-conn, max conn ID count (min 4UL) */
115 : ulong stream_id_cnt; /* per-conn, max concurrent stream ID count */
116 : ulong inflight_frame_cnt; /* instance-wide, total max inflight frame count */
117 : ulong min_inflight_frame_cnt_conn; /* per-conn, min inflight frame count */
118 :
119 : ulong tx_buf_sz; /* per-stream, tx buf sz in bytes */
120 : /* the user consumes rx directly from the network buffer */
121 :
122 : ulong stream_pool_cnt; /* instance-wide, number of streams in stream pool */
123 : };
124 : typedef struct fd_quic_limits fd_quic_limits_t;
125 :
126 : /* fd_quic_layout_t is an offset table describing the memory layout of
127 : an fd_quic_t object. It is deived from fd_quic_limits_t. */
128 :
129 : struct fd_quic_layout {
130 : ulong meta_sz; /* size of this struct */
131 : ulong log_off; /* offset to quic_log */
132 : ulong conns_off; /* offset of connection mem region */
133 : ulong conn_footprint; /* sizeof a conn */
134 : ulong conn_map_off; /* offset of conn map mem region */
135 : int lg_slot_cnt; /* see conn_map_new */
136 : ulong hs_pool_off; /* offset of the handshake pool */
137 : ulong stream_pool_off; /* offset of the stream pool */
138 : ulong pkt_meta_pool_off; /* offset of the pkt_meta pool */
139 : };
140 :
141 : typedef struct fd_quic_layout fd_quic_layout_t;
142 :
143 : /* fd_quic_now_t is the clock source used internally by quic for
144 : scheduling events. context is an arbitrary pointer earlier provided
145 : by the caller during config. */
146 :
147 : typedef ulong
148 : (*fd_quic_now_t)( void * context );
149 :
150 : /* fd_quic_config_t defines mutable config of an fd_quic_t. The config is
151 : immutable during an active join. */
152 :
153 : struct __attribute__((aligned(16UL))) fd_quic_config {
154 : /* Used by tracing/logging code */
155 : #define FD_QUIC_CONFIG_ENUM_LIST_role(X,...) \
156 : X( FD_QUIC_ROLE_CLIENT, "ROLE_CLIENT" ) \
157 : X( FD_QUIC_ROLE_SERVER, "ROLE_SERVER" )
158 :
159 : #define FD_QUIC_CONFIG_LIST(X,...) \
160 0 : X( role, "%d", enum, "enum", __VA_ARGS__ ) \
161 0 : X( retry, "%d", bool, "bool", __VA_ARGS__ ) \
162 0 : X( tick_per_us, "%f", units, "ticks per ms", __VA_ARGS__ ) \
163 0 : X( idle_timeout, "%lu", units, "ns", __VA_ARGS__ ) \
164 0 : X( keep_alive, "%d", bool, "bool", __VA_ARGS__ ) \
165 0 : X( ack_delay, "%lu", units, "ns", __VA_ARGS__ ) \
166 0 : X( ack_threshold, "%lu", units, "bytes", __VA_ARGS__ ) \
167 0 : X( retry_ttl, "%lu", units, "ns", __VA_ARGS__ ) \
168 0 : X( tls_hs_ttl, "%lu", units, "ns", __VA_ARGS__ ) \
169 0 : X( identity_public_key, "%x", hex32, "", __VA_ARGS__ ) \
170 0 : X( sign, "%p", ptr, "", __VA_ARGS__ ) \
171 0 : X( sign_ctx, "%p", ptr, "", __VA_ARGS__ ) \
172 0 : X( keylog_file, "%s", value, "", __VA_ARGS__ ) \
173 0 : X( initial_rx_max_stream_data, "%lu", units, "bytes", __VA_ARGS__ ) \
174 0 : X( net.dscp, "0x%02x", value, "", __VA_ARGS__ )
175 :
176 : /* Protocol config ***************************************/
177 :
178 : /* role: one of FD_QUIC_ROLE_{CLIENT,SERVER} */
179 : int role;
180 :
181 : /* retry: whether address validation using retry packets is enabled (RFC 9000, Section 8.1.2) */
182 : int retry;
183 :
184 : /* tick_per_us: clock ticks per microsecond */
185 : double tick_per_us;
186 :
187 : /* idle_timeout: Upper bound on conn idle timeout.
188 : Also sent to peer via max_idle_timeout transport param.
189 : If the peer specifies a lower idle timeout, that is used instead. */
190 : ulong idle_timeout;
191 4272 : # define FD_QUIC_DEFAULT_IDLE_TIMEOUT (ulong)(1e9) /* 1s */
192 :
193 : /* keep_alive
194 : * whether the fd_quic should use QUIC PING frames to keep connections alive
195 : * Set to 1 to keep connections alive
196 : * Set to 0 to allow connections to close on idle
197 : * default is 0 */
198 : int keep_alive;
199 :
200 : /* ack_delay: median delay on outgoing ACKs. Greater delays allow
201 : fd_quic to coalesce packet ACKs. */
202 : ulong ack_delay;
203 4272 : # define FD_QUIC_DEFAULT_ACK_DELAY (ulong)(50e6) /* 50ms */
204 :
205 : /* ack_threshold: immediately send an ACK when the number of
206 : unacknowledged stream bytes exceeds this value. */
207 : ulong ack_threshold;
208 2142 : # define FD_QUIC_DEFAULT_ACK_THRESHOLD (65536UL) /* 64 KiB */
209 :
210 : /* retry_ttl: time-to-live for retry tokens */
211 : ulong retry_ttl;
212 2139 : # define FD_QUIC_DEFAULT_RETRY_TTL (ulong)(1e9) /* 1s */
213 :
214 : /* hs_ttl: time-to-live for tls_hs */
215 : ulong tls_hs_ttl;
216 2139 : # define FD_QUIC_DEFAULT_TLS_HS_TTL (ulong)(3e9) /* 3s */
217 :
218 : /* TLS config ********************************************/
219 :
220 : /* identity_key: Ed25519 public key of node identity */
221 : uchar identity_public_key[ 32 ];
222 :
223 : /* Callback for signing TLS 1.3 certificate verify payload */
224 : fd_tls_sign_fn_t sign;
225 : void * sign_ctx;
226 :
227 0 : # define FD_QUIC_PATH_LEN 1023UL
228 : char keylog_file[ FD_QUIC_PATH_LEN+1UL ];
229 :
230 : ulong initial_rx_max_stream_data; /* per-stream, rx buf sz in bytes, set by the user. */
231 :
232 : /* Network config ****************************************/
233 :
234 : struct { /* Internet config */
235 : /* dscp: Differentiated services code point.
236 : Set on all outgoing IPv4 packets. */
237 : uchar dscp;
238 : } net;
239 : };
240 :
241 : /* Callback API *******************************************************/
242 :
243 : /* Note: QUIC library invokes callbacks during RX or service. Callback
244 : may only invoke fd_quic API methods labelled CB-safe. Callbacks are
245 : not re-entrant. */
246 :
247 : /* fd_quic_cb_conn_new_t: server received a new conn and completed
248 : handshakes. */
249 : typedef void
250 : (* fd_quic_cb_conn_new_t)( fd_quic_conn_t * conn,
251 : void * quic_ctx );
252 :
253 : /* fd_quic_cb_conn_handshake_complete_t: client completed a handshake
254 : of a conn it created. */
255 : typedef void
256 : (* fd_quic_cb_conn_handshake_complete_t)( fd_quic_conn_t * conn,
257 : void * quic_ctx );
258 :
259 : /* fd_quic_cb_conn_final_t: Conn termination notification. The conn
260 : object is freed immediately after returning. User should destroy any
261 : remaining references to conn in this callback. */
262 : typedef void
263 : (* fd_quic_cb_conn_final_t)( fd_quic_conn_t * conn,
264 : void * quic_ctx );
265 :
266 : /* fd_quic_cb_stream_notify_t signals a notable stream event.
267 : stream_ctx object is the user-provided stream context set in the new
268 : callback.
269 :
270 : TODO will only one notify max be served?
271 : TODO will stream be deallocated immediately after callback?
272 :
273 : notify_type is one of FD_QUIC_NOTIFY_{...} */
274 : typedef void
275 : (* fd_quic_cb_stream_notify_t)( fd_quic_stream_t * stream,
276 : void * stream_ctx,
277 : int notify_type );
278 :
279 : typedef int
280 : (* fd_quic_cb_stream_rx_t)( fd_quic_conn_t * conn,
281 : ulong stream_id,
282 : ulong offset,
283 : uchar const * data,
284 : ulong data_sz,
285 : int fin );
286 :
287 : /* fd_quic_cb_tls_keylog_t is called when a new encryption secret
288 : becomes available. line is a cstr containing the secret in NSS key
289 : log format (intended for tests only). */
290 :
291 : typedef void
292 : (* fd_quic_cb_tls_keylog_t)( void * quic_ctx,
293 : char const * line );
294 :
295 : /* fd_quic_callbacks_t defines the set of user-provided callbacks that
296 : are invoked by the QUIC library. Resets on leave. */
297 :
298 : struct fd_quic_callbacks {
299 : /* Function pointers to user callbacks */
300 :
301 : void * quic_ctx; /* user-provided context pointer
302 : for instance-wide callbacks */
303 :
304 : fd_quic_cb_conn_new_t conn_new; /* non-NULL, with quic_ctx */
305 : fd_quic_cb_conn_handshake_complete_t conn_hs_complete; /* non-NULL, with quic_ctx */
306 : fd_quic_cb_conn_final_t conn_final; /* non-NULL, with quic_ctx */
307 : fd_quic_cb_stream_notify_t stream_notify; /* non-NULL, with stream_ctx */
308 : fd_quic_cb_stream_rx_t stream_rx; /* non-NULL, with stream_ctx */
309 : fd_quic_cb_tls_keylog_t tls_keylog; /* nullable, with quic_ctx */
310 :
311 : /* Clock source */
312 :
313 : fd_quic_now_t now; /* non-NULL */
314 : void * now_ctx; /* user-provided context pointer for now_fn calls */
315 :
316 : };
317 : typedef struct fd_quic_callbacks fd_quic_callbacks_t;
318 :
319 : /* fd_quic metrics ****************************************************/
320 :
321 : /* TODO: evaluate performance impact of metrics */
322 :
323 : union fd_quic_metrics {
324 : struct {
325 : /* Network metrics */
326 : ulong net_rx_pkt_cnt; /* number of IP packets received */
327 : ulong net_rx_byte_cnt; /* total bytes received (including IP, UDP, QUIC headers) */
328 : ulong net_tx_pkt_cnt; /* number of IP packets sent */
329 : ulong net_tx_byte_cnt; /* total bytes sent */
330 : ulong retry_tx_cnt; /* number of Retry packets sent */
331 :
332 : /* Conn metrics */
333 : ulong conn_active_cnt; /* number of active conns */
334 : ulong conn_created_cnt; /* number of conns created */
335 : ulong conn_closed_cnt; /* number of conns gracefully closed */
336 : ulong conn_aborted_cnt; /* number of conns aborted */
337 : ulong conn_timeout_cnt; /* number of conns timed out */
338 : ulong conn_retry_cnt; /* number of conns established with retry */
339 : ulong conn_err_no_slots_cnt; /* number of conns that failed to create due to lack of slots */
340 : ulong conn_err_retry_fail_cnt; /* number of conns that failed during retry (e.g. invalid token) */
341 :
342 : /* Packet metrics */
343 : ulong pkt_net_hdr_err_cnt; /* number of packets dropped due to weird IPv4/UDP headers */
344 : ulong pkt_quic_hdr_err_cnt; /* number of packets dropped due to weird QUIC header */
345 : ulong pkt_undersz_cnt; /* number of QUIC packets dropped due to being too small */
346 : ulong pkt_oversz_cnt; /* number of QUIC packets dropped due to being too large */
347 : ulong pkt_decrypt_fail_cnt[4]; /* number of packets that failed decryption due to auth tag */
348 : ulong pkt_no_key_cnt[4]; /* number of packets that failed decryption due to missing key */
349 : ulong pkt_no_conn_cnt; /* number of packets with unknown conn ID (excl. Initial) */
350 : ulong frame_tx_alloc_cnt[3]; /* number of pkt_meta alloc successes, fails for empty pool, fails at conn max */
351 : ulong pkt_verneg_cnt; /* number of QUIC version negotiation packets or packets with wrong version */
352 : ulong pkt_retransmissions_cnt; /* number of pkt_meta retries */
353 :
354 : /* Frame metrics */
355 : ulong frame_rx_cnt[ 22 ]; /* number of frames received (indexed by implementation-defined IDs) */
356 : ulong frame_rx_err_cnt; /* number of frames failed */
357 :
358 : /* Handshake metrics */
359 : ulong hs_created_cnt; /* number of handshake flows created */
360 : ulong hs_err_alloc_fail_cnt; /* number of handshakes dropped due to alloc fail */
361 : ulong hs_evicted_cnt; /* number of handshakes evicted */
362 :
363 : /* Stream metrics */
364 : ulong stream_opened_cnt; /* number of streams opened */
365 : ulong stream_closed_cnt[5]; /* indexed by FD_QUIC_STREAM_NOTIFY_{...} */
366 : ulong stream_active_cnt; /* number of active streams */
367 : ulong stream_rx_event_cnt; /* number of stream RX events */
368 : ulong stream_rx_byte_cnt; /* total stream payload bytes received */
369 :
370 : /* ACK metrics */
371 : ulong ack_tx[ 5 ];
372 :
373 : /* Performance metrics */
374 : fd_histf_t service_duration[ 1 ]; /* time spent in service */
375 : fd_histf_t receive_duration[ 1 ]; /* time spent in RX calls */
376 : };
377 : };
378 : typedef union fd_quic_metrics fd_quic_metrics_t;
379 :
380 : /* fd_quic_t memory layout ********************************************/
381 :
382 : struct fd_quic {
383 : ulong magic; /* ==FD_QUIC_MAGIC */
384 :
385 : fd_quic_layout_t layout; /* position-independent, persistent, read only */
386 : fd_quic_limits_t limits; /* position-independent, persistent, read only */
387 : fd_quic_config_t config; /* position-independent, persistent, writable pre init */
388 : fd_quic_callbacks_t cb; /* position-dependent, reset on join, writable pre init */
389 : fd_quic_metrics_t metrics; /* position-independent, persistent, read only */
390 :
391 : fd_aio_t aio_rx; /* local AIO */
392 : fd_aio_t aio_tx; /* remote AIO */
393 :
394 : /* ... private variable-length structures follow ... */
395 : };
396 :
397 : FD_PROTOTYPES_BEGIN
398 :
399 : /* Object lifecycle ***************************************************/
400 :
401 : /* fd_quic_{align,footprint} return the required alignment and footprint
402 : of a memory region suitable for use as an fd_quic_t. align returns
403 : FD_QUIC_ALIGN. limits is a temporary reference to the requested
404 :
405 : On failure, footprint will silently return 0 (and thus can be used by
406 : the caller to validate fd_quic_new params) */
407 :
408 : FD_QUIC_API FD_FN_CONST ulong
409 : fd_quic_align( void );
410 :
411 : FD_QUIC_API ulong
412 : fd_quic_footprint( fd_quic_limits_t const * limits );
413 :
414 : /* fd_quic_new formats an unused memory region for use as a QUIC client
415 : or server. mem is a non-NULL pointer to this region in the local
416 : address with the required footprint and alignment. limits is a
417 : temporary reference, identical to the one given to fd_quic_footprint
418 : used to figure out the required footprint. */
419 :
420 : FD_QUIC_API void *
421 : fd_quic_new( void * mem,
422 : fd_quic_limits_t const * limits );
423 :
424 : /* fd_quic_join joins the caller to the fd_quic. shquic points to the
425 : first byte of the memory region backing the QUIC in the caller's
426 : address space.
427 :
428 : Returns a pointer in the local address space to the public fd_quic_t
429 : region on success (do not assume this to be just a cast of shquic)
430 : and NULL on failure (logs details). Reasons for failure are that
431 : shquic is obviously not a pointer to a correctly formatted QUIC
432 : object. Every successful join should have a matching leave. The
433 : lifetime of the join is until the matching leave or the thread group
434 : is terminated. */
435 :
436 : FD_QUIC_API fd_quic_t *
437 : fd_quic_join( void * shquic );
438 :
439 : /* fd_quic_leave leaves a current local join and frees all dynamically
440 : managed resources (heap allocs, OS handles). Returns the given quic
441 : on success and NULL on failure (logs details). Reasons for failure
442 : include quic is NULL or no active join */
443 :
444 : FD_QUIC_API void *
445 : fd_quic_leave( fd_quic_t * quic );
446 :
447 : /* fd_quic_delete unformats a memory region used as an fd_quic_t.
448 : Assumes nobody is joined to the region. Returns the given quic
449 : pointer on success and NULL if used obviously in error (e.g. quic is
450 : obviously not an fd_quic_t ... logs details). The ownership of the
451 : memory region is transferred ot the caller. */
452 :
453 : FD_QUIC_API void *
454 : fd_quic_delete( fd_quic_t * quic );
455 :
456 : /* Configuration ******************************************************/
457 :
458 : /* fd_quic_{limits,config}_from_env populates the given QUIC limits or
459 : config from command-line args and env vars. If parg{c,v} are non-
460 : NULL, they are updated to strip the parsed args. The last element of
461 : the *argv array must be NULL. Returns given config on success and
462 : NULL on failure (logs details). It is up to the caller to properly
463 : initialize the given limits/config. */
464 :
465 : FD_QUIC_API fd_quic_limits_t *
466 : fd_quic_limits_from_env( int * pargc,
467 : char *** pargv,
468 : fd_quic_limits_t * limits );
469 :
470 : FD_QUIC_API fd_quic_config_t *
471 : fd_quic_config_from_env( int * pargc,
472 : char *** pargv,
473 : fd_quic_config_t * config );
474 :
475 : /* fd_quic_get_aio_net_rx returns this QUIC's aio base class. Valid
476 : for lifetime of QUIC. While pointer to aio can be obtained before
477 : init, calls to aio may only be dispatched by the thread with
478 : exclusive access to QUIC that owns it. */
479 :
480 : FD_QUIC_API fd_aio_t const *
481 : fd_quic_get_aio_net_rx( fd_quic_t * quic );
482 :
483 : /* fd_quic_set_aio_net_tx sets the fd_aio_t used by the fd_quic_t to
484 : send tx data to the network driver. Cleared on fini. */
485 :
486 : FD_QUIC_API void
487 : fd_quic_set_aio_net_tx( fd_quic_t * quic,
488 : fd_aio_t const * aio_tx );
489 :
490 : /* fd_quic_set_clock sets the clock source. Converts all timing values
491 : in the config to the new time scale. */
492 :
493 : FD_QUIC_API void
494 : fd_quic_set_clock( fd_quic_t * quic,
495 : fd_quic_now_t now_fn,
496 : void * now_ctx,
497 : double tick_per_us );
498 :
499 : /* fd_quic_set_clock_tickcount sets fd_tickcount as the clock source. */
500 :
501 : FD_QUIC_API void
502 : fd_quic_set_clock_tickcount( fd_quic_t * quic );
503 :
504 : /* Initialization *****************************************************/
505 :
506 : /* fd_quic_init initializes the QUIC such that it is ready to serve.
507 : permits the calling thread exclusive access during which no other
508 : thread may write to the QUIC. Exclusive rights get released when the
509 : thread exits or calls fd_quic_fini.
510 :
511 : Requires valid configuration and external objects (aio, callbacks).
512 : Returns given quic on success and NULL on failure (logs details).
513 : Performs various heap allocations and file system accesses such
514 : reading certs. Reasons for failure include invalid config or
515 : fd_tls error. */
516 :
517 : FD_QUIC_API fd_quic_t *
518 : fd_quic_init( fd_quic_t * quic );
519 :
520 : /* fd_quic_fini releases exclusive access over a QUIC. Zero-initializes
521 : references to external objects (aio, callbacks). Frees any heap
522 : allocs made by fd_quic_init. Returns quic. */
523 :
524 : FD_QUIC_API fd_quic_t *
525 : fd_quic_fini( fd_quic_t * quic );
526 :
527 : /* NOTE: Calling any of the below requires valid initialization from
528 : this thread group. */
529 :
530 : /* Connection API *****************************************************/
531 :
532 : /* fd_quic_connect initiates a new client connection to a remote QUIC
533 : server. On success, returns a pointer to the conn object managed by
534 : QUIC. On failure, returns NULL. Reasons for failure include quic
535 : not a valid join or out of free conns. Lifetime of returned conn is
536 : until conn_final callback.
537 :
538 : args
539 : dst_ip_addr destination ip address
540 : dst_udp_port destination port number */
541 :
542 : FD_QUIC_API fd_quic_conn_t *
543 : fd_quic_connect( fd_quic_t * quic, /* requires exclusive access */
544 : uint dst_ip_addr,
545 : ushort dst_udp_port,
546 : uint src_ip_addr,
547 : ushort src_udp_port );
548 :
549 : /* fd_quic_conn_close asynchronously initiates a shutdown of the conn.
550 : The given reason code is returned to the peer via a CONNECTION_CLOSE
551 : frame, if possible. Causes conn_final callback to be issued
552 : eventually. */
553 :
554 : FD_QUIC_API void
555 : fd_quic_conn_close( fd_quic_conn_t * conn,
556 : uint reason );
557 :
558 : /* Service API ********************************************************/
559 :
560 : /* fd_quic_get_next_wakeup returns the next requested service time.
561 : This is only intended for unit tests. */
562 :
563 : FD_QUIC_API ulong
564 : fd_quic_get_next_wakeup( fd_quic_t * quic );
565 :
566 : /* fd_quic_service services the next QUIC connection, including stream
567 : transmit ops, ACK transmit, loss timeout, and idle timeout. The
568 : user should call service at high frequency. Returns 1 if the service
569 : call did any work, or 0 otherwise. */
570 :
571 : FD_QUIC_API int
572 : fd_quic_service( fd_quic_t * quic );
573 :
574 : /* fd_quic_svc_validate checks for violations of service queue and free
575 : list invariants, such as cycles in linked lists. Prints to warning/
576 : error log and exits the process if checks fail. Intended for use in
577 : tests. */
578 :
579 : void
580 : fd_quic_svc_validate( fd_quic_t * quic );
581 :
582 : /* Stream Send API ****************************************************/
583 :
584 : /* fd_quic_conn_new_stream creates a new unidirectional stream on the
585 : given conn. On success, returns the newly created stream.
586 : On failure, returns NULL. Reasons for failure include invalid conn
587 : state or out of stream quota.
588 :
589 : The user does not own the returned pointer: its lifetime is managed
590 : by the connection. */
591 :
592 : FD_QUIC_API fd_quic_stream_t *
593 : fd_quic_conn_new_stream( fd_quic_conn_t * conn );
594 :
595 : /* fd_quic_stream_send sends a chunk on a stream in order.
596 :
597 : Use fd_quic_conn_new_stream to create a new stream for sending
598 : or use the new stream callback to obtain a stream for replying.
599 :
600 : args
601 : stream the stream to send on
602 : data points to first byte of buffer (ignored if data_sz==0)
603 : data_sz number of bytes to send
604 : fin final: bool
605 : set to indicate the stream is finalized by the last byte
606 : in the batch
607 : If the last buffer in the batch was rejected, the FIN
608 : flag is not set, and may be applied in a future send
609 : or via the fd_quic_stream_fin(...) function
610 :
611 : returns
612 : 0 success
613 : <0 one of FD_QUIC_SEND_ERR_{INVAL_STREAM,INVAL_CONN,AGAIN} */
614 : FD_QUIC_API int
615 : fd_quic_stream_send( fd_quic_stream_t * stream,
616 : void const * data,
617 : ulong data_sz,
618 : int fin );
619 :
620 : /* fd_quic_stream_fin: finish sending on a stream. Called to signal
621 : no more data will be sent to self-to-peer flow of stream. Peer may
622 : continue sending data on their side of the stream. Caller should
623 : only call stream_fin once per stream, except when fin was already
624 : indicated via stream_send. */
625 :
626 : FD_QUIC_API void
627 : fd_quic_stream_fin( fd_quic_stream_t * stream );
628 :
629 : FD_QUIC_API void
630 : fd_quic_process_packet( fd_quic_t * quic,
631 : uchar * data,
632 : ulong data_sz );
633 :
634 : uint
635 : fd_quic_tx_buffered_raw( fd_quic_t * quic,
636 : uchar ** tx_ptr_ptr,
637 : uchar * tx_buf,
638 : ushort * ipv4_id,
639 : uint dst_ipv4_addr,
640 : ushort dst_udp_port,
641 : uint src_ipv4_addr,
642 : ushort src_udp_port );
643 :
644 : FD_PROTOTYPES_END
645 :
646 : /* Convenience exports for consumers of API */
647 : #include "fd_quic_conn.h"
648 : #include "fd_quic_stream.h"
649 :
650 : /* FD_DEBUG_MODE: set to enable debug-only code
651 : TODO move to util? */
652 : #ifdef FD_DEBUG_MODE
653 : #define FD_DEBUG(...) __VA_ARGS__
654 : #else
655 : #define FD_DEBUG(...)
656 : #endif
657 :
658 : #endif /* HEADER_fd_src_waltz_quic_fd_quic_h */
|