1use std::collections::HashSet;
31use std::mem::size_of;
32
33use crate::ConnectionId;
34use crate::Error;
35use crate::Result;
36use crate::MAX_STREAM_ID;
37
38#[cfg(feature = "qlog")]
39use crate::crypto;
40#[cfg(feature = "qlog")]
41use qlog::events::quic::TransportInitiator;
42#[cfg(feature = "qlog")]
43use qlog::events::EventData;
44
45pub const MAX_ACK_DELAY_EXPONENT: u64 = 20;
48
49#[derive(Clone, Debug, PartialEq)]
54pub struct UnknownTransportParameter<T> {
55 pub id: u64,
57
58 pub value: T,
60}
61
62impl<T> UnknownTransportParameter<T> {
63 pub fn is_reserved(&self) -> bool {
68 let n = (self.id - 27) / 31;
69 self.id == 31 * n + 27
70 }
71}
72
73#[cfg(feature = "qlog")]
74impl From<UnknownTransportParameter<Vec<u8>>>
75 for qlog::events::quic::UnknownTransportParameter
76{
77 fn from(value: UnknownTransportParameter<Vec<u8>>) -> Self {
78 Self {
79 id: value.id,
80 value: qlog::HexSlice::maybe_string(Some(value.value.as_slice()))
81 .unwrap_or_default(),
82 }
83 }
84}
85
86impl From<UnknownTransportParameter<&[u8]>>
87 for UnknownTransportParameter<Vec<u8>>
88{
89 fn from(value: UnknownTransportParameter<&[u8]>) -> Self {
94 Self {
95 id: value.id,
96 value: value.value.to_vec(),
97 }
98 }
99}
100
101#[derive(Clone, Debug, PartialEq, Default)]
103pub struct UnknownTransportParameters {
104 pub capacity: usize,
106 pub parameters: Vec<UnknownTransportParameter<Vec<u8>>>,
108}
109
110impl UnknownTransportParameters {
111 pub fn push(&mut self, new: UnknownTransportParameter<&[u8]>) -> Result<()> {
114 let new_unknown_tp_size = new.value.len() + size_of::<u64>();
115 if new_unknown_tp_size < self.capacity {
116 self.capacity -= new_unknown_tp_size;
117 self.parameters.push(new.into());
118 Ok(())
119 } else {
120 Err(octets::BufferTooShortError.into())
121 }
122 }
123}
124
125pub struct UnknownTransportParameterIterator<'a> {
127 index: usize,
128 parameters: &'a Vec<UnknownTransportParameter<Vec<u8>>>,
129}
130
131impl<'a> IntoIterator for &'a UnknownTransportParameters {
132 type IntoIter = UnknownTransportParameterIterator<'a>;
133 type Item = &'a UnknownTransportParameter<Vec<u8>>;
134
135 fn into_iter(self) -> Self::IntoIter {
136 UnknownTransportParameterIterator {
137 index: 0,
138 parameters: &self.parameters,
139 }
140 }
141}
142
143impl<'a> Iterator for UnknownTransportParameterIterator<'a> {
144 type Item = &'a UnknownTransportParameter<Vec<u8>>;
145
146 fn next(&mut self) -> Option<Self::Item> {
147 let result = self.parameters.get(self.index);
148 self.index += 1;
149 result
150 }
151}
152
153#[derive(Clone, Debug, PartialEq)]
155pub struct TransportParams {
156 pub original_destination_connection_id: Option<ConnectionId<'static>>,
158 pub max_idle_timeout: u64,
160 pub stateless_reset_token: Option<u128>,
162 pub max_udp_payload_size: u64,
164 pub initial_max_data: u64,
166 pub initial_max_stream_data_bidi_local: u64,
168 pub initial_max_stream_data_bidi_remote: u64,
170 pub initial_max_stream_data_uni: u64,
172 pub initial_max_streams_bidi: u64,
174 pub initial_max_streams_uni: u64,
176 pub ack_delay_exponent: u64,
178 pub max_ack_delay: u64,
180 pub disable_active_migration: bool,
182 pub active_conn_id_limit: u64,
184 pub initial_source_connection_id: Option<ConnectionId<'static>>,
187 pub retry_source_connection_id: Option<ConnectionId<'static>>,
190 pub max_datagram_frame_size: Option<u64>,
192 pub unknown_params: Option<UnknownTransportParameters>,
194 }
196
197impl Default for TransportParams {
198 fn default() -> TransportParams {
199 TransportParams {
200 original_destination_connection_id: None,
201 max_idle_timeout: 0,
202 stateless_reset_token: None,
203 max_udp_payload_size: 65527,
204 initial_max_data: 0,
205 initial_max_stream_data_bidi_local: 0,
206 initial_max_stream_data_bidi_remote: 0,
207 initial_max_stream_data_uni: 0,
208 initial_max_streams_bidi: 0,
209 initial_max_streams_uni: 0,
210 ack_delay_exponent: 3,
211 max_ack_delay: 25,
212 disable_active_migration: false,
213 active_conn_id_limit: 2,
214 initial_source_connection_id: None,
215 retry_source_connection_id: None,
216 max_datagram_frame_size: None,
217 unknown_params: Default::default(),
218 }
219 }
220}
221
222impl TransportParams {
223 pub(crate) fn decode(
224 buf: &[u8], is_server: bool, unknown_size: Option<usize>,
225 ) -> Result<TransportParams> {
226 let mut params = octets::Octets::with_slice(buf);
227 let mut seen_params = HashSet::new();
228
229 let mut tp = TransportParams::default();
230
231 if let Some(unknown_transport_param_tracking_size) = unknown_size {
232 tp.unknown_params = Some(UnknownTransportParameters {
233 capacity: unknown_transport_param_tracking_size,
234 parameters: vec![],
235 });
236 }
237
238 while params.cap() > 0 {
239 let id = params.get_varint()?;
240
241 if seen_params.contains(&id) {
242 return Err(Error::InvalidTransportParam);
243 }
244 seen_params.insert(id);
245
246 let mut val = params.get_bytes_with_varint_length()?;
247
248 match id {
249 0x0000 => {
250 if is_server {
251 return Err(Error::InvalidTransportParam);
252 }
253
254 tp.original_destination_connection_id =
255 Some(val.to_vec().into());
256 },
257
258 0x0001 => {
259 tp.max_idle_timeout = val.get_varint()?;
260 },
261
262 0x0002 => {
263 if is_server {
264 return Err(Error::InvalidTransportParam);
265 }
266
267 tp.stateless_reset_token = Some(u128::from_be_bytes(
268 val.get_bytes(16)?
269 .to_vec()
270 .try_into()
271 .map_err(|_| Error::BufferTooShort)?,
272 ));
273 },
274
275 0x0003 => {
276 tp.max_udp_payload_size = val.get_varint()?;
277
278 if tp.max_udp_payload_size < 1200 {
279 return Err(Error::InvalidTransportParam);
280 }
281 },
282
283 0x0004 => {
284 tp.initial_max_data = val.get_varint()?;
285 },
286
287 0x0005 => {
288 tp.initial_max_stream_data_bidi_local = val.get_varint()?;
289 },
290
291 0x0006 => {
292 tp.initial_max_stream_data_bidi_remote = val.get_varint()?;
293 },
294
295 0x0007 => {
296 tp.initial_max_stream_data_uni = val.get_varint()?;
297 },
298
299 0x0008 => {
300 let max = val.get_varint()?;
301
302 if max > MAX_STREAM_ID {
303 return Err(Error::InvalidTransportParam);
304 }
305
306 tp.initial_max_streams_bidi = max;
307 },
308
309 0x0009 => {
310 let max = val.get_varint()?;
311
312 if max > MAX_STREAM_ID {
313 return Err(Error::InvalidTransportParam);
314 }
315
316 tp.initial_max_streams_uni = max;
317 },
318
319 0x000a => {
320 let ack_delay_exponent = val.get_varint()?;
321
322 if ack_delay_exponent > MAX_ACK_DELAY_EXPONENT {
323 return Err(Error::InvalidTransportParam);
324 }
325
326 tp.ack_delay_exponent = ack_delay_exponent;
327 },
328
329 0x000b => {
330 let max_ack_delay = val.get_varint()?;
331
332 if max_ack_delay >= 2_u64.pow(14) {
333 return Err(Error::InvalidTransportParam);
334 }
335
336 tp.max_ack_delay = max_ack_delay;
337 },
338
339 0x000c => {
340 tp.disable_active_migration = true;
341 },
342
343 0x000d => {
344 if is_server {
345 return Err(Error::InvalidTransportParam);
346 }
347
348 },
350
351 0x000e => {
352 let limit = val.get_varint()?;
353
354 if limit < 2 {
355 return Err(Error::InvalidTransportParam);
356 }
357
358 tp.active_conn_id_limit = limit;
359 },
360
361 0x000f => {
362 tp.initial_source_connection_id = Some(val.to_vec().into());
363 },
364
365 0x00010 => {
366 if is_server {
367 return Err(Error::InvalidTransportParam);
368 }
369
370 tp.retry_source_connection_id = Some(val.to_vec().into());
371 },
372
373 0x0020 => {
374 tp.max_datagram_frame_size = Some(val.get_varint()?);
375 },
376
377 unknown_tp_id => {
379 if let Some(unknown_params) = &mut tp.unknown_params {
380 let _ = unknown_params.push(UnknownTransportParameter {
383 id: unknown_tp_id,
384 value: val.buf(),
385 });
386 }
387 },
388 }
389 }
390
391 Ok(tp)
392 }
393
394 pub(crate) fn encode_param(
395 b: &mut octets::OctetsMut, ty: u64, len: usize,
396 ) -> Result<()> {
397 b.put_varint(ty)?;
398 b.put_varint(len as u64)?;
399
400 Ok(())
401 }
402
403 pub(crate) fn encode<'a>(
404 tp: &TransportParams, is_server: bool, out: &'a mut [u8],
405 ) -> Result<&'a mut [u8]> {
406 let mut b = octets::OctetsMut::with_slice(out);
407
408 if is_server {
409 if let Some(ref odcid) = tp.original_destination_connection_id {
410 TransportParams::encode_param(&mut b, 0x0000, odcid.len())?;
411 b.put_bytes(odcid)?;
412 }
413 };
414
415 if tp.max_idle_timeout != 0 {
416 assert!(tp.max_idle_timeout <= octets::MAX_VAR_INT);
417 TransportParams::encode_param(
418 &mut b,
419 0x0001,
420 octets::varint_len(tp.max_idle_timeout),
421 )?;
422 b.put_varint(tp.max_idle_timeout)?;
423 }
424
425 if is_server {
426 if let Some(ref token) = tp.stateless_reset_token {
427 TransportParams::encode_param(&mut b, 0x0002, 16)?;
428 b.put_bytes(&token.to_be_bytes())?;
429 }
430 }
431
432 if tp.max_udp_payload_size != 0 {
433 assert!(tp.max_udp_payload_size <= octets::MAX_VAR_INT);
434 TransportParams::encode_param(
435 &mut b,
436 0x0003,
437 octets::varint_len(tp.max_udp_payload_size),
438 )?;
439 b.put_varint(tp.max_udp_payload_size)?;
440 }
441
442 if tp.initial_max_data != 0 {
443 assert!(tp.initial_max_data <= octets::MAX_VAR_INT);
444 TransportParams::encode_param(
445 &mut b,
446 0x0004,
447 octets::varint_len(tp.initial_max_data),
448 )?;
449 b.put_varint(tp.initial_max_data)?;
450 }
451
452 if tp.initial_max_stream_data_bidi_local != 0 {
453 assert!(tp.initial_max_stream_data_bidi_local <= octets::MAX_VAR_INT);
454 TransportParams::encode_param(
455 &mut b,
456 0x0005,
457 octets::varint_len(tp.initial_max_stream_data_bidi_local),
458 )?;
459 b.put_varint(tp.initial_max_stream_data_bidi_local)?;
460 }
461
462 if tp.initial_max_stream_data_bidi_remote != 0 {
463 assert!(
464 tp.initial_max_stream_data_bidi_remote <= octets::MAX_VAR_INT
465 );
466 TransportParams::encode_param(
467 &mut b,
468 0x0006,
469 octets::varint_len(tp.initial_max_stream_data_bidi_remote),
470 )?;
471 b.put_varint(tp.initial_max_stream_data_bidi_remote)?;
472 }
473
474 if tp.initial_max_stream_data_uni != 0 {
475 assert!(tp.initial_max_stream_data_uni <= octets::MAX_VAR_INT);
476 TransportParams::encode_param(
477 &mut b,
478 0x0007,
479 octets::varint_len(tp.initial_max_stream_data_uni),
480 )?;
481 b.put_varint(tp.initial_max_stream_data_uni)?;
482 }
483
484 if tp.initial_max_streams_bidi != 0 {
485 assert!(tp.initial_max_streams_bidi <= octets::MAX_VAR_INT);
486 TransportParams::encode_param(
487 &mut b,
488 0x0008,
489 octets::varint_len(tp.initial_max_streams_bidi),
490 )?;
491 b.put_varint(tp.initial_max_streams_bidi)?;
492 }
493
494 if tp.initial_max_streams_uni != 0 {
495 assert!(tp.initial_max_streams_uni <= octets::MAX_VAR_INT);
496 TransportParams::encode_param(
497 &mut b,
498 0x0009,
499 octets::varint_len(tp.initial_max_streams_uni),
500 )?;
501 b.put_varint(tp.initial_max_streams_uni)?;
502 }
503
504 if tp.ack_delay_exponent != 0 {
505 assert!(tp.ack_delay_exponent <= MAX_ACK_DELAY_EXPONENT);
506 TransportParams::encode_param(
507 &mut b,
508 0x000a,
509 octets::varint_len(tp.ack_delay_exponent),
510 )?;
511 b.put_varint(tp.ack_delay_exponent)?;
512 }
513
514 if tp.max_ack_delay != 0 {
515 assert!(tp.max_ack_delay <= octets::MAX_VAR_INT);
516 TransportParams::encode_param(
517 &mut b,
518 0x000b,
519 octets::varint_len(tp.max_ack_delay),
520 )?;
521 b.put_varint(tp.max_ack_delay)?;
522 }
523
524 if tp.disable_active_migration {
525 TransportParams::encode_param(&mut b, 0x000c, 0)?;
526 }
527
528 if tp.active_conn_id_limit != 2 {
531 assert!(tp.active_conn_id_limit <= octets::MAX_VAR_INT);
532 TransportParams::encode_param(
533 &mut b,
534 0x000e,
535 octets::varint_len(tp.active_conn_id_limit),
536 )?;
537 b.put_varint(tp.active_conn_id_limit)?;
538 }
539
540 if let Some(scid) = &tp.initial_source_connection_id {
541 TransportParams::encode_param(&mut b, 0x000f, scid.len())?;
542 b.put_bytes(scid)?;
543 }
544
545 if is_server {
546 if let Some(scid) = &tp.retry_source_connection_id {
547 TransportParams::encode_param(&mut b, 0x0010, scid.len())?;
548 b.put_bytes(scid)?;
549 }
550 }
551
552 if let Some(max_datagram_frame_size) = tp.max_datagram_frame_size {
553 assert!(max_datagram_frame_size <= octets::MAX_VAR_INT);
554 TransportParams::encode_param(
555 &mut b,
556 0x0020,
557 octets::varint_len(max_datagram_frame_size),
558 )?;
559 b.put_varint(max_datagram_frame_size)?;
560 }
561
562 let out_len = b.off();
563
564 Ok(&mut out[..out_len])
565 }
566
567 #[cfg(feature = "qlog")]
569 pub fn to_qlog(
570 &self, initiator: TransportInitiator, cipher: Option<crypto::Algorithm>,
571 ) -> EventData {
572 let original_destination_connection_id = qlog::HexSlice::maybe_string(
573 self.original_destination_connection_id.as_ref(),
574 );
575
576 let stateless_reset_token = qlog::HexSlice::maybe_string(
577 self.stateless_reset_token.map(|s| s.to_be_bytes()).as_ref(),
578 );
579
580 let tls_cipher: Option<String> = cipher.map(|f| format!("{f:?}"));
581
582 EventData::QuicParametersSet(Box::new(
583 qlog::events::quic::ParametersSet {
584 initiator: Some(initiator),
585 tls_cipher,
586 original_destination_connection_id,
587 stateless_reset_token,
588 disable_active_migration: Some(self.disable_active_migration),
589 max_idle_timeout: Some(self.max_idle_timeout),
590 max_udp_payload_size: Some(self.max_udp_payload_size),
591 ack_delay_exponent: Some(self.ack_delay_exponent),
592 max_ack_delay: Some(self.max_ack_delay),
593 active_connection_id_limit: Some(self.active_conn_id_limit),
594
595 initial_max_data: Some(self.initial_max_data),
596 initial_max_stream_data_bidi_local: Some(
597 self.initial_max_stream_data_bidi_local,
598 ),
599 initial_max_stream_data_bidi_remote: Some(
600 self.initial_max_stream_data_bidi_remote,
601 ),
602 initial_max_stream_data_uni: Some(
603 self.initial_max_stream_data_uni,
604 ),
605 initial_max_streams_bidi: Some(self.initial_max_streams_bidi),
606 initial_max_streams_uni: Some(self.initial_max_streams_uni),
607
608 unknown_parameters: self
609 .unknown_params
610 .as_ref()
611 .map(|unknown_params| {
612 unknown_params
613 .into_iter()
614 .cloned()
615 .map(
616 Into::<
617 qlog::events::quic::UnknownTransportParameter,
618 >::into,
619 )
620 .collect()
621 })
622 .unwrap_or_default(),
623
624 ..Default::default()
625 },
626 ))
627 }
628}