s2n_quic_core/packet/long.rs
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5 packet::{encoding::PacketPayloadLenCursor, number::TruncatedPacketNumber},
6 varint::VarInt,
7};
8use s2n_codec::{
9 decoder_invariant, CheckedRange, DecoderError, Encoder, EncoderBuffer, EncoderValue,
10};
11
12//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
13//# Long Header Packet {
14//# Header Form (1) = 1,
15//# Fixed Bit (1) = 1,
16//# Long Packet Type (2),
17//# Type-Specific Bits (4),
18//# Version (32),
19//# Destination Connection ID Length (8),
20//# Destination Connection ID (0..160),
21//# Source Connection ID Length (8),
22//# Source Connection ID (0..160),
23//# }
24
25//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
26//# Header Form: The most significant bit (0x80) of byte 0 (the first
27//# byte) is set to 1 for long headers.
28
29//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
30//# Fixed Bit: The next bit (0x40) of byte 0 is set to 1.
31
32//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
33//# Long Packet Type: The next two bits (those with a mask of 0x30)
34//# of byte 0 contain a packet type. Packet types are listed in
35//# Table 5.
36
37pub(crate) const PACKET_TYPE_MASK: u8 = 0x30;
38const PACKET_TYPE_OFFSET: u8 = 4;
39
40//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
41//# Type-Specific Bits: The semantics of the lower four bits (those with
42//# a mask of 0x0f) of byte 0 are determined by the packet type.
43
44//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
45//# Version: The QUIC Version is a 32-bit field that follows the first
46//# byte. This field indicates the version of QUIC that is in use and
47//# determines how the rest of the protocol fields are interpreted.
48
49pub(crate) type Version = u32;
50
51//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
52//# Destination Connection ID Length: The byte following the version
53//# contains the length in bytes of the Destination Connection ID
54//# field that follows it. This length is encoded as an 8-bit
55//# unsigned integer. In QUIC version 1, this value MUST NOT exceed
56//# 20.
57
58pub(crate) type DestinationConnectionIdLen = u8;
59pub(crate) const DESTINATION_CONNECTION_ID_MAX_LEN: usize = 20;
60
61//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
62//# Destination Connection ID: The Destination Connection ID field
63//# follows the Destination Connection ID Length field, which
64//# indicates the length of this field. Section 7.2 describes the use
65//# of this field in more detail.
66
67pub(crate) fn validate_destination_connection_id_range(
68 range: &CheckedRange,
69) -> Result<(), DecoderError> {
70 validate_destination_connection_id_len(range.len())
71}
72
73pub(crate) fn validate_destination_connection_id_len(len: usize) -> Result<(), DecoderError> {
74 //= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
75 //# Endpoints that receive a version 1 long header with a value
76 //# larger than 20 MUST drop the packet.
77 decoder_invariant!(
78 len <= DESTINATION_CONNECTION_ID_MAX_LEN,
79 "destination connection exceeds max length"
80 );
81 Ok(())
82}
83
84//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
85//# Source Connection ID Length: The byte following the Destination
86//# Connection ID contains the length in bytes of the Source
87//# Connection ID field that follows it. This length is encoded as a
88//# 8-bit unsigned integer. In QUIC version 1, this value MUST NOT
89//# exceed 20 bytes.
90
91pub(crate) type SourceConnectionIdLen = u8;
92pub(crate) const SOURCE_CONNECTION_ID_MAX_LEN: usize = 20;
93
94//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
95//# Source Connection ID: The Source Connection ID field follows the
96//# Source Connection ID Length field, which indicates the length of
97//# this field. Section 7.2 describes the use of this field in more
98//# detail.
99
100pub(crate) fn validate_source_connection_id_range(
101 range: &CheckedRange,
102) -> Result<(), DecoderError> {
103 //= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
104 //# Endpoints that receive a version 1 long header
105 //# with a value larger than 20 MUST drop the packet.
106 validate_source_connection_id_len(range.len())
107}
108
109pub(crate) fn validate_source_connection_id_len(len: usize) -> Result<(), DecoderError> {
110 decoder_invariant!(
111 len <= SOURCE_CONNECTION_ID_MAX_LEN,
112 "source connection exceeds max length"
113 );
114 Ok(())
115}
116
117//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
118//# In this version of QUIC, the following packet types with the long
119//# header are defined:
120//#
121//# +======+===========+================+
122//# | Type | Name | Section |
123//# +======+===========+================+
124//# | 0x00 | Initial | Section 17.2.2 |
125//# +------+-----------+----------------+
126//# | 0x01 | 0-RTT | Section 17.2.3 |
127//# +------+-----------+----------------+
128//# | 0x02 | Handshake | Section 17.2.4 |
129//# +------+-----------+----------------+
130//# | 0x03 | Retry | Section 17.2.5 |
131//# +------+-----------+----------------+
132//#
133//# Table 5: Long Header Packet Types
134
135#[repr(u8)]
136#[derive(Clone, Copy, Debug)]
137pub enum PacketType {
138 Initial = 0x0,
139 ZeroRtt = 0x1,
140 Handshake = 0x2,
141 Retry = 0x3,
142}
143
144impl PacketType {
145 pub const fn into_bits(self) -> u8 {
146 ((self as u8) << PACKET_TYPE_OFFSET) & PACKET_TYPE_MASK
147 }
148
149 pub fn from_bits(bits: u8) -> Self {
150 (bits & (PACKET_TYPE_MASK >> PACKET_TYPE_OFFSET)).into()
151 }
152}
153
154impl From<u8> for PacketType {
155 fn from(bits: u8) -> Self {
156 match bits {
157 0x0 => PacketType::Initial,
158 0x1 => PacketType::ZeroRtt,
159 0x2 => PacketType::Handshake,
160 0x3 => PacketType::Retry,
161 _ => PacketType::Initial,
162 }
163 }
164}
165
166impl From<PacketType> for u8 {
167 fn from(v: PacketType) -> Self {
168 v.into_bits()
169 }
170}
171
172//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
173//# Reserved Bits: Two bits (those with a mask of 0x0c) of byte 0 are
174//# reserved across multiple packet types. These bits are protected
175//# using header protection; see Section 5.4 of [QUIC-TLS].
176pub const RESERVED_BITS_MASK: u8 = 0x0c;
177
178//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
179//# Packet Number Length: In packet types that contain a Packet Number
180//# field, the least significant two bits (those with a mask of 0x03)
181//# of byte 0 contain the length of the Packet Number field, encoded
182//# as an unsigned two-bit integer that is one less than the length of
183//# the Packet Number field in bytes.
184
185//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
186//# Length: This is the length of the remainder of the packet (that is,
187//# the Packet Number and Payload fields) in bytes, encoded as a
188//# variable-length integer (Section 16).
189
190//= https://www.rfc-editor.org/rfc/rfc9000#section-17.2
191//# Packet Number: This field is 1 to 4 bytes long. The packet number
192//# is protected using header protection; see Section 5.4 of
193//# [QUIC-TLS]. The length of the Packet Number field is encoded in
194//# the Packet Number Length bits of byte 0; see above.
195
196pub(crate) struct LongPayloadEncoder<Payload> {
197 pub packet_number: TruncatedPacketNumber,
198 pub payload: Payload,
199}
200
201impl<Payload: EncoderValue> EncoderValue for LongPayloadEncoder<&Payload> {
202 fn encode<E: Encoder>(&self, encoder: &mut E) {
203 self.packet_number.encode(encoder);
204 self.payload.encode(encoder);
205 }
206}
207
208impl<Payload: EncoderValue> EncoderValue for LongPayloadEncoder<&mut Payload> {
209 fn encode<E: Encoder>(&self, encoder: &mut E) {
210 self.packet_number.encode(encoder);
211 self.payload.encode(encoder);
212 }
213
214 fn encode_mut<E: Encoder>(&mut self, encoder: &mut E) {
215 self.packet_number.encode_mut(encoder);
216 self.payload.encode_mut(encoder);
217 }
218}
219
220// used internally for estimating long packet payload len values.
221#[doc(hidden)]
222#[derive(Clone, Copy, Debug, PartialEq)]
223pub struct LongPayloadLenCursor {
224 position: usize,
225 max_value: VarInt,
226}
227
228impl PacketPayloadLenCursor for LongPayloadLenCursor {
229 fn new() -> Self {
230 let max_value = VarInt::MAX;
231 Self {
232 position: 0,
233 max_value,
234 }
235 }
236
237 fn update(&self, buffer: &mut EncoderBuffer, actual_len: usize) {
238 debug_assert!(
239 self.position != 0,
240 "position cursor was not updated. encode_mut should be called instead of encode"
241 );
242
243 let actual_value =
244 VarInt::try_from(actual_len).expect("packets should not be larger than VarInt::MAX");
245 let max_value = self.max_value;
246
247 let prev_pos = buffer.len();
248 buffer.set_position(self.position);
249 max_value.encode_updated(actual_value, buffer);
250 buffer.set_position(prev_pos);
251 }
252}
253
254impl EncoderValue for LongPayloadLenCursor {
255 fn encode<E: Encoder>(&self, encoder: &mut E) {
256 self.max_value.encode(encoder)
257 }
258
259 fn encode_mut<E: Encoder>(&mut self, encoder: &mut E) {
260 self.position = encoder.len();
261 self.max_value = VarInt::try_from(encoder.remaining_capacity()).unwrap_or(VarInt::MAX);
262 self.max_value.encode(encoder)
263 }
264}