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 */
|