net_wire/quic/packet/
terminal.rs1use core::iter::FusedIterator;
4
5use super::header::{QuicConnectionIdField, QuicLongHeader, QuicLongPacketType, QuicVersion};
6use super::parse::QuicPacketParseError;
7
8const RETRY_INTEGRITY_TAG_LEN: usize = 16;
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct QuicVersionNegotiationPacket<'a> {
17 bytes: &'a [u8],
18 header: QuicLongHeader<'a>,
19 versions: &'a [u8],
20}
21
22impl<'a> QuicVersionNegotiationPacket<'a> {
23 pub(crate) const fn from_validated(
25 bytes: &'a [u8],
26 header: QuicLongHeader<'a>,
27 versions: &'a [u8],
28 ) -> Self {
29 Self {
30 bytes,
31 header,
32 versions,
33 }
34 }
35
36 pub fn parse(bytes: &'a [u8]) -> Result<Self, QuicPacketParseError> {
38 let header = QuicLongHeader::parse(bytes)?;
39 if header.version() != QuicVersion::NEGOTIATION {
40 return Err(QuicPacketParseError::WrongVersion {
41 version: header.version(),
42 });
43 }
44
45 let versions = header.version_specific();
46 if versions.is_empty() {
47 return Err(QuicPacketParseError::EmptyVersionList);
48 }
49 if !versions.len().is_multiple_of(4) {
50 return Err(QuicPacketParseError::MisalignedVersionList {
51 length: versions.len(),
52 });
53 }
54
55 Ok(Self {
56 bytes,
57 header,
58 versions,
59 })
60 }
61
62 pub const fn header(self) -> QuicLongHeader<'a> {
64 self.header
65 }
66
67 pub const fn version_list_bytes(self) -> &'a [u8] {
69 self.versions
70 }
71
72 pub const fn versions(self) -> QuicVersionIter<'a> {
74 QuicVersionIter {
75 bytes: self.versions,
76 }
77 }
78
79 pub const fn as_bytes(self) -> &'a [u8] {
81 self.bytes
82 }
83}
84
85#[derive(Clone, Debug)]
87pub struct QuicVersionIter<'a> {
88 bytes: &'a [u8],
89}
90
91impl Iterator for QuicVersionIter<'_> {
92 type Item = QuicVersion;
93
94 fn next(&mut self) -> Option<Self::Item> {
95 let (version, remainder) = self.bytes.split_first_chunk::<4>()?;
96 self.bytes = remainder;
97 Some(QuicVersion::new(u32::from_be_bytes(*version)))
98 }
99
100 fn size_hint(&self) -> (usize, Option<usize>) {
101 let length = self.len();
102 (length, Some(length))
103 }
104}
105
106impl ExactSizeIterator for QuicVersionIter<'_> {
107 fn len(&self) -> usize {
108 self.bytes.len() / 4
109 }
110}
111
112impl FusedIterator for QuicVersionIter<'_> {}
113
114#[derive(Clone, Copy, Debug, Eq, PartialEq)]
119pub struct QuicRetryPacket<'a> {
120 bytes: &'a [u8],
121 header: QuicLongHeader<'a>,
122 packet_type: QuicLongPacketType,
123 token: &'a [u8],
124 integrity_tag: &'a [u8],
125}
126
127impl<'a> QuicRetryPacket<'a> {
128 pub(crate) const fn from_validated(
130 bytes: &'a [u8],
131 header: QuicLongHeader<'a>,
132 packet_type: QuicLongPacketType,
133 token: &'a [u8],
134 integrity_tag: &'a [u8],
135 ) -> Self {
136 Self {
137 bytes,
138 header,
139 packet_type,
140 token,
141 integrity_tag,
142 }
143 }
144
145 pub fn parse(bytes: &'a [u8]) -> Result<Self, QuicPacketParseError> {
147 let header = QuicLongHeader::parse(bytes)?;
148 let version = header.version();
149 if version != QuicVersion::V1 && version != QuicVersion::V2 {
150 return Err(QuicPacketParseError::UnsupportedVersion { version });
151 }
152 if !header.has_fixed_bit() {
153 return Err(QuicPacketParseError::FixedBitNotSet {
154 first_byte: header.first_byte(),
155 });
156 }
157 validate_connection_id(
158 QuicConnectionIdField::Destination,
159 header.destination_connection_id().len(),
160 )?;
161 validate_connection_id(
162 QuicConnectionIdField::Source,
163 header.source_connection_id().len(),
164 )?;
165
166 let packet_type = header
167 .long_packet_type()
168 .ok_or(QuicPacketParseError::UnsupportedVersion { version })?;
169 if packet_type != QuicLongPacketType::Retry {
170 return Err(QuicPacketParseError::NotRetry { packet_type });
171 }
172
173 let header_end = header.as_bytes().len();
174 let required = header_end.checked_add(RETRY_INTEGRITY_TAG_LEN).ok_or(
175 QuicPacketParseError::LengthOverflow {
176 offset: header_end,
177 length: RETRY_INTEGRITY_TAG_LEN,
178 },
179 )?;
180 if bytes.len() < required {
181 return Err(QuicPacketParseError::Incomplete {
182 required,
183 available: bytes.len(),
184 });
185 }
186 if bytes.len() == required {
187 return Err(QuicPacketParseError::EmptyRetryToken);
188 }
189
190 let tag_start = bytes.len() - RETRY_INTEGRITY_TAG_LEN;
191 Ok(Self {
192 bytes,
193 header,
194 packet_type,
195 token: &bytes[header_end..tag_start],
196 integrity_tag: &bytes[tag_start..],
197 })
198 }
199
200 pub const fn header(self) -> QuicLongHeader<'a> {
202 self.header
203 }
204
205 pub const fn version(self) -> QuicVersion {
207 self.header.version()
208 }
209
210 pub const fn packet_type(self) -> QuicLongPacketType {
212 self.packet_type
213 }
214
215 pub const fn token(self) -> &'a [u8] {
217 self.token
218 }
219
220 pub const fn integrity_tag(self) -> &'a [u8] {
222 self.integrity_tag
223 }
224
225 pub const fn as_bytes(self) -> &'a [u8] {
227 self.bytes
228 }
229}
230
231fn validate_connection_id(
232 field: QuicConnectionIdField,
233 length: usize,
234) -> Result<(), QuicPacketParseError> {
235 if length > 20 {
236 return Err(QuicPacketParseError::ConnectionIdTooLong { field, length });
237 }
238 Ok(())
239}