LCOV - code coverage report
Current view: top level - waltz/quic - fd_quic_private.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 55 60 91.7 %
Date: 2024-11-13 11:58:15 Functions: 14 143 9.8 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_quic_fd_quic_private_h
       2             : #define HEADER_fd_src_waltz_quic_fd_quic_private_h
       3             : 
       4             : #include "fd_quic.h"
       5             : #include "templ/fd_quic_transport_params.h"
       6             : #include "fd_quic_conn_map.h"
       7             : #include "fd_quic_stream.h"
       8             : #include "fd_quic_pkt_meta.h"
       9             : #include "crypto/fd_quic_crypto_suites.h"
      10             : #include "tls/fd_quic_tls.h"
      11             : #include "fd_quic_stream_pool.h"
      12             : 
      13             : #include "../../util/net/fd_eth.h"
      14             : #include "../../util/net/fd_ip4.h"
      15             : #include "../../util/net/fd_udp.h"
      16             : 
      17             : /* FD_QUIC_DISABLE_CRYPTO: set to 1 to disable packet protection and
      18             :    encryption.  Only intended for testing. */
      19             : #ifndef FD_QUIC_DISABLE_CRYPTO
      20             : #define FD_QUIC_DISABLE_CRYPTO 0
      21             : #endif
      22             : 
      23    61579271 : #define FD_QUIC_PKT_NUM_UNUSED  (~0ul)
      24    85321477 : #define FD_QUIC_PKT_NUM_PENDING (~1ul)
      25             : 
      26             : /* FD_QUIC_MAGIC is used to signal the layout of shared memory region
      27             :    of an fd_quic_t. */
      28             : 
      29        2124 : #define FD_QUIC_MAGIC (0xdadf8cfa01cc5460UL)
      30             : 
      31             : /* FD_QUIC_SVC_{...} specify connection timer types. */
      32             : 
      33    60880140 : #define FD_QUIC_SVC_INSTANT (0U)  /* as soon as possible */
      34    84587776 : #define FD_QUIC_SVC_ACK_TX  (1U)  /* within local max_ack_delay (ACK TX coalesce) */
      35    73584430 : #define FD_QUIC_SVC_WAIT    (2U)  /* within min(idle_timeout, peer max_ack_delay) */
      36    92110367 : #define FD_QUIC_SVC_CNT     (3U)  /* number of FD_QUIC_SVC_{...} levels */
      37             : 
      38             : /* fd_quic_svc_queue_t is a simple doubly linked list. */
      39             : 
      40             : struct fd_quic_svc_queue {
      41             :   /* FIXME track count */ // uint cnt;
      42             :   uint head;
      43             :   uint tail;
      44             : };
      45             : 
      46             : typedef struct fd_quic_svc_queue fd_quic_svc_queue_t;
      47             : 
      48             : /* fd_quic_state_t is the internal state of an fd_quic_t.  Valid for
      49             :    lifetime of join. */
      50             : 
      51             : struct __attribute__((aligned(16UL))) fd_quic_state_private {
      52             :   /* Flags */
      53             :   ulong flags;
      54             : 
      55             :   ulong now; /* the time we entered into fd_quic_service, or fd_quic_aio_cb_receive */
      56             : 
      57             :   /* Pointer to TLS state (part of quic memory region) */
      58             : 
      59             :   fd_quic_tls_t * tls;
      60             : 
      61             :   /* transport_params: Template for QUIC-TLS transport params extension.
      62             :      Contains a mix of mutable and immutable fields.  Immutable fields
      63             :      are set on join.  Mutable fields may be modified during packet
      64             :      processing.  Any code using this struct must ensure that the
      65             :      mutable fields are cleared before using (otherwise would leak a
      66             :      side channel).
      67             : 
      68             :      Mutable fields include:
      69             :      - original_destination_connection_id
      70             :      - initial_source_conn_id */
      71             : 
      72             :   fd_quic_transport_params_t transport_params;
      73             : 
      74             :   /* Various internal state */
      75             : 
      76             :   uint                    free_conn_list; /* free list of unused connections */
      77             :   fd_quic_conn_map_t *    conn_map;       /* map connection ids -> connection */
      78             :   fd_quic_stream_pool_t * stream_pool;    /* stream pool */
      79             :   fd_rng_t                _rng[1];        /* random number generator */
      80             :   fd_quic_svc_queue_t     svc_queue[ FD_QUIC_SVC_CNT ]; /* dlists */
      81             :   ulong                   svc_delay[ FD_QUIC_SVC_CNT ]; /* target service delay */
      82             : 
      83             :   /* need to be able to access connections by index */
      84             :   ulong                   conn_base;      /* address of array of all connections */
      85             :                                           /* not using fd_quic_conn_t* to avoid confusion */
      86             :                                           /* use fd_quic_conn_at_idx instead */
      87             :   ulong                   conn_sz;        /* size of one connection element */
      88             : 
      89             :   fd_quic_pkt_meta_t *    pkt_meta;       /* records the metadata for the contents
      90             :                                              of each sent packet */
      91             : 
      92             :   /* flow control - configured initial limits */
      93             :   ulong initial_max_data;           /* directly from transport params */
      94             :   ulong initial_max_stream_data[4]; /* from 4 transport params indexed by stream type */
      95             : 
      96             :   /* next_ephem_udp_port: Next ephemeral UDP port to allocate */
      97             :   ushort next_ephem_udp_port;
      98             : 
      99             :   /* last arp/routing tables update */
     100             :   ulong ip_table_upd;
     101             : 
     102             :   /* secret for generating RETRY tokens */
     103             :   uchar retry_secret[FD_QUIC_RETRY_SECRET_SZ];
     104             :   uchar retry_iv    [FD_QUIC_RETRY_IV_SZ];
     105             : 
     106             :   /* Scratch space for packet protection */
     107             :   uchar                   crypt_scratch[FD_QUIC_MTU];
     108             : };
     109             : 
     110             : /* FD_QUIC_STATE_OFF is the offset of fd_quic_state_t within fd_quic_t. */
     111   460124182 : #define FD_QUIC_STATE_OFF (fd_ulong_align_up( sizeof(fd_quic_t), alignof(fd_quic_state_t) ))
     112             : 
     113             : struct fd_quic_pkt {
     114             :   fd_eth_hdr_t       eth[1];
     115             :   fd_ip4_hdr_t       ip4[1];
     116             :   fd_udp_hdr_t       udp[1];
     117             : 
     118             :   /* the following are the "current" values only. There may be more QUIC packets
     119             :      in a UDP datagram */
     120             :   fd_quic_long_hdr_t long_hdr[1];
     121             :   ulong              pkt_number;  /* quic packet number currently being decoded/parsed */
     122             :   ulong              rcv_time;    /* time packet was received */
     123             :   uint               enc_level;   /* encryption level */
     124             :   uint               datagram_sz; /* length of the original datagram */
     125             :   uint               ack_flag;    /* ORed together: 0-don't ack  1-ack  2-cancel ack */
     126   130097577 : # define ACK_FLAG_RQD     1
     127    43362190 : # define ACK_FLAG_CANCEL  2
     128             : };
     129             : 
     130             : FD_PROTOTYPES_BEGIN
     131             : 
     132             : /* fd_quic_get_state returns a pointer to private state area given a
     133             :    pointer to fd_quic_t.  Const func, guaranteed to not access memory. */
     134             : 
     135             : FD_FN_CONST static inline fd_quic_state_t *
     136   460124182 : fd_quic_get_state( fd_quic_t * quic ) {
     137   460124182 :   return (fd_quic_state_t *)( (ulong)quic + FD_QUIC_STATE_OFF );
     138   460124182 : }
     139             : 
     140             : FD_FN_CONST static inline fd_quic_state_t const *
     141           0 : fd_quic_get_state_const( fd_quic_t const * quic ) {
     142           0 :   return (fd_quic_state_t const *)( (ulong)quic + FD_QUIC_STATE_OFF );
     143           0 : }
     144             : 
     145             : /* fd_quic_conn_service is called periodically to perform pending
     146             :    operations and time based operations.
     147             : 
     148             :    args
     149             :      quic        managing quic
     150             :      conn        connection to service
     151             :      now         the current time in ns */
     152             : void
     153             : fd_quic_conn_service( fd_quic_t *      quic,
     154             :                       fd_quic_conn_t * conn,
     155             :                       ulong            now );
     156             : 
     157             : /* fd_quic_svc_schedule installs a connection timer.  svc_type is in
     158             :    [0,FD_QUIC_SVC_CNT) and specifies the timer delay.  Lower timers
     159             :    override higher ones. */
     160             : 
     161             : void
     162             : fd_quic_svc_schedule( fd_quic_state_t * state,
     163             :                       fd_quic_conn_t *  conn,
     164             :                       uint              svc_type );
     165             : 
     166             : static inline void
     167             : fd_quic_svc_schedule1( fd_quic_conn_t * conn,
     168    17453471 :                        uint             svc_type ) {
     169    17453471 :   fd_quic_svc_schedule( fd_quic_get_state( conn->quic ), conn, svc_type );
     170    17453471 : }
     171             : 
     172             : /* Memory management **************************************************/
     173             : 
     174             : fd_quic_conn_t *
     175             : fd_quic_conn_create( fd_quic_t *               quic,
     176             :                      ulong                     our_conn_id,
     177             :                      fd_quic_conn_id_t const * peer_conn_id,
     178             :                      uint                      dst_ip_addr,
     179             :                      ushort                    dst_udp_port,
     180             :                      int                       server );
     181             : 
     182             : /* fd_quic_conn_free frees up resources related to the connection and
     183             :    returns it to the connection free list. */
     184             : void
     185             : fd_quic_conn_free( fd_quic_t *      quic,
     186             :                    fd_quic_conn_t * conn );
     187             : 
     188             : void
     189             : fd_quic_tx_stream_free( fd_quic_t *        quic,
     190             :                         fd_quic_conn_t *   conn,
     191             :                         fd_quic_stream_t * stream,
     192             :                         int                code );
     193             : 
     194             : /* fd_quic_stream_rx_reclaim frees streams and hashmap entries for
     195             :    incoming unidirectional streams in range [stream_id_lo,stream_id_hi) */
     196             : 
     197             : void
     198             : fd_quic_stream_rx_reclaim( fd_quic_t *      quic,
     199             :                            fd_quic_conn_t * conn,
     200             :                            ulong            stream_id_lo,
     201             :                            ulong            stream_id_hi );
     202             : 
     203             : /* Callbacks provided by fd_quic **************************************/
     204             : 
     205             : /* used by quic to receive data from network */
     206             : int
     207             : fd_quic_aio_cb_receive( void *                    context,
     208             :                         fd_aio_pkt_info_t const * batch,
     209             :                         ulong                     batch_sz,
     210             :                         ulong *                   opt_batch_idx,
     211             :                         int                       flush );
     212             : 
     213             : /* declare callbacks from quic-tls into quic */
     214             : int
     215             : fd_quic_tls_cb_client_hello( fd_quic_tls_hs_t * hs,
     216             :                              void *             context );
     217             : 
     218             : int
     219             : fd_quic_tls_cb_handshake_data( fd_quic_tls_hs_t * hs,
     220             :                                void *             context,
     221             :                                uint               enc_level,
     222             :                                uchar const *      data,
     223             :                                ulong              data_sz );
     224             : 
     225             : void
     226             : fd_quic_tls_cb_alert( fd_quic_tls_hs_t * hs,
     227             :                       void *             context,
     228             :                       int                alert );
     229             : 
     230             : void
     231             : fd_quic_tls_cb_secret( fd_quic_tls_hs_t *           hs,
     232             :                        void *                       context,
     233             :                        fd_quic_tls_secret_t const * secret );
     234             : 
     235             : void
     236             : fd_quic_tls_cb_handshake_complete( fd_quic_tls_hs_t * hs,
     237             :                                    void *             context  );
     238             : 
     239             : void
     240             : fd_quic_tls_cb_peer_params( void *        context,
     241             :                             uchar const * peer_tp_enc,
     242             :                             ulong         peer_tp_enc_sz );
     243             : 
     244             : /* Helpers for calling callbacks **************************************/
     245             : 
     246             : static inline ulong
     247    70169355 : fd_quic_now( fd_quic_t * quic ) {
     248    70169355 :   return quic->cb.now( quic->cb.now_ctx );
     249    70169355 : }
     250             : 
     251             : static inline void
     252             : fd_quic_cb_conn_new( fd_quic_t *      quic,
     253        6012 :                      fd_quic_conn_t * conn ) {
     254        6012 :   if( FD_UNLIKELY( !quic->cb.conn_new || conn->called_conn_new ) ) {
     255           0 :     return;
     256           0 :   }
     257             : 
     258        6012 :   quic->cb.conn_new( conn, quic->cb.quic_ctx );
     259        6012 :   conn->called_conn_new = 1;
     260        6012 : }
     261             : 
     262             : static inline void
     263             : fd_quic_cb_conn_hs_complete( fd_quic_t *      quic,
     264        6012 :                              fd_quic_conn_t * conn ) {
     265        6012 :   if( FD_UNLIKELY( !quic->cb.conn_hs_complete ) ) return;
     266        6012 :   quic->cb.conn_hs_complete( conn, quic->cb.quic_ctx );
     267        6012 : }
     268             : 
     269             : static inline void
     270             : fd_quic_cb_conn_final( fd_quic_t *      quic,
     271       14475 :                        fd_quic_conn_t * conn ) {
     272       14475 :   if( FD_UNLIKELY( !quic->cb.conn_final || !conn->called_conn_new ) ) return;
     273       12021 :   quic->cb.conn_final( conn, quic->cb.quic_ctx );
     274       12021 : }
     275             : 
     276             : static inline void
     277             : fd_quic_cb_stream_new( fd_quic_t *        quic,
     278    33708163 :                        fd_quic_stream_t * stream ) {
     279    33708163 :   quic->metrics.stream_opened_cnt++;
     280    33708163 :   quic->metrics.stream_active_cnt++;
     281             : 
     282    33708163 :   if( FD_UNLIKELY( !quic->cb.stream_new ) ) return;
     283     8546440 :   quic->cb.stream_new( stream, quic->cb.quic_ctx );
     284     8546440 : }
     285             : 
     286             : static inline void
     287             : fd_quic_cb_stream_receive( fd_quic_t *        quic,
     288             :                            fd_quic_stream_t * stream,
     289             :                            void *             stream_ctx,
     290             :                            uchar const *      data,
     291             :                            ulong              data_sz,
     292             :                            ulong              offset,
     293    42252410 :                            int                fin ) {
     294    42252410 :   quic->metrics.stream_rx_event_cnt++;
     295    42252410 :   quic->metrics.stream_rx_byte_cnt += data_sz;
     296             : 
     297    42252410 :   if( FD_UNLIKELY( !quic->cb.stream_receive ) ) return;
     298    17090687 :   quic->cb.stream_receive( stream, stream_ctx, data, data_sz, offset, fin );
     299    17090687 : }
     300             : 
     301             : static inline void
     302             : fd_quic_cb_stream_notify( fd_quic_t *        quic,
     303             :                           fd_quic_stream_t * stream,
     304             :                           void *             stream_ctx,
     305    42308609 :                           int                event ) {
     306    42308609 :   quic->metrics.stream_closed_cnt[ event ]++;
     307    42308609 :   quic->metrics.stream_active_cnt--;
     308             : 
     309    42308609 :   if( FD_UNLIKELY( !quic->cb.stream_notify ) ) return;
     310    17146886 :   quic->cb.stream_notify( stream, stream_ctx, event );
     311    17146886 : }
     312             : 
     313             : 
     314             : void
     315             : fd_quic_pkt_meta_retry( fd_quic_t *          quic,
     316             :                         fd_quic_conn_t *     conn,
     317             :                         int                  force,
     318             :                         uint                 arg_enc_level );
     319             : 
     320             : /* reclaim resources associated with packet metadata
     321             :    this is called in response to received acks */
     322             : void
     323             : fd_quic_reclaim_pkt_meta( fd_quic_conn_t *     conn,
     324             :                           fd_quic_pkt_meta_t * pkt_meta,
     325             :                           uint                 enc_level );
     326             : 
     327             : ulong
     328             : fd_quic_send_retry( fd_quic_t *                  quic,
     329             :                     fd_quic_pkt_t *              pkt,
     330             :                     fd_quic_conn_id_t const *    orig_dst_conn_id,
     331             :                     fd_quic_conn_id_t const *    new_conn_id,
     332             :                     uchar const                  dst_mac_addr_u6[ 6 ],
     333             :                     uint                         dst_ip_addr,
     334             :                     ushort                       dst_udp_port );
     335             : 
     336             : ulong
     337             : fd_quic_process_quic_packet_v1( fd_quic_t *     quic,
     338             :                                 fd_quic_pkt_t * pkt,
     339             :                                 uchar *         cur_ptr,
     340             :                                 ulong           cur_sz );
     341             : 
     342             : ulong
     343             : fd_quic_handle_v1_initial( fd_quic_t *               quic,
     344             :                            fd_quic_conn_t **         p_conn,
     345             :                            fd_quic_pkt_t *           pkt,
     346             :                            fd_quic_conn_id_t const * conn_id,
     347             :                            uchar *                   cur_ptr,
     348             :                            ulong                     cur_sz );
     349             : 
     350             : ulong
     351             : fd_quic_handle_v1_one_rtt( fd_quic_t *      quic,
     352             :                            fd_quic_conn_t * conn,
     353             :                            fd_quic_pkt_t *  pkt,
     354             :                            uchar *          cur_ptr,
     355             :                            ulong            cur_sz );
     356             : 
     357             : /* fd_quic_handle_v1_frame is the primary entrypoint for handling of
     358             :    incoming QUIC frames.  {quic,conn,pkt} identify the frame context.
     359             :    Memory region [frame_ptr,frame_ptr+frame_sz) contains the serialized
     360             :    QUIC frame (may contain arbitrary zero padding at the beginning).
     361             : 
     362             :    Returns value in (0,buf_sz) if the frame was successfully processed.
     363             :    Returns FD_QUIC_PARSE_FAIL if the frame was inherently malformed.
     364             :    Returns 0 or value in [buf_sz,ULONG_MAX) in case of a protocol
     365             :    violation. */
     366             : 
     367             : ulong
     368             : fd_quic_handle_v1_frame( fd_quic_t *       quic,
     369             :                          fd_quic_conn_t *  conn,
     370             :                          fd_quic_pkt_t *   pkt,
     371             :                          uint              pkt_type,
     372             :                          uchar const *     frame_ptr,
     373             :                          ulong             frame_sz );
     374             : 
     375             : /* fd_quic_lazy_ack_pkt enqueues future acknowledgement for the given
     376             :    packet.  The ACK will be sent out at a fd_quic_service call.  The
     377             :    delay is determined by the fd_quic_config_t ack_threshold and
     378             :    ack_delay settings.   Respects pkt->ack_flag (ACK_FLAG_RQD schedules
     379             :    an ACK instantly, ACK_FLAG_CANCEL suppresses the ACK by making this
     380             :    function behave like a no-op)  */
     381             : 
     382             : void
     383             : fd_quic_lazy_ack_pkt( fd_quic_t *           quic,
     384             :                       fd_quic_conn_t *      conn,
     385             :                       fd_quic_pkt_t const * pkt );
     386             : 
     387             : /* fd_quic_conn_error sets the connection state to aborted.  This does
     388             :    not destroy the connection object.  Rather, it will eventually cause
     389             :    the connection to be freed during a later fd_quic_service call.
     390             :    reason is a RFC 9000 QUIC error code.  error_line is a implementation
     391             :    defined error code for internal use (usually the source line of code
     392             :    in fd_quic.c) */
     393             : 
     394             : void
     395             : fd_quic_conn_error( fd_quic_conn_t * conn,
     396             :                     uint             reason,
     397             :                     uint             error_line );
     398             : 
     399             : static inline fd_quic_conn_t *
     400   138648778 : fd_quic_conn_at_idx( fd_quic_state_t * quic_state, ulong idx ) {
     401   138648778 :   ulong addr = quic_state->conn_base;
     402   138648778 :   ulong sz   = quic_state->conn_sz;
     403   138648778 :   return (fd_quic_conn_t*)( addr + idx * sz );
     404   138648778 : }
     405             : 
     406             : FD_PROTOTYPES_END
     407             : 
     408             : #endif /* HEADER_fd_src_waltz_quic_fd_quic_private_h */

Generated by: LCOV version 1.14