s2n_quic_core/packet/
version_negotiation.rs1use crate::packet::{
5 initial::ProtectedInitial,
6 long::{
7 validate_destination_connection_id_len, validate_source_connection_id_len,
8 DestinationConnectionIdLen, SourceConnectionIdLen, Version,
9 },
10 Tag,
11};
12use core::mem::size_of;
13use s2n_codec::{
14 decoder_invariant, DecoderBuffer, DecoderBufferMut, DecoderBufferMutResult, Encoder,
15 EncoderValue,
16};
17
18macro_rules! version_negotiation_no_fixed_bit_tag {
38 () => {
39 0b1000u8..=0b1011u8
40 };
41}
42
43const ENCODING_TAG: u8 = 0b1100_0000;
44
45pub(crate) const VERSION: u32 = 0x0000_0000;
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
52pub struct VersionNegotiation<'a, SupportedVersions> {
53 pub tag: Tag,
54 pub destination_connection_id: &'a [u8],
55 pub source_connection_id: &'a [u8],
56 pub supported_versions: SupportedVersions,
57}
58
59pub type ProtectedVersionNegotiation<'a> = VersionNegotiation<'a, &'a [u8]>;
60pub type EncryptedVersionNegotiation<'a> = VersionNegotiation<'a, &'a [u8]>;
61pub type CleartextVersionNegotiation<'a> = VersionNegotiation<'a, &'a [u8]>;
62
63impl<'a> ProtectedVersionNegotiation<'a> {
64 #[inline]
65 pub fn decode(
66 tag: Tag,
67 _version: Version,
68 buffer: DecoderBufferMut<'_>,
69 ) -> DecoderBufferMutResult<'_, VersionNegotiation<'_, &[u8]>> {
70 let buffer = buffer
71 .skip(size_of::<Tag>() + size_of::<Version>())
72 .expect("tag and version already verified");
73
74 let (destination_connection_id, buffer) =
75 buffer.decode_slice_with_len_prefix::<DestinationConnectionIdLen>()?;
76 let destination_connection_id = destination_connection_id.into_less_safe_slice();
77 validate_destination_connection_id_len(destination_connection_id.len())?;
78
79 let (source_connection_id, buffer) =
80 buffer.decode_slice_with_len_prefix::<SourceConnectionIdLen>()?;
81 let source_connection_id = source_connection_id.into_less_safe_slice();
82 validate_source_connection_id_len(source_connection_id.len())?;
83
84 let (supported_versions, buffer) = buffer.decode::<DecoderBufferMut>()?;
85 let supported_versions: &[u8] = supported_versions.into_less_safe_slice();
86
87 decoder_invariant!(
89 supported_versions.len() >= size_of::<u32>(),
90 "missing at least one version"
91 );
92
93 decoder_invariant!(
95 supported_versions.len() % size_of::<u32>() == 0,
96 "invalid payload length"
97 );
98
99 let packet = VersionNegotiation {
100 tag,
101 destination_connection_id,
102 source_connection_id,
103 supported_versions,
104 };
105
106 Ok((packet, buffer))
107 }
108
109 #[inline]
110 pub fn iter(&'a self) -> VersionNegotiationIterator<'a> {
111 self.into_iter()
112 }
113
114 #[inline]
115 pub fn destination_connection_id(&self) -> &[u8] {
116 self.destination_connection_id
117 }
118
119 #[inline]
120 pub fn source_connection_id(&self) -> &[u8] {
121 self.source_connection_id
122 }
123}
124
125impl<'a, SupportedVersions: EncoderValue> VersionNegotiation<'a, SupportedVersions> {
126 pub fn from_initial(
127 initial_packet: &'a ProtectedInitial,
128 supported_versions: SupportedVersions,
129 ) -> Self {
130 Self {
133 tag: 0,
134 destination_connection_id: initial_packet.source_connection_id(),
138 source_connection_id: initial_packet.destination_connection_id(),
143 supported_versions,
144 }
145 }
146}
147
148impl<'a> IntoIterator for ProtectedVersionNegotiation<'a> {
149 type IntoIter = VersionNegotiationIterator<'a>;
150 type Item = u32;
151
152 fn into_iter(self) -> Self::IntoIter {
153 VersionNegotiationIterator(DecoderBuffer::new(self.supported_versions))
154 }
155}
156
157#[derive(Clone, Copy, Debug)]
158pub struct VersionNegotiationIterator<'a>(DecoderBuffer<'a>);
159
160impl Iterator for VersionNegotiationIterator<'_> {
161 type Item = u32;
162
163 fn next(&mut self) -> Option<Self::Item> {
164 if let Ok((value, buffer)) = self.0.decode() {
165 self.0 = buffer;
166 Some(value)
167 } else {
168 None
169 }
170 }
171}
172
173impl<SupportedVersions: EncoderValue> EncoderValue for VersionNegotiation<'_, SupportedVersions> {
174 fn encode<E: Encoder>(&self, encoder: &mut E) {
175 (self.tag | ENCODING_TAG).encode(encoder);
176 VERSION.encode(encoder);
177 self.destination_connection_id
178 .encode_with_len_prefix::<DestinationConnectionIdLen, _>(encoder);
179 self.source_connection_id
180 .encode_with_len_prefix::<SourceConnectionIdLen, _>(encoder);
181 self.supported_versions.encode(encoder);
182 }
183}