Line data Source code
1 : #include "../fd_quic_common.h"
2 :
3 : #include "fd_quic_transport_params.h"
4 : #include "fd_quic_parse_util.h"
5 :
6 : #include <stdio.h>
7 :
8 : void
9 3 : fd_quic_dump_transport_param_desc( FILE * out ) {
10 3 : fprintf( out, "Transport parameter descriptions:\n" );
11 :
12 3 : #define __( NAME, ID, TYPE, DFT, DESC, ... ) \
13 51 : fprintf( out, #ID " " #TYPE " " #NAME "\n" DESC "\n\n" );
14 :
15 51 : FD_QUIC_TRANSPORT_PARAMS( __, _ )
16 3 : #undef __
17 3 : }
18 :
19 :
20 : #define FD_QUIC_PARSE_TP_VARINT(NAME) \
21 96222 : do { \
22 96222 : if( FD_UNLIKELY( sz==0 ) ) return -2; \
23 96222 : uint width = 1u << ( (unsigned)buf[0] >> 6u ); \
24 96222 : if( FD_UNLIKELY( sz<width ) ) return -3; \
25 96222 : ulong value = (ulong)( buf[0] & 0x3f ); \
26 294657 : for( ulong j=1; j<width; ++j ) { \
27 198435 : value= ( value<<8u ) + (ulong)buf[j]; \
28 198435 : } \
29 96222 : params->NAME = value; \
30 96222 : params->NAME##_present = 1; \
31 96222 : } while(0)
32 :
33 : #define FD_QUIC_PARSE_TP_CONN_ID(NAME) \
34 18330 : do { \
35 18330 : if( FD_UNLIKELY( sz>sizeof(params->NAME) ) ) return -1; \
36 18330 : fd_memcpy( params->NAME, buf, sz ); \
37 18330 : params->NAME##_len = (uchar)sz; \
38 18330 : params->NAME##_present = 1; \
39 18330 : } while(0)
40 :
41 : #define FD_QUIC_PARSE_TP_ZERO_LENGTH(NAME) \
42 12027 : params->NAME##_present = 1;
43 :
44 : #define FD_QUIC_PARSE_TP_TOKEN(NAME) \
45 0 : do { \
46 0 : if( FD_UNLIKELY( sz>sizeof(params->NAME) ) ) return -1; \
47 0 : fd_memcpy( params->NAME, buf, sz ); \
48 0 : params->NAME##_len = (uchar)sz; \
49 0 : params->NAME##_present = 1; \
50 0 : } while(0)
51 :
52 : #define FD_QUIC_PARSE_TP_PREFERRED_ADDRESS(NAME) \
53 0 : do { \
54 0 : if( FD_UNLIKELY( sz>sizeof(params->NAME) ) ) return -1; \
55 0 : fd_memcpy( params->NAME, buf, sz ); \
56 0 : params->NAME##_len = (uchar)sz; \
57 0 : params->NAME##_present = 1; \
58 0 : } while(0)
59 :
60 :
61 : static int
62 : fd_quic_decode_transport_param( fd_quic_transport_params_t * params,
63 : ulong id,
64 : uchar const * buf,
65 126588 : ulong sz ) {
66 : // This compiles into a jump table, which is reasonably fast
67 126588 : switch( id ) {
68 0 : #define __( NAME, ID, TYPE, DFT, DESC, ... ) \
69 126579 : case ID: { \
70 126579 : FD_QUIC_PARSE_TP_##TYPE(NAME); \
71 126579 : return 0; \
72 114552 : } \
73 0 :
74 126588 : FD_QUIC_TRANSPORT_PARAMS( __, _ )
75 126588 : #undef __
76 :
77 126588 : }
78 :
79 9 : return 0; /* ignore unknown IDs */
80 126588 : }
81 :
82 : int
83 : fd_quic_decode_transport_params( fd_quic_transport_params_t * params,
84 : uchar const * buf,
85 12036 : ulong buf_sz ) {
86 138624 : while( buf_sz > 0 ) {
87 : /* upon success, this function adjusts buf and sz by bytes consumed */
88 126591 : ulong param_id = fd_quic_tp_parse_varint( &buf, &buf_sz );
89 126591 : ulong param_sz = fd_quic_tp_parse_varint( &buf, &buf_sz );
90 126591 : if( FD_UNLIKELY( param_sz > buf_sz ) ) return -1; /* length OOB */
91 :
92 126588 : int param_err = fd_quic_decode_transport_param( params, param_id, buf, param_sz );
93 126588 : if( FD_UNLIKELY( param_err ) ) return -1; /* parse failure */
94 :
95 : /* update buf and buf_sz */
96 126588 : buf += param_sz;
97 126588 : buf_sz -= param_sz;
98 126588 : }
99 :
100 12033 : return 0; /* success */
101 12036 : }
102 :
103 : #define FD_QUIC_DUMP_TP_VARINT(NAME) \
104 33 : fprintf( out, "%lu", (ulong)params->NAME )
105 : #define FD_QUIC_DUMP_TP_CONN_ID(NAME) \
106 15 : do { \
107 15 : ulong sz = params->NAME##_len; \
108 15 : fprintf( out, "len(%d) ", (int)sz ); \
109 39 : for( ulong j = 0; j < sz; ++j ) { \
110 24 : fprintf( out, "%2.2x ", (unsigned)params->NAME[j] ); \
111 24 : } \
112 15 : } while(0)
113 : #define FD_QUIC_DUMP_TP_ZERO_LENGTH(NAME) \
114 3 : fprintf( out, "%u", (unsigned)params->NAME##_present )
115 3 : #define FD_QUIC_DUMP_TP_TOKEN(NAME) FD_QUIC_DUMP_TP_CONN_ID(NAME)
116 3 : #define FD_QUIC_DUMP_TP_PREFERRED_ADDRESS(NAME) FD_QUIC_DUMP_TP_CONN_ID(NAME)
117 :
118 : void
119 3 : fd_quic_dump_transport_params( fd_quic_transport_params_t const * params, FILE * out ) {
120 3 : fprintf( out, "Transport params:\n" );
121 3 : #define __( NAME, ID, TYPE, DFT, DESC, ... ) \
122 51 : fprintf( out, " %-50s: %s ", #NAME " (" #ID ")", params->NAME##_present ? "*" : " " ); \
123 51 : FD_QUIC_DUMP_TP_##TYPE(NAME); \
124 51 : fprintf( out, "\n" );
125 51 : FD_QUIC_TRANSPORT_PARAMS( __, _ )
126 3 : #undef __
127 3 : }
128 :
129 :
130 : #define FD_QUIC_ENCODE_TP_VARINT(NAME,ID) \
131 96285 : do { \
132 96285 : ulong val_len = fd_quic_varint_min_sz( params->NAME ); \
133 96285 : if( val_len == FD_QUIC_ENCODE_FAIL ) return FD_QUIC_ENCODE_FAIL; \
134 96285 : FD_QUIC_ENCODE_VARINT( buf, buf_sz, ID ); \
135 96285 : FD_QUIC_ENCODE_VARINT( buf, buf_sz, val_len ); \
136 96285 : FD_QUIC_ENCODE_VARINT(buf,buf_sz,params->NAME); \
137 96285 : } while(0)
138 :
139 : #define FD_QUIC_ENCODE_TP_CONN_ID(NAME,ID) \
140 18060 : do { \
141 18060 : ulong val_len = params->NAME##_len; \
142 18060 : FD_QUIC_ENCODE_VARINT( buf, buf_sz, ID ); \
143 18060 : FD_QUIC_ENCODE_VARINT( buf, buf_sz, val_len ); \
144 18060 : if( val_len + 1 > buf_sz ) return FD_QUIC_ENCODE_FAIL; \
145 162831 : for( ulong j = 0; j < val_len; ++j ) { \
146 144771 : buf[j] = params->NAME[j]; \
147 144771 : } \
148 18060 : buf += val_len; buf_sz -= val_len; \
149 18060 : } while(0);
150 :
151 : #define FD_QUIC_ENCODE_TP_ZERO_LENGTH(NAME,ID) \
152 12027 : do { \
153 12027 : if( params->NAME##_present ) { \
154 12027 : FD_QUIC_ENCODE_VARINT( buf, buf_sz, ID ); \
155 12027 : FD_QUIC_ENCODE_VARINT( buf, buf_sz, 0 ); \
156 12027 : } \
157 12027 : } while(0)
158 :
159 : #define FD_QUIC_ENCODE_TP_TOKEN(NAME,ID) \
160 3 : FD_QUIC_ENCODE_TP_CONN_ID(NAME,ID)
161 :
162 : #define FD_QUIC_ENCODE_TP_PREFERRED_ADDRESS(NAME,ID) \
163 3 : FD_QUIC_ENCODE_TP_CONN_ID(NAME,ID)
164 :
165 :
166 : /* determine footprint of each type */
167 :
168 : #define FD_QUIC_FOOTPRINT_FAIL ((ulong)1 << (ulong)62)
169 :
170 : /* we need the length of the ID + the length of the length of the parameter value
171 : plus the length of the parameter value */
172 : #define FD_QUIC_FOOTPRINT_TP_VARINT(NAME,ID) \
173 : ( \
174 : fd_quic_varint_min_sz( ID ) + \
175 : fd_quic_varint_min_sz( fd_quic_varint_min_sz( params->NAME ) ) + \
176 : fd_quic_varint_min_sz( params->NAME ) \
177 : )
178 :
179 : /* the length of a connection id is specified by *_len */
180 : #define FD_QUIC_FOOTPRINT_TP_CONN_ID(NAME,ID) \
181 : ( \
182 : fd_quic_varint_min_sz( ID ) + \
183 : fd_quic_varint_min_sz( params->NAME##_len ) + \
184 : params->NAME##_len \
185 : )
186 :
187 : #define FD_QUIC_FOOTPRINT_TP_ZERO_LENGTH(NAME,ID) \
188 : ( \
189 : fd_quic_varint_min_sz( ID ) + \
190 : fd_quic_varint_min_sz( 0 ) \
191 : )
192 :
193 : #define FD_QUIC_FOOTPRINT_TP_TOKEN(NAME,ID) \
194 : FD_QUIC_FOOTPRINT_TP_CONN_ID(NAME,ID)
195 :
196 : #define FD_QUIC_FOOTPRINT_TP_PREFERRED_ADDRESS(NAME,ID) \
197 : FD_QUIC_FOOTPRINT_TP_CONN_ID(NAME,ID)
198 :
199 :
200 : #define FD_QUIC_VALIDATE_TP_TOKEN(NAME,ID) \
201 : FD_QUIC_VALIDATE_TP_CONN_ID(NAME,ID)
202 :
203 : #define FD_QUIC_VALIDATE_TP_PREFERRED_ADDRESS(NAME,ID) \
204 : FD_QUIC_VALIDATE_TP_CONN_ID(NAME,ID)
205 :
206 :
207 : // encode transport parameters into a buffer
208 : // returns the number of bytes written
209 : ulong
210 : fd_quic_encode_transport_params( uchar * buf,
211 : ulong buf_sz,
212 12033 : fd_quic_transport_params_t const * params ) {
213 12033 : ulong orig_buf_sz = buf_sz;
214 12033 : #define __( NAME, ID, TYPE, DFT, DESC, ... ) \
215 204561 : if( params->NAME##_present ) { \
216 126372 : FD_QUIC_ENCODE_TP_##TYPE(NAME,ID); \
217 18060 : }
218 204561 : FD_QUIC_TRANSPORT_PARAMS( __, _ )
219 12033 : #undef __
220 :
221 12033 : return orig_buf_sz - buf_sz;
222 192528 : }
|