1
2
3
4
5
6
7 package quic
8
9 import (
10 "bytes"
11 "math"
12 "net/netip"
13 "reflect"
14 "testing"
15 "time"
16 )
17
18 func TestTransportParametersMarshalUnmarshal(t *testing.T) {
19 for _, test := range []struct {
20 params func(p *transportParameters)
21 enc []byte
22 }{{
23 params: func(p *transportParameters) {
24 p.originalDstConnID = []byte("connid")
25 },
26 enc: []byte{
27 0x00,
28 byte(len("connid")),
29 'c', 'o', 'n', 'n', 'i', 'd',
30 },
31 }, {
32 params: func(p *transportParameters) {
33 p.maxIdleTimeout = 10 * time.Millisecond
34 },
35 enc: []byte{
36 0x01,
37 1,
38 10,
39 },
40 }, {
41 params: func(p *transportParameters) {
42 p.statelessResetToken = []byte("0123456789abcdef")
43 },
44 enc: []byte{
45 0x02,
46 16,
47 '0', '1', '2', '3', '4', '5', '6', '7',
48 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
49 },
50 }, {
51 params: func(p *transportParameters) {
52 p.maxUDPPayloadSize = 1200
53 },
54 enc: []byte{
55 0x03,
56 2,
57 0x44, 0xb0,
58 },
59 }, {
60 params: func(p *transportParameters) {
61 p.initialMaxData = 10
62 },
63 enc: []byte{
64 0x04,
65 1,
66 10,
67 },
68 }, {
69 params: func(p *transportParameters) {
70 p.initialMaxStreamDataBidiLocal = 10
71 },
72 enc: []byte{
73 0x05,
74 1,
75 10,
76 },
77 }, {
78 params: func(p *transportParameters) {
79 p.initialMaxStreamDataBidiRemote = 10
80 },
81 enc: []byte{
82 0x06,
83 1,
84 10,
85 },
86 }, {
87 params: func(p *transportParameters) {
88 p.initialMaxStreamDataUni = 10
89 },
90 enc: []byte{
91 0x07,
92 1,
93 10,
94 },
95 }, {
96 params: func(p *transportParameters) {
97 p.initialMaxStreamsBidi = 10
98 },
99 enc: []byte{
100 0x08,
101 1,
102 10,
103 },
104 }, {
105 params: func(p *transportParameters) {
106 p.initialMaxStreamsUni = 10
107 },
108 enc: []byte{
109 0x09,
110 1,
111 10,
112 },
113 }, {
114 params: func(p *transportParameters) {
115 p.ackDelayExponent = 4
116 },
117 enc: []byte{
118 0x0a,
119 1,
120 4,
121 },
122 }, {
123 params: func(p *transportParameters) {
124 p.maxAckDelay = 10 * time.Millisecond
125 },
126 enc: []byte{
127 0x0b,
128 1,
129 10,
130 },
131 }, {
132 params: func(p *transportParameters) {
133 p.disableActiveMigration = true
134 },
135 enc: []byte{
136 0x0c,
137 0,
138 },
139 }, {
140 params: func(p *transportParameters) {
141 p.preferredAddrV4 = netip.MustParseAddrPort("127.0.0.1:80")
142 p.preferredAddrV6 = netip.MustParseAddrPort("[fe80::1]:1024")
143 p.preferredAddrConnID = []byte("connid")
144 p.preferredAddrResetToken = []byte("0123456789abcdef")
145 },
146 enc: []byte{
147 0x0d,
148 byte(4 + 2 + 16 + 2 + 1 + len("connid") + 16),
149 127, 0, 0, 1,
150 0, 80,
151 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
152 0x04, 0x00,
153 6,
154 'c', 'o', 'n', 'n', 'i', 'd',
155 '0', '1', '2', '3', '4', '5', '6', '7',
156 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
157 },
158 }, {
159 params: func(p *transportParameters) {
160 p.activeConnIDLimit = 10
161 },
162 enc: []byte{
163 0x0e,
164 1,
165 10,
166 },
167 }, {
168 params: func(p *transportParameters) {
169 p.initialSrcConnID = []byte("connid")
170 },
171 enc: []byte{
172 0x0f,
173 byte(len("connid")),
174 'c', 'o', 'n', 'n', 'i', 'd',
175 },
176 }, {
177 params: func(p *transportParameters) {
178 p.retrySrcConnID = []byte("connid")
179 },
180 enc: []byte{
181 0x10,
182 byte(len("connid")),
183 'c', 'o', 'n', 'n', 'i', 'd',
184 },
185 }} {
186 wantParams := defaultTransportParameters()
187 test.params(&wantParams)
188 gotBytes := marshalTransportParameters(wantParams)
189 if !bytes.Equal(gotBytes, test.enc) {
190 t.Errorf("marshalTransportParameters(%#v):\n got: %x\nwant: %x", wantParams, gotBytes, test.enc)
191 }
192 gotParams, err := unmarshalTransportParams(test.enc)
193 if err != nil {
194 t.Errorf("unmarshalTransportParams(%x): unexpected error: %v", test.enc, err)
195 } else if !reflect.DeepEqual(gotParams, wantParams) {
196 t.Errorf("unmarshalTransportParams(%x):\n got: %#v\nwant: %#v", test.enc, gotParams, wantParams)
197 }
198 }
199 }
200
201 func TestTransportParametersErrors(t *testing.T) {
202 for _, test := range []struct {
203 desc string
204 enc []byte
205 }{{
206 desc: "invalid id",
207 enc: []byte{
208 0x40,
209 },
210 }, {
211 desc: "parameter too short",
212 enc: []byte{
213 0x00,
214 0x04,
215 1, 2, 3,
216 },
217 }, {
218 desc: "extra data in parameter",
219 enc: []byte{
220 0x01,
221 2,
222 10,
223 0,
224 },
225 }, {
226 desc: "invalid varint in parameter",
227 enc: []byte{
228 0x01,
229 1,
230 0x40,
231 },
232 }, {
233 desc: "stateless_reset_token not 16 bytes",
234 enc: []byte{
235 0x02,
236 15,
237 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
238 },
239 }, {
240 desc: "initial_max_streams_bidi is too large",
241 enc: []byte{
242 0x08,
243 8,
244 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
245 },
246 }, {
247 desc: "initial_max_streams_uni is too large",
248 enc: []byte{
249 0x08,
250 9,
251 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
252 },
253 }, {
254 desc: "preferred_address is too short",
255 enc: []byte{
256 0x0d,
257 byte(3),
258 127, 0, 0,
259 },
260 }, {
261 desc: "preferred_address reset token too short",
262 enc: []byte{
263 0x0d,
264 byte(4 + 2 + 16 + 2 + 1 + len("connid") + 15),
265 127, 0, 0, 1,
266 0, 80,
267 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
268 0x04, 0x00,
269 6,
270 'c', 'o', 'n', 'n', 'i', 'd',
271 '0', '1', '2', '3', '4', '5', '6', '7',
272 '8', '9', 'a', 'b', 'c', 'd', 'e',
273
274 },
275 }, {
276 desc: "preferred_address conn id too long",
277 enc: []byte{
278 0x0d,
279 byte(4 + 2 + 16 + 2 + 1 + len("connid") + 16),
280 127, 0, 0, 1,
281 0, 80,
282 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
283 0x04, 0x00,
284 byte(len("connid")) + 16 + 1,
285 'c', 'o', 'n', 'n', 'i', 'd',
286 '0', '1', '2', '3', '4', '5', '6', '7',
287 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
288
289 },
290 }} {
291 _, err := unmarshalTransportParams(test.enc)
292 if err == nil {
293 t.Errorf("%v:\nunmarshalTransportParams(%x): unexpectedly succeeded", test.desc, test.enc)
294 }
295 }
296 }
297
298 func TestTransportParametersRangeErrors(t *testing.T) {
299 for _, test := range []struct {
300 desc string
301 params func(p *transportParameters)
302 }{{
303 desc: "max_udp_payload_size < 1200",
304 params: func(p *transportParameters) {
305 p.maxUDPPayloadSize = 1199
306 },
307 }, {
308 desc: "ack_delay_exponent > 20",
309 params: func(p *transportParameters) {
310 p.ackDelayExponent = 21
311 },
312 }, {
313 desc: "max_ack_delay > 1^14 ms",
314 params: func(p *transportParameters) {
315 p.maxAckDelay = (1 << 14) * time.Millisecond
316 },
317 }, {
318 desc: "active_connection_id_limit < 2",
319 params: func(p *transportParameters) {
320 p.activeConnIDLimit = 1
321 },
322 }} {
323 p := defaultTransportParameters()
324 test.params(&p)
325 enc := marshalTransportParameters(p)
326 _, err := unmarshalTransportParams(enc)
327 if err == nil {
328 t.Errorf("%v: unmarshalTransportParams unexpectedly succeeded", test.desc)
329 }
330 }
331 }
332
333 func TestTransportParameterMaxIdleTimeoutOverflowsDuration(t *testing.T) {
334 tooManyMS := 1 + (math.MaxInt64 / uint64(time.Millisecond))
335
336 var enc []byte
337 enc = appendVarint(enc, paramMaxIdleTimeout)
338 enc = appendVarint(enc, uint64(sizeVarint(tooManyMS)))
339 enc = appendVarint(enc, uint64(tooManyMS))
340
341 dec, err := unmarshalTransportParams(enc)
342 if err != nil {
343 t.Fatalf("unmarshalTransportParameters(enc) = %v", err)
344 }
345 if got, want := dec.maxIdleTimeout, time.Duration(0); got != want {
346 t.Errorf("max_idle_timeout=%v, got maxIdleTimeout=%v; want %v", tooManyMS, got, want)
347 }
348 }
349
350 func TestTransportParametersSkipUnknownParameters(t *testing.T) {
351 enc := []byte{
352 0x20,
353 1,
354 0,
355
356 0x04,
357 1,
358 10,
359
360 0x21,
361 1,
362 0,
363 }
364 dec, err := unmarshalTransportParams(enc)
365 if err != nil {
366 t.Fatalf("unmarshalTransportParameters(enc) = %v", err)
367 }
368 if got, want := dec.initialMaxData, int64(10); got != want {
369 t.Errorf("got initial_max_data=%v; want %v", got, want)
370 }
371 }
372
373 func FuzzTransportParametersMarshalUnmarshal(f *testing.F) {
374 f.Fuzz(func(t *testing.T, in []byte) {
375 p1, err := unmarshalTransportParams(in)
376 if err != nil {
377 return
378 }
379 out := marshalTransportParameters(p1)
380 p2, err := unmarshalTransportParams(out)
381 if err != nil {
382 t.Fatalf("round trip unmarshal/remarshal: unmarshal error: %v\n%x", err, in)
383 }
384 if !reflect.DeepEqual(p1, p2) {
385 t.Fatalf("round trip unmarshal/remarshal: parameters differ:\n%x\n%#v\n%#v", in, p1, p2)
386 }
387 })
388 }
389
View as plain text