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_ack_tx.h" 6 : #include "fd_quic_retry.h" 7 : #include "fd_quic_stream.h" 8 : #include "fd_quic_conn_id.h" 9 : #include "crypto/fd_quic_crypto_suites.h" 10 : #include "templ/fd_quic_transport_params.h" 11 : #include "fd_quic_pkt_meta.h" 12 : 13 945690 : #define FD_QUIC_CONN_STATE_INVALID 0 /* dead object / freed */ 14 339663 : #define FD_QUIC_CONN_STATE_HANDSHAKE 1 /* currently doing handshaking with peer */ 15 85863 : #define FD_QUIC_CONN_STATE_HANDSHAKE_COMPLETE 2 /* handshake complete, confirming with peer */ 16 42726425 : #define FD_QUIC_CONN_STATE_ACTIVE 3 /* connection established - data may be transferred */ 17 42084 : #define FD_QUIC_CONN_STATE_PEER_CLOSE 4 /* peer requested close */ 18 15036 : #define FD_QUIC_CONN_STATE_ABORT 5 /* connection terminating due to error */ 19 43947 : #define FD_QUIC_CONN_STATE_CLOSE_PENDING 6 /* connection is closing */ 20 56646189 : #define FD_QUIC_CONN_STATE_DEAD 7 /* connection about to be freed */ 21 : 22 : enum { 23 : FD_QUIC_CONN_REASON_NO_ERROR = 0x00, /* No error */ 24 : FD_QUIC_CONN_REASON_INTERNAL_ERROR = 0x01, /* Implementation error */ 25 : FD_QUIC_CONN_REASON_CONNECTION_REFUSED = 0x02, /* Server refuses a connection */ 26 : FD_QUIC_CONN_REASON_FLOW_CONTROL_ERROR = 0x03, /* Flow control error */ 27 : FD_QUIC_CONN_REASON_STREAM_LIMIT_ERROR = 0x04, /* Too many streams opened */ 28 : FD_QUIC_CONN_REASON_STREAM_STATE_ERROR = 0x05, /* Frame received in invalid stream state */ 29 : FD_QUIC_CONN_REASON_FINAL_SIZE_ERROR = 0x06, /* Change to final size */ 30 : FD_QUIC_CONN_REASON_FRAME_ENCODING_ERROR = 0x07, /* Frame encoding error */ 31 : FD_QUIC_CONN_REASON_TRANSPORT_PARAMETER_ERROR = 0x08, /* Error in transport parameters */ 32 : FD_QUIC_CONN_REASON_CONNECTION_ID_LIMIT_ERROR = 0x09, /* Too many connection IDs received */ 33 : FD_QUIC_CONN_REASON_PROTOCOL_VIOLATION = 0x0a, /* Generic protocol violation */ 34 : FD_QUIC_CONN_REASON_INVALID_TOKEN = 0x0b, /* Invalid Token received */ 35 : FD_QUIC_CONN_REASON_APPLICATION_ERROR = 0x0c, /* Application error */ 36 : FD_QUIC_CONN_REASON_CRYPTO_BUFFER_EXCEEDED = 0x0d, /* CRYPTO data buffer overflowed */ 37 : FD_QUIC_CONN_REASON_KEY_UPDATE_ERROR = 0x0e, /* Invalid packet protection update */ 38 : FD_QUIC_CONN_REASON_AEAD_LIMIT_REACHED = 0x0f, /* Excessive use of packet protection keys */ 39 : FD_QUIC_CONN_REASON_NO_VIABLE_PATH = 0x10, /* No viable network path exists */ 40 : FD_QUIC_CONN_REASON_CRYPTO_BASE = 0x100, /* 0x0100-0x01ff CRYPTO_ERROR TLS alert code*/ 41 : /* QUIC permits the use of a generic code in place of a specific error code [...] 42 : such as handshake_failure (0x0128 in QUIC). */ 43 : FD_QUIC_CONN_REASON_HANDSHAKE_FAILURE = 0x128 /* Handshake failed. */ 44 : }; 45 : 46 : typedef struct fd_quic_conn fd_quic_conn_t; 47 : 48 : struct fd_quic_conn { 49 : uint conn_idx; /* connection index */ 50 : /* connections are sized at runtime */ 51 : /* storing the index avoids a division */ 52 : 53 : fd_quic_t * quic; 54 : void * context; /* user context */ 55 : 56 : uint server : 1; /* role from self POV: 0=client, 1=server */ 57 : uint established : 1; /* used by clients to determine whether to 58 : switch the destination conn id used */ 59 : uint transport_params_set : 1; 60 : uint called_conn_new : 1; /* whether we need to call conn_final on teardown */ 61 : uint visited : 1; /* scratch bit, no strict definition */ 62 : 63 : /* Service queue dlist membership. All active conns (state not INVALID) 64 : are in a service queue, FD_QUIC_SVC_TYPE_WAIT by default. 65 : Free conns (svc_type==UINT_MAX) are members of a singly linked list 66 : (only src_next set) */ 67 : uint svc_type; /* FD_QUIC_SVC_{...} or UINT_MAX */ 68 : uint svc_prev; 69 : uint svc_next; 70 : ulong svc_time; /* service may be delayed until this timestamp */ 71 : 72 : ulong our_conn_id; 73 : 74 : /* Save original retry_source_connection_id 75 : * This is used by clients to compare against the retry_source_connection_id 76 : * in the transport parameters as specified in rfc 9000 7.3 */ 77 : fd_quic_conn_id_t retry_src_conn_id; 78 : 79 : /* Host network endpoint 80 : - for server, just a copy of config->net 81 : - for client, an allocated ephemeral UDP port */ 82 : fd_quic_net_endpoint_t host; 83 : 84 : /* Peer network endpoints – have multiple connection ids and ip:port */ 85 : /* TODO: footprint allows specifying conn_id_cnt but hardcoded limit used here */ 86 : fd_quic_net_endpoint_t peer[1]; 87 : fd_quic_conn_id_t peer_cids[1]; /* FIXME support new/retire conn ID */ 88 : 89 : ulong local_conn_id; /* FIXME: hack to locally identify conns */ 90 : 91 : /* initial source connection id */ 92 : fd_quic_conn_id_t initial_source_conn_id; 93 : 94 : uint tx_max_datagram_sz; /* size of maximum datagram allowed by peer */ 95 : 96 : /* handshake members */ 97 : uint handshake_complete : 1; /* have we completed a successful handshake? */ 98 : uint handshake_done_send : 1; /* do we need to send handshake-done to peer? */ 99 : uint handshake_done_ackd : 1; /* was handshake_done ack'ed? */ 100 : uint hs_data_empty : 1; /* has all hs_data been consumed? */ 101 : fd_quic_tls_hs_t * tls_hs; 102 : 103 : /* expected handshake data offset - one per encryption level 104 : data received lower than this on a new packet is a protocol error 105 : duplicate packets should already have been dropped 106 : data received higher than this would be a gap 107 : ignore at present, assuming will be resent in order */ 108 : ulong rx_crypto_offset[4]; /* expected handshake data (crypto) offset 109 : one per encryption level */ 110 : 111 : /* amount of handshake data already sent from head of queue */ 112 : ulong hs_sent_bytes[4]; 113 : 114 : /* amount of handshake data ack'ed by peer counted from head of queue */ 115 : ulong hs_ackd_bytes[4]; 116 : 117 : /* secret members */ 118 : fd_quic_crypto_secrets_t secrets; 119 : fd_quic_crypto_keys_t keys[4][2]; /* a set of keys for each of the encoding levels, and for client/server */ 120 : fd_quic_crypto_keys_t new_keys[2]; /* a set of keys for use during key update */ 121 : uint keys_avail; /* bit set, LSB indexed by encryption level */ 122 : uint key_phase; /* current key phase - represents the current phase of the 123 : value of keys */ 124 : uint key_phase_upd; /* set to 1 if we're undertaking a key update */ 125 : 126 : fd_quic_stream_t send_streams[1]; /* sentinel of list of streams needing action */ 127 : fd_quic_stream_t used_streams[1]; /* sentinel of list of used streams */ 128 : /* invariant: an allocated stream must be in exactly one of the following lists: 129 : send_streams 130 : used_streams */ 131 : 132 : /* stream id members */ 133 : ulong next_stream_id[4]; /* next unused stream id by type - see rfc9000 2.1 */ 134 : /* next_stream_id is used for streams coming from the stream pool */ 135 : 136 : ulong rx_hi_stream_id; /* highest RX stream ID sent by peer + 4 */ 137 : ulong rx_sup_stream_id; /* highest allowed RX stream ID + 4 */ 138 : ulong tx_next_stream_id; /* stream ID to be used for new stream */ 139 : ulong tx_sup_stream_id; /* highest allowed TX stream ID + 4 */ 140 : 141 : ulong max_concur_streams[4]; /* user set concurrent max */ 142 : 143 : /* stream id limits */ 144 : /* limits->stream_cnt */ 145 : /* used to size stream_map, and provides an upper limit on the temporary limits */ 146 : /* on streams */ 147 : 148 : /* max_concur_streams */ 149 : /* temporary limit on the number of streams */ 150 : /* currently only applies to peers */ 151 : /* may be adjusted via fd_quic_conn_set_max_streams */ 152 : 153 : /* limits->initial_stream_cnt */ 154 : /* new connections attempt to assign initial_stream_cnt streams from the pool */ 155 : /* for peer initiated streams */ 156 : /* however many streams are assigned at this point becomes the limit imposed */ 157 : /* on the peer */ 158 : 159 : /* peer initiated streams */ 160 : /* the peer will create streams at will up to our imposed limit via max_streams */ 161 : /* frames */ 162 : /* max_streams frames are derived from changes to sup_stream_id */ 163 : 164 : /* self initiated streams */ 165 : /* we can create streams at will up to the peer imposed limit in peer_sup_stream_id */ 166 : /* these streams also come from the stream pool, and so the size of the stream pool */ 167 : /* also imposes a limit on self initiated streams */ 168 : 169 : /* rfc9000: 170 : 19.11 Note that these frames (and the corresponding transport parameters) 171 : do not describe the number of streams that can be opened concurrently. 172 : 4.6 Only streams with a stream ID less than 173 : (max_streams * 4 + first_stream_id_of_type) can be opened 174 : 2.1 Stream types: 175 : 0x00 Client-Initiated, Bidirectional 176 : 0x01 Server-Initiated, Bidirectional 177 : 0x02 Client-Initiated, Unidirectional 178 : 0x03 Server-Initiated, Unidirectional */ 179 : 180 : ulong rx_max_streams_unidir_ackd; /* value of MAX_STREAMS acked for UNIDIR */ 181 : 182 : fd_quic_stream_map_t * stream_map; /* map stream_id -> stream */ 183 : 184 : /* packet number info 185 : each encryption level maps to a packet number space 186 : 0-RTT and 1-RTT both map to APPLICATION 187 : pkt_number[j] represents the minimum acceptable packet number 188 : "expected packet number" 189 : packets with a number lower than this will be dropped */ 190 : ulong exp_pkt_number[3]; /* different packet number spaces: 191 : INITIAL, HANDSHAKE and APPLICATION */ 192 : ulong pkt_number[3]; /* tx packet number by pn space */ 193 : ulong last_pkt_number[3]; /* last (highest) packet numer seen */ 194 : 195 : ushort ipv4_id; /* ipv4 id field */ 196 : 197 : /* buffer to send next */ 198 : /* rename tx_buf, since it's easy to confuse with stream->tx_buf */ 199 : /* must be at least FD_QUIC_MAX_UDP_PAYLOAD_SZ */ 200 : uchar tx_buf[2048]; 201 : uchar * tx_ptr; /* ptr to free space in tx_scratch */ 202 : ulong tx_sz; /* sz remaining at ptr */ 203 : 204 : uint state; 205 : uint reason; /* quic reason for closing. see FD_QUIC_CONN_REASON_* */ 206 : uint app_reason; /* application reason for closing */ 207 : uint int_reason; /* internal reason */ 208 : 209 : fd_quic_ack_gen_t ack_gen[1]; 210 : ulong unacked_sz; /* Number of received stream frame payload bytes pending ACK */ 211 : /* Resets to zero when conn is rescheduled or ACKs are sent */ 212 : 213 : /* TODO find better name than pool */ 214 : fd_quic_pkt_meta_pool_t pkt_meta_pool; 215 : fd_quic_pkt_meta_t * pkt_meta_mem; /* owns the memory */ 216 : 217 : /* flow control */ 218 : ulong tx_max_data; /* the limit on the number of bytes we are allowed 219 : to send to the peer across all streams */ 220 : /* even if a bytes on a stream are not received, 221 : higher offsets received imply the usage of those bytes, 222 : and they count against the max */ 223 : ulong tx_tot_data; /* total of all bytes received across all streams 224 : and including implied bytes */ 225 : ulong rx_max_data; /* the limit on the number of bytes the peer is allowed to 226 : send to us */ 227 : ulong rx_tot_data; /* total of all bytes received across all streams 228 : and including implied bytes */ 229 : ulong rx_max_data_ackd; /* max max_data acked by peer */ 230 : 231 : uint flags; 232 47136203 : # define FD_QUIC_CONN_FLAGS_MAX_DATA (1u<<0u) 233 44517 : # define FD_QUIC_CONN_FLAGS_CLOSE_SENT (1u<<1u) 234 2285202 : # define FD_QUIC_CONN_FLAGS_MAX_STREAMS_UNIDIR (1u<<2u) 235 20485666 : # define FD_QUIC_CONN_FLAGS_PING (1u<<4u) 236 18200464 : # define FD_QUIC_CONN_FLAGS_PING_SENT (1u<<5u) 237 : 238 : uchar spin_bit; /* spin bit used for latency measurements */ 239 : 240 : /* max stream data per stream type */ 241 : ulong tx_initial_max_stream_data_uni; 242 : 243 : /* last tx packet num with max_data frame referring to this stream 244 : set to next_pkt_number to indicate a new max_data frame should be sent 245 : if we time out this packet (or possibly a later packet) we resend the frame 246 : and update this value */ 247 : ulong upd_pkt_number; 248 : 249 : /* current round-trip-time (FIXME this never updates) */ 250 : ulong rtt; 251 : 252 : /* highest peer encryption level */ 253 : uchar peer_enc_level; 254 : 255 : /* idle timeout arguments */ 256 : ulong idle_timeout; 257 : ulong last_activity; 258 : 259 : /* rx_limit_pktnum is the newest inflight packet number in which 260 : the current rx_{sup_stream_id,max_data} values were sent to the 261 : peer. (via MAX_STREAMS and MAX_DATA quota frames) 262 : FD_QUIC_PKT_NUM_UNUSED indicates that the peer ACked the latest 263 : quota update, and thus is in sync with the server. 264 : FD_QUIC_PKT_NUM_PENDING indicates that no packet with the current 265 : rx_{sup_stream_id,max_data} value was sent yet. Will trigger a 266 : send attempt at the next fd_quic_conn_tx call. */ 267 : ulong rx_limit_pktnum; 268 : 269 : ulong token_len; 270 : uchar token[ FD_QUIC_RETRY_MAX_TOKEN_SZ ]; 271 : }; 272 : 273 : FD_PROTOTYPES_BEGIN 274 : 275 : /* returns the alignment requirement of fd_quic_conn_t */ 276 : FD_FN_CONST ulong 277 : fd_quic_conn_align( void ); 278 : 279 : /* returns the footprint of the connection object for given limits */ 280 : FD_FN_PURE ulong 281 : fd_quic_conn_footprint( fd_quic_limits_t const * ); 282 : 283 : /* called by fd_quic_new to initialize the connection objects 284 : used by fd_quic */ 285 : fd_quic_conn_t * 286 : fd_quic_conn_new( void * mem, 287 : fd_quic_t * quic, 288 : fd_quic_limits_t const * limits ); 289 : 290 : /* set the user-defined context value on the connection */ 291 : void 292 : fd_quic_conn_set_context( fd_quic_conn_t * conn, void * context ); 293 : 294 : /* get the user-defined context value from a connection */ 295 : void * 296 : fd_quic_conn_get_context( fd_quic_conn_t * conn ); 297 : 298 : FD_PROTOTYPES_END 299 : 300 : #endif /* HEADER_fd_src_waltz_quic_fd_quic_conn_h */