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