Line data Source code
1 : #ifndef HEADER_fd_src_waltz_quic_templ_fd_quic_transport_params_h
2 : #define HEADER_fd_src_waltz_quic_templ_fd_quic_transport_params_h
3 :
4 : #include "../../../util/fd_util_base.h"
5 : #include <stdio.h>
6 :
7 : // TODO set proper defaults, and delete DFT_UNKNOWN
8 : #define DFT_UNKNOWN 0
9 :
10 : /* QUIC VARINT bounds - RFC 9000 variable-length integers can encode up to 2^62-1 */
11 194571 : #define FD_QUIC_VARINT_MAX ((1UL<<62)-1UL)
12 194592 : #define FD_QUIC_VARINT_MIN 0UL
13 :
14 : /* RFC 9000 Section 19.11: Stream count maximum cannot exceed 2^60, as it is not possible to encode stream IDs larger than 2^62-1. */
15 6 : #define FD_QUIC_STREAM_COUNT_MAX (1UL<<60)
16 :
17 : /* RFC 9000 Section 18.2: ack_delay_exponent values above 20 are invalid */
18 : #define FD_QUIC_ACK_DELAY_EXPONENT_MAX 20UL
19 :
20 : /* RFC 9000 Section 18.2: max_ack_delay values of 2^14 or greater are invalid */
21 : #define FD_QUIC_MAX_ACK_DELAY_MAX ((1UL<<14)-1UL)
22 :
23 : /* RFC 9000 Section 18.2: max_udp_payload_size minimum is 1200 */
24 : #define FD_QUIC_MAX_UDP_PAYLOAD_SIZE_MIN 1200UL
25 :
26 : /* RFC 9000 Section 18.2: The value of the active_connection_id_limit parameter MUST be at least 2 */
27 : #define FD_QUIC_ACTIVE_CONNECTION_ID_LIMIT_MIN 2UL
28 :
29 : //23456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789
30 : //........1.........2.........3.........4.........5.........6.........7.........8.........9.........0.........
31 : // Fields: NAME, ID, TYPE, DFT, DESC, MIN, MAX (MIN and MAX ignored except for VARINT types)
32 18726 : #define FD_QUIC_TRANSPORT_PARAMS(X, ...) \
33 18726 : X( original_destination_connection_id, \
34 6357 : 0x00, \
35 6357 : CONN_ID, \
36 6357 : DFT_UNKNOWN, \
37 6357 : "This parameter is the value of the Destination Connection ID field from the " \
38 6357 : "first Initial packet sent by the client; see Section 7.3. This transport " \
39 6357 : "parameter is only sent by a server.", \
40 6357 : 0, 0, \
41 24522 : __VA_ARGS__ ) \
42 24522 : X( max_idle_timeout_ms, \
43 24516 : 0x01, \
44 24516 : VARINT, \
45 24516 : DFT_UNKNOWN, \
46 24516 : "The maximum idle timeout is a value in milliseconds that is encoded as an " \
47 24516 : "integer; see (Section 10.1). Idle timeout is disabled when both endpoints omit " \
48 24516 : "this transport parameter or specify a value of 0.", \
49 24516 : FD_QUIC_VARINT_MIN, FD_QUIC_VARINT_MAX, \
50 24516 : __VA_ARGS__ ) \
51 12369 : X( stateless_reset_token, \
52 12363 : 0x02, \
53 12363 : TOKEN, \
54 12363 : DFT_UNKNOWN, \
55 12363 : "A stateless reset token is used in verifying a stateless reset; see Section " \
56 12363 : "10.3. This parameter is a sequence of 16 bytes. This transport parameter MUST " \
57 12363 : "NOT be sent by a client but MAY be sent by a server. A server that does not send " \
58 12363 : "this transport parameter cannot use stateless reset (Section 10.3) for the " \
59 12363 : "connection ID negotiated during the handshake.", \
60 12363 : 0, 0, \
61 24522 : __VA_ARGS__ ) \
62 24522 : X( max_udp_payload_size, \
63 24510 : 0x03, \
64 24510 : VARINT, \
65 24510 : 65527, \
66 24510 : "The maximum UDP payload size parameter is an integer value that limits the size " \
67 24510 : "of UDP payloads that the endpoint is willing to receive. UDP datagrams with " \
68 24510 : "payloads larger than this limit are not likely to be processed by the receiver. " \
69 24510 : "The default for this parameter is the maximum permitted UDP payload of 65527. " \
70 24510 : "Values below 1200 are invalid.\n" \
71 24510 : "This limit does act as an additional constraint on datagram size in the same way " \
72 24510 : "as the path MTU, but it is a property of the endpoint and not the path; see " \
73 24510 : "Section 14. It is expected that this is the space an endpoint dedicates to " \
74 24510 : "holding incoming packets.", \
75 24510 : FD_QUIC_MAX_UDP_PAYLOAD_SIZE_MIN, FD_QUIC_VARINT_MAX, \
76 24513 : __VA_ARGS__ ) \
77 24513 : X( initial_max_data, \
78 24507 : 0x04, \
79 24507 : VARINT, \
80 24507 : DFT_UNKNOWN, \
81 24507 : "The initial maximum data parameter is an integer value that contains the initial " \
82 24507 : "value for the maximum amount of data that can be sent on the connection. This is " \
83 24507 : "equivalent to sending a MAX_DATA (Section 19.9) for the connection immediately " \
84 24507 : "after completing the handshake.", \
85 24507 : FD_QUIC_VARINT_MIN, FD_QUIC_VARINT_MAX, \
86 24507 : __VA_ARGS__ ) \
87 12375 : X( initial_max_stream_data_bidi_local, \
88 12369 : 0x05, \
89 12369 : VARINT, \
90 12369 : DFT_UNKNOWN, \
91 12369 : "This parameter is an integer value specifying the initial flow control limit for " \
92 12369 : "locally initiated bidirectional streams. This limit applies to newly created " \
93 12369 : "bidirectional streams opened by the endpoint that sends the transport parameter. " \
94 12369 : "In client transport parameters, this applies to streams with an identifier with " \
95 12369 : "the least significant two bits set to 0x00; in server transport parameters, this " \
96 12369 : "applies to streams with the least significant two bits set to 0x01.", \
97 12369 : FD_QUIC_VARINT_MIN, FD_QUIC_VARINT_MAX, \
98 12375 : __VA_ARGS__ ) \
99 12375 : X( initial_max_stream_data_bidi_remote, \
100 12369 : 0x06, \
101 12369 : VARINT, \
102 12369 : DFT_UNKNOWN, \
103 12369 : "This parameter is an integer value specifying the initial flow control limit for " \
104 12369 : "peer-initiated bidirectional streams. This limit applies to newly created " \
105 12369 : "bidirectional streams opened by the endpoint that receives the transport " \
106 12369 : "parameter. In client transport parameters, this applies to streams with an " \
107 12369 : "identifier with the least significant two bits set to 0x01; in server transport " \
108 12369 : "parameters, this applies to streams with the least significant two bits set to " \
109 12369 : "0x00.", \
110 12369 : FD_QUIC_VARINT_MIN, FD_QUIC_VARINT_MAX, \
111 24513 : __VA_ARGS__ ) \
112 24513 : X( initial_max_stream_data_uni, \
113 24507 : 0x07, \
114 24507 : VARINT, \
115 24507 : DFT_UNKNOWN, \
116 24507 : "This parameter is an integer value specifying the initial flow control limit for " \
117 24507 : "unidirectional streams. This limit applies to newly created unidirectional " \
118 24507 : "streams opened by the endpoint that receives the transport parameter. In client " \
119 24507 : "transport parameters, this applies to streams with an identifier with the least " \
120 24507 : "significant two bits set to 0x03; in server transport parameters, this applies " \
121 24507 : "to streams with the least significant two bits set to 0x02.", \
122 24507 : FD_QUIC_VARINT_MIN, FD_QUIC_VARINT_MAX, \
123 24525 : __VA_ARGS__ ) \
124 24525 : X( initial_max_streams_bidi, \
125 24516 : 0x08, \
126 24516 : VARINT, \
127 24516 : DFT_UNKNOWN, \
128 24516 : "The initial maximum bidirectional streams parameter is an integer value that " \
129 24516 : "contains the initial maximum number of bidirectional streams the endpoint that " \
130 24516 : "receives this transport parameter is permitted to initiate. If this parameter is " \
131 24516 : "absent or zero, the peer cannot open bidirectional streams until a MAX_STREAMS " \
132 24516 : "frame is sent. Setting this parameter is equivalent to sending a MAX_STREAMS " \
133 24516 : "(Section 19.11) of the corresponding type with the same value.", \
134 24516 : FD_QUIC_VARINT_MIN, FD_QUIC_STREAM_COUNT_MAX, \
135 24519 : __VA_ARGS__ ) \
136 24519 : X( initial_max_streams_uni, \
137 24510 : 0x09, \
138 24510 : VARINT, \
139 24510 : DFT_UNKNOWN, \
140 24510 : "The initial maximum unidirectional streams parameter is an integer value that " \
141 24510 : "contains the initial maximum number of unidirectional streams the endpoint that " \
142 24510 : "receives this transport parameter is permitted to initiate. If this parameter is " \
143 24510 : "absent or zero, the peer cannot open unidirectional streams until a MAX_STREAMS " \
144 24510 : "frame is sent. Setting this parameter is equivalent to sending a MAX_STREAMS " \
145 24510 : "(Section 19.11) of the corresponding type with the same value.", \
146 24510 : FD_QUIC_VARINT_MIN, FD_QUIC_STREAM_COUNT_MAX, \
147 24579 : __VA_ARGS__ ) \
148 24579 : X( ack_delay_exponent, \
149 24567 : 0x0a, \
150 24567 : VARINT, \
151 24567 : DFT_UNKNOWN, \
152 24567 : "The acknowledgment delay exponent is an integer value indicating an exponent " \
153 24567 : "used to decode the ACK Delay field in the ACK frame (Section 19.3). If this " \
154 24567 : "value is absent, a default value of 3 is assumed (indicating a multiplier of 8).\n" \
155 24567 : "Values above 20 are invalid.", \
156 24567 : FD_QUIC_VARINT_MIN, FD_QUIC_ACK_DELAY_EXPONENT_MAX, \
157 24567 : __VA_ARGS__ ) \
158 24525 : X( max_ack_delay, \
159 24513 : 0x0b, \
160 24513 : VARINT, \
161 24513 : 25, \
162 24513 : "The maximum acknowledgment delay is an integer value indicating the maximum " \
163 24513 : "amount of time in milliseconds by which the endpoint will delay sending " \
164 24513 : "acknowledgments. This value SHOULD include the receiver's expected delays in " \
165 24513 : "alarms firing. For example, if a receiver sets a timer for 5ms and alarms " \
166 24513 : "commonly fire up to 1ms late, then it should send a max_ack_delay of 6ms. If " \
167 24513 : "this value is absent, a default of 25 milliseconds is assumed. Values of 2^14 or " \
168 24513 : "greater are invalid.", \
169 24513 : FD_QUIC_VARINT_MIN, FD_QUIC_MAX_ACK_DELAY_MAX, \
170 24513 : __VA_ARGS__ ) \
171 24513 : X( disable_active_migration, \
172 24507 : 0x0c, \
173 24507 : ZERO_LENGTH, \
174 24507 : DFT_UNKNOWN, \
175 24507 : "The disable active migration transport parameter is included if the endpoint " \
176 24507 : "does not support active connection migration (Section 9) on the address being " \
177 24507 : "used during the handshake. An endpoint that receives this transport parameter " \
178 24507 : "MUST NOT use a new local address when sending to the address that the peer used " \
179 24507 : "during the handshake. This transport parameter does not prohibit connection " \
180 24507 : "migration after a client has acted on a preferred_address transport parameter.\n" \
181 24507 : "This parameter is a zero-length value.", \
182 24507 : 0, 0, \
183 24507 : __VA_ARGS__ ) \
184 12369 : X( preferred_address, \
185 12363 : 0x0d, \
186 12363 : PREFERRED_ADDRESS, \
187 12363 : DFT_UNKNOWN, \
188 12363 : "The server's preferred address is used to effect a change in server address at " \
189 12363 : "the end of the handshake, as described in Section 9.6. This transport parameter " \
190 12363 : "is only sent by a server. Servers MAY choose to only send a preferred address of " \
191 12363 : "one address family by sending an all-zero address and port (0.0.0.0:0 or [::]:0) " \
192 12363 : "for the other family. IP addresses are encoded in network byte order.\n" \
193 12363 : "The preferred_address transport parameter contains an address and port for both " \
194 12363 : "IPv4 and IPv6. The four-byte IPv4 Address field is followed by the associated " \
195 12363 : "two-byte IPv4 Port field. This is followed by a 16-byte IPv6 Address field and " \
196 12363 : "two-byte IPv6 Port field. After address and port pairs, a Connection ID Length " \
197 12363 : "field describes the length of the following Connection ID field. Finally, a " \
198 12363 : "16-byte Stateless Reset Token field includes the stateless reset token " \
199 12363 : "associated with the connection ID. The format of this transport parameter is " \
200 12363 : "shown in Figure 22 below.", \
201 12363 : 0, 0, \
202 12384 : __VA_ARGS__ ) \
203 12384 : X( active_connection_id_limit, \
204 12372 : 0x0e, \
205 12372 : VARINT, \
206 12372 : 2, \
207 12372 : "This is an integer value specifying the maximum number of connection IDs from " \
208 12372 : "the peer that an endpoint is willing to store. This value includes the " \
209 12372 : "connection ID received during the handshake, that received in the " \
210 12372 : "preferred_address transport parameter, and those received in NEW_CONNECTION_ID " \
211 12372 : "frames. The value of the active_connection_id_limit parameter MUST be at least " \
212 12372 : "2. An endpoint that receives a value less than 2 MUST close the connection with " \
213 12372 : "an error of type TRANSPORT_PARAMETER_ERROR. If this transport parameter is " \
214 12372 : "absent, a default of 2 is assumed. If an endpoint issues a zero-length " \
215 12372 : "connection ID, it will never send a NEW_CONNECTION_ID frame and therefore " \
216 12372 : "ignores the active_connection_id_limit value received from its peer.", \
217 12372 : FD_QUIC_ACTIVE_CONNECTION_ID_LIMIT_MIN, FD_QUIC_VARINT_MAX, \
218 24513 : __VA_ARGS__ ) \
219 24513 : X( initial_source_connection_id, \
220 24507 : 0x0f, \
221 24507 : CONN_ID, \
222 24507 : DFT_UNKNOWN, \
223 24507 : "This is the value that the endpoint included in the Source Connection ID field " \
224 24507 : "of the first Initial packet it sends for the connection; see Section 7.3.", \
225 24507 : 0, 0, \
226 24507 : __VA_ARGS__ ) \
227 12375 : X( retry_source_connection_id, \
228 12369 : 0x10, \
229 12369 : CONN_ID, \
230 12369 : DFT_UNKNOWN, \
231 12369 : "This is the value that the server included in the Source Connection ID field of " \
232 12369 : "a Retry packet; see Section 7.3. This transport parameter is only sent by a " \
233 12369 : "server.", \
234 12369 : 0, 0, \
235 12372 : __VA_ARGS__ ) \
236 12372 : X( max_datagram_frame_size, \
237 12366 : 0x20, \
238 12366 : VARINT, \
239 12366 : DFT_UNKNOWN, \
240 12366 : "RFC 9221 maximum DATAGRAM frame size. Omitting this parameter disables DATAGRAM.", \
241 12366 : FD_QUIC_VARINT_MIN, FD_QUIC_VARINT_MAX, \
242 12366 : __VA_ARGS__ )
243 :
244 3 : #define FD_QUIC_PREFERRED_ADDRESS_SZ_MAX (61)
245 :
246 : void
247 : fd_quic_dump_transport_param_desc( FILE * out );
248 :
249 : // TODO verify max length on these - CONN_ID and TOKEN
250 : // PREFERRED_ADDRESS is incomplete
251 : #define FD_QUIC_MBR_TYPE_VARINT(NAME,TYPE) \
252 : ulong NAME; \
253 : uchar NAME##_present;
254 : #define FD_QUIC_MBR_TYPE_CONN_ID(NAME,TYPE) \
255 : uchar NAME##_len; \
256 : uchar NAME[20]; \
257 : uchar NAME##_present;
258 : #define FD_QUIC_MBR_TYPE_ZERO_LENGTH(NAME,TYPE) \
259 : uchar NAME##_present;
260 : #define FD_QUIC_MBR_TYPE_TOKEN(NAME,TYPE) \
261 : uint NAME##_len; \
262 : uchar NAME[16]; \
263 : uchar NAME##_present;
264 : #define FD_QUIC_MBR_TYPE_PREFERRED_ADDRESS(NAME,TYPE) \
265 : uint NAME##_len; \
266 : uchar NAME[FD_QUIC_PREFERRED_ADDRESS_SZ_MAX]; \
267 : uchar NAME##_present;
268 :
269 : struct fd_quic_transport_params {
270 : #define __( NAME, ID, TYPE, DFT, DESC, ... ) \
271 : FD_QUIC_MBR_TYPE_##TYPE(NAME,TYPE)
272 : FD_QUIC_TRANSPORT_PARAMS( __, _ )
273 : #undef __
274 : };
275 : typedef struct fd_quic_transport_params fd_quic_transport_params_t;
276 :
277 : #define FD_QUIC_TRANSPORT_PARAM_SET( TP, NAME, VALUE ) \
278 2370 : do { (TP)->NAME##_present = 1; (TP)->NAME = VALUE; } while(0);
279 : #define FD_QUIC_TRANSPORT_PARAM_UNSET( TP, NAME ) \
280 : do { (TP)->NAME##_present = 0; } while(0);
281 :
282 : /* parses the varint at *buf (capacity *buf_sz)
283 : advances the *buf and reduces *buf_sz by the number of bytes
284 : consumed */
285 : static inline ulong
286 : fd_quic_tp_parse_varint( uchar const ** buf,
287 255918 : ulong * buf_sz ) {
288 :
289 255918 : if( FD_UNLIKELY( *buf_sz == 0 ) ) return ~(ulong)0;
290 :
291 255915 : uint width = 1u << ( (uint)(*buf)[0] >> 6u );
292 255915 : if( FD_UNLIKELY( *buf_sz < width ) ) return ~(ulong)0;
293 :
294 255915 : ulong value = (ulong)( (*buf)[0] & 0x3f );
295 255987 : for( ulong j=1; j<width; ++j ) {
296 72 : value = ( value<<8UL ) + (ulong)(*buf)[j];
297 72 : }
298 :
299 255915 : *buf += width;
300 255915 : *buf_sz -= width;
301 :
302 255915 : return value;
303 255915 : }
304 :
305 : /* parse the entire buffer into the supplied transport parameters
306 :
307 : unknown transport parameters are ignored as per spec
308 :
309 : returns
310 : 0 success
311 : -1 failed to parse */
312 : int
313 : fd_quic_decode_transport_params( fd_quic_transport_params_t * params,
314 : uchar const * buf,
315 : ulong buf_sz );
316 :
317 : /* dump all transport parameters to stdout */
318 : void
319 : fd_quic_dump_transport_params( fd_quic_transport_params_t const * params,
320 : FILE * out );
321 :
322 :
323 : /* encode transport parameters into a buffer
324 : args
325 : buf the buffer to write encoded transport params into
326 : buf_sz the size of buffer buf
327 : params the parameters to be encoded
328 :
329 : returns the number of bytes written */
330 : ulong
331 : fd_quic_encode_transport_params( uchar * buf,
332 : ulong buf_sz,
333 : fd_quic_transport_params_t const * params );
334 :
335 : #endif /* HEADER_fd_src_waltz_quic_templ_fd_quic_transport_params_h */
|