LCOV - code coverage report
Current view: top level - waltz/quic - fd_quic.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 5 19 26.3 %
Date: 2026-09-17 04:28:31 Functions: 0 0 -

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

Generated by: LCOV version 1.14