internet/ietf/quic/encoding/
packet_headers.rs1use crate::{Buf, BufError, BufMut, BufResult, Codec, Cursor};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22#[repr(u8)]
23pub enum HeaderForm {
24 ShortHeader = 0x00,
26 LongHeader = 0x01,
28}
29
30impl Codec for HeaderForm {
31 fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
32 let current_byte = writer.peek_u8().unwrap_or(0x00);
33 let header_bit = (*self as u8) << 7;
34 let byte = (current_byte & !0x80) | header_bit;
35 writer.poke_u8(byte)
36 }
37
38 fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
39 let value = reader.peek_u8()? & 0x80;
40 match value {
41 0 => Ok(Self::ShortHeader),
42 _ => Ok(Self::LongHeader),
43 }
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
54pub struct Version(pub u32);
55
56impl Version {
57 pub const VERSION_NEGOTIATION: Self = Self(0x00000000);
59
60 pub const QUIC_V1: Self = Self(0x00000001);
62
63 pub const QUIC_V2: Self = Self(0x6b3343cf);
65
66 pub fn is_grease(&self) -> bool {
68 (self.0 & 0x0f0f0f0f) == 0x0a0a0a0a
69 }
70}
71
72impl Codec for Version {
73 fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
74 self.0.encode(writer, ())
75 }
76
77 fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
78 Ok(Self(u32::decode(reader, ())?))
79 }
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
88pub struct ConnectionId(Vec<u8>);
89
90impl ConnectionId {
91 pub const MAXIMAL_LENGTH: u8 = u8::MAX;
93
94 pub fn from_slice(connection_id: &[u8]) -> BufResult<Self> {
96 if connection_id.length() > Self::MAXIMAL_LENGTH as usize {
97 return Err(BufError::InvalidLength);
98 }
99 Ok(Self(connection_id.to_vec()))
100 }
101
102 pub fn from_vec(connection_id: Vec<u8>) -> BufResult<Self> {
104 if connection_id.len() > Self::MAXIMAL_LENGTH as usize {
105 return Err(BufError::InvalidLength);
106 }
107 Ok(Self(connection_id))
108 }
109
110 pub fn length(&self) -> u8 {
112 self.0.len() as u8
113 }
114
115 pub fn bytes(&self) -> Vec<u8> {
117 self.0.clone()
118 }
119}
120
121impl Codec for ConnectionId {
122 fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
123 (self.0.len() as u8).encode(writer, ())?;
124 self.0.encode(writer, self.0.len())
125 }
126
127 fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
128 let bytes = &mut [0u8; Self::MAXIMAL_LENGTH as usize];
129 let length = u8::decode(reader, ())?;
130 reader.read_into(&mut bytes[..length as usize])?;
131 Ok(Self::from_slice(&bytes[..length as usize])?)
132 }
133}
134
135impl Codec<u8> for ConnectionId {
136 fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: u8) -> BufResult<()> {
137 writer.write_slice(&self.0[..self.length() as usize])
138 }
139
140 fn decode<R: Buf>(reader: &mut Cursor<R>, cil: u8) -> BufResult<Self> {
141 let bytes = &mut [0u8; Self::MAXIMAL_LENGTH as usize];
142 reader.read_into(&mut bytes[..cil as usize])?;
143 Ok(Self::from_slice(&bytes[..cil as usize])?)
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub struct VersionNegotiationPacket {
154 pub destination_connection_id: ConnectionId,
156 pub source_connection_id: ConnectionId,
158 pub supported_version: Vec<Version>,
160}
161
162impl VersionNegotiationPacket {
163 pub const HEADER_FORM: HeaderForm = HeaderForm::LongHeader;
165 pub const VERSION: Version = Version::VERSION_NEGOTIATION;
167}
168
169impl Codec for VersionNegotiationPacket {
170 fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
171 Self::HEADER_FORM.encode(writer, ())?;
172 writer.advance(1)?;
173 Self::VERSION.encode(writer, ())?;
174 self.destination_connection_id.encode(writer, ())?;
175 self.source_connection_id.encode(writer, ())?;
176 self.supported_version.encode(writer, ())
177 }
178
179 fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
180 if HeaderForm::decode(reader, ())? != Self::HEADER_FORM {
181 return Err(BufError::UnexpectedValue);
182 }
183 reader.advance(1)?;
184 if Version::decode(reader, ())? != Self::VERSION {
185 return Err(BufError::UnexpectedValue);
186 }
187 let destination_connection_id = ConnectionId::decode(reader, ())?;
188 let source_connection_id = ConnectionId::decode(reader, ())?;
189 let supported_version = Vec::decode(reader, ())?;
190
191 Ok(Self {
192 destination_connection_id,
193 source_connection_id,
194 supported_version,
195 })
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use core::fmt::Debug;
202
203 use crate::{
204 BufError, Codec, Cursor,
205 ietf::quic::{ConnectionId, HeaderForm, Version, VersionNegotiationPacket},
206 };
207
208 fn codec_roundtrip<T: Codec<C> + Debug + Eq, C: Copy>(
209 etalon_struct: T,
210 etalon_bytes: &[u8],
211 context: C,
212 ) {
213 let mut encoded_bytes = vec![];
214 {
215 let writer = &mut Cursor::new(&mut encoded_bytes);
216 etalon_struct.encode(writer, context).unwrap();
217 }
218 assert_eq!(etalon_bytes, &encoded_bytes);
219
220 let decoded_struct = {
221 let reader = &mut Cursor::new(&mut encoded_bytes);
222 T::decode(reader, context).unwrap()
223 };
224 assert_eq!(etalon_struct, decoded_struct);
225
226 encoded_bytes.fill(0x00);
227 {
228 let writer = &mut Cursor::new(&mut encoded_bytes);
229 decoded_struct.encode(writer, context).unwrap();
230 }
231 assert_eq!(etalon_bytes, &encoded_bytes);
232 }
233
234 #[test]
235 fn header_form() {
236 let etalon_bytes = &[0b10000000];
237 let etalon_struct = HeaderForm::LongHeader;
238 codec_roundtrip(etalon_struct, etalon_bytes, ());
239
240 let etalon_bytes = &[0b00000000];
241 let etalon_struct = HeaderForm::ShortHeader;
242 codec_roundtrip(etalon_struct, etalon_bytes, ());
243 }
244
245 #[test]
246 fn version() {
247 let etalon_bytes = &[0x00, 0x00, 0x00, 0x01];
248 let etalon_struct = Version(1);
249 codec_roundtrip(etalon_struct, etalon_bytes, ());
250 assert_eq!(etalon_struct.is_grease(), false);
251
252 let etalon_bytes = &[0x1a, 0x1a, 0x1a, 0x1a];
253 let etalon_struct = Version(0x1a1a1a1a);
254 codec_roundtrip(etalon_struct, etalon_bytes, ());
255 assert_eq!(etalon_struct.is_grease(), true);
256 }
257
258 #[test]
259 fn connection_id() {
260 assert_eq!(
261 ConnectionId::from_slice(&[0x08; 256]),
262 Err(BufError::InvalidLength)
263 );
264
265 let etalon_bytes = &[0x08; 9];
266 let etalon_struct = ConnectionId::from_slice(&[0x08; 8]).unwrap();
267 codec_roundtrip(etalon_struct, etalon_bytes, ());
268
269 let etalon_bytes = &[0x014; 21];
270 let etalon_struct = ConnectionId::from_slice(&[0x014; 20]).unwrap();
271 codec_roundtrip(etalon_struct, etalon_bytes, ());
272 }
273
274 #[test]
275 fn version_negotiation_packet() {
276 let etalon_struct = VersionNegotiationPacket {
277 destination_connection_id: ConnectionId::from_slice(&[0x82; 8]).unwrap(),
278 source_connection_id: ConnectionId::from_slice(&[0x41; 8]).unwrap(),
279 supported_version: vec![Version(0)],
280 };
281
282 let etalon_bytes: &[u8] = &[
283 0b10000000, 0x00, 0x00, 0x00, 0x00, 0x08, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x08, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00,
288 ];
289 codec_roundtrip(etalon_struct, etalon_bytes, ());
290 }
291}