net_wire/quic/transport_parameters/
mod.rs1mod semantic;
4mod value;
5
6use core::{fmt, iter::FusedIterator};
7
8use super::varint::{QuicVarInt, QuicVarIntParseError};
9#[cfg(feature = "tls")]
10use crate::tls::extensions::extension::TlsExtension;
11#[cfg(feature = "tls")]
12use crate::tls::types::TlsExtensionType;
13
14pub use semantic::{
15 QuicTransportParameterHandshakeContext, QuicTransportParameterHandshakeError,
16 QuicTransportParameterSemanticError, QuicTransportParameterSender, QuicTransportParametersV1,
17};
18pub use value::{
19 QuicPreferredAddress, QuicTransportParameterValueError, QuicTransportParameterValueKind,
20};
21
22#[repr(transparent)]
24#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
25pub struct QuicTransportParameterId(u64);
26
27impl QuicTransportParameterId {
28 pub const ORIGINAL_DESTINATION_CONNECTION_ID: Self = Self(0x00);
30 pub const MAX_IDLE_TIMEOUT: Self = Self(0x01);
32 pub const STATELESS_RESET_TOKEN: Self = Self(0x02);
34 pub const MAX_UDP_PAYLOAD_SIZE: Self = Self(0x03);
36 pub const INITIAL_MAX_DATA: Self = Self(0x04);
38 pub const INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: Self = Self(0x05);
40 pub const INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: Self = Self(0x06);
42 pub const INITIAL_MAX_STREAM_DATA_UNI: Self = Self(0x07);
44 pub const INITIAL_MAX_STREAMS_BIDI: Self = Self(0x08);
46 pub const INITIAL_MAX_STREAMS_UNI: Self = Self(0x09);
48 pub const ACK_DELAY_EXPONENT: Self = Self(0x0a);
50 pub const MAX_ACK_DELAY: Self = Self(0x0b);
52 pub const DISABLE_ACTIVE_MIGRATION: Self = Self(0x0c);
54 pub const PREFERRED_ADDRESS: Self = Self(0x0d);
56 pub const ACTIVE_CONNECTION_ID_LIMIT: Self = Self(0x0e);
58 pub const INITIAL_SOURCE_CONNECTION_ID: Self = Self(0x0f);
60 pub const RETRY_SOURCE_CONNECTION_ID: Self = Self(0x10);
62
63 pub const fn new(raw: u64) -> Self {
65 Self(raw)
66 }
67
68 pub const fn raw(self) -> u64 {
70 self.0
71 }
72
73 pub const fn is_reserved(self) -> bool {
75 self.0 % 31 == 27
76 }
77}
78
79#[derive(Clone, Copy, Debug, Eq, PartialEq)]
81pub enum QuicTransportParameterField {
82 Id,
84 Length,
86 Value,
88}
89
90#[derive(Clone, Copy, Debug, Eq, PartialEq)]
92pub enum QuicTransportParameterParseError {
93 IncompleteVarInt {
95 field: QuicTransportParameterField,
97 offset: usize,
99 error: QuicVarIntParseError,
101 },
102 LengthNotRepresentable {
104 offset: usize,
106 value: u64,
108 },
109 LengthOverflow {
111 offset: usize,
113 length: usize,
115 },
116 IncompleteValue {
118 offset: usize,
120 required: usize,
122 available: usize,
124 },
125 DuplicateId {
127 id: QuicTransportParameterId,
129 first_offset: usize,
131 duplicate_offset: usize,
133 },
134}
135
136impl fmt::Display for QuicTransportParameterParseError {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 match self {
139 Self::IncompleteVarInt {
140 field,
141 offset,
142 error,
143 } => write!(
144 f,
145 "QUIC transport parameter {field:?} at offset {offset} cannot be parsed: {error}"
146 ),
147 Self::LengthNotRepresentable { offset, value } => write!(
148 f,
149 "QUIC transport parameter length at offset {offset} has unrepresentable value {value}"
150 ),
151 Self::LengthOverflow { offset, length } => write!(
152 f,
153 "QUIC transport parameter value at offset {offset} overflows with length {length}"
154 ),
155 Self::IncompleteValue {
156 offset,
157 required,
158 available,
159 } => write!(
160 f,
161 "QUIC transport parameter value at offset {offset} is incomplete: need {required} bytes, have {available}"
162 ),
163 Self::DuplicateId {
164 id,
165 first_offset,
166 duplicate_offset,
167 } => write!(
168 f,
169 "QUIC transport parameter ID {} is duplicated at offset {duplicate_offset}; first occurred at offset {first_offset}",
170 id.raw()
171 ),
172 }
173 }
174}
175
176#[cfg(feature = "tls")]
178#[derive(Clone, Copy, Debug, Eq, PartialEq)]
179pub enum QuicTransportParametersTlsExtensionError {
180 WrongExtensionType {
182 actual: TlsExtensionType,
184 },
185 Parse(QuicTransportParameterParseError),
187}
188
189#[cfg(feature = "tls")]
190impl fmt::Display for QuicTransportParametersTlsExtensionError {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 match self {
193 Self::WrongExtensionType { actual } => write!(
194 f,
195 "TLS extension type {} is not QUIC transport parameters",
196 actual.raw()
197 ),
198 Self::Parse(error) => {
199 write!(f, "TLS QUIC transport parameters cannot be parsed: {error}")
200 }
201 }
202 }
203}
204
205#[derive(Clone, Copy, Debug, Eq, PartialEq)]
207pub struct QuicTransportParameter<'a> {
208 bytes: &'a [u8],
209 id: QuicVarInt<'a>,
210 length: QuicVarInt<'a>,
211 value: &'a [u8],
212}
213
214impl<'a> QuicTransportParameter<'a> {
215 pub const fn as_bytes(self) -> &'a [u8] {
217 self.bytes
218 }
219
220 pub const fn id(self) -> QuicVarInt<'a> {
222 self.id
223 }
224
225 pub const fn parameter_id(self) -> QuicTransportParameterId {
227 QuicTransportParameterId::new(self.id.value())
228 }
229
230 pub const fn length(self) -> QuicVarInt<'a> {
232 self.length
233 }
234
235 pub const fn value(self) -> &'a [u8] {
237 self.value
238 }
239}
240
241#[derive(Clone, Copy, Debug, Eq, PartialEq)]
243pub struct QuicTransportParameters<'a> {
244 bytes: &'a [u8],
245}
246
247impl<'a> QuicTransportParameters<'a> {
248 pub fn parse(bytes: &'a [u8]) -> Result<Self, QuicTransportParameterParseError> {
250 let mut remaining = bytes;
251 let mut offset = 0;
252 while !remaining.is_empty() {
253 let (parameter, suffix) = parse_at(remaining, offset)?;
254 if let Some(first_offset) = first_id_offset(bytes, offset, parameter.parameter_id()) {
255 return Err(QuicTransportParameterParseError::DuplicateId {
256 id: parameter.parameter_id(),
257 first_offset,
258 duplicate_offset: offset,
259 });
260 }
261 let consumed = parameter.as_bytes().len();
262 remaining = suffix;
263 offset += consumed;
264 }
265 Ok(Self { bytes })
266 }
267
268 pub fn validate_v1(
270 self,
271 sender: QuicTransportParameterSender,
272 ) -> Result<QuicTransportParametersV1<'a>, QuicTransportParameterSemanticError> {
273 semantic::validate(self.bytes, sender)
274 }
275
276 pub const fn as_bytes(self) -> &'a [u8] {
278 self.bytes
279 }
280
281 pub const fn iter(self) -> QuicTransportParameterIter<'a> {
283 QuicTransportParameterIter::new(self.bytes)
284 }
285}
286
287#[cfg(feature = "tls")]
288impl<'a> TlsExtension<'a> {
289 pub fn quic_transport_parameters(
295 &self,
296 ) -> Result<QuicTransportParameters<'a>, QuicTransportParametersTlsExtensionError> {
297 if self.extension_type() != TlsExtensionType::QUIC_TRANSPORT_PARAMETERS {
298 return Err(
299 QuicTransportParametersTlsExtensionError::WrongExtensionType {
300 actual: self.extension_type(),
301 },
302 );
303 }
304 QuicTransportParameters::parse(self.data())
305 .map_err(QuicTransportParametersTlsExtensionError::Parse)
306 }
307}
308
309#[derive(Clone, Debug)]
311pub struct QuicTransportParameterIter<'a> {
312 remaining: &'a [u8],
313 offset: usize,
314 failed: bool,
315}
316
317impl<'a> QuicTransportParameterIter<'a> {
318 pub(super) const fn new(bytes: &'a [u8]) -> Self {
319 Self {
320 remaining: bytes,
321 offset: 0,
322 failed: false,
323 }
324 }
325}
326
327impl<'a> Iterator for QuicTransportParameterIter<'a> {
328 type Item = Result<QuicTransportParameter<'a>, QuicTransportParameterParseError>;
329
330 fn next(&mut self) -> Option<Self::Item> {
331 if self.failed || self.remaining.is_empty() {
332 return None;
333 }
334
335 match parse_at(self.remaining, self.offset) {
336 Ok((parameter, suffix)) => {
337 let consumed = parameter.as_bytes().len();
338 self.remaining = suffix;
339 self.offset += consumed;
340 Some(Ok(parameter))
341 }
342 Err(error) => {
343 self.failed = true;
344 self.remaining = &[];
345 Some(Err(error))
346 }
347 }
348 }
349}
350
351impl FusedIterator for QuicTransportParameterIter<'_> {}
352
353fn parse_at<'a>(
354 bytes: &'a [u8],
355 offset: usize,
356) -> Result<(QuicTransportParameter<'a>, &'a [u8]), QuicTransportParameterParseError> {
357 let id = QuicVarInt::parse(bytes).map_err(|error| {
358 QuicTransportParameterParseError::IncompleteVarInt {
359 field: QuicTransportParameterField::Id,
360 offset,
361 error,
362 }
363 })?;
364 let length_start = id.byte_len();
365 let length_offset = offset + length_start;
366 let length = QuicVarInt::parse(&bytes[length_start..]).map_err(|error| {
367 QuicTransportParameterParseError::IncompleteVarInt {
368 field: QuicTransportParameterField::Length,
369 offset: length_offset,
370 error,
371 }
372 })?;
373 let value_start = length_start + length.byte_len();
374 let value_offset = offset + value_start;
375 let value_length = usize::try_from(length.value()).map_err(|_| {
376 QuicTransportParameterParseError::LengthNotRepresentable {
377 offset: length_offset,
378 value: length.value(),
379 }
380 })?;
381 let value_end = value_start.checked_add(value_length).ok_or(
382 QuicTransportParameterParseError::LengthOverflow {
383 offset: value_offset,
384 length: value_length,
385 },
386 )?;
387 let available = bytes.len() - value_start;
388 if available < value_length {
389 return Err(QuicTransportParameterParseError::IncompleteValue {
390 offset: value_offset,
391 required: value_length,
392 available,
393 });
394 }
395
396 Ok((
397 QuicTransportParameter {
398 bytes: &bytes[..value_end],
399 id,
400 length,
401 value: &bytes[value_start..value_end],
402 },
403 &bytes[value_end..],
404 ))
405}
406
407fn first_id_offset(bytes: &[u8], end: usize, id: QuicTransportParameterId) -> Option<usize> {
408 let mut remaining = &bytes[..end];
409 let mut offset = 0;
410 while !remaining.is_empty() {
411 let (parameter, suffix) = match parse_at(remaining, offset) {
412 Ok(parsed) => parsed,
413 Err(_) => return None,
414 };
415 if parameter.parameter_id() == id {
416 return Some(offset);
417 }
418 offset += parameter.as_bytes().len();
419 remaining = suffix;
420 }
421 None
422}