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