Skip to main content

net_wire/quic/frame/
connection_id.rs

1//! RFC 9000 NEW_CONNECTION_ID and RETIRE_CONNECTION_ID frame parsing.
2
3use super::super::packet::header::QuicConnectionId;
4use super::super::varint::QuicVarInt;
5use super::parse::{QuicFrameField, QuicFrameParseError};
6
7const STATELESS_RESET_TOKEN_LEN: usize = 16;
8const MAX_CONNECTION_ID_LEN: u8 = 20;
9
10/// A checked borrowed RFC 9000 NEW_CONNECTION_ID frame view.
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub struct QuicNewConnectionIdFrame<'a> {
13    bytes: &'a [u8],
14    frame_type: QuicVarInt<'a>,
15    sequence_number: QuicVarInt<'a>,
16    retire_prior_to: QuicVarInt<'a>,
17    connection_id_length: u8,
18    connection_id: QuicConnectionId<'a>,
19    stateless_reset_token: &'a [u8; STATELESS_RESET_TOKEN_LEN],
20}
21
22impl<'a> QuicNewConnectionIdFrame<'a> {
23    /// Returns the exact encoded frame bytes.
24    pub const fn as_bytes(self) -> &'a [u8] {
25        self.bytes
26    }
27
28    /// Returns the exact encoded frame-type variable integer.
29    pub const fn frame_type(self) -> QuicVarInt<'a> {
30        self.frame_type
31    }
32
33    /// Returns the exact encoded sequence-number variable integer.
34    pub const fn sequence_number(self) -> QuicVarInt<'a> {
35        self.sequence_number
36    }
37
38    /// Returns the exact encoded retire-prior-to variable integer.
39    pub const fn retire_prior_to(self) -> QuicVarInt<'a> {
40        self.retire_prior_to
41    }
42
43    /// Returns the decoded connection-ID length byte.
44    pub const fn connection_id_length(self) -> u8 {
45        self.connection_id_length
46    }
47
48    /// Returns the nonempty opaque connection ID.
49    pub const fn connection_id(self) -> QuicConnectionId<'a> {
50        self.connection_id
51    }
52
53    /// Returns the stateless reset token.
54    pub const fn stateless_reset_token(self) -> &'a [u8; STATELESS_RESET_TOKEN_LEN] {
55        self.stateless_reset_token
56    }
57}
58
59/// A checked borrowed RFC 9000 RETIRE_CONNECTION_ID frame view.
60#[derive(Clone, Copy, Debug, Eq, PartialEq)]
61pub struct QuicRetireConnectionIdFrame<'a> {
62    bytes: &'a [u8],
63    frame_type: QuicVarInt<'a>,
64    sequence_number: QuicVarInt<'a>,
65}
66
67impl<'a> QuicRetireConnectionIdFrame<'a> {
68    /// Returns the exact encoded frame bytes.
69    pub const fn as_bytes(self) -> &'a [u8] {
70        self.bytes
71    }
72
73    /// Returns the exact encoded frame-type variable integer.
74    pub const fn frame_type(self) -> QuicVarInt<'a> {
75        self.frame_type
76    }
77
78    /// Returns the exact encoded sequence-number variable integer.
79    pub const fn sequence_number(self) -> QuicVarInt<'a> {
80        self.sequence_number
81    }
82}
83
84pub(super) fn parse_new_connection_id<'a>(
85    bytes: &'a [u8],
86    frame_type: QuicVarInt<'a>,
87    offset: usize,
88) -> Result<(QuicNewConnectionIdFrame<'a>, &'a [u8]), QuicFrameParseError> {
89    let sequence_start = frame_type.byte_len();
90    let sequence_offset = offset + sequence_start;
91    let sequence_number = QuicVarInt::parse(&bytes[sequence_start..]).map_err(|error| {
92        QuicFrameParseError::Field {
93            field: QuicFrameField::SequenceNumber,
94            offset: sequence_offset,
95            error,
96        }
97    })?;
98
99    let retire_start = sequence_start + sequence_number.byte_len();
100    let retire_offset = offset + retire_start;
101    let retire_prior_to =
102        QuicVarInt::parse(&bytes[retire_start..]).map_err(|error| QuicFrameParseError::Field {
103            field: QuicFrameField::RetirePriorTo,
104            offset: retire_offset,
105            error,
106        })?;
107
108    if retire_prior_to.value() > sequence_number.value() {
109        return Err(QuicFrameParseError::FieldValueExceedsField {
110            field: QuicFrameField::RetirePriorTo,
111            offset: retire_offset,
112            value: retire_prior_to.value(),
113            maximum_field: QuicFrameField::SequenceNumber,
114            maximum: sequence_number.value(),
115        });
116    }
117
118    let connection_id_length_start = retire_start + retire_prior_to.byte_len();
119    let connection_id_length_offset = offset + connection_id_length_start;
120    let Some(&connection_id_length) = bytes.get(connection_id_length_start) else {
121        return Err(QuicFrameParseError::IncompleteBytes {
122            field: QuicFrameField::ConnectionIdLength,
123            offset: connection_id_length_offset,
124            required: 1,
125            available: 0,
126        });
127    };
128    if connection_id_length > MAX_CONNECTION_ID_LEN {
129        return Err(QuicFrameParseError::FieldValueOutOfRange {
130            field: QuicFrameField::ConnectionIdLength,
131            offset: connection_id_length_offset,
132            value: u64::from(connection_id_length),
133            maximum: u64::from(MAX_CONNECTION_ID_LEN),
134        });
135    }
136
137    let connection_id_start = connection_id_length_start + 1;
138    let connection_id_offset = offset + connection_id_start;
139    let connection_id_len = usize::from(connection_id_length);
140    if connection_id_len == 0 {
141        return Err(QuicFrameParseError::EmptyField {
142            field: QuicFrameField::ConnectionId,
143            offset: connection_id_offset,
144        });
145    }
146    let connection_id_end = connection_id_start.checked_add(connection_id_len).ok_or(
147        QuicFrameParseError::LengthOverflow {
148            field: QuicFrameField::ConnectionId,
149            offset: connection_id_offset,
150            length: connection_id_len,
151        },
152    )?;
153    let connection_id_input = &bytes[connection_id_start..];
154    if connection_id_input.len() < connection_id_len {
155        return Err(QuicFrameParseError::IncompleteBytes {
156            field: QuicFrameField::ConnectionId,
157            offset: connection_id_offset,
158            required: connection_id_len,
159            available: connection_id_input.len(),
160        });
161    }
162
163    let stateless_reset_token_offset = offset + connection_id_end;
164    let token_input = &bytes[connection_id_end..];
165    let Some((stateless_reset_token, suffix)) =
166        token_input.split_first_chunk::<STATELESS_RESET_TOKEN_LEN>()
167    else {
168        return Err(QuicFrameParseError::IncompleteBytes {
169            field: QuicFrameField::StatelessResetToken,
170            offset: stateless_reset_token_offset,
171            required: STATELESS_RESET_TOKEN_LEN,
172            available: token_input.len(),
173        });
174    };
175    let frame_len = bytes.len() - suffix.len();
176
177    Ok((
178        QuicNewConnectionIdFrame {
179            bytes: &bytes[..frame_len],
180            frame_type,
181            sequence_number,
182            retire_prior_to,
183            connection_id_length,
184            connection_id: QuicConnectionId::new(&bytes[connection_id_start..connection_id_end]),
185            stateless_reset_token,
186        },
187        suffix,
188    ))
189}
190
191pub(super) fn parse_retire_connection_id<'a>(
192    bytes: &'a [u8],
193    frame_type: QuicVarInt<'a>,
194    offset: usize,
195) -> Result<(QuicRetireConnectionIdFrame<'a>, &'a [u8]), QuicFrameParseError> {
196    let sequence_start = frame_type.byte_len();
197    let sequence_number = QuicVarInt::parse(&bytes[sequence_start..]).map_err(|error| {
198        QuicFrameParseError::Field {
199            field: QuicFrameField::SequenceNumber,
200            offset: offset + sequence_start,
201            error,
202        }
203    })?;
204    let frame_len = sequence_start + sequence_number.byte_len();
205
206    Ok((
207        QuicRetireConnectionIdFrame {
208            bytes: &bytes[..frame_len],
209            frame_type,
210            sequence_number,
211        },
212        &bytes[frame_len..],
213    ))
214}