@@ -25,6 +25,41 @@ use crate::{
25
25
RESET_TOKEN_SIZE , TIMER_GRANULARITY ,
26
26
} ;
27
27
28
+ #[ repr( u32 ) ]
29
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
30
+ pub ( crate ) enum TransportParameterId {
31
+ // https://www.rfc-editor.org/rfc/rfc9000.html#iana-tp-table
32
+ OriginalDestinationConnectionId = 0x00 ,
33
+ MaxIdleTimeout = 0x01 ,
34
+ StatelessResetToken = 0x02 ,
35
+ MaxUdpPayloadSize = 0x03 ,
36
+ InitialMaxData = 0x04 ,
37
+ InitialMaxStreamDataBidiLocal = 0x05 ,
38
+ InitialMaxStreamDataBidiRemote = 0x06 ,
39
+ InitialMaxStreamDataUni = 0x07 ,
40
+ InitialMaxStreamsBidi = 0x08 ,
41
+ InitialMaxStreamsUni = 0x09 ,
42
+ AckDelayExponent = 0x0A ,
43
+ MaxAckDelay = 0x0B ,
44
+ DisableActiveMigration = 0x0C ,
45
+ PreferredAddress = 0x0D ,
46
+ ActiveConnectionIdLimit = 0x0E ,
47
+ InitialSourceConnectionId = 0x0F ,
48
+ RetrySourceConnectionId = 0x10 ,
49
+
50
+ // Smallest possible ID of reserved transport parameter https://datatracker.ietf.org/doc/html/rfc9000#section-22.3
51
+ ReservedTransportParameter = 0x1B ,
52
+
53
+ // https://www.rfc-editor.org/rfc/rfc9221.html#section-3
54
+ MaxDatagramFrameSize = 0x20 ,
55
+
56
+ // https://www.rfc-editor.org/rfc/rfc9287.html#section-3
57
+ GreaseQuicBit = 0x2AB2 ,
58
+
59
+ // https://datatracker.ietf.org/doc/html/draft-ietf-quic-ack-frequency#section-10.1
60
+ MinAckDelayDraft07 = 0xFF04DE1B ,
61
+ }
62
+
28
63
// Apply a given macro to a list of all the transport parameters having integer types, along with
29
64
// their codes and default values. Using this helps us avoid error-prone duplication of the
30
65
// contained information across decoding, encoding, and the `Default` impl. Whenever we want to do
@@ -35,42 +70,61 @@ macro_rules! apply_params {
35
70
$macro! {
36
71
// #[doc] name (id) = default,
37
72
/// Milliseconds, disabled if zero
38
- max_idle_timeout( 0x0001 ) = 0 ,
73
+ max_idle_timeout( MaxIdleTimeout ) = 0 ,
39
74
/// Limits the size of UDP payloads that the endpoint is willing to receive
40
- max_udp_payload_size( 0x0003 ) = 65527 ,
75
+ max_udp_payload_size( MaxUdpPayloadSize ) = 65527 ,
41
76
42
77
/// Initial value for the maximum amount of data that can be sent on the connection
43
- initial_max_data( 0x0004 ) = 0 ,
78
+ initial_max_data( InitialMaxData ) = 0 ,
44
79
/// Initial flow control limit for locally-initiated bidirectional streams
45
- initial_max_stream_data_bidi_local( 0x0005 ) = 0 ,
80
+ initial_max_stream_data_bidi_local( InitialMaxStreamDataBidiLocal ) = 0 ,
46
81
/// Initial flow control limit for peer-initiated bidirectional streams
47
- initial_max_stream_data_bidi_remote( 0x0006 ) = 0 ,
82
+ initial_max_stream_data_bidi_remote( InitialMaxStreamDataBidiRemote ) = 0 ,
48
83
/// Initial flow control limit for unidirectional streams
49
- initial_max_stream_data_uni( 0x0007 ) = 0 ,
84
+ initial_max_stream_data_uni( InitialMaxStreamDataUni ) = 0 ,
50
85
51
86
/// Initial maximum number of bidirectional streams the peer may initiate
52
- initial_max_streams_bidi( 0x0008 ) = 0 ,
87
+ initial_max_streams_bidi( InitialMaxStreamsBidi ) = 0 ,
53
88
/// Initial maximum number of unidirectional streams the peer may initiate
54
- initial_max_streams_uni( 0x0009 ) = 0 ,
89
+ initial_max_streams_uni( InitialMaxStreamsUni ) = 0 ,
55
90
56
91
/// Exponent used to decode the ACK Delay field in the ACK frame
57
- ack_delay_exponent( 0x000a ) = 3 ,
92
+ ack_delay_exponent( AckDelayExponent ) = 3 ,
58
93
/// Maximum amount of time in milliseconds by which the endpoint will delay sending
59
94
/// acknowledgments
60
- max_ack_delay( 0x000b ) = 25 ,
95
+ max_ack_delay( MaxAckDelay ) = 25 ,
61
96
/// Maximum number of connection IDs from the peer that an endpoint is willing to store
62
- active_connection_id_limit( 0x000e ) = 2 ,
97
+ active_connection_id_limit( ActiveConnectionIdLimit ) = 2 ,
63
98
}
64
99
} ;
65
100
}
66
101
67
- const DEFAULT_TRANSPORT_PARAMETERS_ORDER : [ u32 ; 21 ] = [
68
- 0x0001 , 0x0003 , 0x0004 , 0x0005 , 0x0006 , 0x0007 , 0x0008 , 0x0009 , 0x000a , 0x000b , 0x000e , 27 ,
69
- 0x02 , 0x0c , 0x20 , 0x000d , 0x00 , 0x0f , 0x10 , 0x2ab2 , 0xff04de1b ,
102
+ const DEFAULT_TRANSPORT_PARAMETERS_ORDER : [ TransportParameterId ; 21 ] = [
103
+ TransportParameterId :: MaxIdleTimeout ,
104
+ TransportParameterId :: MaxUdpPayloadSize ,
105
+ TransportParameterId :: InitialMaxData ,
106
+ TransportParameterId :: InitialMaxStreamDataBidiLocal ,
107
+ TransportParameterId :: InitialMaxStreamDataBidiRemote ,
108
+ TransportParameterId :: InitialMaxStreamDataUni ,
109
+ TransportParameterId :: InitialMaxStreamsBidi ,
110
+ TransportParameterId :: InitialMaxStreamsUni ,
111
+ TransportParameterId :: AckDelayExponent ,
112
+ TransportParameterId :: MaxAckDelay ,
113
+ TransportParameterId :: ActiveConnectionIdLimit ,
114
+ TransportParameterId :: ReservedTransportParameter ,
115
+ TransportParameterId :: StatelessResetToken ,
116
+ TransportParameterId :: DisableActiveMigration ,
117
+ TransportParameterId :: MaxDatagramFrameSize ,
118
+ TransportParameterId :: PreferredAddress ,
119
+ TransportParameterId :: OriginalDestinationConnectionId ,
120
+ TransportParameterId :: InitialSourceConnectionId ,
121
+ TransportParameterId :: RetrySourceConnectionId ,
122
+ TransportParameterId :: GreaseQuicBit ,
123
+ TransportParameterId :: MinAckDelayDraft07 ,
70
124
] ;
71
125
72
126
macro_rules! make_struct {
73
- { $( $( #[ $doc: meta] ) * $name: ident ( $code : expr ) = $default: expr, ) * } => {
127
+ { $( $( #[ $doc: meta] ) * $name: ident ( $id : ident ) = $default: expr, ) * } => {
74
128
/// Transport parameters used to negotiate connection-level preferences between peers
75
129
#[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
76
130
pub struct TransportParameters {
@@ -111,7 +165,7 @@ macro_rules! make_struct {
111
165
pub ( crate ) grease_transport_parameter: Option <ReservedTransportParameter >,
112
166
113
167
/// The order in which transport parameters are serialized
114
- pub ( crate ) write_order: Option <[ u32 ; 21 ] >,
168
+ pub ( crate ) write_order: Option <[ TransportParameterId ; 21 ] >,
115
169
}
116
170
117
171
// We deliberately don't implement the `Default` trait, since that would be public, and
@@ -309,91 +363,91 @@ impl From<UnexpectedEnd> for Error {
309
363
impl TransportParameters {
310
364
/// Encode `TransportParameters` into buffer
311
365
pub fn write < W : BufMut > ( & self , w : & mut W ) {
312
- for id in self
366
+ for & id in self
313
367
. write_order
314
368
. as_ref ( )
315
369
. unwrap_or ( & DEFAULT_TRANSPORT_PARAMETERS_ORDER )
316
370
{
317
371
match id {
318
- 27 => {
372
+ TransportParameterId :: ReservedTransportParameter => {
319
373
if let Some ( param) = self . grease_transport_parameter {
320
374
param. write ( w) ;
321
375
}
322
376
}
323
- 0x02 => {
377
+ TransportParameterId :: StatelessResetToken => {
324
378
if let Some ( ref x) = self . stateless_reset_token {
325
- w. write_var ( 0x02 ) ;
379
+ w. write_var ( id as u64 ) ;
326
380
w. write_var ( 16 ) ;
327
381
w. put_slice ( x) ;
328
382
}
329
383
}
330
- 0x0c => {
384
+ TransportParameterId :: DisableActiveMigration => {
331
385
if self . disable_active_migration {
332
- w. write_var ( 0x0c ) ;
386
+ w. write_var ( id as u64 ) ;
333
387
w. write_var ( 0 ) ;
334
388
}
335
389
}
336
- 0x20 => {
390
+ TransportParameterId :: MaxDatagramFrameSize => {
337
391
if let Some ( x) = self . max_datagram_frame_size {
338
- w. write_var ( 0x20 ) ;
392
+ w. write_var ( id as u64 ) ;
339
393
w. write_var ( x. size ( ) as u64 ) ;
340
394
w. write ( x) ;
341
395
}
342
396
}
343
- 0x0d => {
397
+ TransportParameterId :: PreferredAddress => {
344
398
if let Some ( ref x) = self . preferred_address {
345
- w. write_var ( 0x000d ) ;
399
+ w. write_var ( id as u64 ) ;
346
400
w. write_var ( x. wire_size ( ) as u64 ) ;
347
401
x. write ( w) ;
348
402
}
349
403
}
350
- 0x00 => {
404
+ TransportParameterId :: OriginalDestinationConnectionId => {
351
405
if let Some ( ref cid) = self . original_dst_cid {
352
- w. write_var ( 0x00 ) ;
406
+ w. write_var ( id as u64 ) ;
353
407
w. write_var ( cid. len ( ) as u64 ) ;
354
408
w. put_slice ( cid) ;
355
409
}
356
410
}
357
- 0x0f => {
411
+ TransportParameterId :: InitialSourceConnectionId => {
358
412
if let Some ( ref cid) = self . initial_src_cid {
359
- w. write_var ( 0x0f ) ;
413
+ w. write_var ( id as u64 ) ;
360
414
w. write_var ( cid. len ( ) as u64 ) ;
361
415
w. put_slice ( cid) ;
362
416
}
363
417
}
364
- 0x10 => {
418
+ TransportParameterId :: RetrySourceConnectionId => {
365
419
if let Some ( ref cid) = self . retry_src_cid {
366
- w. write_var ( 0x10 ) ;
420
+ w. write_var ( id as u64 ) ;
367
421
w. write_var ( cid. len ( ) as u64 ) ;
368
422
w. put_slice ( cid) ;
369
423
}
370
424
}
371
- 0x2ab2 => {
425
+ TransportParameterId :: GreaseQuicBit => {
372
426
if self . grease_quic_bit {
373
- w. write_var ( 0x2ab2 ) ;
427
+ w. write_var ( id as u64 ) ;
374
428
w. write_var ( 0 ) ;
375
429
}
376
430
}
377
- 0xff04de1b => {
431
+ TransportParameterId :: MinAckDelayDraft07 => {
378
432
if let Some ( x) = self . min_ack_delay {
379
- w. write_var ( 0xff04de1b ) ;
433
+ w. write_var ( id as u64 ) ;
380
434
w. write_var ( x. size ( ) as u64 ) ;
381
435
w. write ( x) ;
382
436
}
383
437
}
384
438
id => {
385
439
macro_rules! write_params {
386
- { $( $( #[ $doc: meta] ) * $name: ident ( $code : expr ) = $default: expr, ) * } => {
440
+ { $( $( #[ $doc: meta] ) * $name: ident ( $id : ident ) = $default: expr, ) * } => {
387
441
match id {
388
- $( $code => {
442
+ $( TransportParameterId :: $id => {
389
443
if self . $name. 0 != $default {
390
- w. write_var( $code ) ;
444
+ w. write_var( id as u64 ) ;
391
445
w. write( VarInt :: try_from( self . $name. size( ) ) . unwrap( ) ) ;
392
446
w. write( self . $name) ;
393
447
}
394
448
} ) * ,
395
449
_ => {
396
- unreachable !( "Missing implementation of write for transport parameter with code {id:X }" ) ;
450
+ unimplemented !( "Missing implementation of write for transport parameter with code {id:? }" ) ;
397
451
}
398
452
}
399
453
}
@@ -411,7 +465,7 @@ impl TransportParameters {
411
465
412
466
// State to check for duplicate transport parameters.
413
467
macro_rules! param_state {
414
- { $( $( #[ $doc: meta] ) * $name: ident ( $code : expr ) = $default: expr, ) * } => { {
468
+ { $( $( #[ $doc: meta] ) * $name: ident ( $id : ident ) = $default: expr, ) * } => { {
415
469
struct ParamState {
416
470
$( $name: bool , ) *
417
471
}
@@ -432,45 +486,53 @@ impl TransportParameters {
432
486
let len = len as usize ;
433
487
434
488
match id {
435
- 0x00 => decode_cid ( len, & mut params. original_dst_cid , r) ?,
436
- 0x02 => {
489
+ id if id == TransportParameterId :: OriginalDestinationConnectionId as u64 => {
490
+ decode_cid ( len, & mut params. original_dst_cid , r) ?
491
+ }
492
+ id if id == TransportParameterId :: StatelessResetToken as u64 => {
437
493
if len != 16 || params. stateless_reset_token . is_some ( ) {
438
494
return Err ( Error :: Malformed ) ;
439
495
}
440
496
let mut tok = [ 0 ; RESET_TOKEN_SIZE ] ;
441
497
r. copy_to_slice ( & mut tok) ;
442
498
params. stateless_reset_token = Some ( tok. into ( ) ) ;
443
499
}
444
- 0x0c => {
500
+ id if id == TransportParameterId :: DisableActiveMigration as u64 => {
445
501
if len != 0 || params. disable_active_migration {
446
502
return Err ( Error :: Malformed ) ;
447
503
}
448
504
params. disable_active_migration = true ;
449
505
}
450
- 0x0d => {
506
+ id if id == TransportParameterId :: PreferredAddress as u64 => {
451
507
if params. preferred_address . is_some ( ) {
452
508
return Err ( Error :: Malformed ) ;
453
509
}
454
510
params. preferred_address = Some ( PreferredAddress :: read ( & mut r. take ( len) ) ?) ;
455
511
}
456
- 0x0f => decode_cid ( len, & mut params. initial_src_cid , r) ?,
457
- 0x10 => decode_cid ( len, & mut params. retry_src_cid , r) ?,
458
- 0x20 => {
512
+ id if id == TransportParameterId :: InitialSourceConnectionId as u64 => {
513
+ decode_cid ( len, & mut params. initial_src_cid , r) ?
514
+ }
515
+ id if id == TransportParameterId :: RetrySourceConnectionId as u64 => {
516
+ decode_cid ( len, & mut params. retry_src_cid , r) ?
517
+ }
518
+ id if id == TransportParameterId :: MaxDatagramFrameSize as u64 => {
459
519
if len > 8 || params. max_datagram_frame_size . is_some ( ) {
460
520
return Err ( Error :: Malformed ) ;
461
521
}
462
522
params. max_datagram_frame_size = Some ( r. get ( ) . unwrap ( ) ) ;
463
523
}
464
- 0x2ab2 => match len {
524
+ id if id == TransportParameterId :: GreaseQuicBit as u64 => match len {
465
525
0 => params. grease_quic_bit = true ,
466
526
_ => return Err ( Error :: Malformed ) ,
467
527
} ,
468
- 0xff04de1b => params. min_ack_delay = Some ( r. get ( ) . unwrap ( ) ) ,
528
+ id if id == TransportParameterId :: MinAckDelayDraft07 as u64 => {
529
+ params. min_ack_delay = Some ( r. get ( ) . unwrap ( ) )
530
+ }
469
531
_ => {
470
532
macro_rules! parse {
471
- { $( $( #[ $doc: meta] ) * $name: ident ( $code : expr ) = $default: expr, ) * } => {
533
+ { $( $( #[ $doc: meta] ) * $name: ident ( $id : ident ) = $default: expr, ) * } => {
472
534
match id {
473
- $( $code => {
535
+ $( id if TransportParameterId :: $id as u64 == id => {
474
536
let value = r. get:: <VarInt >( ) ?;
475
537
if len != value. size( ) || got. $name { return Err ( Error :: Malformed ) ; }
476
538
params. $name = value. into( ) ;
0 commit comments