1use crate::coding::{put_varint, varint_len, Reader};
4use crate::error::{TransportError, TRANSPORT_PARAMETER_ERROR};
5use crate::frame::MAX_STREAMS_LIMIT;
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
9pub struct Cid {
10 len: u8,
11 b: [u8; 20],
12}
13
14impl Cid {
15 pub fn new(s: &[u8]) -> Self {
17 let mut b = [0u8; 20];
18 b[..s.len()].copy_from_slice(s);
19 Cid { len: s.len() as u8, b }
20 }
21 pub fn as_slice(&self) -> &[u8] {
22 &self.b[..self.len as usize]
23 }
24 pub fn len(&self) -> usize {
25 self.len as usize
26 }
27 pub fn is_empty(&self) -> bool {
28 self.len == 0
29 }
30}
31
32impl std::ops::Deref for Cid {
33 type Target = [u8];
34 fn deref(&self) -> &[u8] {
35 self.as_slice()
36 }
37}
38
39impl std::fmt::Debug for Cid {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 for b in self.as_slice() {
42 write!(f, "{b:02x}")?;
43 }
44 Ok(())
45 }
46}
47
48#[derive(Clone, Debug, PartialEq, Eq)]
49pub struct PreferredAddress {
50 pub v4: [u8; 6],
51 pub v6: [u8; 18],
52 pub cid: Cid,
53 pub reset_token: [u8; 16],
54}
55
56#[derive(Clone, Debug, PartialEq, Eq)]
57pub struct TransportParams {
58 pub original_destination_connection_id: Option<Cid>,
59 pub max_idle_timeout: u64,
61 pub stateless_reset_token: Option<[u8; 16]>,
62 pub max_udp_payload_size: u64,
63 pub initial_max_data: u64,
64 pub initial_max_stream_data_bidi_local: u64,
65 pub initial_max_stream_data_bidi_remote: u64,
66 pub initial_max_stream_data_uni: u64,
67 pub initial_max_streams_bidi: u64,
68 pub initial_max_streams_uni: u64,
69 pub ack_delay_exponent: u64,
70 pub max_ack_delay: u64,
72 pub disable_active_migration: bool,
73 pub preferred_address: Option<PreferredAddress>,
74 pub active_connection_id_limit: u64,
75 pub initial_source_connection_id: Option<Cid>,
76 pub retry_source_connection_id: Option<Cid>,
77 pub version_information: Option<(u32, Vec<u32>)>,
79}
80
81impl Default for TransportParams {
82 fn default() -> Self {
84 TransportParams {
85 original_destination_connection_id: None,
86 max_idle_timeout: 0,
87 stateless_reset_token: None,
88 max_udp_payload_size: 65527,
89 initial_max_data: 0,
90 initial_max_stream_data_bidi_local: 0,
91 initial_max_stream_data_bidi_remote: 0,
92 initial_max_stream_data_uni: 0,
93 initial_max_streams_bidi: 0,
94 initial_max_streams_uni: 0,
95 ack_delay_exponent: 3,
96 max_ack_delay: 25,
97 disable_active_migration: false,
98 preferred_address: None,
99 active_connection_id_limit: 2,
100 initial_source_connection_id: None,
101 retry_source_connection_id: None,
102 version_information: None,
103 }
104 }
105}
106
107fn put_int(out: &mut Vec<u8>, id: u64, v: u64, default: u64) {
108 if v != default {
109 put_varint(out, id);
110 put_varint(out, varint_len(v) as u64);
111 put_varint(out, v);
112 }
113}
114
115fn put_bytes(out: &mut Vec<u8>, id: u64, b: &[u8]) {
116 put_varint(out, id);
117 put_varint(out, b.len() as u64);
118 out.extend_from_slice(b);
119}
120
121impl TransportParams {
122 pub fn encode(&self, out: &mut Vec<u8>) {
123 let d = TransportParams::default();
124 if let Some(c) = &self.original_destination_connection_id {
125 put_bytes(out, 0x00, c);
126 }
127 put_int(out, 0x01, self.max_idle_timeout, 0);
128 if let Some(t) = &self.stateless_reset_token {
129 put_bytes(out, 0x02, t);
130 }
131 put_int(out, 0x03, self.max_udp_payload_size, d.max_udp_payload_size);
132 put_int(out, 0x04, self.initial_max_data, 0);
133 put_int(out, 0x05, self.initial_max_stream_data_bidi_local, 0);
134 put_int(out, 0x06, self.initial_max_stream_data_bidi_remote, 0);
135 put_int(out, 0x07, self.initial_max_stream_data_uni, 0);
136 put_int(out, 0x08, self.initial_max_streams_bidi, 0);
137 put_int(out, 0x09, self.initial_max_streams_uni, 0);
138 put_int(out, 0x0a, self.ack_delay_exponent, 3);
139 put_int(out, 0x0b, self.max_ack_delay, 25);
140 if self.disable_active_migration {
141 put_bytes(out, 0x0c, &[]);
142 }
143 if let Some(p) = &self.preferred_address {
144 let mut b = Vec::with_capacity(61);
145 b.extend_from_slice(&p.v4);
146 b.extend_from_slice(&p.v6);
147 b.push(p.cid.len() as u8);
148 b.extend_from_slice(&p.cid);
149 b.extend_from_slice(&p.reset_token);
150 put_bytes(out, 0x0d, &b);
151 }
152 put_int(out, 0x0e, self.active_connection_id_limit, 2);
153 if let Some(c) = &self.initial_source_connection_id {
154 put_bytes(out, 0x0f, c);
155 }
156 if let Some(c) = &self.retry_source_connection_id {
157 put_bytes(out, 0x10, c);
158 }
159 if let Some((chosen, available)) = &self.version_information {
160 put_bytes(out, crate::vn::VERSION_INFORMATION, &crate::vn::encode(*chosen, available));
161 }
162 }
163
164 pub fn decode(buf: &[u8], from_server: bool) -> Result<Self, TransportError> {
166 let err = |r: &'static str| TransportError::new(TRANSPORT_PARAMETER_ERROR, r);
167 let mut p = TransportParams::default();
168 let mut seen = 0u32;
169 let mut r = Reader::new(buf);
170 while !r.is_empty() {
171 let id = r.varint().ok_or(err("truncated parameter"))?;
172 let v = r.vbytes().ok_or(err("truncated parameter"))?;
173 if id <= 0x10 {
174 if seen & (1 << id) != 0 {
175 return Err(err("duplicate parameter"));
176 }
177 seen |= 1 << id;
178 if !from_server && matches!(id, 0x00 | 0x02 | 0x0d | 0x10) {
179 return Err(err("server-only parameter from a client"));
180 }
181 }
182 let int = || -> Result<u64, TransportError> {
183 let mut vr = Reader::new(v);
184 let x = vr.varint().ok_or(err("bad integer"))?;
185 if !vr.is_empty() {
186 return Err(err("bad integer"));
187 }
188 Ok(x)
189 };
190 let cid = || -> Result<Cid, TransportError> {
191 if v.len() > 20 {
192 return Err(err("connection ID too long"));
193 }
194 Ok(Cid::new(v))
195 };
196 match id {
197 0x00 => p.original_destination_connection_id = Some(cid()?),
198 0x01 => p.max_idle_timeout = int()?,
199 0x02 => p.stateless_reset_token = Some(v.try_into().map_err(|_| err("bad reset token"))?),
200 0x03 => {
201 p.max_udp_payload_size = int()?;
202 if p.max_udp_payload_size < 1200 {
203 return Err(err("max_udp_payload_size below 1200"));
204 }
205 }
206 0x04 => p.initial_max_data = int()?,
207 0x05 => p.initial_max_stream_data_bidi_local = int()?,
208 0x06 => p.initial_max_stream_data_bidi_remote = int()?,
209 0x07 => p.initial_max_stream_data_uni = int()?,
210 0x08 | 0x09 => {
211 let n = int()?;
212 if n > MAX_STREAMS_LIMIT {
213 return Err(err("stream limit above 2^60"));
214 }
215 if id == 0x08 {
216 p.initial_max_streams_bidi = n
217 } else {
218 p.initial_max_streams_uni = n
219 }
220 }
221 0x0a => {
222 p.ack_delay_exponent = int()?;
223 if p.ack_delay_exponent > 20 {
224 return Err(err("ack_delay_exponent above 20"));
225 }
226 }
227 0x0b => {
228 p.max_ack_delay = int()?;
229 if p.max_ack_delay >= 1 << 14 {
230 return Err(err("max_ack_delay too large"));
231 }
232 }
233 0x0c => {
234 if !v.is_empty() {
235 return Err(err("disable_active_migration not empty"));
236 }
237 p.disable_active_migration = true;
238 }
239 0x0d => {
240 let mut pr = Reader::new(v);
241 let v4 = pr.bytes(6).ok_or(err("bad preferred_address"))?.try_into().unwrap();
242 let v6 = pr.bytes(18).ok_or(err("bad preferred_address"))?.try_into().unwrap();
243 let n = pr.u8().ok_or(err("bad preferred_address"))? as usize;
244 if n == 0 || n > 20 {
245 return Err(err("bad preferred_address"));
246 }
247 let c = Cid::new(pr.bytes(n).ok_or(err("bad preferred_address"))?);
248 let t = pr.bytes(16).ok_or(err("bad preferred_address"))?.try_into().unwrap();
249 if !pr.is_empty() {
250 return Err(err("bad preferred_address"));
251 }
252 p.preferred_address = Some(PreferredAddress { v4, v6, cid: c, reset_token: t });
253 }
254 0x0e => {
255 p.active_connection_id_limit = int()?;
256 if p.active_connection_id_limit < 2 {
257 return Err(err("active_connection_id_limit below 2"));
258 }
259 }
260 0x0f => p.initial_source_connection_id = Some(cid()?),
261 0x10 => p.retry_source_connection_id = Some(cid()?),
262 crate::vn::VERSION_INFORMATION => {
263 if p.version_information.is_some() {
264 return Err(err("duplicate parameter"));
265 }
266 p.version_information = Some(crate::vn::decode(v).ok_or(err("bad version_information"))?);
267 }
268 _ => {} }
270 }
271 if p.initial_source_connection_id.is_none() {
272 return Err(err("missing initial_source_connection_id"));
273 }
274 if from_server && p.original_destination_connection_id.is_none() {
275 return Err(err("missing original_destination_connection_id"));
276 }
277 Ok(p)
278 }
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn roundtrip_and_validation() {
287 let p = TransportParams {
288 original_destination_connection_id: Some(Cid::new(&[1, 2, 3, 4, 5, 6, 7, 8])),
289 max_idle_timeout: 30_000,
290 stateless_reset_token: Some([9; 16]),
291 max_udp_payload_size: 1452,
292 initial_max_data: 1 << 20,
293 initial_max_stream_data_bidi_local: 1 << 16,
294 initial_max_stream_data_bidi_remote: 1 << 16,
295 initial_max_stream_data_uni: 1 << 16,
296 initial_max_streams_bidi: 100,
297 initial_max_streams_uni: 3,
298 ack_delay_exponent: 5,
299 max_ack_delay: 20,
300 disable_active_migration: true,
301 preferred_address: Some(PreferredAddress {
302 v4: [127, 0, 0, 1, 1, 187],
303 v6: [0; 18],
304 cid: Cid::new(&[7; 8]),
305 reset_token: [3; 16],
306 }),
307 active_connection_id_limit: 4,
308 initial_source_connection_id: Some(Cid::new(&[5; 8])),
309 retry_source_connection_id: Some(Cid::new(&[6; 8])),
310 version_information: Some((crate::VERSION_2, vec![crate::VERSION_2, crate::VERSION_1])),
311 };
312 let mut b = Vec::new();
313 p.encode(&mut b);
314 assert_eq!(TransportParams::decode(&b, true).unwrap(), p);
315 assert_eq!(TransportParams::decode(&b, false).unwrap_err().code, TRANSPORT_PARAMETER_ERROR);
317
318 let bad = |extra: &[u8]| {
319 let mut b = vec![0x0f, 0x01, 0x07];
320 b.extend_from_slice(extra);
321 TransportParams::decode(&b, false)
322 };
323 assert!(bad(&[]).is_ok());
324 assert!(bad(&[0x03, 0x02, 0x44, 0xaf]).is_err()); assert!(bad(&[0x0a, 0x01, 21]).is_err());
326 assert!(bad(&[0x0b, 0x04, 0x80, 0, 0x40, 0]).is_err());
327 assert!(bad(&[0x0e, 0x01, 1]).is_err());
328 assert!(bad(&[0x01, 0x02, 0x40]).is_err()); assert!(bad(&[0x01, 0x02, 5, 5]).is_err()); assert!(bad(&[0x0f, 0x00]).is_err()); assert!(bad(&[0x0c, 0x01, 0]).is_err());
332 assert!(bad(&[0x7f, 0xff, 0x02, 1, 2]).is_ok()); assert!(TransportParams::decode(&[], false).is_err()); assert!(bad(&[0x11, 0x05, 0, 0, 0, 1, 2]).is_err()); assert!(bad(&[0x11, 0x04, 0, 0, 0, 0]).is_err()); }
337}