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