LCOV - code coverage report
Current view: top level - waltz/quic - fd_quic_conn.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 26 54 48.1 %
Date: 2025-10-14 04:31:44 Functions: 1 152 0.7 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_quic_fd_quic_conn_h
       2             : #define HEADER_fd_src_waltz_quic_fd_quic_conn_h
       3             : 
       4             : #include "fd_quic.h"
       5             : #include "fd_quic_common.h"
       6             : #include "fd_quic_ack_tx.h"
       7             : #include "fd_quic_stream.h"
       8             : #include "fd_quic_conn_id.h"
       9             : #include "crypto/fd_quic_crypto_suites.h"
      10             : #include "fd_quic_pkt_meta.h"
      11             : #include "fd_quic_svc_q.h"
      12             : #include "../fd_rtt_est.h"
      13             : 
      14    29686839 : #define FD_QUIC_CONN_STATE_INVALID            0 /* dead object / freed */
      15      344691 : #define FD_QUIC_CONN_STATE_HANDSHAKE          1 /* currently doing handshaking with peer */
      16       90918 : #define FD_QUIC_CONN_STATE_HANDSHAKE_COMPLETE 2 /* handshake complete, confirming with peer */
      17   114529781 : #define FD_QUIC_CONN_STATE_ACTIVE             3 /* connection established - data may be transferred */
      18       42039 : #define FD_QUIC_CONN_STATE_PEER_CLOSE         4 /* peer requested close */
      19       12432 : #define FD_QUIC_CONN_STATE_ABORT              5 /* connection terminating due to error */
      20       42357 : #define FD_QUIC_CONN_STATE_CLOSE_PENDING      6 /* connection is closing */
      21   154910742 : #define FD_QUIC_CONN_STATE_DEAD               7 /* connection about to be freed */
      22             : #define FD_QUIC_CONN_STATE_CNT                8
      23             : 
      24             : FD_STATIC_ASSERT( FD_QUIC_CONN_STATE_CNT == sizeof(((fd_quic_metrics_t*)0)->conn_state_cnt)/sizeof(((fd_quic_metrics_t*)0)->conn_state_cnt[0]),
      25             :                   "metrics conn_state_cnt is the wrong size" );
      26             : 
      27             : #define FD_QUIC_REASON_CODES(X,SEP) \
      28           0 :   X(NO_ERROR                     , 0x00  , "No error"                                  ) SEP \
      29           0 :   X(INTERNAL_ERROR               , 0x01  , "Implementation error"                      ) SEP \
      30           0 :   X(CONNECTION_REFUSED           , 0x02  , "Server refuses a connection"               ) SEP \
      31           0 :   X(FLOW_CONTROL_ERROR           , 0x03  , "Flow control error"                        ) SEP \
      32           0 :   X(STREAM_LIMIT_ERROR           , 0x04  , "Too many streams opened"                   ) SEP \
      33           0 :   X(STREAM_STATE_ERROR           , 0x05  , "Frame received in invalid stream state"    ) SEP \
      34           0 :   X(FINAL_SIZE_ERROR             , 0x06  , "Change to final size"                      ) SEP \
      35           0 :   X(FRAME_ENCODING_ERROR         , 0x07  , "Frame encoding error"                      ) SEP \
      36           0 :   X(TRANSPORT_PARAMETER_ERROR    , 0x08  , "Error in transport parameters"             ) SEP \
      37           0 :   X(CONNECTION_ID_LIMIT_ERROR    , 0x09  , "Too many connection IDs received"          ) SEP \
      38           0 :   X(PROTOCOL_VIOLATION           , 0x0a  , "Generic protocol violation"                ) SEP \
      39           0 :   X(INVALID_TOKEN                , 0x0b  , "Invalid Token received"                    ) SEP \
      40           0 :   X(APPLICATION_ERROR            , 0x0c  , "Application error"                         ) SEP \
      41           0 :   X(CRYPTO_BUFFER_EXCEEDED       , 0x0d  , "CRYPTO data buffer overflowed"             ) SEP \
      42           0 :   X(KEY_UPDATE_ERROR             , 0x0e  , "Invalid packet protection update"          ) SEP \
      43           0 :   X(AEAD_LIMIT_REACHED           , 0x0f  , "Excessive use of packet protection keys"   ) SEP \
      44           0 :   X(NO_VIABLE_PATH               , 0x10  , "No viable network path exists"             ) SEP \
      45           0 :   X(CRYPTO_BASE                  , 0x100 , "0x0100-0x01ff CRYPTO_ERROR TLS alert code" ) SEP \
      46           0 :   X(HANDSHAKE_FAILURE            , 0x128 , "Handshake failed"                          )
      47             : 
      48             : enum {
      49             : # define COMMA ,
      50             : # define _(NAME,CODE,DESC) \
      51             :   FD_QUIC_CONN_REASON_##NAME = CODE
      52             :   FD_QUIC_REASON_CODES(_,COMMA)
      53             : # undef _
      54             : # undef COMMA
      55             : };
      56             : 
      57             : char const *
      58             : fd_quic_conn_reason_name( uint reason );
      59             : 
      60             : 
      61             : struct fd_quic_conn_stream_rx {
      62             :   ulong rx_hi_stream_id;    /* highest RX stream ID sent by peer + 4 */
      63             :   ulong rx_sup_stream_id;   /* highest allowed RX stream ID + 4 */
      64             : 
      65             :   ulong rx_max_data;        /* the limit on the number of bytes the peer is allowed to send to us */
      66             :   ulong rx_tot_data;        /* total of all bytes received across all streams and including implied bytes */
      67             :   ulong rx_max_data_ackd;   /* max max_data acked by peer */
      68             : 
      69             :   ulong rx_max_streams_unidir_ackd; /* value of MAX_STREAMS acked for UNIDIR */
      70             : 
      71             :   long  rx_streams_active;  /* FIXME: This is a user scratch field, not in use by fd_quic */
      72             : 
      73             :   /* FIXME add a TLB */
      74             : };
      75             : 
      76             : typedef struct fd_quic_conn_stream_rx fd_quic_conn_stream_rx_t;
      77             : 
      78             : struct fd_quic_conn {
      79             :   /* 'PERSISTENT' means field should survive a conn_clear */
      80             :   uint               conn_idx;            /* connection index - PERSISTENT */
      81             :                                           /* connections are sized at runtime */
      82             :                                           /* storing the index avoids a division */
      83             :   uint               conn_gen;            /* generation of this connection slot - PERSISTENT */
      84             : 
      85             :   fd_quic_t *        quic;                /* PERSISTENT */
      86             :   void *             context;             /* user context */
      87             : 
      88             :   uint               server      : 1;     /* role from self POV: 0=client, 1=server */
      89             :   uint               established : 1;     /* used by clients to determine whether to
      90             :                                              switch the destination conn id used */
      91             :   uint               transport_params_set : 1;
      92             :   uint               called_conn_new : 1; /* whether we need to call conn_final on teardown */
      93             :   uint               visited : 1;         /* scratch bit, no strict definition */
      94             :   uint               key_phase : 1;
      95             :   uint               key_update : 1;
      96             : 
      97             :   /* metadata used by service queue */
      98             :   fd_quic_svc_timers_conn_meta_t svc_meta;
      99             : 
     100             :   /* Dlist membership  */
     101             :   uint               free_conn_next;
     102             : 
     103             :   ulong              our_conn_id;
     104             : 
     105             :   /* Save original retry_source_connection_id
     106             :    * This is used by clients to compare against the retry_source_connection_id
     107             :    * in the transport parameters as specified in rfc 9000 7.3 */
     108             :   fd_quic_conn_id_t  retry_src_conn_id;
     109             : 
     110             :   /* Host network endpoint. Used to determine src address and port */
     111             :   fd_quic_net_endpoint_t host;
     112             : 
     113             :   /* Peer network endpoints – have multiple connection ids and ip:port */
     114             :   /* TODO: footprint allows specifying conn_id_cnt but hardcoded limit used here */
     115             :   fd_quic_net_endpoint_t peer[1];
     116             :   fd_quic_conn_id_t      peer_cids[1]; /* FIXME support new/retire conn ID */
     117             : 
     118             :   /* initial source connection id */
     119             :   ulong              initial_source_conn_id;
     120             : 
     121             :   uint               tx_max_datagram_sz;  /* size of maximum datagram allowed by peer */
     122             : 
     123             :   /* handshake members */
     124             :   uint               handshake_complete  : 1; /* have we completed a successful handshake? */
     125             :   uint               handshake_done_send : 1; /* do we need to send handshake-done to peer? */
     126             :   uint               handshake_done_ackd : 1; /* was handshake_done ack'ed? */
     127             :   fd_quic_tls_hs_t * tls_hs;
     128             : 
     129             :   /* amount of handshake data already sent from head of queue */
     130             :   ulong hs_sent_bytes[4];
     131             : 
     132             :   /* amount of handshake data ack'ed by peer counted from head of queue */
     133             :   ulong hs_ackd_bytes[4];
     134             : 
     135             :   /* Keys for header and packet protection
     136             :        secrets:     Contains 'master' secrets used to derive other keys
     137             :        keys[e][d]:  Current pair of keys for each encryption level (e)
     138             :                     and direction (d==0 is incoming, d==1 is outgoing)
     139             :        new_keys[e]: App keys to use for the next key update.  Once app
     140             :                     keys are available these are always kept up-to-date
     141             :        keys_avail:  Bit set of available keys, LSB indexed by enc level */
     142             :   fd_quic_crypto_secrets_t secrets;
     143             :   fd_quic_crypto_keys_t    keys[FD_QUIC_NUM_ENC_LEVELS][2];
     144             :   fd_quic_crypto_keys_t    new_keys[2];
     145             :   uint                     keys_avail;
     146             : 
     147             :   fd_quic_stream_t         send_streams[1];      /* sentinel of list of streams needing action */
     148             :   fd_quic_stream_t         used_streams[1];      /* sentinel of list of used streams */
     149             :   /* invariant: an allocated stream must be in exactly one of the following lists:
     150             :      send_streams
     151             :      used_streams */
     152             : 
     153             :   /* stream id members */
     154             :   ulong tx_next_stream_id;  /* stream ID to be used for new stream */
     155             :   ulong tx_sup_stream_id;   /* highest allowed TX stream ID + 4 */
     156             : 
     157             :   fd_quic_stream_map_t *  stream_map;           /* map stream_id -> stream - PERSISTENT */
     158             : 
     159             :   /* packet number info
     160             :      each encryption level maps to a packet number space
     161             :      0-RTT and 1-RTT both map to APPLICATION
     162             :      pkt_number[j] represents the minimum acceptable packet number
     163             :        "expected packet number"
     164             :        packets with a number lower than this will be dropped */
     165             :   ulong exp_pkt_number[3];  /* different packet number spaces:
     166             :                                  INITIAL, HANDSHAKE and APPLICATION */
     167             :   ulong pkt_number[3];      /* tx packet number by pn space */
     168             :   ulong last_pkt_number[3]; /* last (highest) packet number seen */
     169             : 
     170             :   ushort ipv4_id;           /* ipv4 id field */
     171             : 
     172             :   /* buffer to send next */
     173             :   /* must be at least FD_QUIC_MAX_UDP_PAYLOAD_SZ */
     174             :   uchar   tx_buf_conn[2048];
     175             :   uchar * tx_ptr; /* ptr to free space in tx_buf_conn */
     176             : 
     177             :   uint state;      /* PERSISTENT to keep state counters correct */
     178             :   uint reason;     /* quic reason for closing. see FD_QUIC_CONN_REASON_* */
     179             :   uint app_reason; /* application reason for closing */
     180             : 
     181             :   fd_quic_ack_gen_t ack_gen[1];
     182             :   ulong             unacked_sz;  /* Number of received stream frame payload bytes pending ACK */
     183             :                                  /* Resets to zero when conn is rescheduled or ACKs are sent */
     184             : 
     185             :   fd_quic_pkt_meta_tracker_t pkt_meta_tracker;
     186             : 
     187             :   /* flow control */
     188             :   ulong                tx_max_data;        /* the limit on the number of bytes we are allowed
     189             :                                               to send to the peer across all streams */
     190             :                                            /* even if a bytes on a stream are not received,
     191             :                                               higher offsets received imply the usage of those bytes,
     192             :                                               and they count against the max */
     193             :   ulong                tx_tot_data;        /* total of all bytes received across all streams
     194             :                                               and including implied bytes */
     195             : 
     196             :   uint                 flags;
     197       12264 : # define FD_QUIC_CONN_FLAGS_MAX_DATA           (1u<<0u)
     198       42408 : # define FD_QUIC_CONN_FLAGS_CLOSE_SENT         (1u<<1u)
     199       12264 : # define FD_QUIC_CONN_FLAGS_MAX_STREAMS_UNIDIR (1u<<2u)
     200       48738 : # define FD_QUIC_CONN_FLAGS_PING               (1u<<4u)
     201       36540 : # define FD_QUIC_CONN_FLAGS_PING_SENT          (1u<<5u)
     202             : 
     203             :   /* max stream data per stream type */
     204             :   ulong                tx_initial_max_stream_data_uni;
     205             : 
     206             :   /* last tx packet num with max_data frame referring to this stream
     207             :      set to next_pkt_number to indicate a new max_data frame should be sent
     208             :      if we time out this packet (or possibly a later packet) we resend the frame
     209             :        and update this value */
     210             :   ulong                upd_pkt_number;
     211             : 
     212             :   /* highest peer encryption level */
     213             :   uchar                peer_enc_level;
     214             : 
     215             :   /* idle timeout arguments */
     216             :   long                 idle_timeout_ns;
     217             :   long                 last_activity;
     218             :   long                 last_ack;
     219             :   long                 let_die_time_ns; /* stop keep-alive after this time */
     220             : 
     221             :   /* round trip time related members */
     222             :   fd_rtt_estimate_t rtt[1];
     223             :   float rtt_period_ns;         /* bound on time between RTT measurements */
     224             :   float peer_ack_delay_scale;  /* convert ACK delay units to nanoseconds */
     225             :   float peer_max_ack_delay_ns; /* peer max ack delay in nanoseconds */
     226             : 
     227             :   ulong token_len;
     228             :   uchar token[ FD_QUIC_RETRY_MAX_TOKEN_SZ ];
     229             : 
     230             :   fd_quic_conn_stream_rx_t srx[1];
     231             : 
     232             :   ulong used_pkt_meta;
     233             : };
     234             : 
     235             : FD_PROTOTYPES_BEGIN
     236             : 
     237             : FD_FN_CONST static inline ulong
     238           0 : fd_quic_conn_uid( fd_quic_conn_t const * conn ) {
     239           0 :   return ( (ulong)conn->conn_idx << 32UL ) | ( (ulong)conn->conn_gen );
     240           0 : }
     241             : 
     242             : FD_FN_CONST static inline uint
     243           0 : fd_quic_conn_uid_idx( ulong conn_uid ) {
     244           0 :   return (uint)( conn_uid >> 32UL );
     245           0 : }
     246             : 
     247             : FD_FN_CONST static inline uint
     248           0 : fd_quic_conn_uid_gen( ulong conn_uid ) {
     249           0 :   return (uint)( conn_uid & 0xffffffffUL );
     250           0 : }
     251             : 
     252             : /* returns the alignment requirement of fd_quic_conn_t */
     253             : FD_FN_CONST ulong
     254             : fd_quic_conn_align( void );
     255             : 
     256             : /* returns the footprint of the connection object for given limits */
     257             : ulong
     258             : fd_quic_conn_footprint( fd_quic_limits_t const * );
     259             : 
     260             : /* called by fd_quic_new to initialize the connection objects
     261             :    used by fd_quic */
     262             : fd_quic_conn_t *
     263             : fd_quic_conn_new( void *                   mem,
     264             :                   fd_quic_t *              quic,
     265             :                   fd_quic_limits_t const * limits );
     266             : 
     267             : /* clears all non-persistent members of the connection object */
     268             : static inline void
     269      314385 : fd_quic_conn_clear( fd_quic_conn_t * conn ) {
     270      314385 :   fd_quic_t            * quic       = conn->quic;
     271      314385 :   uint                   conn_idx   = conn->conn_idx;
     272      314385 :   uint                   conn_gen   = conn->conn_gen;
     273      314385 :   uint                   conn_state = conn->state;
     274      314385 :   fd_quic_stream_map_t * stream_map = conn->stream_map;
     275             : 
     276      314385 :   fd_memset( conn, 0, sizeof( fd_quic_conn_t ) );
     277             : 
     278      314385 :   conn->quic       = quic;
     279      314385 :   conn->conn_idx   = conn_idx;
     280      314385 :   conn->conn_gen   = conn_gen;
     281      314385 :   conn->state      = conn_state;
     282      314385 :   conn->stream_map = stream_map;
     283      314385 : }
     284             : 
     285             : /* set the user-defined context value on the connection */
     286             : void
     287             : fd_quic_conn_set_context( fd_quic_conn_t * conn, void * context );
     288             : 
     289             : /* get the user-defined context value from a connection */
     290             : void *
     291             : fd_quic_conn_get_context( fd_quic_conn_t * conn );
     292             : 
     293             : 
     294             : /* set all conns to not visited, used for validation */
     295             : void
     296             : fd_quic_conn_validate_init( fd_quic_t * quic );
     297             : 
     298             : FD_PROTOTYPES_END
     299             : 
     300             : #endif /* HEADER_fd_src_waltz_quic_fd_quic_conn_h */

Generated by: LCOV version 1.14