1use std::{
2 fmt::{self, Display},
3 mem,
4 net::{IpAddr, SocketAddr},
5 ops::{Range, RangeInclusive},
6};
7
8use bytes::{Buf, BufMut, Bytes};
9use tinyvec::TinyVec;
10
11use crate::{
12 Dir, MAX_CID_SIZE, RESET_TOKEN_SIZE, ResetToken, StreamId, TransportError, TransportErrorCode,
13 VarInt,
14 coding::{self, BufExt, BufMutExt, Decodable, Encodable, UnexpectedEnd},
15 connection::PathId,
16 range_set::ArrayRangeSet,
17 shared::{ConnectionId, EcnCodepoint},
18};
19
20#[cfg(feature = "qlog")]
21use super::connection::qlog::ToQlog;
22
23#[cfg(test)]
24use crate::varint::varint_u64;
25#[cfg(test)]
26use proptest::{collection, prelude::any, strategy::Strategy};
27#[cfg(test)]
28use test_strategy::Arbitrary;
29
30#[derive(
31 Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display, enum_assoc::Assoc,
32)]
33#[cfg_attr(test, derive(Arbitrary))]
34#[display(rename_all = "SCREAMING_SNAKE_CASE")]
35#[allow(missing_docs)]
36#[func(
37 pub(crate) const fn to_u64(self) -> u64,
38 const fn from_u64(rev: u64) -> Option<Self>,
39)]
40pub enum FrameType {
41 #[assoc(to_u64 = 0x00)]
42 Padding,
43 #[assoc(to_u64 = 0x01)]
44 Ping,
45 #[assoc(to_u64 = 0x02)]
46 Ack,
47 #[assoc(to_u64 = 0x03)]
48 AckEcn,
49 #[assoc(to_u64 = 0x04)]
50 ResetStream,
51 #[assoc(to_u64 = 0x05)]
52 StopSending,
53 #[assoc(to_u64 = 0x06)]
54 Crypto,
55 #[assoc(to_u64 = 0x07)]
56 NewToken,
57 #[assoc(to_u64 = _0.to_u64())]
59 Stream(StreamInfo),
60 #[assoc(to_u64 = 0x10)]
61 MaxData,
62 #[assoc(to_u64 = 0x11)]
63 MaxStreamData,
64 #[assoc(to_u64 = 0x12)]
65 MaxStreamsBidi,
66 #[assoc(to_u64 = 0x13)]
67 MaxStreamsUni,
68 #[assoc(to_u64 = 0x14)]
69 DataBlocked,
70 #[assoc(to_u64 = 0x15)]
71 StreamDataBlocked,
72 #[assoc(to_u64 = 0x16)]
73 StreamsBlockedBidi,
74 #[assoc(to_u64 = 0x17)]
75 StreamsBlockedUni,
76 #[assoc(to_u64 = 0x18)]
77 NewConnectionId,
78 #[assoc(to_u64 = 0x19)]
79 RetireConnectionId,
80 #[assoc(to_u64 = 0x1a)]
81 PathChallenge,
82 #[assoc(to_u64 = 0x1b)]
83 PathResponse,
84 #[assoc(to_u64 = 0x1c)]
85 ConnectionClose,
86 #[assoc(to_u64 = 0x1d)]
87 ApplicationClose,
88 #[assoc(to_u64 = 0x1e)]
89 HandshakeDone,
90 #[assoc(to_u64 = 0xaf)]
92 AckFrequency,
93 #[assoc(to_u64 = 0x1f)]
94 ImmediateAck,
95 #[assoc(to_u64 = _0.to_u64())]
97 Datagram(DatagramInfo),
98 #[assoc(to_u64 = 0x9f81a6)]
100 ObservedIpv4Addr,
101 #[assoc(to_u64 = 0x9f81a7)]
102 ObservedIpv6Addr,
103 #[assoc(to_u64 = 0x3e)]
105 PathAck,
106 #[assoc(to_u64 = 0x3f)]
107 PathAckEcn,
108 #[assoc(to_u64 = 0x3e75)]
109 PathAbandon,
110 #[assoc(to_u64 = 0x3e76)]
111 PathStatusBackup,
112 #[assoc(to_u64 = 0x3e77)]
113 PathStatusAvailable,
114 #[assoc(to_u64 = 0x3e78)]
115 PathNewConnectionId,
116 #[assoc(to_u64 = 0x3e79)]
117 PathRetireConnectionId,
118 #[assoc(to_u64 = 0x3e7a)]
119 MaxPathId,
120 #[assoc(to_u64 = 0x3e7b)]
121 PathsBlocked,
122 #[assoc(to_u64 = 0x3e7c)]
123 PathCidsBlocked,
124 #[assoc(to_u64 = 0x3d7f90)]
126 AddIpv4Address,
127 #[assoc(to_u64 = 0x3d7f91)]
128 AddIpv6Address,
129 #[assoc(to_u64 = 0x3d7f92)]
130 ReachOutAtIpv4,
131 #[assoc(to_u64 = 0x3d7f93)]
132 ReachOutAtIpv6,
133 #[assoc(to_u64 = 0x3d7f94)]
134 RemoveAddress,
135}
136
137#[derive(Debug, PartialEq, Eq, thiserror::Error)]
139#[error("Invalid frame identifier {_0:02x}")]
140pub struct InvalidFrameId(u64);
141
142impl TryFrom<u64> for FrameType {
143 type Error = InvalidFrameId;
144 fn try_from(value: u64) -> Result<Self, Self::Error> {
145 match Self::from_u64(value) {
146 Some(t) => Ok(t),
147 None => {
148 if DatagramInfo::VALUES.contains(&value) {
149 return Ok(Self::Datagram(DatagramInfo(value as u8)));
150 }
151 if StreamInfo::VALUES.contains(&value) {
152 return Ok(Self::Stream(StreamInfo(value as u8)));
153 }
154 Err(InvalidFrameId(value))
155 }
156 }
157 }
158}
159
160impl FrameType {
161 const fn size(&self) -> usize {
163 VarInt(self.to_u64()).size()
164 }
165}
166
167impl Decodable for FrameType {
168 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
169 Self::try_from(buf.get_var()?).map_err(|_| coding::UnexpectedEnd)
170 }
171}
172
173impl Encodable for FrameType {
174 fn encode<B: BufMut>(&self, buf: &mut B) {
175 buf.write_var(self.to_u64());
176 }
177}
178
179#[derive(derive_more::From, enum_assoc::Assoc, derive_more::Display)]
184#[func(fn encode_inner<B: BufMut>(&self, buf: &mut B) {_0.encode(buf)})]
185#[func(pub(crate) const fn get_type(&self) -> FrameType {_0.get_type()})]
186#[cfg_attr(feature = "qlog", func(pub(crate) fn to_qlog(&self) -> qlog::events::quic::QuicFrame {_0.to_qlog()}))]
187pub(super) enum EncodableFrame<'a> {
188 PathAck(PathAckEncoder<'a>),
189 Ack(AckEncoder<'a>),
190 Close(CloseEncoder<'a>),
191 PathResponse(PathResponse),
192 HandshakeDone(HandshakeDone),
193 ReachOut(ReachOut),
194 ObservedAddr(ObservedAddr),
195 Ping(Ping),
196 ImmediateAck(ImmediateAck),
197 AckFrequency(AckFrequency),
198 PathChallenge(PathChallenge),
199 Crypto(Crypto),
200 PathAbandon(PathAbandon),
201 PathStatusAvailable(PathStatusAvailable),
202 PathStatusBackup(PathStatusBackup),
203 MaxPathId(MaxPathId),
204 PathsBlocked(PathsBlocked),
205 PathCidsBlocked(PathCidsBlocked),
206 ResetStream(ResetStream),
207 StopSending(StopSending),
208 NewConnectionId(NewConnectionId),
209 RetireConnectionId(RetireConnectionId),
210 Datagram(Datagram),
211 NewToken(NewToken),
212 AddAddress(AddAddress),
213 RemoveAddress(RemoveAddress),
214 StreamMeta(StreamMetaEncoder),
215 MaxData(MaxData),
216 MaxStreamData(MaxStreamData),
217 MaxStreams(MaxStreams),
218}
219
220impl<'a> Encodable for EncodableFrame<'a> {
221 fn encode<B: BufMut>(&self, buf: &mut B) {
222 self.encode_inner(buf)
223 }
224}
225
226pub(crate) trait FrameStruct {
227 const SIZE_BOUND: usize;
229}
230
231#[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)]
233pub enum MaybeFrame {
234 None,
236 #[display("UNKNOWN({:02x})", _0)]
238 #[debug("Unknown({:02x})", _0)]
239 Unknown(u64),
240 Known(FrameType),
242}
243
244impl MaybeFrame {
245 const fn size(&self) -> usize {
247 match self {
248 Self::None => VarInt(0).size(),
249 Self::Unknown(other) => VarInt(*other).size(),
250 Self::Known(frame_type) => frame_type.size(),
251 }
252 }
253}
254
255impl Decodable for MaybeFrame {
256 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
257 match FrameType::try_from(buf.get_var()?) {
258 Ok(FrameType::Padding) => Ok(Self::None),
259 Ok(other_frame) => Ok(Self::Known(other_frame)),
260 Err(InvalidFrameId(other)) => Ok(Self::Unknown(other)),
261 }
262 }
263}
264
265impl Encodable for MaybeFrame {
266 fn encode<B: BufMut>(&self, buf: &mut B) {
267 match self {
268 Self::None => buf.write_var(0u64),
269 Self::Unknown(frame_id) => buf.write_var(*frame_id),
270 Self::Known(frame_type) => buf.write(*frame_type),
271 }
272 }
273}
274
275#[cfg(test)]
276impl proptest::arbitrary::Arbitrary for MaybeFrame {
277 type Parameters = ();
278 type Strategy = proptest::strategy::BoxedStrategy<Self>;
279
280 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
281 use proptest::prelude::*;
282 prop_oneof![
283 Just(Self::None),
284 any::<VarInt>().prop_map(|v| Self::Unknown(v.0)),
285 any::<FrameType>()
287 .prop_filter("not Padding", |ft| *ft != FrameType::Padding)
288 .prop_map(MaybeFrame::Known),
289 ]
290 .boxed()
291 }
292}
293
294#[derive(derive_more::Display)]
295#[cfg_attr(test, derive(Arbitrary, Debug, Clone, PartialEq, Eq))]
296#[display("HANDSHAKE_DONE")]
297pub(crate) struct HandshakeDone;
298
299impl HandshakeDone {
300 const fn get_type(&self) -> FrameType {
301 FrameType::HandshakeDone
302 }
303}
304
305impl Encodable for HandshakeDone {
306 fn encode<B: BufMut>(&self, buf: &mut B) {
307 FrameType::HandshakeDone.encode(buf);
308 }
309}
310
311#[derive(derive_more::Display)]
312#[cfg_attr(test, derive(Arbitrary, Debug, Clone, PartialEq, Eq))]
313#[display("PING")]
314pub(crate) struct Ping;
315
316impl Ping {
317 const fn get_type(&self) -> FrameType {
318 FrameType::Ping
319 }
320}
321
322impl Encodable for Ping {
323 fn encode<B: BufMut>(&self, buf: &mut B) {
324 FrameType::Ping.encode(buf);
325 }
326}
327
328#[derive(derive_more::Display)]
329#[cfg_attr(test, derive(Arbitrary, Debug, Clone, PartialEq, Eq))]
330#[display("IMMEDIATE_ACK")]
331pub(crate) struct ImmediateAck;
332
333impl ImmediateAck {
334 const fn get_type(&self) -> FrameType {
335 FrameType::ImmediateAck
336 }
337}
338
339impl Encodable for ImmediateAck {
340 fn encode<B: BufMut>(&self, buf: &mut B) {
341 FrameType::ImmediateAck.encode(buf);
342 }
343}
344
345#[allow(missing_docs)]
346#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)]
347#[display("STREAM")]
348#[cfg_attr(test, derive(Arbitrary))]
349pub struct StreamInfo(#[cfg_attr(test, strategy(0x08u8..=0x0f))] u8);
350
351impl StreamInfo {
352 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f);
353 fn fin(self) -> bool {
354 self.0 & 0x01 != 0
355 }
356 fn len(self) -> bool {
357 self.0 & 0x02 != 0
358 }
359 fn off(self) -> bool {
360 self.0 & 0x04 != 0
361 }
362
363 const fn to_u64(self) -> u64 {
364 self.0 as u64
365 }
366}
367
368#[allow(missing_docs)]
369#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)]
370#[display("DATAGRAM")]
371#[cfg_attr(test, derive(Arbitrary))]
372pub struct DatagramInfo(#[cfg_attr(test, strategy(0x30u8..=0x31))] u8);
373
374impl DatagramInfo {
375 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31);
376
377 fn len(self) -> bool {
378 self.0 & 0x01 != 0
379 }
380
381 const fn to_u64(self) -> u64 {
382 self.0 as u64
383 }
384}
385
386#[derive(Debug, derive_more::Display)]
387#[cfg_attr(test, derive(Arbitrary))]
388pub(crate) enum Frame {
389 #[display("PADDING")]
390 Padding,
391 #[display("PING")]
392 Ping,
393 Ack(Ack),
394 PathAck(PathAck),
395 ResetStream(ResetStream),
396 StopSending(StopSending),
397 Crypto(Crypto),
398 NewToken(NewToken),
399 Stream(Stream),
400 MaxData(MaxData),
401 MaxStreamData(MaxStreamData),
402 MaxStreams(MaxStreams),
403 DataBlocked(DataBlocked),
404 StreamDataBlocked(StreamDataBlocked),
405 StreamsBlocked(StreamsBlocked),
406 NewConnectionId(NewConnectionId),
407 RetireConnectionId(RetireConnectionId),
408 PathChallenge(PathChallenge),
409 PathResponse(PathResponse),
410 Close(Close),
411 Datagram(Datagram),
412 AckFrequency(AckFrequency),
413 #[display("IMMEDIATE_ACK")]
414 ImmediateAck,
415 #[display("HANDSHAKE_DONE")]
416 HandshakeDone,
417 ObservedAddr(ObservedAddr),
418 PathAbandon(PathAbandon),
419 PathStatusAvailable(PathStatusAvailable),
420 PathStatusBackup(PathStatusBackup),
421 MaxPathId(MaxPathId),
422 PathsBlocked(PathsBlocked),
423 PathCidsBlocked(PathCidsBlocked),
424 AddAddress(AddAddress),
425 ReachOut(ReachOut),
426 RemoveAddress(RemoveAddress),
427}
428
429impl Frame {
430 pub(crate) fn ty(&self) -> FrameType {
431 use Frame::*;
432 match &self {
433 Padding => FrameType::Padding,
434 ResetStream(_) => FrameType::ResetStream,
435 Close(self::Close::Connection(_)) => FrameType::ConnectionClose,
436 Close(self::Close::Application(_)) => FrameType::ConnectionClose,
437 MaxData(_) => FrameType::MaxData,
438 MaxStreamData(_) => FrameType::MaxStreamData,
439 MaxStreams(max_streams) => max_streams.get_type(),
440 Ping => FrameType::Ping,
441 DataBlocked(_) => FrameType::DataBlocked,
442 StreamDataBlocked(sdb) => sdb.get_type(),
443 StreamsBlocked(sb) => sb.get_type(),
444 StopSending { .. } => FrameType::StopSending,
445 RetireConnectionId(retire_frame) => retire_frame.get_type(),
446 Ack(ack) => ack.get_type(),
447 PathAck(path_ack) => path_ack.get_type(),
448 Stream(x) => {
449 let mut ty = *StreamInfo::VALUES.start() as u8;
450 if x.fin {
451 ty |= 0x01;
452 }
453 if x.offset != 0 {
454 ty |= 0x04;
455 }
456 FrameType::Stream(StreamInfo(ty))
458 }
459 PathChallenge(_) => FrameType::PathChallenge,
460 PathResponse(_) => FrameType::PathResponse,
461 NewConnectionId(cid) => cid.get_type(),
462 Crypto(_) => FrameType::Crypto,
463 NewToken(_) => FrameType::NewToken,
464 Datagram(_) => FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)),
465 AckFrequency(_) => FrameType::AckFrequency,
466 ImmediateAck => FrameType::ImmediateAck,
467 HandshakeDone => FrameType::HandshakeDone,
468 ObservedAddr(observed) => observed.get_type(),
469 PathAbandon(_) => FrameType::PathAbandon,
470 PathStatusAvailable(_) => FrameType::PathStatusAvailable,
471 PathStatusBackup(_) => FrameType::PathStatusBackup,
472 MaxPathId(_) => FrameType::MaxPathId,
473 PathsBlocked(_) => FrameType::PathsBlocked,
474 PathCidsBlocked(_) => FrameType::PathCidsBlocked,
475 AddAddress(frame) => frame.get_type(),
476 ReachOut(frame) => frame.get_type(),
477 RemoveAddress(_) => self::RemoveAddress::TYPE,
478 }
479 }
480
481 pub(crate) fn is_ack_eliciting(&self) -> bool {
482 !matches!(
483 *self,
484 Self::Ack(_) | Self::PathAck(_) | Self::Padding | Self::Close(_)
485 )
486 }
487
488 pub(crate) fn is_1rtt(&self) -> bool {
490 self.is_multipath_frame() || self.is_qad_frame()
496 }
497
498 fn is_qad_frame(&self) -> bool {
499 matches!(*self, Self::ObservedAddr(_))
500 }
501
502 fn is_multipath_frame(&self) -> bool {
503 matches!(
504 *self,
505 Self::PathAck(_)
506 | Self::PathAbandon(_)
507 | Self::PathStatusBackup(_)
508 | Self::PathStatusAvailable(_)
509 | Self::MaxPathId(_)
510 | Self::PathsBlocked(_)
511 | Self::PathCidsBlocked(_)
512 | Self::NewConnectionId(NewConnectionId {
513 path_id: Some(_),
514 ..
515 })
516 | Self::RetireConnectionId(RetireConnectionId {
517 path_id: Some(_),
518 ..
519 })
520 )
521 }
522}
523
524#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)]
525#[cfg_attr(test, derive(Arbitrary))]
526#[display("PATH_CHALLENGE({_0:08x})")]
527pub(crate) struct PathChallenge(pub(crate) u64);
528
529impl PathChallenge {
530 pub(crate) const SIZE_BOUND: usize = 9;
531
532 const fn get_type(&self) -> FrameType {
533 FrameType::PathChallenge
534 }
535}
536
537impl Decodable for PathChallenge {
538 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
539 Ok(Self(buf.get()?))
540 }
541}
542
543impl Encodable for PathChallenge {
544 fn encode<B: BufMut>(&self, buf: &mut B) {
545 buf.write(FrameType::PathChallenge);
546 buf.write(self.0);
547 }
548}
549
550#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Display)]
551#[cfg_attr(test, derive(Arbitrary))]
552#[display("PATH_RESPONSE({_0:08x})")]
553pub(crate) struct PathResponse(pub(crate) u64);
554
555impl PathResponse {
556 pub(crate) const SIZE_BOUND: usize = 9;
557
558 const fn get_type(&self) -> FrameType {
559 FrameType::PathResponse
560 }
561}
562
563impl Decodable for PathResponse {
564 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
565 Ok(Self(buf.get()?))
566 }
567}
568
569impl Encodable for PathResponse {
570 fn encode<B: BufMut>(&self, buf: &mut B) {
571 buf.write(FrameType::PathResponse);
572 buf.write(self.0);
573 }
574}
575
576#[derive(Debug, Clone, Copy, derive_more::Display)]
577#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
578#[display("DATA_BLOCKED offset: {_0}")]
579pub(crate) struct DataBlocked(#[cfg_attr(test, strategy(varint_u64()))] pub(crate) u64);
580
581impl Encodable for DataBlocked {
582 fn encode<B: BufMut>(&self, buf: &mut B) {
583 buf.write(FrameType::DataBlocked);
584 buf.write_var(self.0);
585 }
586}
587
588#[derive(Debug, Clone, Copy, derive_more::Display)]
589#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
590#[display("STREAM_DATA_BLOCKED id: {id} offset: {offset}")]
591pub(crate) struct StreamDataBlocked {
592 pub(crate) id: StreamId,
593 #[cfg_attr(test, strategy(varint_u64()))]
594 pub(crate) offset: u64,
595}
596
597impl StreamDataBlocked {
598 const fn get_type(&self) -> FrameType {
599 FrameType::StreamDataBlocked
600 }
601}
602
603impl Encodable for StreamDataBlocked {
604 fn encode<B: BufMut>(&self, buf: &mut B) {
605 buf.write(FrameType::StreamDataBlocked);
606 buf.write(self.id);
607 buf.write_var(self.offset);
608 }
609}
610
611#[derive(Debug, Clone, Copy, derive_more::Display)]
612#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
613#[display("STREAMS_BLOCKED dir: {:?} limit: {limit}", dir)]
614pub(crate) struct StreamsBlocked {
615 pub(crate) dir: Dir,
616 #[cfg_attr(test, strategy(varint_u64()))]
617 pub(crate) limit: u64,
618}
619
620impl StreamsBlocked {
621 const fn get_type(&self) -> FrameType {
622 match self.dir {
623 Dir::Bi => FrameType::StreamsBlockedBidi,
624 Dir::Uni => FrameType::StreamsBlockedUni,
625 }
626 }
627}
628
629impl Encodable for StreamsBlocked {
630 fn encode<B: BufMut>(&self, buf: &mut B) {
631 buf.write(self.get_type());
632 buf.write_var(self.limit);
633 }
634}
635
636#[derive(Debug, Clone, Copy, derive_more::Display)]
637#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
638#[display("MAX_DATA({_0})")]
639pub(crate) struct MaxData(pub(crate) VarInt);
640
641impl MaxData {
642 const fn get_type(&self) -> FrameType {
643 FrameType::MaxData
644 }
645}
646
647impl Decodable for MaxData {
648 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
649 Ok(Self(buf.get()?))
650 }
651}
652
653impl Encodable for MaxData {
654 fn encode<B: BufMut>(&self, buf: &mut B) {
655 buf.write(FrameType::MaxData);
656 buf.write(self.0);
657 }
658}
659
660#[derive(Debug, Clone, Copy, derive_more::Display)]
661#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
662#[display("MAX_STREAM_DATA id: {id} max: {offset}")]
663pub(crate) struct MaxStreamData {
664 pub(crate) id: StreamId,
665 #[cfg_attr(test, strategy(varint_u64()))]
666 pub(crate) offset: u64,
667}
668
669impl MaxStreamData {
670 const fn get_type(&self) -> FrameType {
671 FrameType::MaxStreamData
672 }
673}
674
675impl Decodable for MaxStreamData {
676 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
677 Ok(Self {
678 id: buf.get()?,
679 offset: buf.get_var()?,
680 })
681 }
682}
683
684impl Encodable for MaxStreamData {
685 fn encode<B: BufMut>(&self, buf: &mut B) {
686 buf.write(FrameType::MaxStreamData);
687 buf.write(self.id);
688 buf.write_var(self.offset);
689 }
690}
691
692#[derive(Debug, Clone, Copy, derive_more::Display)]
693#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
694#[display("{} count: {count}", self.get_type())]
695pub(crate) struct MaxStreams {
696 pub(crate) dir: Dir,
697 #[cfg_attr(test, strategy(varint_u64()))]
698 pub(crate) count: u64,
699}
700
701impl MaxStreams {
702 const fn get_type(&self) -> FrameType {
703 match self.dir {
704 Dir::Bi => FrameType::MaxStreamsBidi,
705 Dir::Uni => FrameType::MaxStreamsUni,
706 }
707 }
708}
709
710impl Encodable for MaxStreams {
711 fn encode<B: BufMut>(&self, buf: &mut B) {
712 buf.write(self.get_type());
713 buf.write_var(self.count);
714 }
715}
716
717#[derive(Debug, PartialEq, Eq, derive_more::Display)]
718#[cfg_attr(test, derive(Arbitrary))]
719#[display("{} {} seq: {sequence}", self.get_type(), DisplayOption::new("path_id", path_id.as_ref()))]
720pub(crate) struct RetireConnectionId {
721 pub(crate) path_id: Option<PathId>,
722 #[cfg_attr(test, strategy(varint_u64()))]
723 pub(crate) sequence: u64,
724}
725
726impl RetireConnectionId {
727 pub(crate) const SIZE_BOUND: usize = {
729 let type_len = FrameType::RetireConnectionId.size();
730 let seq_max_len = 8usize;
731 type_len + seq_max_len
732 };
733
734 pub(crate) const SIZE_BOUND_MULTIPATH: usize = {
736 let type_len = FrameType::PathRetireConnectionId.size();
737 let path_id_len = VarInt::from_u32(u32::MAX).size();
738 let seq_max_len = 8usize;
739 type_len + path_id_len + seq_max_len
740 };
741
742 pub(crate) fn decode<R: Buf>(bytes: &mut R, read_path: bool) -> coding::Result<Self> {
745 Ok(Self {
746 path_id: if read_path { Some(bytes.get()?) } else { None },
747 sequence: bytes.get_var()?,
748 })
749 }
750
751 const fn get_type(&self) -> FrameType {
753 if self.path_id.is_some() {
754 FrameType::PathRetireConnectionId
755 } else {
756 FrameType::RetireConnectionId
757 }
758 }
759
760 pub(crate) const fn size_bound(path_retire_cid: bool) -> usize {
765 match path_retire_cid {
766 true => Self::SIZE_BOUND_MULTIPATH,
767 false => Self::SIZE_BOUND,
768 }
769 }
770}
771
772impl Encodable for RetireConnectionId {
773 fn encode<W: BufMut>(&self, buf: &mut W) {
774 buf.write(self.get_type());
775 if let Some(id) = self.path_id {
776 buf.write(id);
777 }
778 buf.write_var(self.sequence);
779 }
780}
781
782#[cfg_attr(test, derive(Arbitrary))]
783#[derive(Clone, Debug, derive_more::Display)]
784pub(crate) enum Close {
785 Connection(ConnectionClose),
786 Application(ApplicationClose),
787}
788
789impl Close {
790 pub(crate) fn encoder(&self, max_len: usize) -> CloseEncoder<'_> {
791 CloseEncoder {
792 close: self,
793 max_len,
794 }
795 }
796
797 pub(crate) fn is_transport_layer(&self) -> bool {
798 matches!(*self, Self::Connection(_))
799 }
800}
801
802#[derive(derive_more::Display)]
803#[display("{close}")]
804pub(crate) struct CloseEncoder<'a> {
805 pub(crate) close: &'a Close,
806 max_len: usize,
807}
808
809impl<'a> CloseEncoder<'a> {
810 const fn get_type(&self) -> FrameType {
811 match self.close {
812 Close::Connection(_) => FrameType::ConnectionClose,
813 Close::Application(_) => FrameType::ApplicationClose,
814 }
815 }
816}
817
818impl<'a> Encodable for CloseEncoder<'a> {
819 fn encode<W: BufMut>(&self, out: &mut W) {
820 match self.close {
821 Close::Connection(x) => x.encode(out, self.max_len),
822 Close::Application(x) => x.encode(out, self.max_len),
823 }
824 }
825}
826
827impl From<TransportError> for Close {
828 fn from(x: TransportError) -> Self {
829 Self::Connection(x.into())
830 }
831}
832impl From<ConnectionClose> for Close {
833 fn from(x: ConnectionClose) -> Self {
834 Self::Connection(x)
835 }
836}
837impl From<ApplicationClose> for Close {
838 fn from(x: ApplicationClose) -> Self {
839 Self::Application(x)
840 }
841}
842
843#[derive(Debug, Clone, PartialEq, Eq)]
845#[cfg_attr(test, derive(Arbitrary))]
846pub struct ConnectionClose {
847 pub error_code: TransportErrorCode,
849 pub frame_type: MaybeFrame,
851 #[cfg_attr(test, strategy(proptest::collection::vec(any::<u8>(), 0..64).prop_map(Bytes::from)))]
853 pub reason: Bytes,
854}
855
856impl fmt::Display for ConnectionClose {
857 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
858 self.error_code.fmt(f)?;
859 if !self.reason.as_ref().is_empty() {
860 f.write_str(": ")?;
861 f.write_str(&String::from_utf8_lossy(&self.reason))?;
862 }
863 Ok(())
864 }
865}
866
867impl From<TransportError> for ConnectionClose {
868 fn from(x: TransportError) -> Self {
869 Self {
870 error_code: x.code,
871 frame_type: x.frame,
872 reason: x.reason.into(),
873 }
874 }
875}
876
877impl FrameStruct for ConnectionClose {
878 const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
879}
880
881impl ConnectionClose {
882 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
883 out.write(FrameType::ConnectionClose); out.write(self.error_code); out.write(self.frame_type); let max_len = max_len
887 - 3
888 - self.frame_type.size()
889 - VarInt::from_u64(self.reason.len() as u64).unwrap().size();
890 let actual_len = self.reason.len().min(max_len);
891 out.write_var(actual_len as u64); out.put_slice(&self.reason[0..actual_len]); }
894}
895
896#[derive(Debug, Clone, PartialEq, Eq)]
898#[cfg_attr(test, derive(Arbitrary))]
899pub struct ApplicationClose {
900 pub error_code: VarInt,
902 #[cfg_attr(test, strategy(proptest::collection::vec(any::<u8>(), 0..64).prop_map(Bytes::from)))]
904 pub reason: Bytes,
905}
906
907impl fmt::Display for ApplicationClose {
908 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
909 if !self.reason.as_ref().is_empty() {
910 f.write_str(&String::from_utf8_lossy(&self.reason))?;
911 f.write_str(" (code ")?;
912 self.error_code.fmt(f)?;
913 f.write_str(")")?;
914 } else {
915 self.error_code.fmt(f)?;
916 }
917 Ok(())
918 }
919}
920
921impl FrameStruct for ApplicationClose {
922 const SIZE_BOUND: usize = 1 + 8 + 8;
923}
924
925impl ApplicationClose {
926 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
927 out.write(FrameType::ApplicationClose); out.write(self.error_code); let max_len = max_len - 3 - VarInt::from_u64(self.reason.len() as u64).unwrap().size();
930 let actual_len = self.reason.len().min(max_len);
931 out.write_var(actual_len as u64); out.put_slice(&self.reason[0..actual_len]); }
934}
935
936#[derive(Debug, Clone, Eq, PartialEq, derive_more::Display)]
937#[display("{} path_id: {path_id} ranges: {ranges:?} delay: {delay}µs", self.get_type())]
938pub(crate) struct PathAck {
939 pub path_id: PathId,
940 pub largest: u64,
941 pub delay: u64,
942 pub ranges: ArrayRangeSet,
943 pub ecn: Option<EcnCounts>,
944}
945
946#[cfg(test)]
947impl proptest::arbitrary::Arbitrary for PathAck {
948 type Parameters = ();
949 type Strategy = proptest::strategy::BoxedStrategy<Self>;
950
951 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
952 use proptest::prelude::*;
953 (
954 any::<PathId>(),
955 varint_u64(),
956 any::<ArrayRangeSet>()
957 .prop_filter("ranges must be non empty", |ranges| !ranges.is_empty()),
958 any::<Option<EcnCounts>>(),
959 )
960 .prop_map(|(path_id, delay, ranges, ecn)| Self {
961 path_id,
962 largest: ranges.max().expect("ranges must be non empty"),
963 delay,
964 ranges,
965 ecn,
966 })
967 .boxed()
968 }
969}
970
971impl PathAck {
972 pub(crate) fn into_ack(self) -> (Ack, PathId) {
973 let ack = Ack {
974 largest: self.largest,
975 delay: self.delay,
976 ranges: self.ranges,
977 ecn: self.ecn,
978 };
979
980 (ack, self.path_id)
981 }
982
983 fn get_type(&self) -> FrameType {
984 if self.ecn.is_some() {
985 FrameType::PathAckEcn
986 } else {
987 FrameType::PathAck
988 }
989 }
990
991 pub(crate) fn encoder<'a>(
992 path_id: PathId,
993 delay: u64,
994 ranges: &'a ArrayRangeSet,
995 ecn: Option<&'a EcnCounts>,
996 ) -> PathAckEncoder<'a> {
997 PathAckEncoder {
998 path_id,
999 delay,
1000 ranges,
1001 ecn,
1002 }
1003 }
1004}
1005
1006#[derive(derive_more::Display)]
1007#[display("{} path_id: {path_id} ranges: {ranges:?} delay: {delay}µs", self.get_type())]
1008pub(crate) struct PathAckEncoder<'a> {
1009 pub(super) path_id: PathId,
1010 pub(super) delay: u64,
1011 pub(super) ranges: &'a ArrayRangeSet,
1012 pub(super) ecn: Option<&'a EcnCounts>,
1013}
1014
1015impl<'a> PathAckEncoder<'a> {
1016 const fn get_type(&self) -> FrameType {
1017 match self.ecn.is_some() {
1018 true => FrameType::PathAckEcn,
1019 false => FrameType::PathAck,
1020 }
1021 }
1022}
1023
1024impl<'a> Encodable for PathAckEncoder<'a> {
1025 fn encode<W: BufMut>(&self, buf: &mut W) {
1032 let PathAckEncoder {
1033 path_id,
1034 delay,
1035 ranges,
1036 ecn,
1037 } = self;
1038 let mut rest = ranges.iter().rev();
1039 let first = rest
1040 .next()
1041 .expect("Caller has verified ranges is non empty");
1042 let largest = first.end - 1;
1043 let first_size = first.end - first.start;
1044 let kind = match ecn.is_some() {
1045 true => FrameType::PathAckEcn,
1046 false => FrameType::PathAck,
1047 };
1048 buf.write(kind);
1049 buf.write(*path_id);
1050 buf.write_var(largest);
1051 buf.write_var(*delay);
1052 buf.write_var(ranges.len() as u64 - 1);
1053 buf.write_var(first_size - 1);
1054 let mut prev = first.start;
1055 for block in rest {
1056 let size = block.end - block.start;
1057 buf.write_var(prev - block.end - 1);
1058 buf.write_var(size - 1);
1059 prev = block.start;
1060 }
1061 if let Some(x) = ecn {
1062 x.encode(buf)
1063 }
1064 }
1065}
1066
1067#[derive(Debug, Clone, Eq, PartialEq, derive_more::Display)]
1068#[display("{} ranges: {ranges:?} delay: {delay}µs largest: {largest}", self.get_type())]
1069pub(crate) struct Ack {
1070 pub largest: u64,
1071 pub delay: u64,
1072 pub ranges: ArrayRangeSet,
1073 pub ecn: Option<EcnCounts>,
1074}
1075
1076#[cfg(test)]
1077impl proptest::arbitrary::Arbitrary for Ack {
1078 type Parameters = ();
1079 type Strategy = proptest::strategy::BoxedStrategy<Self>;
1080
1081 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
1082 use proptest::prelude::*;
1083 (
1084 varint_u64(),
1085 any::<ArrayRangeSet>()
1086 .prop_filter("ranges must be non empty", |ranges| !ranges.is_empty()),
1087 any::<Option<EcnCounts>>(),
1088 )
1089 .prop_map(|(delay, ranges, ecn)| Self {
1090 largest: ranges.max().expect("ranges must be non empty"),
1091 delay,
1092 ranges,
1093 ecn,
1094 })
1095 .boxed()
1096 }
1097}
1098
1099impl Ack {
1100 pub(crate) fn encoder<'a>(
1101 delay: u64,
1102 ranges: &'a ArrayRangeSet,
1103 ecn: Option<&'a EcnCounts>,
1104 ) -> AckEncoder<'a> {
1105 AckEncoder { delay, ranges, ecn }
1106 }
1107
1108 pub(crate) fn iter(&self) -> impl DoubleEndedIterator<Item = Range<u64>> + '_ {
1109 self.ranges.iter()
1110 }
1111
1112 pub(crate) const fn get_type(&self) -> FrameType {
1113 if self.ecn.is_some() {
1114 FrameType::AckEcn
1115 } else {
1116 FrameType::Ack
1117 }
1118 }
1119}
1120
1121#[derive(derive_more::Display)]
1122#[display("{} ranges: {ranges:?} delay: {delay}µs", self.get_type())]
1123pub(crate) struct AckEncoder<'a> {
1124 pub(crate) delay: u64,
1125 pub(crate) ranges: &'a ArrayRangeSet,
1126 pub(crate) ecn: Option<&'a EcnCounts>,
1127}
1128
1129impl<'a> AckEncoder<'a> {
1130 const fn get_type(&self) -> FrameType {
1131 match self.ecn.is_some() {
1132 true => FrameType::AckEcn,
1133 false => FrameType::Ack,
1134 }
1135 }
1136}
1137
1138impl<'a> Encodable for AckEncoder<'a> {
1139 fn encode<W: BufMut>(&self, buf: &mut W) {
1140 let AckEncoder { delay, ranges, ecn } = self;
1141 let mut rest = ranges.iter().rev();
1142 let first = rest.next().unwrap();
1143 let largest = first.end - 1;
1144 let first_size = first.end - first.start;
1145 let kind = match ecn.is_some() {
1146 true => FrameType::AckEcn,
1147 false => FrameType::Ack,
1148 };
1149 buf.write(kind);
1150 buf.write_var(largest);
1151 buf.write_var(*delay);
1152 buf.write_var(ranges.len() as u64 - 1);
1153 buf.write_var(first_size - 1);
1154 let mut prev = first.start;
1155 for block in rest {
1156 let size = block.end - block.start;
1157 buf.write_var(prev - block.end - 1);
1158 buf.write_var(size - 1);
1159 prev = block.start;
1160 }
1161 if let Some(x) = ecn {
1162 x.encode(buf)
1163 }
1164 }
1165}
1166
1167#[cfg_attr(test, derive(Arbitrary))]
1168#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1169pub(crate) struct EcnCounts {
1170 #[cfg_attr(test, strategy(varint_u64()))]
1171 pub ect0: u64,
1172 #[cfg_attr(test, strategy(varint_u64()))]
1173 pub ect1: u64,
1174 #[cfg_attr(test, strategy(varint_u64()))]
1175 pub ce: u64,
1176}
1177
1178impl std::ops::AddAssign<EcnCodepoint> for EcnCounts {
1179 fn add_assign(&mut self, rhs: EcnCodepoint) {
1180 match rhs {
1181 EcnCodepoint::Ect0 => {
1182 self.ect0 += 1;
1183 }
1184 EcnCodepoint::Ect1 => {
1185 self.ect1 += 1;
1186 }
1187 EcnCodepoint::Ce => {
1188 self.ce += 1;
1189 }
1190 }
1191 }
1192}
1193
1194impl EcnCounts {
1195 pub(crate) const ZERO: Self = Self {
1196 ect0: 0,
1197 ect1: 0,
1198 ce: 0,
1199 };
1200}
1201
1202impl Encodable for EcnCounts {
1203 fn encode<W: BufMut>(&self, out: &mut W) {
1204 out.write_var(self.ect0);
1205 out.write_var(self.ect1);
1206 out.write_var(self.ce);
1207 }
1208}
1209
1210#[derive(Debug, Clone, derive_more::Display)]
1211#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
1212#[display("STREAM id: {id} off: {offset} len: {} fin: {fin}", data.len())]
1213pub(crate) struct Stream {
1214 pub(crate) id: StreamId,
1215 #[cfg_attr(test, strategy(varint_u64()))]
1216 pub(crate) offset: u64,
1217 pub(crate) fin: bool,
1218 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..100), Bytes::from)))]
1219 pub(crate) data: Bytes,
1220}
1221
1222impl FrameStruct for Stream {
1223 const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
1224}
1225
1226#[derive(Debug, Clone, derive_more::Display)]
1228#[display("STREAM id: {id} off: {} len: {} fin: {fin}", offsets.start, offsets.end - offsets.start)]
1229pub(crate) struct StreamMeta {
1230 pub(crate) id: StreamId,
1231 pub(crate) offsets: Range<u64>,
1232 pub(crate) fin: bool,
1233}
1234
1235impl Default for StreamMeta {
1237 fn default() -> Self {
1238 Self {
1239 id: StreamId(0),
1240 offsets: 0..0,
1241 fin: false,
1242 }
1243 }
1244}
1245
1246impl StreamMeta {
1247 pub(crate) fn encoder(self, encode_length: bool) -> StreamMetaEncoder {
1248 StreamMetaEncoder {
1249 meta: self,
1250 encode_length,
1251 }
1252 }
1253
1254 const fn get_type(&self, encode_length: bool) -> StreamInfo {
1255 let mut ty = *StreamInfo::VALUES.start();
1256 if self.offsets.start != 0 {
1257 ty |= 0x04;
1258 }
1259 if encode_length {
1260 ty |= 0x02;
1261 }
1262 if self.fin {
1263 ty |= 0x01;
1264 }
1265 StreamInfo(ty as u8)
1266 }
1267}
1268
1269#[derive(derive_more::Display)]
1270#[display("{meta}")]
1271pub(crate) struct StreamMetaEncoder {
1272 pub(crate) meta: StreamMeta,
1273 encode_length: bool,
1274}
1275
1276impl StreamMetaEncoder {
1277 const fn get_type(&self) -> FrameType {
1278 FrameType::Stream(self.meta.get_type(self.encode_length))
1279 }
1280}
1281
1282impl Encodable for StreamMetaEncoder {
1283 fn encode<W: BufMut>(&self, out: &mut W) {
1284 let Self {
1285 meta,
1286 encode_length,
1287 } = self;
1288 out.write_var(meta.get_type(*encode_length).0 as u64); out.write(meta.id); if meta.offsets.start != 0 {
1291 out.write_var(meta.offsets.start); }
1293 if *encode_length {
1294 out.write_var(meta.offsets.end - meta.offsets.start); }
1296 }
1297}
1298
1299pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>;
1301
1302#[derive(Debug, Clone, derive_more::Display)]
1303#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
1304#[display("CRYPTO off: {offset} len = {}", data.len())]
1305pub(crate) struct Crypto {
1306 #[cfg_attr(test, strategy(varint_u64()))]
1307 pub(crate) offset: u64,
1308 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..1024), Bytes::from)))]
1309 pub(crate) data: Bytes,
1310}
1311
1312impl Crypto {
1313 pub(crate) const SIZE_BOUND: usize = 17;
1314
1315 const fn get_type(&self) -> FrameType {
1316 FrameType::Crypto
1317 }
1318}
1319
1320impl Encodable for Crypto {
1321 fn encode<W: BufMut>(&self, out: &mut W) {
1322 out.write(FrameType::Crypto);
1323 out.write_var(self.offset);
1324 out.write_var(self.data.len() as u64);
1325 out.put_slice(&self.data);
1326 }
1327}
1328
1329#[derive(Debug, Clone, derive_more::Display)]
1330#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
1331#[display("NEW_TOKEN")]
1332pub(crate) struct NewToken {
1333 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..1024), Bytes::from)))]
1334 pub(crate) token: Bytes,
1335}
1336
1337impl Encodable for NewToken {
1338 fn encode<W: BufMut>(&self, out: &mut W) {
1339 out.write(FrameType::NewToken);
1340 out.write_var(self.token.len() as u64);
1341 out.put_slice(&self.token);
1342 }
1343}
1344
1345impl NewToken {
1346 pub(crate) fn size(&self) -> usize {
1347 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len()
1348 }
1349
1350 const fn get_type(&self) -> FrameType {
1351 FrameType::NewToken
1352 }
1353}
1354
1355#[derive(Debug, Clone, derive_more::Display)]
1356#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))]
1357#[display("MAX_PATH_ID path_id: {_0}")]
1358pub(crate) struct MaxPathId(pub(crate) PathId);
1359
1360impl MaxPathId {
1361 pub(crate) const SIZE_BOUND: usize =
1362 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size();
1363
1364 const fn get_type(&self) -> FrameType {
1365 FrameType::MaxPathId
1366 }
1367}
1368
1369impl Decodable for MaxPathId {
1370 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
1371 Ok(Self(buf.get()?))
1372 }
1373}
1374
1375impl Encodable for MaxPathId {
1376 fn encode<B: BufMut>(&self, buf: &mut B) {
1377 buf.write(FrameType::MaxPathId);
1378 buf.write(self.0);
1379 }
1380}
1381
1382#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
1383#[cfg_attr(test, derive(Arbitrary))]
1384#[display("PATHS_BLOCKED remote_max_path_id: {_0}")]
1385pub(crate) struct PathsBlocked(pub(crate) PathId);
1386
1387impl PathsBlocked {
1388 pub(crate) const SIZE_BOUND: usize =
1389 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size();
1390
1391 const fn get_type(&self) -> FrameType {
1392 FrameType::PathsBlocked
1393 }
1394}
1395
1396impl Encodable for PathsBlocked {
1397 fn encode<B: BufMut>(&self, buf: &mut B) {
1398 buf.write(FrameType::PathsBlocked);
1399 buf.write(self.0);
1400 }
1401}
1402
1403impl Decodable for PathsBlocked {
1404 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
1406 Ok(Self(buf.get()?))
1407 }
1408}
1409
1410#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
1411#[cfg_attr(test, derive(Arbitrary))]
1412#[display("PATH_CIDS_BLOCKED path_id: {path_id} next_seq: {next_seq}")]
1413pub(crate) struct PathCidsBlocked {
1414 pub(crate) path_id: PathId,
1415 pub(crate) next_seq: VarInt,
1416}
1417
1418impl PathCidsBlocked {
1419 pub(crate) const SIZE_BOUND: usize =
1420 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size();
1421
1422 const fn get_type(&self) -> FrameType {
1423 FrameType::PathCidsBlocked
1424 }
1425}
1426
1427impl Decodable for PathCidsBlocked {
1428 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> {
1429 Ok(Self {
1430 path_id: buf.get()?,
1431 next_seq: buf.get()?,
1432 })
1433 }
1434}
1435
1436impl Encodable for PathCidsBlocked {
1437 fn encode<W: BufMut>(&self, buf: &mut W) {
1438 buf.write(FrameType::PathCidsBlocked);
1439 buf.write(self.path_id);
1440 buf.write(self.next_seq);
1441 }
1442}
1443
1444pub(crate) struct Iter {
1445 bytes: Bytes,
1446 last_ty: MaybeFrame,
1447}
1448
1449impl Iter {
1450 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> {
1451 if payload.is_empty() {
1452 return Err(TransportError::PROTOCOL_VIOLATION(
1456 "packet payload is empty",
1457 ));
1458 }
1459
1460 Ok(Self {
1461 bytes: payload,
1462 last_ty: MaybeFrame::None,
1463 })
1464 }
1465
1466 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> {
1467 let len = self.bytes.get_var()?;
1468 if len > self.bytes.remaining() as u64 {
1469 return Err(UnexpectedEnd);
1470 }
1471 Ok(self.bytes.split_to(len as usize))
1472 }
1473
1474 #[track_caller]
1475 fn try_next(&mut self) -> Result<Frame, IterErr> {
1476 self.last_ty = self.bytes.get()?;
1477
1478 let ty = match self.last_ty {
1479 MaybeFrame::None => FrameType::Padding,
1480 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId),
1481 MaybeFrame::Known(frame_type) => frame_type,
1482 };
1483 Ok(match ty {
1484 FrameType::Padding => Frame::Padding,
1485 FrameType::ResetStream => Frame::ResetStream(ResetStream {
1486 id: self.bytes.get()?,
1487 error_code: self.bytes.get()?,
1488 final_offset: self.bytes.get()?,
1489 }),
1490 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose {
1491 error_code: self.bytes.get()?,
1492 frame_type: self.bytes.get()?,
1493 reason: self.take_len()?,
1494 })),
1495 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose {
1496 error_code: self.bytes.get()?,
1497 reason: self.take_len()?,
1498 })),
1499 FrameType::MaxData => Frame::MaxData(self.bytes.get()?),
1500 FrameType::MaxStreamData => Frame::MaxStreamData(self.bytes.get()?),
1501 FrameType::MaxStreamsBidi => Frame::MaxStreams(MaxStreams {
1502 dir: Dir::Bi,
1503 count: self.bytes.get_var()?,
1504 }),
1505 FrameType::MaxStreamsUni => Frame::MaxStreams(MaxStreams {
1506 dir: Dir::Uni,
1507 count: self.bytes.get_var()?,
1508 }),
1509 FrameType::Ping => Frame::Ping,
1510 FrameType::DataBlocked => Frame::DataBlocked(DataBlocked(self.bytes.get_var()?)),
1511 FrameType::StreamDataBlocked => Frame::StreamDataBlocked(StreamDataBlocked {
1512 id: self.bytes.get()?,
1513 offset: self.bytes.get_var()?,
1514 }),
1515 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked(StreamsBlocked {
1516 dir: Dir::Bi,
1517 limit: self.bytes.get_var()?,
1518 }),
1519 FrameType::StreamsBlockedUni => Frame::StreamsBlocked(StreamsBlocked {
1520 dir: Dir::Uni,
1521 limit: self.bytes.get_var()?,
1522 }),
1523 FrameType::StopSending => Frame::StopSending(StopSending {
1524 id: self.bytes.get()?,
1525 error_code: self.bytes.get()?,
1526 }),
1527 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => {
1528 Frame::RetireConnectionId(RetireConnectionId::decode(
1529 &mut self.bytes,
1530 ty == FrameType::PathRetireConnectionId,
1531 )?)
1532 }
1533 FrameType::Ack => {
1534 let largest = self.bytes.get_var()?;
1535 let delay = self.bytes.get_var()?;
1536 let ranges = read_ack_blocks(&mut self.bytes, largest)?;
1537 Frame::Ack(Ack {
1538 delay,
1539 largest,
1540 ranges,
1541 ecn: None,
1542 })
1543 }
1544 FrameType::AckEcn => {
1545 let largest = self.bytes.get_var()?;
1546 let delay = self.bytes.get_var()?;
1547 let ranges = read_ack_blocks(&mut self.bytes, largest)?;
1548 let ecn = Some(EcnCounts {
1549 ect0: self.bytes.get_var()?,
1550 ect1: self.bytes.get_var()?,
1551 ce: self.bytes.get_var()?,
1552 });
1553
1554 Frame::Ack(Ack {
1555 delay,
1556 largest,
1557 ranges,
1558 ecn,
1559 })
1560 }
1561 FrameType::PathAck => {
1562 let path_id = self.bytes.get()?;
1563 let largest = self.bytes.get_var()?;
1564 let delay = self.bytes.get_var()?;
1565 let ranges = read_ack_blocks(&mut self.bytes, largest)?;
1566 Frame::PathAck(PathAck {
1567 path_id,
1568 delay,
1569 largest,
1570 ranges,
1571 ecn: None,
1572 })
1573 }
1574 FrameType::PathAckEcn => {
1575 let path_id = self.bytes.get()?;
1576 let largest = self.bytes.get_var()?;
1577 let delay = self.bytes.get_var()?;
1578 let ranges = read_ack_blocks(&mut self.bytes, largest)?;
1579 let ecn = Some(EcnCounts {
1580 ect0: self.bytes.get_var()?,
1581 ect1: self.bytes.get_var()?,
1582 ce: self.bytes.get_var()?,
1583 });
1584 Frame::PathAck(PathAck {
1585 path_id,
1586 delay,
1587 largest,
1588 ranges,
1589 ecn,
1590 })
1591 }
1592 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?),
1593 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?),
1594 FrameType::NewConnectionId | FrameType::PathNewConnectionId => {
1595 let read_path = ty == FrameType::PathNewConnectionId;
1596 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?)
1597 }
1598 FrameType::Crypto => Frame::Crypto(Crypto {
1599 offset: self.bytes.get_var()?,
1600 data: self.take_len()?,
1601 }),
1602 FrameType::NewToken => Frame::NewToken(NewToken {
1603 token: self.take_len()?,
1604 }),
1605 FrameType::HandshakeDone => Frame::HandshakeDone,
1606 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency {
1607 sequence: self.bytes.get()?,
1608 ack_eliciting_threshold: self.bytes.get()?,
1609 request_max_ack_delay: self.bytes.get()?,
1610 reordering_threshold: self.bytes.get()?,
1611 }),
1612 FrameType::ImmediateAck => Frame::ImmediateAck,
1613 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => {
1614 let is_ipv6 = ty == FrameType::ObservedIpv6Addr;
1615 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?;
1616 Frame::ObservedAddr(observed)
1617 }
1618 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?),
1619 FrameType::PathStatusAvailable => {
1620 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?)
1621 }
1622 FrameType::PathStatusBackup => {
1623 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?)
1624 }
1625 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?),
1626 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?),
1627 FrameType::PathCidsBlocked => {
1628 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?)
1629 }
1630 FrameType::AddIpv4Address | FrameType::AddIpv6Address => {
1631 let is_ipv6 = ty == FrameType::AddIpv6Address;
1632 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?;
1633 Frame::AddAddress(add_address)
1634 }
1635 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => {
1636 let is_ipv6 = ty == FrameType::ReachOutAtIpv6;
1637 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?;
1638 Frame::ReachOut(reach_out)
1639 }
1640 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?),
1641 FrameType::Stream(s) => Frame::Stream(Stream {
1642 id: self.bytes.get()?,
1643 offset: if s.off() { self.bytes.get_var()? } else { 0 },
1644 fin: s.fin(),
1645 data: if s.len() {
1646 self.take_len()?
1647 } else {
1648 self.take_remaining()
1649 },
1650 }),
1651 FrameType::Datagram(d) => Frame::Datagram(Datagram {
1652 data: if d.len() {
1653 self.take_len()?
1654 } else {
1655 self.take_remaining()
1656 },
1657 }),
1658 })
1659 }
1660
1661 pub(crate) fn take_remaining(&mut self) -> Bytes {
1662 mem::take(&mut self.bytes)
1663 }
1664}
1665
1666impl Iterator for Iter {
1667 type Item = Result<Frame, InvalidFrame>;
1668 fn next(&mut self) -> Option<Self::Item> {
1669 if !self.bytes.has_remaining() {
1670 return None;
1671 }
1672 match self.try_next() {
1673 Ok(x) => Some(Ok(x)),
1674 Err(e) => {
1675 self.bytes.clear();
1677 Some(Err(InvalidFrame {
1678 ty: self.last_ty,
1679 reason: e.reason(),
1680 }))
1681 }
1682 }
1683 }
1684}
1685
1686#[derive(Debug)]
1687pub(crate) struct InvalidFrame {
1688 pub(crate) ty: MaybeFrame,
1689 pub(crate) reason: &'static str,
1690}
1691
1692impl From<InvalidFrame> for TransportError {
1693 fn from(err: InvalidFrame) -> Self {
1694 let mut te = Self::FRAME_ENCODING_ERROR(err.reason);
1695 te.frame = err.ty;
1696 te
1697 }
1698}
1699
1700fn read_ack_blocks(buf: &mut Bytes, mut largest: u64) -> Result<ArrayRangeSet, IterErr> {
1709 let num_blocks = buf.get_var()?;
1711
1712 let mut out = ArrayRangeSet::new();
1713 let mut block_to_block;
1714 let mut range;
1715
1716 for num_block in 0..num_blocks + 1 {
1717 range = buf.get_var()?;
1718 range += 1;
1719
1720 let start = (largest + 1).checked_sub(range).ok_or(IterErr::Malformed)?;
1721
1722 if range > 0 {
1723 out.insert(start..largest + 1);
1724 }
1725
1726 if num_block < num_blocks {
1728 block_to_block = buf.get_var()?;
1730 block_to_block += 1;
1731 block_to_block += range;
1732
1733 largest = largest
1734 .checked_sub(block_to_block)
1735 .ok_or(IterErr::Malformed)?;
1736 }
1737 }
1738
1739 Ok(out)
1740}
1741
1742#[derive(Debug)]
1743enum IterErr {
1744 UnexpectedEnd,
1745 InvalidFrameId,
1746 Malformed,
1747}
1748
1749impl IterErr {
1750 fn reason(&self) -> &'static str {
1751 use IterErr::*;
1752 match *self {
1753 UnexpectedEnd => "unexpected end",
1754 InvalidFrameId => "invalid frame ID",
1755 Malformed => "malformed",
1756 }
1757 }
1758}
1759
1760impl From<UnexpectedEnd> for IterErr {
1761 fn from(_: UnexpectedEnd) -> Self {
1762 Self::UnexpectedEnd
1763 }
1764}
1765
1766#[allow(unreachable_pub)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1768#[cfg_attr(test, derive(Arbitrary))]
1769#[derive(Debug, Copy, Clone, derive_more::Display)]
1770#[display("RESET_STREAM id: {id}")]
1771pub struct ResetStream {
1772 pub(crate) id: StreamId,
1773 pub(crate) error_code: VarInt,
1774 pub(crate) final_offset: VarInt,
1775}
1776
1777impl ResetStream {
1778 const fn get_type(&self) -> FrameType {
1779 FrameType::ResetStream
1780 }
1781}
1782
1783impl FrameStruct for ResetStream {
1784 const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
1785}
1786
1787impl Encodable for ResetStream {
1788 fn encode<W: BufMut>(&self, out: &mut W) {
1789 out.write(FrameType::ResetStream); out.write(self.id); out.write(self.error_code); out.write(self.final_offset); }
1794}
1795
1796#[cfg_attr(test, derive(Arbitrary))]
1797#[derive(Debug, Copy, Clone, derive_more::Display)]
1798#[display("STOP_SENDING id: {id}")]
1799pub(crate) struct StopSending {
1800 pub(crate) id: StreamId,
1801 pub(crate) error_code: VarInt,
1802}
1803
1804impl FrameStruct for StopSending {
1805 const SIZE_BOUND: usize = 1 + 8 + 8;
1806}
1807
1808impl StopSending {
1809 const fn get_type(&self) -> FrameType {
1810 FrameType::StopSending
1811 }
1812}
1813
1814impl Encodable for StopSending {
1815 fn encode<W: BufMut>(&self, out: &mut W) {
1816 out.write(FrameType::StopSending); out.write(self.id); out.write(self.error_code) }
1820}
1821
1822#[derive(Debug, Copy, Clone, PartialEq, Eq, derive_more::Display)]
1823#[display("{} {} seq: {sequence} id: {id}", self.get_type(), DisplayOption::new("path_id", path_id.as_ref()))]
1824pub(crate) struct NewConnectionId {
1825 pub(crate) path_id: Option<PathId>,
1826 pub(crate) sequence: u64,
1827 pub(crate) retire_prior_to: u64,
1828 pub(crate) id: ConnectionId,
1829 pub(crate) reset_token: ResetToken,
1830}
1831
1832#[cfg(test)]
1833fn connection_id_and_reset_token() -> impl Strategy<Value = (crate::ConnectionId, ResetToken)> {
1834 (any::<ConnectionId>(), any::<[u8; 64]>()).prop_map(|(id, reset_key)| {
1835 #[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
1836 use aws_lc_rs::hmac;
1837 #[cfg(feature = "ring")]
1838 use ring::hmac;
1839 let key = hmac::Key::new(hmac::HMAC_SHA256, &reset_key);
1840 (id, ResetToken::new(&key, id))
1841 })
1842}
1843
1844#[cfg(test)]
1845impl proptest::arbitrary::Arbitrary for NewConnectionId {
1846 type Parameters = ();
1847 type Strategy = proptest::strategy::BoxedStrategy<Self>;
1848
1849 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
1850 use proptest::prelude::*;
1851 (
1852 any::<Option<PathId>>(),
1853 varint_u64(),
1854 varint_u64(),
1855 connection_id_and_reset_token(),
1856 )
1857 .prop_map(|(path_id, a, b, (id, reset_token))| {
1858 let sequence = std::cmp::max(a, b);
1859 let retire_prior_to = std::cmp::min(a, b);
1860 Self {
1861 path_id,
1862 sequence,
1863 retire_prior_to,
1864 id,
1865 reset_token,
1866 }
1867 })
1868 .boxed()
1869 }
1870}
1871
1872impl NewConnectionId {
1873 pub(crate) const SIZE_BOUND: usize = {
1875 let type_len = FrameType::NewConnectionId.size();
1876 let seq_max_len = 8usize;
1877 let retire_prior_to_max_len = 8usize;
1878 let cid_len_len = 1;
1879 let cid_len = 160;
1880 let reset_token_len = 16;
1881 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len
1882 };
1883
1884 pub(crate) const SIZE_BOUND_MULTIPATH: usize = {
1886 let type_len = FrameType::PathNewConnectionId.size();
1887 let path_id_len = VarInt::from_u32(u32::MAX).size();
1888 let seq_max_len = 8usize;
1889 let retire_prior_to_max_len = 8usize;
1890 let cid_len_len = 1;
1891 let cid_len = 160;
1892 let reset_token_len = 16;
1893 type_len
1894 + path_id_len
1895 + seq_max_len
1896 + retire_prior_to_max_len
1897 + cid_len_len
1898 + cid_len
1899 + reset_token_len
1900 };
1901
1902 const fn get_type(&self) -> FrameType {
1903 if self.path_id.is_some() {
1904 FrameType::PathNewConnectionId
1905 } else {
1906 FrameType::NewConnectionId
1907 }
1908 }
1909
1910 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize {
1914 let upper_bound = match path_new_cid {
1915 true => Self::SIZE_BOUND_MULTIPATH,
1916 false => Self::SIZE_BOUND,
1917 };
1918 upper_bound - 160 + cid_len
1920 }
1921
1922 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> {
1923 let path_id = if read_path { Some(bytes.get()?) } else { None };
1924 let sequence = bytes.get_var()?;
1925 let retire_prior_to = bytes.get_var()?;
1926 if retire_prior_to > sequence {
1927 return Err(IterErr::Malformed);
1928 }
1929 let length = bytes.get::<u8>()? as usize;
1930 if length > MAX_CID_SIZE || length == 0 {
1931 return Err(IterErr::Malformed);
1932 }
1933 if length > bytes.remaining() {
1934 return Err(IterErr::UnexpectedEnd);
1935 }
1936 let mut stage = [0; MAX_CID_SIZE];
1937 bytes.copy_to_slice(&mut stage[0..length]);
1938 let id = ConnectionId::new(&stage[..length]);
1939 if bytes.remaining() < 16 {
1940 return Err(IterErr::UnexpectedEnd);
1941 }
1942 let mut reset_token = [0; RESET_TOKEN_SIZE];
1943 bytes.copy_to_slice(&mut reset_token);
1944 Ok(Self {
1945 path_id,
1946 sequence,
1947 retire_prior_to,
1948 id,
1949 reset_token: reset_token.into(),
1950 })
1951 }
1952
1953 pub(crate) fn issued(&self) -> crate::shared::IssuedCid {
1954 crate::shared::IssuedCid {
1955 path_id: self.path_id.unwrap_or_default(),
1956 sequence: self.sequence,
1957 id: self.id,
1958 reset_token: self.reset_token,
1959 }
1960 }
1961}
1962
1963impl Encodable for NewConnectionId {
1964 fn encode<W: BufMut>(&self, out: &mut W) {
1965 out.write(self.get_type());
1966 if let Some(id) = self.path_id {
1967 out.write(id);
1968 }
1969 out.write_var(self.sequence);
1970 out.write_var(self.retire_prior_to);
1971 out.write(self.id.len() as u8);
1972 out.put_slice(&self.id);
1973 out.put_slice(&self.reset_token);
1974 }
1975}
1976
1977impl FrameStruct for NewConnectionId {
1978 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE;
1979}
1980
1981#[derive(Debug, Clone, derive_more::Display)]
1983#[cfg_attr(test, derive(Arbitrary))]
1984#[display("DATAGRAM len: {}", data.len())]
1985pub struct Datagram {
1986 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..100), Bytes::from)))]
1988 pub data: Bytes,
1989}
1990
1991impl FrameStruct for Datagram {
1992 const SIZE_BOUND: usize = 1 + 8;
1993}
1994
1995impl Datagram {
1996 pub(crate) fn size(&self, length: bool) -> usize {
1997 1 + if length {
1998 VarInt::from_u64(self.data.len() as u64).unwrap().size()
1999 } else {
2000 0
2001 } + self.data.len()
2002 }
2003
2004 const fn get_type(&self) -> FrameType {
2005 FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8))
2006 }
2007}
2008
2009impl Encodable for Datagram {
2010 fn encode<B: BufMut>(&self, out: &mut B) {
2011 const ENCODE_LEN: bool = true;
2013 out.write(FrameType::Datagram(DatagramInfo(
2014 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN),
2015 ))); out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); out.put_slice(&self.data);
2019 }
2020}
2021
2022#[derive(Debug, Copy, Clone, PartialEq, Eq, derive_more::Display)]
2023#[cfg_attr(test, derive(Arbitrary))]
2024#[display("ACK_FREQUENCY max_ack_delay: {}µs", request_max_ack_delay.0)]
2025pub(crate) struct AckFrequency {
2026 pub(crate) sequence: VarInt,
2027 pub(crate) ack_eliciting_threshold: VarInt,
2028 pub(crate) request_max_ack_delay: VarInt,
2029 pub(crate) reordering_threshold: VarInt,
2030}
2031
2032impl AckFrequency {
2033 const fn get_type(&self) -> FrameType {
2034 FrameType::AckFrequency
2035 }
2036}
2037
2038impl Encodable for AckFrequency {
2039 fn encode<W: BufMut>(&self, buf: &mut W) {
2040 buf.write(FrameType::AckFrequency);
2041 buf.write(self.sequence);
2042 buf.write(self.ack_eliciting_threshold);
2043 buf.write(self.request_max_ack_delay);
2044 buf.write(self.reordering_threshold);
2045 }
2046}
2047
2048#[derive(Debug, PartialEq, Eq, Clone, derive_more::Display)]
2053#[display("{} seq_no: {seq_no} addr: {}", self.get_type(), self.socket_addr())]
2054#[cfg_attr(test, derive(Arbitrary))]
2055pub(crate) struct ObservedAddr {
2056 pub(crate) seq_no: VarInt,
2058 pub(crate) ip: IpAddr,
2060 pub(crate) port: u16,
2062}
2063
2064impl ObservedAddr {
2065 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self {
2066 Self {
2067 ip: remote.ip(),
2068 port: remote.port(),
2069 seq_no: seq_no.into(),
2070 }
2071 }
2072
2073 const fn get_type(&self) -> FrameType {
2075 if self.ip.is_ipv6() {
2076 FrameType::ObservedIpv6Addr
2077 } else {
2078 FrameType::ObservedIpv4Addr
2079 }
2080 }
2081
2082 pub(crate) fn size(&self) -> usize {
2084 let type_size = self.get_type().size();
2085 let req_id_bytes = self.seq_no.size();
2086 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
2087 let port_bytes = 2;
2088 type_size + req_id_bytes + ip_bytes + port_bytes
2089 }
2090
2091 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
2096 let seq_no = bytes.get()?;
2097 let ip = if is_ipv6 {
2098 IpAddr::V6(bytes.get()?)
2099 } else {
2100 IpAddr::V4(bytes.get()?)
2101 };
2102 let port = bytes.get()?;
2103 Ok(Self { seq_no, ip, port })
2104 }
2105
2106 pub(crate) fn socket_addr(&self) -> SocketAddr {
2108 (self.ip, self.port).into()
2109 }
2110}
2111
2112impl Encodable for ObservedAddr {
2113 fn encode<W: BufMut>(&self, buf: &mut W) {
2114 buf.write(self.get_type());
2115 buf.write(self.seq_no);
2116 match self.ip {
2117 IpAddr::V4(ipv4_addr) => {
2118 buf.write(ipv4_addr);
2119 }
2120 IpAddr::V6(ipv6_addr) => {
2121 buf.write(ipv6_addr);
2122 }
2123 }
2124 buf.write::<u16>(self.port);
2125 }
2126}
2127
2128#[derive(Debug, PartialEq, Eq, derive_more::Display)]
2131#[cfg_attr(test, derive(Arbitrary))]
2132#[display("PATH_ABANDON path_id: {path_id}")]
2133pub(crate) struct PathAbandon {
2134 pub(crate) path_id: PathId,
2135 pub(crate) error_code: TransportErrorCode,
2136}
2137
2138impl PathAbandon {
2139 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8;
2140
2141 const fn get_type(&self) -> FrameType {
2142 FrameType::PathAbandon
2143 }
2144}
2145
2146impl Encodable for PathAbandon {
2147 fn encode<W: BufMut>(&self, buf: &mut W) {
2148 buf.write(FrameType::PathAbandon);
2149 buf.write(self.path_id);
2150 buf.write(self.error_code);
2151 }
2152}
2153
2154impl Decodable for PathAbandon {
2155 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
2156 Ok(Self {
2157 path_id: bytes.get()?,
2158 error_code: bytes.get()?,
2159 })
2160 }
2161}
2162
2163#[derive(Debug, PartialEq, Eq, derive_more::Display)]
2164#[cfg_attr(test, derive(Arbitrary))]
2165#[display("PATH_STATUS_AVAILABLE path_id: {path_id} seq_no: {status_seq_no}")]
2166pub(crate) struct PathStatusAvailable {
2167 pub(crate) path_id: PathId,
2168 pub(crate) status_seq_no: VarInt,
2169}
2170
2171impl PathStatusAvailable {
2172 const TYPE: FrameType = FrameType::PathStatusAvailable;
2173 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8;
2174
2175 const fn get_type(&self) -> FrameType {
2176 FrameType::PathStatusAvailable
2177 }
2178}
2179
2180impl Encodable for PathStatusAvailable {
2181 fn encode<W: BufMut>(&self, buf: &mut W) {
2182 buf.write(Self::TYPE);
2183 buf.write(self.path_id);
2184 buf.write(self.status_seq_no);
2185 }
2186}
2187
2188impl Decodable for PathStatusAvailable {
2189 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
2190 Ok(Self {
2191 path_id: bytes.get()?,
2192 status_seq_no: bytes.get()?,
2193 })
2194 }
2195}
2196
2197#[derive(Debug, PartialEq, Eq, derive_more::Display)]
2198#[cfg_attr(test, derive(Arbitrary))]
2199#[display("PATH_STATUS_BACKUP path_id: {path_id} seq_no: {status_seq_no}")]
2200pub(crate) struct PathStatusBackup {
2201 pub(crate) path_id: PathId,
2202 pub(crate) status_seq_no: VarInt,
2203}
2204
2205impl PathStatusBackup {
2206 const TYPE: FrameType = FrameType::PathStatusBackup;
2207
2208 const fn get_type(&self) -> FrameType {
2209 FrameType::PathStatusBackup
2210 }
2211}
2212
2213impl Encodable for PathStatusBackup {
2214 fn encode<W: BufMut>(&self, buf: &mut W) {
2215 buf.write(Self::TYPE);
2216 buf.write(self.path_id);
2217 buf.write(self.status_seq_no);
2218 }
2219}
2220
2221impl Decodable for PathStatusBackup {
2222 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
2223 Ok(Self {
2224 path_id: bytes.get()?,
2225 status_seq_no: bytes.get()?,
2226 })
2227 }
2228}
2229
2230#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, derive_more::Display)]
2235#[display("{} seq_no: {seq_no} addr: {}", self.get_type(), self.socket_addr())]
2236#[cfg_attr(test, derive(Arbitrary))]
2237pub(crate) struct AddAddress {
2238 pub(crate) seq_no: VarInt,
2241 pub(crate) ip: IpAddr,
2243 pub(crate) port: u16,
2245}
2246
2247#[allow(dead_code)]
2249impl AddAddress {
2250 pub(crate) const SIZE_BOUND: usize = Self {
2252 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST),
2253 port: u16::MAX,
2254 seq_no: VarInt::MAX,
2255 }
2256 .size();
2257
2258 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self {
2259 Self { ip, port, seq_no }
2260 }
2261
2262 const fn get_type(&self) -> FrameType {
2264 if self.ip.is_ipv6() {
2265 FrameType::AddIpv6Address
2266 } else {
2267 FrameType::AddIpv4Address
2268 }
2269 }
2270
2271 pub(crate) const fn size(&self) -> usize {
2273 let type_size = self.get_type().size();
2274 let seq_no_bytes = self.seq_no.size();
2275 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
2276 let port_bytes = 2;
2277 type_size + seq_no_bytes + ip_bytes + port_bytes
2278 }
2279
2280 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
2285 let seq_no = bytes.get()?;
2286 let ip = if is_ipv6 {
2287 IpAddr::V6(bytes.get()?)
2288 } else {
2289 IpAddr::V4(bytes.get()?)
2290 };
2291 let port = bytes.get()?;
2292 Ok(Self { seq_no, ip, port })
2293 }
2294
2295 pub(crate) fn socket_addr(&self) -> SocketAddr {
2297 self.ip_port().into()
2298 }
2299
2300 pub(crate) fn ip_port(&self) -> (IpAddr, u16) {
2301 (self.ip, self.port)
2302 }
2303}
2304
2305impl Encodable for AddAddress {
2306 fn encode<W: BufMut>(&self, buf: &mut W) {
2307 buf.write(self.get_type());
2308 buf.write(self.seq_no);
2309 match self.ip {
2310 IpAddr::V4(ipv4_addr) => {
2311 buf.write(ipv4_addr);
2312 }
2313 IpAddr::V6(ipv6_addr) => {
2314 buf.write(ipv6_addr);
2315 }
2316 }
2317 buf.write::<u16>(self.port);
2318 }
2319}
2320
2321#[derive(Debug, PartialEq, Eq, Clone, derive_more::Display)]
2324#[display("REACH_OUT round: {round} local_addr: {}", self.socket_addr())]
2325#[cfg_attr(test, derive(Arbitrary))]
2326pub(crate) struct ReachOut {
2327 pub(crate) round: VarInt,
2329 pub(crate) ip: IpAddr,
2331 pub(crate) port: u16,
2333}
2334
2335#[allow(dead_code)]
2337impl ReachOut {
2338 pub(crate) const SIZE_BOUND: usize = Self {
2340 round: VarInt::MAX,
2341 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST),
2342 port: u16::MAX,
2343 }
2344 .size();
2345
2346 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self {
2347 Self { round, ip, port }
2348 }
2349
2350 pub(crate) const fn get_type(&self) -> FrameType {
2352 if self.ip.is_ipv6() {
2353 FrameType::ReachOutAtIpv6
2354 } else {
2355 FrameType::ReachOutAtIpv4
2356 }
2357 }
2358
2359 pub(crate) const fn size(&self) -> usize {
2361 let type_size = self.get_type().size();
2362 let round_bytes = self.round.size();
2363 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
2364 let port_bytes = 2;
2365 type_size + round_bytes + ip_bytes + port_bytes
2366 }
2367
2368 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
2373 let round = bytes.get()?;
2374 let ip = if is_ipv6 {
2375 IpAddr::V6(bytes.get()?)
2376 } else {
2377 IpAddr::V4(bytes.get()?)
2378 };
2379 let port = bytes.get()?;
2380 Ok(Self { round, ip, port })
2381 }
2382
2383 pub(crate) fn socket_addr(&self) -> SocketAddr {
2385 (self.ip, self.port).into()
2386 }
2387}
2388
2389impl Encodable for ReachOut {
2390 fn encode<W: BufMut>(&self, buf: &mut W) {
2391 buf.write(self.get_type());
2392 buf.write(self.round);
2393 match self.ip {
2394 IpAddr::V4(ipv4_addr) => {
2395 buf.write(ipv4_addr);
2396 }
2397 IpAddr::V6(ipv6_addr) => {
2398 buf.write(ipv6_addr);
2399 }
2400 }
2401 buf.write::<u16>(self.port);
2402 }
2403}
2404
2405#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, derive_more::Display)]
2407#[cfg_attr(test, derive(Arbitrary))]
2408#[display("REMOVE_ADDRESS seq_no: {seq_no}")]
2409pub(crate) struct RemoveAddress {
2410 pub(crate) seq_no: VarInt,
2412}
2413
2414#[allow(dead_code)]
2416impl RemoveAddress {
2417 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress;
2419
2420 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size();
2422
2423 pub(crate) const fn new(seq_no: VarInt) -> Self {
2424 Self { seq_no }
2425 }
2426
2427 pub(crate) const fn size(&self) -> usize {
2429 let type_size = Self::TYPE.size();
2430 let seq_no_bytes = self.seq_no.size();
2431 type_size + seq_no_bytes
2432 }
2433
2434 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
2439 Ok(Self {
2440 seq_no: bytes.get()?,
2441 })
2442 }
2443
2444 const fn get_type(&self) -> FrameType {
2445 FrameType::RemoveAddress
2446 }
2447}
2448
2449impl Encodable for RemoveAddress {
2450 fn encode<W: BufMut>(&self, buf: &mut W) {
2451 buf.write(Self::TYPE);
2452 buf.write(self.seq_no);
2453 }
2454}
2455
2456struct DisplayOption<T: Display> {
2460 field_name: &'static str,
2461 op: Option<T>,
2462}
2463
2464impl<T: Display> DisplayOption<T> {
2465 fn new(field_name: &'static str, op: Option<T>) -> Self {
2466 Self { field_name, op }
2467 }
2468}
2469
2470impl<T: Display> Display for DisplayOption<T> {
2471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2472 if let Some(x) = self.op.as_ref() {
2473 write!(f, "{}: {x}", self.field_name)
2474 } else {
2475 fmt::Result::Ok(())
2476 }
2477 }
2478}
2479
2480#[cfg(test)]
2481mod test {
2482 use super::*;
2483 use crate::coding::Encodable;
2484 use assert_matches::assert_matches;
2485
2486 #[test]
2487 fn frame_type() {
2488 assert_eq!(
2489 FrameType::try_from(FrameType::Padding.to_u64()),
2490 Ok(FrameType::Padding),
2491 );
2492
2493 assert_eq!(
2494 FrameType::try_from(FrameType::Datagram(DatagramInfo(0x30)).to_u64()),
2495 Ok(FrameType::Datagram(DatagramInfo(0x30))),
2496 );
2497
2498 assert_eq!(
2499 FrameType::try_from(FrameType::Stream(StreamInfo(0x08)).to_u64()),
2500 Ok(FrameType::Stream(StreamInfo(0x08))),
2501 );
2502 }
2503
2504 #[track_caller]
2505 fn frames(buf: Vec<u8>) -> Vec<Frame> {
2506 Iter::new(Bytes::from(buf))
2507 .unwrap()
2508 .collect::<Result<Vec<_>, _>>()
2509 .unwrap()
2510 }
2511
2512 #[test]
2513 fn ack_coding() {
2514 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
2515 let mut ranges = ArrayRangeSet::new();
2516 for &packet in PACKETS {
2517 ranges.insert(packet..packet + 1);
2518 }
2519 let mut buf = Vec::new();
2520 const ECN: EcnCounts = EcnCounts {
2521 ect0: 42,
2522 ect1: 24,
2523 ce: 12,
2524 };
2525 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf);
2526 let frames = frames(buf);
2527 assert_eq!(frames.len(), 1);
2528 match frames[0] {
2529 Frame::Ack(ref ack) => {
2530 let mut packets = ack.iter().flatten().collect::<Vec<_>>();
2531 packets.sort_unstable();
2532 assert_eq!(&packets[..], PACKETS);
2533 assert_eq!(ack.ecn, Some(ECN));
2534 }
2535 ref x => panic!("incorrect frame {x:?}"),
2536 }
2537 }
2538
2539 #[test]
2540 #[allow(clippy::range_plus_one)]
2541 fn path_ack_coding_with_ecn() {
2542 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
2543 let mut ranges = ArrayRangeSet::new();
2544 for &packet in PACKETS {
2545 ranges.insert(packet..packet + 1);
2546 }
2547 let mut buf = Vec::new();
2548 const ECN: EcnCounts = EcnCounts {
2549 ect0: 42,
2550 ect1: 24,
2551 ce: 12,
2552 };
2553 const PATH_ID: PathId = PathId::MAX;
2554 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf);
2555 let frames = frames(buf);
2556 assert_eq!(frames.len(), 1);
2557 match frames[0] {
2558 Frame::PathAck(ref ack) => {
2559 assert_eq!(ack.path_id, PATH_ID);
2560 let mut packets = ack.ranges.iter().flatten().collect::<Vec<_>>();
2561 packets.sort_unstable();
2562 assert_eq!(&packets[..], PACKETS);
2563 assert_eq!(ack.ecn, Some(ECN));
2564 }
2565 ref x => panic!("incorrect frame {x:?}"),
2566 }
2567 }
2568
2569 #[test]
2570 #[allow(clippy::range_plus_one)]
2571 fn path_ack_coding_no_ecn() {
2572 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
2573 let mut ranges = ArrayRangeSet::new();
2574 for &packet in PACKETS {
2575 ranges.insert(packet..packet + 1);
2576 }
2577 let mut buf = Vec::new();
2578 const PATH_ID: PathId = PathId::MAX;
2579 PathAck::encoder(PATH_ID, 42, &ranges, None).encode(&mut buf);
2580 let frames = frames(buf);
2581 assert_eq!(frames.len(), 1);
2582 match frames[0] {
2583 Frame::PathAck(ref ack) => {
2584 assert_eq!(ack.path_id, PATH_ID);
2585 let mut packets = ack.ranges.iter().flatten().collect::<Vec<_>>();
2586 packets.sort_unstable();
2587 assert_eq!(&packets[..], PACKETS);
2588 assert_eq!(ack.ecn, None);
2589 }
2590 ref x => panic!("incorrect frame {x:?}"),
2591 }
2592 }
2593
2594 #[test]
2595 fn ack_frequency_coding() {
2596 let mut buf = Vec::new();
2597 let original = AckFrequency {
2598 sequence: VarInt(42),
2599 ack_eliciting_threshold: VarInt(20),
2600 request_max_ack_delay: VarInt(50_000),
2601 reordering_threshold: VarInt(1),
2602 };
2603 original.encode(&mut buf);
2604 let frames = frames(buf);
2605 assert_eq!(frames.len(), 1);
2606 match &frames[0] {
2607 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original),
2608 x => panic!("incorrect frame {x:?}"),
2609 }
2610 }
2611
2612 #[test]
2613 fn immediate_ack_coding() {
2614 let mut buf = Vec::new();
2615 FrameType::ImmediateAck.encode(&mut buf);
2616 let frames = frames(buf);
2617 assert_eq!(frames.len(), 1);
2618 assert_matches!(&frames[0], Frame::ImmediateAck);
2619 }
2620
2621 #[test]
2623 fn test_observed_addr_roundrip() {
2624 let observed_addr = ObservedAddr {
2625 seq_no: VarInt(42),
2626 ip: std::net::Ipv4Addr::LOCALHOST.into(),
2627 port: 4242,
2628 };
2629 let mut buf = Vec::with_capacity(observed_addr.size());
2630 observed_addr.encode(&mut buf);
2631
2632 assert_eq!(
2633 observed_addr.size(),
2634 buf.len(),
2635 "expected written bytes and actual size differ"
2636 );
2637
2638 let mut decoded = frames(buf);
2639 assert_eq!(decoded.len(), 1);
2640 match decoded.pop().expect("non empty") {
2641 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr),
2642 x => panic!("incorrect frame {x:?}"),
2643 }
2644 }
2645
2646 #[test]
2647 fn test_path_abandon_roundtrip() {
2648 let abandon = PathAbandon {
2649 path_id: PathId(42),
2650 error_code: TransportErrorCode::NO_ERROR,
2651 };
2652 let mut buf = Vec::new();
2653 abandon.encode(&mut buf);
2654
2655 let mut decoded = frames(buf);
2656 assert_eq!(decoded.len(), 1);
2657 match decoded.pop().expect("non empty") {
2658 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon),
2659 x => panic!("incorrect frame {x:?}"),
2660 }
2661 }
2662
2663 #[test]
2664 fn test_path_status_available_roundtrip() {
2665 let path_status_available = PathStatusAvailable {
2666 path_id: PathId(42),
2667 status_seq_no: VarInt(73),
2668 };
2669 let mut buf = Vec::new();
2670 path_status_available.encode(&mut buf);
2671
2672 let mut decoded = frames(buf);
2673 assert_eq!(decoded.len(), 1);
2674 match decoded.pop().expect("non empty") {
2675 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available),
2676 x => panic!("incorrect frame {x:?}"),
2677 }
2678 }
2679
2680 #[test]
2681 fn test_path_status_backup_roundtrip() {
2682 let path_status_backup = PathStatusBackup {
2683 path_id: PathId(42),
2684 status_seq_no: VarInt(73),
2685 };
2686 let mut buf = Vec::new();
2687 path_status_backup.encode(&mut buf);
2688
2689 let mut decoded = frames(buf);
2690 assert_eq!(decoded.len(), 1);
2691 match decoded.pop().expect("non empty") {
2692 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup),
2693 x => panic!("incorrect frame {x:?}"),
2694 }
2695 }
2696
2697 #[test]
2698 fn test_path_new_connection_id_roundtrip() {
2699 let cid = NewConnectionId {
2700 path_id: Some(PathId(22)),
2701 sequence: 31,
2702 retire_prior_to: 13,
2703 id: ConnectionId::new(&[0xAB; 8]),
2704 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]),
2705 };
2706 let mut buf = Vec::new();
2707 cid.encode(&mut buf);
2708
2709 let mut decoded = frames(buf);
2710 assert_eq!(decoded.len(), 1);
2711 match decoded.pop().expect("non empty") {
2712 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid),
2713 x => panic!("incorrect frame {x:?}"),
2714 }
2715 }
2716
2717 #[test]
2718 fn test_path_retire_connection_id_roundtrip() {
2719 let retire_cid = RetireConnectionId {
2720 path_id: Some(PathId(22)),
2721 sequence: 31,
2722 };
2723 let mut buf = Vec::new();
2724 retire_cid.encode(&mut buf);
2725
2726 let mut decoded = frames(buf);
2727 assert_eq!(decoded.len(), 1);
2728 match decoded.pop().expect("non empty") {
2729 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid),
2730 x => panic!("incorrect frame {x:?}"),
2731 }
2732 }
2733
2734 #[test]
2735 fn test_paths_blocked_path_cids_blocked_roundtrip() {
2736 let mut buf = Vec::new();
2737
2738 let frame0 = PathsBlocked(PathId(22));
2739 frame0.encode(&mut buf);
2740 let frame1 = PathCidsBlocked {
2741 path_id: PathId(23),
2742 next_seq: VarInt(32),
2743 };
2744 frame1.encode(&mut buf);
2745
2746 let mut decoded = frames(buf);
2747 assert_eq!(decoded.len(), 2);
2748 match decoded.pop().expect("non empty") {
2749 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1),
2750 x => panic!("incorrect frame {x:?}"),
2751 }
2752 match decoded.pop().expect("non empty") {
2753 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0),
2754 x => panic!("incorrect frame {x:?}"),
2755 }
2756 }
2757
2758 #[test]
2760 fn test_add_address_roundrip() {
2761 let add_address = AddAddress {
2762 seq_no: VarInt(42),
2763 ip: std::net::Ipv4Addr::LOCALHOST.into(),
2764 port: 4242,
2765 };
2766 let mut buf = Vec::with_capacity(add_address.size());
2767 add_address.encode(&mut buf);
2768
2769 assert_eq!(
2770 add_address.size(),
2771 buf.len(),
2772 "expected written bytes and actual size differ"
2773 );
2774
2775 let mut decoded = frames(buf);
2776 assert_eq!(decoded.len(), 1);
2777 match decoded.pop().expect("non empty") {
2778 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address),
2779 x => panic!("incorrect frame {x:?}"),
2780 }
2781 }
2782
2783 #[test]
2785 fn test_reach_out_roundrip() {
2786 let reach_out = ReachOut {
2787 round: VarInt(42),
2788 ip: std::net::Ipv6Addr::LOCALHOST.into(),
2789 port: 4242,
2790 };
2791 let mut buf = Vec::with_capacity(reach_out.size());
2792 reach_out.encode(&mut buf);
2793
2794 assert_eq!(
2795 reach_out.size(),
2796 buf.len(),
2797 "expected written bytes and actual size differ"
2798 );
2799
2800 let mut decoded = frames(buf);
2801 assert_eq!(decoded.len(), 1);
2802 match decoded.pop().expect("non empty") {
2803 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out),
2804 x => panic!("incorrect frame {x:?}"),
2805 }
2806 }
2807
2808 #[test]
2810 fn test_remove_address_roundrip() {
2811 let remove_addr = RemoveAddress::new(VarInt(10));
2812 let mut buf = Vec::with_capacity(remove_addr.size());
2813 remove_addr.encode(&mut buf);
2814
2815 assert_eq!(
2816 remove_addr.size(),
2817 buf.len(),
2818 "expected written bytes and actual size differ"
2819 );
2820
2821 let mut decoded = frames(buf);
2822 assert_eq!(decoded.len(), 1);
2823 match decoded.pop().expect("non empty") {
2824 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr),
2825 x => panic!("incorrect frame {x:?}"),
2826 }
2827 }
2828}