1use std::{
2 fmt::{self, Write},
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 = "arbitrary")]
21use arbitrary::Arbitrary;
22
23macro_rules! frame_types {
25 (enum_defs: [$($enum_defs: tt)*] try_from_arms: [$($try_from_arms: tt)*] to_u64_arms:[$($to_u64_arms: tt)*] $variant: ident = $value: literal, $($token: tt)*) => {
29 frame_types!{
30 enum_defs: [$($enum_defs)* $variant,]
31 try_from_arms: [$($try_from_arms)* $value => Self::$variant,]
32 to_u64_arms: [$($to_u64_arms)* FrameType::$variant => $value,]
33 $($token)*
34 }
35 };
36
37 (enum_defs: [$($enum_defs: tt)*] try_from_arms: [$($try_from_arms: tt)*] to_u64_arms:[$($to_u64_arms: tt)*] $variant: ident($inner: ident), $($token: tt)*) => {
41 frame_types!{
42 enum_defs: [$($enum_defs)* $variant($inner),]
43 try_from_arms: [$($try_from_arms)* value if <$inner>::VALUES.contains(&value) => Self::$variant($inner(value as u8)),]
44 to_u64_arms: [$($to_u64_arms)* FrameType::$variant($inner(value)) => value as u64,]
45 $($token)*
46 }
47 };
48
49 (enum_defs: [$($enum_defs: tt)+] try_from_arms: [$($try_from_arms: tt)+] to_u64_arms: [$($to_u64_arms: tt)+]) => {
51 #[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)]
53 #[display(rename_all = "SCREAMING_SNAKE_CASE")]
54 #[allow(missing_docs)]
55 pub enum FrameType {
56 $($enum_defs)*
57 }
58
59 pub struct InvalidFrameId(u64);
60
61 impl TryFrom<u64> for FrameType {
62 type Error = InvalidFrameId;
63 fn try_from(value: u64) -> Result<Self, Self::Error> {
64 Ok(match value {
65 $($try_from_arms)*
66 other => return Err(InvalidFrameId(other))
67 })
68 }
69 }
70
71 impl FrameType {
72 pub(crate) const fn to_u64(self) -> u64 {
73 match self {
74 $($to_u64_arms)*
75 }
76 }
77 }
78 };
79}
80
81frame_types! {
82 enum_defs: []
83 try_from_arms: []
84 to_u64_arms: []
85 Padding = 0x00,
86 Ping = 0x01,
87 Ack = 0x02,
88 AckEcn = 0x03,
89 ResetStream = 0x04,
90 StopSending = 0x05,
91 Crypto = 0x06,
92 NewToken = 0x07,
93 Stream(StreamInfo),
95 MaxData = 0x10,
96 MaxStreamData = 0x11,
97 MaxStreamsBidi = 0x12,
98 MaxStreamsUni = 0x13,
99 DataBlocked = 0x14,
100 StreamDataBlocked = 0x15,
101 StreamsBlockedBidi = 0x16,
102 StreamsBlockedUni = 0x17,
103 NewConnectionId = 0x18,
104 RetireConnectionId = 0x19,
105 PathChallenge = 0x1a,
106 PathResponse = 0x1b,
107 ConnectionClose = 0x1c,
108 ApplicationClose = 0x1d,
109 HandshakeDone = 0x1e,
110 AckFrequency = 0xaf,
112 ImmediateAck = 0x1f,
113 Datagram(DatagramInfo),
115 ObservedIpv4Addr = 0x9f81a6,
117 ObservedIpv6Addr = 0x9f81a7,
118 PathAck = 0x15228c00,
120 PathAckEcn = 0x15228c01,
121 PathAbandon = 0x15228c05,
122 PathStatusBackup = 0x15228c07,
123 PathStatusAvailable = 0x15228c08,
124 PathNewConnectionId = 0x15228c09,
125 PathRetireConnectionId = 0x15228c0a,
126 MaxPathId = 0x15228c0c,
127 PathsBlocked = 0x15228c0d,
128 PathCidsBlocked = 0x15228c0e,
129 AddIpv4Address = 0x3d7f90,
131 AddIpv6Address = 0x3d7f91,
132 ReachOutAtIpv4 = 0x3d7f92,
133 ReachOutAtIpv6 = 0x3d7f93,
134 RemoveAddress = 0x3d7f94,
135}
136
137impl FrameType {
138 const fn size(&self) -> usize {
140 VarInt(self.to_u64()).size()
141 }
142}
143
144impl Decodable for FrameType {
145 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
146 Self::try_from(buf.get_var()?).map_err(|_| coding::UnexpectedEnd)
147 }
148}
149
150impl Encodable for FrameType {
151 fn encode<B: BufMut>(&self, buf: &mut B) {
152 buf.write_var(self.to_u64());
153 }
154}
155
156pub(crate) trait FrameStruct {
157 const SIZE_BOUND: usize;
159}
160
161#[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)]
163pub enum MaybeFrame {
164 None,
166 #[display("UNKNOWN{:02x}", _0)]
168 #[debug("Unknown{:02x}", _0)]
169 Unknown(u64),
170 Known(FrameType),
172}
173
174impl MaybeFrame {
175 const fn size(&self) -> usize {
177 match self {
178 Self::None => VarInt(0).size(),
179 Self::Unknown(other) => VarInt(*other).size(),
180 Self::Known(frame_type) => frame_type.size(),
181 }
182 }
183}
184
185impl Decodable for MaybeFrame {
186 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
187 match FrameType::try_from(buf.get_var()?) {
188 Ok(FrameType::Padding) => Ok(Self::None),
189 Ok(other_frame) => Ok(Self::Known(other_frame)),
190 Err(InvalidFrameId(other)) => Ok(Self::Unknown(other)),
191 }
192 }
193}
194
195impl Encodable for MaybeFrame {
196 fn encode<B: BufMut>(&self, buf: &mut B) {
197 match self {
198 Self::None => buf.write(0u64),
199 Self::Unknown(frame_id) => buf.write(*frame_id),
200 Self::Known(frame_type) => buf.write(*frame_type),
201 }
202 }
203}
204
205#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)]
206#[display("STREAM")]
207pub struct StreamInfo(u8);
208
209impl StreamInfo {
210 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f);
211 fn fin(self) -> bool {
212 self.0 & 0x01 != 0
213 }
214 fn len(self) -> bool {
215 self.0 & 0x02 != 0
216 }
217 fn off(self) -> bool {
218 self.0 & 0x04 != 0
219 }
220}
221
222#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)]
223#[display("DATAGRAM")]
224pub struct DatagramInfo(u8);
225
226impl DatagramInfo {
227 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31);
228
229 fn len(self) -> bool {
230 self.0 & 0x01 != 0
231 }
232}
233
234#[derive(Debug)]
235pub(crate) enum Frame {
236 Padding,
237 Ping,
238 Ack(Ack),
239 PathAck(PathAck),
240 ResetStream(ResetStream),
241 StopSending(StopSending),
242 Crypto(Crypto),
243 NewToken(NewToken),
244 Stream(Stream),
245 MaxData(VarInt),
246 MaxStreamData { id: StreamId, offset: u64 },
247 MaxStreams { dir: Dir, count: u64 },
248 DataBlocked { offset: u64 },
249 StreamDataBlocked { id: StreamId, offset: u64 },
250 StreamsBlocked { dir: Dir, limit: u64 },
251 NewConnectionId(NewConnectionId),
252 RetireConnectionId(RetireConnectionId),
253 PathChallenge(PathChallenge),
254 PathResponse(PathResponse),
255 Close(Close),
256 Datagram(Datagram),
257 AckFrequency(AckFrequency),
258 ImmediateAck,
259 HandshakeDone,
260 ObservedAddr(ObservedAddr),
261 PathAbandon(PathAbandon),
262 PathStatusAvailable(PathStatusAvailable),
263 PathStatusBackup(PathStatusBackup),
264 MaxPathId(MaxPathId),
265 PathsBlocked(PathsBlocked),
266 PathCidsBlocked(PathCidsBlocked),
267 AddAddress(AddAddress),
268 ReachOut(ReachOut),
269 RemoveAddress(RemoveAddress),
270}
271
272impl fmt::Display for Frame {
273 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
274 match self {
277 Self::Padding => write!(f, "PADDING"),
278 Self::Ping => write!(f, "PING"),
279 Self::PathChallenge(frame) => write!(f, "{frame}"),
280 Self::PathResponse(frame) => write!(f, "{frame}"),
281 Self::ImmediateAck => write!(f, "IMMEDIATE_ACK"),
282 Self::HandshakeDone => write!(f, "HANDSHAKE_DONE"),
283 _ => write!(f, "{self:?}"),
284 }
285 }
286}
287
288impl Frame {
289 pub(crate) fn ty(&self) -> FrameType {
290 use Frame::*;
291 match *self {
292 Padding => FrameType::Padding,
293 ResetStream(_) => FrameType::ResetStream,
294 Close(self::Close::Connection(_)) => FrameType::ConnectionClose,
295 Close(self::Close::Application(_)) => FrameType::ConnectionClose,
296 MaxData(_) => FrameType::MaxData,
297 MaxStreamData { .. } => FrameType::MaxStreamData,
298 MaxStreams { dir: Dir::Bi, .. } => FrameType::MaxStreamsBidi,
299 MaxStreams { dir: Dir::Uni, .. } => FrameType::MaxStreamsUni,
300 Ping => FrameType::Ping,
301 DataBlocked { .. } => FrameType::DataBlocked,
302 StreamDataBlocked { .. } => FrameType::StreamDataBlocked,
303 StreamsBlocked { dir: Dir::Bi, .. } => FrameType::StreamsBlockedBidi,
304 StreamsBlocked { dir: Dir::Uni, .. } => FrameType::StreamsBlockedUni,
305 StopSending { .. } => FrameType::StopSending,
306 RetireConnectionId { .. } => FrameType::RetireConnectionId,
307 Ack(_) => FrameType::Ack,
308 PathAck(_) => FrameType::PathAck,
309 Stream(ref x) => {
310 let mut ty = *StreamInfo::VALUES.start() as u8;
311 if x.fin {
312 ty |= 0x01;
313 }
314 if x.offset != 0 {
315 ty |= 0x04;
316 }
317 FrameType::Stream(StreamInfo(ty))
319 }
320 PathChallenge(_) => FrameType::PathChallenge,
321 PathResponse(_) => FrameType::PathResponse,
322 NewConnectionId(cid) => cid.get_type(),
323 Crypto(_) => FrameType::Crypto,
324 NewToken(_) => FrameType::NewToken,
325 Datagram(_) => FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)),
326 AckFrequency(_) => FrameType::AckFrequency,
327 ImmediateAck => FrameType::ImmediateAck,
328 HandshakeDone => FrameType::HandshakeDone,
329 ObservedAddr(ref observed) => observed.get_type(),
330 PathAbandon(_) => FrameType::PathAbandon,
331 PathStatusAvailable(_) => FrameType::PathStatusAvailable,
332 PathStatusBackup(_) => FrameType::PathStatusBackup,
333 MaxPathId(_) => FrameType::MaxPathId,
334 PathsBlocked(_) => FrameType::PathsBlocked,
335 PathCidsBlocked(_) => FrameType::PathCidsBlocked,
336 AddAddress(ref frame) => frame.get_type(),
337 ReachOut(ref frame) => frame.get_type(),
338 RemoveAddress(_) => self::RemoveAddress::TYPE,
339 }
340 }
341
342 pub(crate) fn is_ack_eliciting(&self) -> bool {
343 !matches!(
344 *self,
345 Self::Ack(_) | Self::PathAck(_) | Self::Padding | Self::Close(_)
346 )
347 }
348
349 pub(crate) fn is_1rtt(&self) -> bool {
351 self.is_multipath_frame() || self.is_qad_frame()
357 }
358
359 fn is_qad_frame(&self) -> bool {
360 matches!(*self, Self::ObservedAddr(_))
361 }
362
363 fn is_multipath_frame(&self) -> bool {
364 matches!(
365 *self,
366 Self::PathAck(_)
367 | Self::PathAbandon(_)
368 | Self::PathStatusBackup(_)
369 | Self::PathStatusAvailable(_)
370 | Self::MaxPathId(_)
371 | Self::PathsBlocked(_)
372 | Self::PathCidsBlocked(_)
373 | Self::NewConnectionId(NewConnectionId {
374 path_id: Some(_),
375 ..
376 })
377 | Self::RetireConnectionId(RetireConnectionId {
378 path_id: Some(_),
379 ..
380 })
381 )
382 }
383}
384
385#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)]
386#[display("PATH_CHALLENGE({_0:08x})")]
387pub(crate) struct PathChallenge(pub(crate) u64);
388
389impl PathChallenge {
390 pub(crate) const SIZE_BOUND: usize = 9;
391}
392impl Decodable for PathChallenge {
393 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
394 Ok(Self(buf.get()?))
395 }
396}
397impl Encodable for PathChallenge {
398 fn encode<B: BufMut>(&self, buf: &mut B) {
399 buf.write(FrameType::PathChallenge);
400 buf.write(self.0);
401 }
402}
403
404#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Display)]
405#[display("PATH_RESPONSE({_0:08x})")]
406pub(crate) struct PathResponse(pub(crate) u64);
407
408impl PathResponse {
409 pub(crate) const SIZE_BOUND: usize = 9;
410}
411
412impl Decodable for PathResponse {
413 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
414 Ok(Self(buf.get()?))
415 }
416}
417impl Encodable for PathResponse {
418 fn encode<B: BufMut>(&self, buf: &mut B) {
419 buf.write(FrameType::PathResponse);
420 buf.write(self.0);
421 }
422}
423
424#[derive(Debug, PartialEq, Eq)]
425pub(crate) struct RetireConnectionId {
426 pub(crate) path_id: Option<PathId>,
427 pub(crate) sequence: u64,
428}
429
430impl RetireConnectionId {
431 pub(crate) const SIZE_BOUND: usize = {
433 let type_len = FrameType::RetireConnectionId.size();
434 let seq_max_len = 8usize;
435 type_len + seq_max_len
436 };
437
438 pub(crate) const SIZE_BOUND_MULTIPATH: usize = {
440 let type_len = FrameType::PathRetireConnectionId.size();
441 let path_id_len = VarInt::from_u32(u32::MAX).size();
442 let seq_max_len = 8usize;
443 type_len + path_id_len + seq_max_len
444 };
445
446 pub(crate) fn decode<R: Buf>(bytes: &mut R, read_path: bool) -> coding::Result<Self> {
449 Ok(Self {
450 path_id: if read_path { Some(bytes.get()?) } else { None },
451 sequence: bytes.get_var()?,
452 })
453 }
454
455 pub(crate) fn get_type(&self) -> FrameType {
457 if self.path_id.is_some() {
458 FrameType::PathRetireConnectionId
459 } else {
460 FrameType::RetireConnectionId
461 }
462 }
463
464 pub(crate) const fn size_bound(path_retire_cid: bool) -> usize {
469 match path_retire_cid {
470 true => Self::SIZE_BOUND_MULTIPATH,
471 false => Self::SIZE_BOUND,
472 }
473 }
474}
475
476impl Encodable for RetireConnectionId {
477 fn encode<W: BufMut>(&self, buf: &mut W) {
478 buf.write(self.get_type());
479 if let Some(id) = self.path_id {
480 buf.write(id);
481 }
482 buf.write_var(self.sequence);
483 }
484}
485
486#[derive(Clone, Debug)]
487pub enum Close {
488 Connection(ConnectionClose),
489 Application(ApplicationClose),
490}
491
492impl Close {
493 pub(crate) fn encoder(&self, max_len: usize) -> CloseEncoder<'_> {
494 CloseEncoder {
495 close: self,
496 max_len,
497 }
498 }
499
500 pub(crate) fn is_transport_layer(&self) -> bool {
501 matches!(*self, Self::Connection(_))
502 }
503}
504
505pub(crate) struct CloseEncoder<'a> {
506 close: &'a Close,
507 max_len: usize,
508}
509
510impl<'a> Encodable for CloseEncoder<'a> {
511 fn encode<W: BufMut>(&self, out: &mut W) {
512 match self.close {
513 Close::Connection(x) => x.encode(out, self.max_len),
514 Close::Application(x) => x.encode(out, self.max_len),
515 }
516 }
517}
518
519impl From<TransportError> for Close {
520 fn from(x: TransportError) -> Self {
521 Self::Connection(x.into())
522 }
523}
524impl From<ConnectionClose> for Close {
525 fn from(x: ConnectionClose) -> Self {
526 Self::Connection(x)
527 }
528}
529impl From<ApplicationClose> for Close {
530 fn from(x: ApplicationClose) -> Self {
531 Self::Application(x)
532 }
533}
534
535#[derive(Debug, Clone, PartialEq, Eq)]
537pub struct ConnectionClose {
538 pub error_code: TransportErrorCode,
540 pub frame_type: MaybeFrame,
542 pub reason: Bytes,
544}
545
546impl fmt::Display for ConnectionClose {
547 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548 self.error_code.fmt(f)?;
549 if !self.reason.as_ref().is_empty() {
550 f.write_str(": ")?;
551 f.write_str(&String::from_utf8_lossy(&self.reason))?;
552 }
553 Ok(())
554 }
555}
556
557impl From<TransportError> for ConnectionClose {
558 fn from(x: TransportError) -> Self {
559 Self {
560 error_code: x.code,
561 frame_type: x.frame,
562 reason: x.reason.into(),
563 }
564 }
565}
566
567impl FrameStruct for ConnectionClose {
568 const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
569}
570
571impl ConnectionClose {
572 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
573 out.write(FrameType::ConnectionClose); out.write(self.error_code); out.write(self.frame_type); let max_len = max_len
577 - 3
578 - self.frame_type.size()
579 - VarInt::from_u64(self.reason.len() as u64).unwrap().size();
580 let actual_len = self.reason.len().min(max_len);
581 out.write_var(actual_len as u64); out.put_slice(&self.reason[0..actual_len]); }
584}
585
586#[derive(Debug, Clone, PartialEq, Eq)]
588pub struct ApplicationClose {
589 pub error_code: VarInt,
591 pub reason: Bytes,
593}
594
595impl fmt::Display for ApplicationClose {
596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
597 if !self.reason.as_ref().is_empty() {
598 f.write_str(&String::from_utf8_lossy(&self.reason))?;
599 f.write_str(" (code ")?;
600 self.error_code.fmt(f)?;
601 f.write_str(")")?;
602 } else {
603 self.error_code.fmt(f)?;
604 }
605 Ok(())
606 }
607}
608
609impl FrameStruct for ApplicationClose {
610 const SIZE_BOUND: usize = 1 + 8 + 8;
611}
612
613impl ApplicationClose {
614 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
615 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();
618 let actual_len = self.reason.len().min(max_len);
619 out.write_var(actual_len as u64); out.put_slice(&self.reason[0..actual_len]); }
622}
623
624#[derive(Clone, Eq, PartialEq)]
625pub struct PathAck {
626 pub path_id: PathId,
627 pub largest: u64,
628 pub delay: u64,
629 pub additional: Bytes,
630 pub ecn: Option<EcnCounts>,
631}
632
633impl fmt::Debug for PathAck {
634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635 let mut ranges = "[".to_string();
636 let mut first = true;
637 for range in self.into_iter() {
638 if !first {
639 ranges.push(',');
640 }
641 write!(ranges, "{range:?}")?;
642 first = false;
643 }
644 ranges.push(']');
645
646 f.debug_struct("PathAck")
647 .field("path_id", &self.path_id)
648 .field("largest", &self.largest)
649 .field("delay", &self.delay)
650 .field("ecn", &self.ecn)
651 .field("ranges", &ranges)
652 .finish()
653 }
654}
655
656impl<'a> IntoIterator for &'a PathAck {
657 type Item = RangeInclusive<u64>;
658 type IntoIter = AckIter<'a>;
659
660 fn into_iter(self) -> AckIter<'a> {
661 AckIter::new(self.largest, &self.additional[..])
662 }
663}
664
665impl PathAck {
666 pub fn into_ack(self) -> (Ack, PathId) {
667 let ack = Ack {
668 largest: self.largest,
669 delay: self.delay,
670 additional: self.additional,
671 ecn: self.ecn,
672 };
673
674 (ack, self.path_id)
675 }
676
677 pub(crate) fn encoder<'a>(
678 path_id: PathId,
679 delay: u64,
680 ranges: &'a ArrayRangeSet,
681 ecn: Option<&'a EcnCounts>,
682 ) -> PathAckEncoder<'a> {
683 PathAckEncoder {
684 path_id,
685 delay,
686 ranges,
687 ecn,
688 }
689 }
690}
691
692pub(crate) struct PathAckEncoder<'a> {
693 path_id: PathId,
694 delay: u64,
695 ranges: &'a ArrayRangeSet,
696 ecn: Option<&'a EcnCounts>,
697}
698
699impl<'a> Encodable for PathAckEncoder<'a> {
700 fn encode<W: BufMut>(&self, buf: &mut W) {
707 let PathAckEncoder {
708 path_id,
709 delay,
710 ranges,
711 ecn,
712 } = self;
713 let mut rest = ranges.iter().rev();
714 let first = rest
715 .next()
716 .expect("Caller has verified ranges is non empty");
717 let largest = first.end - 1;
718 let first_size = first.end - first.start;
719 let kind = match ecn.is_some() {
720 true => FrameType::PathAckEcn,
721 false => FrameType::PathAck,
722 };
723 buf.write(kind);
724 buf.write(*path_id);
725 buf.write_var(largest);
726 buf.write_var(*delay);
727 buf.write_var(ranges.len() as u64 - 1);
728 buf.write_var(first_size - 1);
729 let mut prev = first.start;
730 for block in rest {
731 let size = block.end - block.start;
732 buf.write_var(prev - block.end - 1);
733 buf.write_var(size - 1);
734 prev = block.start;
735 }
736 if let Some(x) = ecn {
737 x.encode(buf)
738 }
739 }
740}
741
742#[derive(Clone, Eq, PartialEq)]
743pub struct Ack {
744 pub largest: u64,
745 pub delay: u64,
746 pub additional: Bytes,
747 pub ecn: Option<EcnCounts>,
748}
749
750impl fmt::Debug for Ack {
751 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
752 let mut ranges = "[".to_string();
753 let mut first = true;
754 for range in self.iter() {
755 if !first {
756 ranges.push(',');
757 }
758 write!(ranges, "{range:?}").unwrap();
759 first = false;
760 }
761 ranges.push(']');
762
763 f.debug_struct("Ack")
764 .field("largest", &self.largest)
765 .field("delay", &self.delay)
766 .field("ecn", &self.ecn)
767 .field("ranges", &ranges)
768 .finish()
769 }
770}
771
772impl<'a> IntoIterator for &'a Ack {
773 type Item = RangeInclusive<u64>;
774 type IntoIter = AckIter<'a>;
775
776 fn into_iter(self) -> AckIter<'a> {
777 AckIter::new(self.largest, &self.additional[..])
778 }
779}
780
781impl Ack {
782 pub(crate) fn encoder<'a>(
783 delay: u64,
784 ranges: &'a ArrayRangeSet,
785 ecn: Option<&'a EcnCounts>,
786 ) -> AckEncoder<'a> {
787 AckEncoder { delay, ranges, ecn }
788 }
789
790 pub fn iter(&self) -> AckIter<'_> {
791 self.into_iter()
792 }
793}
794
795pub(crate) struct AckEncoder<'a> {
796 delay: u64,
797 ranges: &'a ArrayRangeSet,
798 ecn: Option<&'a EcnCounts>,
799}
800
801impl<'a> Encodable for AckEncoder<'a> {
802 fn encode<W: BufMut>(&self, buf: &mut W) {
803 let AckEncoder { delay, ranges, ecn } = self;
804 let mut rest = ranges.iter().rev();
805 let first = rest.next().unwrap();
806 let largest = first.end - 1;
807 let first_size = first.end - first.start;
808 let kind = match ecn.is_some() {
809 true => FrameType::AckEcn,
810 false => FrameType::Ack,
811 };
812 buf.write(kind);
813 buf.write_var(largest);
814 buf.write_var(*delay);
815 buf.write_var(ranges.len() as u64 - 1);
816 buf.write_var(first_size - 1);
817 let mut prev = first.start;
818 for block in rest {
819 let size = block.end - block.start;
820 buf.write_var(prev - block.end - 1);
821 buf.write_var(size - 1);
822 prev = block.start;
823 }
824 if let Some(x) = ecn {
825 x.encode(buf)
826 }
827 }
828}
829
830#[derive(Debug, Copy, Clone, Eq, PartialEq)]
831pub struct EcnCounts {
832 pub ect0: u64,
833 pub ect1: u64,
834 pub ce: u64,
835}
836
837impl std::ops::AddAssign<EcnCodepoint> for EcnCounts {
838 fn add_assign(&mut self, rhs: EcnCodepoint) {
839 match rhs {
840 EcnCodepoint::Ect0 => {
841 self.ect0 += 1;
842 }
843 EcnCodepoint::Ect1 => {
844 self.ect1 += 1;
845 }
846 EcnCodepoint::Ce => {
847 self.ce += 1;
848 }
849 }
850 }
851}
852
853impl EcnCounts {
854 pub const ZERO: Self = Self {
855 ect0: 0,
856 ect1: 0,
857 ce: 0,
858 };
859}
860
861impl Encodable for EcnCounts {
862 fn encode<W: BufMut>(&self, out: &mut W) {
863 out.write_var(self.ect0);
864 out.write_var(self.ect1);
865 out.write_var(self.ce);
866 }
867}
868
869#[derive(Debug, Clone)]
870pub(crate) struct Stream {
871 pub(crate) id: StreamId,
872 pub(crate) offset: u64,
873 pub(crate) fin: bool,
874 pub(crate) data: Bytes,
875}
876
877impl FrameStruct for Stream {
878 const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
879}
880
881#[derive(Debug, Clone)]
883pub(crate) struct StreamMeta {
884 pub(crate) id: StreamId,
885 pub(crate) offsets: Range<u64>,
886 pub(crate) fin: bool,
887}
888
889impl Default for StreamMeta {
891 fn default() -> Self {
892 Self {
893 id: StreamId(0),
894 offsets: 0..0,
895 fin: false,
896 }
897 }
898}
899
900impl StreamMeta {
901 pub(crate) fn encoder(&self, encode_length: bool) -> StreamMetaEncoder<'_> {
902 StreamMetaEncoder {
903 meta: self,
904 encode_length,
905 }
906 }
907}
908
909pub(crate) struct StreamMetaEncoder<'a> {
910 meta: &'a StreamMeta,
911 encode_length: bool,
912}
913
914impl<'a> Encodable for StreamMetaEncoder<'a> {
915 fn encode<W: BufMut>(&self, out: &mut W) {
916 let StreamMetaEncoder {
917 meta,
918 encode_length: length,
919 } = self;
920 let mut ty = *StreamInfo::VALUES.start();
921 if meta.offsets.start != 0 {
922 ty |= 0x04;
923 }
924 if *length {
925 ty |= 0x02;
926 }
927 if meta.fin {
928 ty |= 0x01;
929 }
930 out.write_var(ty); out.write(meta.id); if meta.offsets.start != 0 {
933 out.write_var(meta.offsets.start); }
935 if *length {
936 out.write_var(meta.offsets.end - meta.offsets.start); }
938 }
939}
940
941pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>;
943
944#[derive(Debug, Clone)]
945pub(crate) struct Crypto {
946 pub(crate) offset: u64,
947 pub(crate) data: Bytes,
948}
949
950impl Crypto {
951 pub(crate) const SIZE_BOUND: usize = 17;
952}
953
954impl Encodable for Crypto {
955 fn encode<W: BufMut>(&self, out: &mut W) {
956 out.write(FrameType::Crypto);
957 out.write_var(self.offset);
958 out.write_var(self.data.len() as u64);
959 out.put_slice(&self.data);
960 }
961}
962
963#[derive(Debug, Clone)]
964pub(crate) struct NewToken {
965 pub(crate) token: Bytes,
966}
967
968impl Encodable for NewToken {
969 fn encode<W: BufMut>(&self, out: &mut W) {
970 out.write(FrameType::NewToken);
971 out.write_var(self.token.len() as u64);
972 out.put_slice(&self.token);
973 }
974}
975
976impl NewToken {
977 pub(crate) fn size(&self) -> usize {
978 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len()
979 }
980}
981
982#[derive(Debug, Clone)]
983pub(crate) struct MaxPathId(pub(crate) PathId);
984
985impl MaxPathId {
986 pub(crate) const SIZE_BOUND: usize =
987 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size();
988}
989
990impl Decodable for MaxPathId {
991 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
992 Ok(Self(buf.get()?))
993 }
994}
995
996impl Encodable for MaxPathId {
997 fn encode<B: BufMut>(&self, buf: &mut B) {
998 buf.write(FrameType::MaxPathId);
999 buf.write(self.0);
1000 }
1001}
1002
1003#[derive(Debug, Clone, PartialEq, Eq)]
1004pub(crate) struct PathsBlocked(pub(crate) PathId);
1005
1006impl PathsBlocked {
1007 pub(crate) const SIZE_BOUND: usize =
1008 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size();
1009}
1010
1011impl Encodable for PathsBlocked {
1012 fn encode<B: BufMut>(&self, buf: &mut B) {
1013 buf.write(FrameType::PathsBlocked);
1014 buf.write(self.0);
1015 }
1016}
1017
1018impl Decodable for PathsBlocked {
1019 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
1021 Ok(Self(buf.get()?))
1022 }
1023}
1024
1025#[derive(Debug, Clone, PartialEq, Eq)]
1026pub(crate) struct PathCidsBlocked {
1027 pub(crate) path_id: PathId,
1028 pub(crate) next_seq: VarInt,
1029}
1030
1031impl PathCidsBlocked {
1032 pub(crate) const SIZE_BOUND: usize =
1033 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size();
1034}
1035
1036impl Decodable for PathCidsBlocked {
1037 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> {
1038 Ok(Self {
1039 path_id: buf.get()?,
1040 next_seq: buf.get()?,
1041 })
1042 }
1043}
1044
1045impl Encodable for PathCidsBlocked {
1046 fn encode<W: BufMut>(&self, buf: &mut W) {
1047 buf.write(FrameType::PathCidsBlocked);
1048 buf.write(self.path_id);
1049 buf.write(self.next_seq);
1050 }
1051}
1052
1053pub(crate) struct Iter {
1054 bytes: Bytes,
1055 last_ty: MaybeFrame,
1056}
1057
1058impl Iter {
1059 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> {
1060 if payload.is_empty() {
1061 return Err(TransportError::PROTOCOL_VIOLATION(
1065 "packet payload is empty",
1066 ));
1067 }
1068
1069 Ok(Self {
1070 bytes: payload,
1071 last_ty: MaybeFrame::None,
1072 })
1073 }
1074
1075 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> {
1076 let len = self.bytes.get_var()?;
1077 if len > self.bytes.remaining() as u64 {
1078 return Err(UnexpectedEnd);
1079 }
1080 Ok(self.bytes.split_to(len as usize))
1081 }
1082
1083 #[track_caller]
1084 fn try_next(&mut self) -> Result<Frame, IterErr> {
1085 self.last_ty = self.bytes.get()?;
1086
1087 let ty = match self.last_ty {
1088 MaybeFrame::None => FrameType::Padding,
1089 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId),
1090 MaybeFrame::Known(frame_type) => frame_type,
1091 };
1092 Ok(match ty {
1093 FrameType::Padding => Frame::Padding,
1094 FrameType::ResetStream => Frame::ResetStream(ResetStream {
1095 id: self.bytes.get()?,
1096 error_code: self.bytes.get()?,
1097 final_offset: self.bytes.get()?,
1098 }),
1099 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose {
1100 error_code: self.bytes.get()?,
1101 frame_type: self.bytes.get()?,
1102 reason: self.take_len()?,
1103 })),
1104 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose {
1105 error_code: self.bytes.get()?,
1106 reason: self.take_len()?,
1107 })),
1108 FrameType::MaxData => Frame::MaxData(self.bytes.get()?),
1109 FrameType::MaxStreamData => Frame::MaxStreamData {
1110 id: self.bytes.get()?,
1111 offset: self.bytes.get_var()?,
1112 },
1113 FrameType::MaxStreamsBidi => Frame::MaxStreams {
1114 dir: Dir::Bi,
1115 count: self.bytes.get_var()?,
1116 },
1117 FrameType::MaxStreamsUni => Frame::MaxStreams {
1118 dir: Dir::Uni,
1119 count: self.bytes.get_var()?,
1120 },
1121 FrameType::Ping => Frame::Ping,
1122 FrameType::DataBlocked => Frame::DataBlocked {
1123 offset: self.bytes.get_var()?,
1124 },
1125 FrameType::StreamDataBlocked => Frame::StreamDataBlocked {
1126 id: self.bytes.get()?,
1127 offset: self.bytes.get_var()?,
1128 },
1129 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked {
1130 dir: Dir::Bi,
1131 limit: self.bytes.get_var()?,
1132 },
1133 FrameType::StreamsBlockedUni => Frame::StreamsBlocked {
1134 dir: Dir::Uni,
1135 limit: self.bytes.get_var()?,
1136 },
1137 FrameType::StopSending => Frame::StopSending(StopSending {
1138 id: self.bytes.get()?,
1139 error_code: self.bytes.get()?,
1140 }),
1141 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => {
1142 Frame::RetireConnectionId(RetireConnectionId::decode(
1143 &mut self.bytes,
1144 ty == FrameType::PathRetireConnectionId,
1145 )?)
1146 }
1147 FrameType::Ack | FrameType::AckEcn => {
1148 let largest = self.bytes.get_var()?;
1149 let delay = self.bytes.get_var()?;
1150 let extra_blocks = self.bytes.get_var()? as usize;
1151 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?;
1152 Frame::Ack(Ack {
1153 delay,
1154 largest,
1155 additional: self.bytes.split_to(n),
1156 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn {
1157 None
1158 } else {
1159 Some(EcnCounts {
1160 ect0: self.bytes.get_var()?,
1161 ect1: self.bytes.get_var()?,
1162 ce: self.bytes.get_var()?,
1163 })
1164 },
1165 })
1166 }
1167 FrameType::PathAck | FrameType::PathAckEcn => {
1168 let path_id = self.bytes.get()?;
1169 let largest = self.bytes.get_var()?;
1170 let delay = self.bytes.get_var()?;
1171 let extra_blocks = self.bytes.get_var()? as usize;
1172 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?;
1173 Frame::PathAck(PathAck {
1174 path_id,
1175 delay,
1176 largest,
1177 additional: self.bytes.split_to(n),
1178 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn {
1179 None
1180 } else {
1181 Some(EcnCounts {
1182 ect0: self.bytes.get_var()?,
1183 ect1: self.bytes.get_var()?,
1184 ce: self.bytes.get_var()?,
1185 })
1186 },
1187 })
1188 }
1189 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?),
1190 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?),
1191 FrameType::NewConnectionId | FrameType::PathNewConnectionId => {
1192 let read_path = ty == FrameType::PathNewConnectionId;
1193 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?)
1194 }
1195 FrameType::Crypto => Frame::Crypto(Crypto {
1196 offset: self.bytes.get_var()?,
1197 data: self.take_len()?,
1198 }),
1199 FrameType::NewToken => Frame::NewToken(NewToken {
1200 token: self.take_len()?,
1201 }),
1202 FrameType::HandshakeDone => Frame::HandshakeDone,
1203 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency {
1204 sequence: self.bytes.get()?,
1205 ack_eliciting_threshold: self.bytes.get()?,
1206 request_max_ack_delay: self.bytes.get()?,
1207 reordering_threshold: self.bytes.get()?,
1208 }),
1209 FrameType::ImmediateAck => Frame::ImmediateAck,
1210 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => {
1211 let is_ipv6 = ty == FrameType::ObservedIpv6Addr;
1212 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?;
1213 Frame::ObservedAddr(observed)
1214 }
1215 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?),
1216 FrameType::PathStatusAvailable => {
1217 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?)
1218 }
1219 FrameType::PathStatusBackup => {
1220 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?)
1221 }
1222 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?),
1223 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?),
1224 FrameType::PathCidsBlocked => {
1225 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?)
1226 }
1227 FrameType::AddIpv4Address | FrameType::AddIpv6Address => {
1228 let is_ipv6 = ty == FrameType::AddIpv6Address;
1229 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?;
1230 Frame::AddAddress(add_address)
1231 }
1232 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => {
1233 let is_ipv6 = ty == FrameType::ReachOutAtIpv6;
1234 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?;
1235 Frame::ReachOut(reach_out)
1236 }
1237 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?),
1238 FrameType::Stream(s) => Frame::Stream(Stream {
1239 id: self.bytes.get()?,
1240 offset: if s.off() { self.bytes.get_var()? } else { 0 },
1241 fin: s.fin(),
1242 data: if s.len() {
1243 self.take_len()?
1244 } else {
1245 self.take_remaining()
1246 },
1247 }),
1248 FrameType::Datagram(d) => Frame::Datagram(Datagram {
1249 data: if d.len() {
1250 self.take_len()?
1251 } else {
1252 self.take_remaining()
1253 },
1254 }),
1255 })
1256 }
1257
1258 fn take_remaining(&mut self) -> Bytes {
1259 mem::take(&mut self.bytes)
1260 }
1261}
1262
1263impl Iterator for Iter {
1264 type Item = Result<Frame, InvalidFrame>;
1265 fn next(&mut self) -> Option<Self::Item> {
1266 if !self.bytes.has_remaining() {
1267 return None;
1268 }
1269 match self.try_next() {
1270 Ok(x) => Some(Ok(x)),
1271 Err(e) => {
1272 self.bytes.clear();
1274 Some(Err(InvalidFrame {
1275 ty: self.last_ty,
1276 reason: e.reason(),
1277 }))
1278 }
1279 }
1280 }
1281}
1282
1283#[derive(Debug)]
1284pub(crate) struct InvalidFrame {
1285 pub(crate) ty: MaybeFrame,
1286 pub(crate) reason: &'static str,
1287}
1288
1289impl From<InvalidFrame> for TransportError {
1290 fn from(err: InvalidFrame) -> Self {
1291 let mut te = Self::FRAME_ENCODING_ERROR(err.reason);
1292 te.frame = err.ty;
1293 te
1294 }
1295}
1296
1297fn scan_ack_blocks(mut buf: &[u8], largest: u64, n: usize) -> Result<usize, IterErr> {
1299 let total_len = buf.remaining();
1300 let first_block = buf.get_var()?;
1301 let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?;
1302 for _ in 0..n {
1303 let gap = buf.get_var()?;
1304 smallest = smallest.checked_sub(gap + 2).ok_or(IterErr::Malformed)?;
1305 let block = buf.get_var()?;
1306 smallest = smallest.checked_sub(block).ok_or(IterErr::Malformed)?;
1307 }
1308 Ok(total_len - buf.remaining())
1309}
1310
1311#[derive(Debug)]
1312enum IterErr {
1313 UnexpectedEnd,
1314 InvalidFrameId,
1315 Malformed,
1316}
1317
1318impl IterErr {
1319 fn reason(&self) -> &'static str {
1320 use IterErr::*;
1321 match *self {
1322 UnexpectedEnd => "unexpected end",
1323 InvalidFrameId => "invalid frame ID",
1324 Malformed => "malformed",
1325 }
1326 }
1327}
1328
1329impl From<UnexpectedEnd> for IterErr {
1330 fn from(_: UnexpectedEnd) -> Self {
1331 Self::UnexpectedEnd
1332 }
1333}
1334
1335#[derive(Debug, Clone)]
1336pub struct AckIter<'a> {
1337 largest: u64,
1338 data: &'a [u8],
1339}
1340
1341impl<'a> AckIter<'a> {
1342 fn new(largest: u64, data: &'a [u8]) -> Self {
1343 Self { largest, data }
1344 }
1345}
1346
1347impl Iterator for AckIter<'_> {
1348 type Item = RangeInclusive<u64>;
1349 fn next(&mut self) -> Option<RangeInclusive<u64>> {
1350 if !self.data.has_remaining() {
1351 return None;
1352 }
1353 let block = self.data.get_var().unwrap();
1354 let largest = self.largest;
1355 if let Ok(gap) = self.data.get_var() {
1356 self.largest -= block + gap + 2;
1357 }
1358 Some(largest - block..=largest)
1359 }
1360}
1361
1362#[allow(unreachable_pub)] #[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1364#[derive(Debug, Copy, Clone)]
1365pub struct ResetStream {
1366 pub(crate) id: StreamId,
1367 pub(crate) error_code: VarInt,
1368 pub(crate) final_offset: VarInt,
1369}
1370
1371impl FrameStruct for ResetStream {
1372 const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
1373}
1374
1375impl Encodable for ResetStream {
1376 fn encode<W: BufMut>(&self, out: &mut W) {
1377 out.write(FrameType::ResetStream); out.write(self.id); out.write(self.error_code); out.write(self.final_offset); }
1382}
1383
1384#[derive(Debug, Copy, Clone)]
1385pub(crate) struct StopSending {
1386 pub(crate) id: StreamId,
1387 pub(crate) error_code: VarInt,
1388}
1389
1390impl FrameStruct for StopSending {
1391 const SIZE_BOUND: usize = 1 + 8 + 8;
1392}
1393
1394impl Encodable for StopSending {
1395 fn encode<W: BufMut>(&self, out: &mut W) {
1396 out.write(FrameType::StopSending); out.write(self.id); out.write(self.error_code) }
1400}
1401
1402#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1403pub(crate) struct NewConnectionId {
1404 pub(crate) path_id: Option<PathId>,
1405 pub(crate) sequence: u64,
1406 pub(crate) retire_prior_to: u64,
1407 pub(crate) id: ConnectionId,
1408 pub(crate) reset_token: ResetToken,
1409}
1410
1411impl NewConnectionId {
1412 pub(crate) const SIZE_BOUND: usize = {
1414 let type_len = FrameType::NewConnectionId.size();
1415 let seq_max_len = 8usize;
1416 let retire_prior_to_max_len = 8usize;
1417 let cid_len_len = 1;
1418 let cid_len = 160;
1419 let reset_token_len = 16;
1420 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len
1421 };
1422
1423 pub(crate) const SIZE_BOUND_MULTIPATH: usize = {
1425 let type_len = FrameType::PathNewConnectionId.size();
1426 let path_id_len = VarInt::from_u32(u32::MAX).size();
1427 let seq_max_len = 8usize;
1428 let retire_prior_to_max_len = 8usize;
1429 let cid_len_len = 1;
1430 let cid_len = 160;
1431 let reset_token_len = 16;
1432 type_len
1433 + path_id_len
1434 + seq_max_len
1435 + retire_prior_to_max_len
1436 + cid_len_len
1437 + cid_len
1438 + reset_token_len
1439 };
1440
1441 pub(crate) fn get_type(&self) -> FrameType {
1442 if self.path_id.is_some() {
1443 FrameType::PathNewConnectionId
1444 } else {
1445 FrameType::NewConnectionId
1446 }
1447 }
1448
1449 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize {
1453 let upper_bound = match path_new_cid {
1454 true => Self::SIZE_BOUND_MULTIPATH,
1455 false => Self::SIZE_BOUND,
1456 };
1457 upper_bound - 160 + cid_len
1459 }
1460
1461 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> {
1462 let path_id = if read_path { Some(bytes.get()?) } else { None };
1463 let sequence = bytes.get_var()?;
1464 let retire_prior_to = bytes.get_var()?;
1465 if retire_prior_to > sequence {
1466 return Err(IterErr::Malformed);
1467 }
1468 let length = bytes.get::<u8>()? as usize;
1469 if length > MAX_CID_SIZE || length == 0 {
1470 return Err(IterErr::Malformed);
1471 }
1472 if length > bytes.remaining() {
1473 return Err(IterErr::UnexpectedEnd);
1474 }
1475 let mut stage = [0; MAX_CID_SIZE];
1476 bytes.copy_to_slice(&mut stage[0..length]);
1477 let id = ConnectionId::new(&stage[..length]);
1478 if bytes.remaining() < 16 {
1479 return Err(IterErr::UnexpectedEnd);
1480 }
1481 let mut reset_token = [0; RESET_TOKEN_SIZE];
1482 bytes.copy_to_slice(&mut reset_token);
1483 Ok(Self {
1484 path_id,
1485 sequence,
1486 retire_prior_to,
1487 id,
1488 reset_token: reset_token.into(),
1489 })
1490 }
1491}
1492
1493impl Encodable for NewConnectionId {
1494 fn encode<W: BufMut>(&self, out: &mut W) {
1495 out.write(self.get_type());
1496 if let Some(id) = self.path_id {
1497 out.write(id);
1498 }
1499 out.write_var(self.sequence);
1500 out.write_var(self.retire_prior_to);
1501 out.write(self.id.len() as u8);
1502 out.put_slice(&self.id);
1503 out.put_slice(&self.reset_token);
1504 }
1505}
1506
1507impl FrameStruct for NewConnectionId {
1508 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE;
1509}
1510
1511#[derive(Debug, Clone)]
1513pub struct Datagram {
1514 pub data: Bytes,
1516}
1517
1518impl FrameStruct for Datagram {
1519 const SIZE_BOUND: usize = 1 + 8;
1520}
1521
1522impl Datagram {
1523 pub(crate) fn size(&self, length: bool) -> usize {
1524 1 + if length {
1525 VarInt::from_u64(self.data.len() as u64).unwrap().size()
1526 } else {
1527 0
1528 } + self.data.len()
1529 }
1530}
1531
1532impl Encodable for Datagram {
1533 fn encode<B: BufMut>(&self, out: &mut B) {
1534 const ENCODE_LEN: bool = true;
1536 out.write(FrameType::Datagram(DatagramInfo(
1537 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN),
1538 ))); out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); out.put_slice(&self.data);
1542 }
1543}
1544
1545#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1546pub(crate) struct AckFrequency {
1547 pub(crate) sequence: VarInt,
1548 pub(crate) ack_eliciting_threshold: VarInt,
1549 pub(crate) request_max_ack_delay: VarInt,
1550 pub(crate) reordering_threshold: VarInt,
1551}
1552
1553impl Encodable for AckFrequency {
1554 fn encode<W: BufMut>(&self, buf: &mut W) {
1555 buf.write(FrameType::AckFrequency);
1556 buf.write(self.sequence);
1557 buf.write(self.ack_eliciting_threshold);
1558 buf.write(self.request_max_ack_delay);
1559 buf.write(self.reordering_threshold);
1560 }
1561}
1562
1563#[derive(Debug, PartialEq, Eq, Clone)]
1568pub(crate) struct ObservedAddr {
1569 pub(crate) seq_no: VarInt,
1571 pub(crate) ip: IpAddr,
1573 pub(crate) port: u16,
1575}
1576
1577impl ObservedAddr {
1578 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self {
1579 Self {
1580 ip: remote.ip(),
1581 port: remote.port(),
1582 seq_no: seq_no.into(),
1583 }
1584 }
1585
1586 pub(crate) fn get_type(&self) -> FrameType {
1588 if self.ip.is_ipv6() {
1589 FrameType::ObservedIpv6Addr
1590 } else {
1591 FrameType::ObservedIpv4Addr
1592 }
1593 }
1594
1595 pub(crate) fn size(&self) -> usize {
1597 let type_size = self.get_type().size();
1598 let req_id_bytes = self.seq_no.size();
1599 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
1600 let port_bytes = 2;
1601 type_size + req_id_bytes + ip_bytes + port_bytes
1602 }
1603
1604 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
1609 let seq_no = bytes.get()?;
1610 let ip = if is_ipv6 {
1611 IpAddr::V6(bytes.get()?)
1612 } else {
1613 IpAddr::V4(bytes.get()?)
1614 };
1615 let port = bytes.get()?;
1616 Ok(Self { seq_no, ip, port })
1617 }
1618
1619 pub(crate) fn socket_addr(&self) -> SocketAddr {
1621 (self.ip, self.port).into()
1622 }
1623}
1624
1625impl Encodable for ObservedAddr {
1626 fn encode<W: BufMut>(&self, buf: &mut W) {
1627 buf.write(self.get_type());
1628 buf.write(self.seq_no);
1629 match self.ip {
1630 IpAddr::V4(ipv4_addr) => {
1631 buf.write(ipv4_addr);
1632 }
1633 IpAddr::V6(ipv6_addr) => {
1634 buf.write(ipv6_addr);
1635 }
1636 }
1637 buf.write::<u16>(self.port);
1638 }
1639}
1640
1641#[derive(Debug, PartialEq, Eq)]
1644pub(crate) struct PathAbandon {
1645 pub(crate) path_id: PathId,
1646 pub(crate) error_code: TransportErrorCode,
1647}
1648
1649impl PathAbandon {
1650 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8;
1651}
1652
1653impl Encodable for PathAbandon {
1654 fn encode<W: BufMut>(&self, buf: &mut W) {
1655 buf.write(FrameType::PathAbandon);
1656 buf.write(self.path_id);
1657 buf.write(self.error_code);
1658 }
1659}
1660
1661impl Decodable for PathAbandon {
1662 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1663 Ok(Self {
1664 path_id: bytes.get()?,
1665 error_code: bytes.get()?,
1666 })
1667 }
1668}
1669
1670#[derive(Debug, PartialEq, Eq)]
1671pub(crate) struct PathStatusAvailable {
1672 pub(crate) path_id: PathId,
1673 pub(crate) status_seq_no: VarInt,
1674}
1675
1676impl PathStatusAvailable {
1677 const TYPE: FrameType = FrameType::PathStatusAvailable;
1678 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8;
1679}
1680
1681impl Encodable for PathStatusAvailable {
1682 fn encode<W: BufMut>(&self, buf: &mut W) {
1683 buf.write(Self::TYPE);
1684 buf.write(self.path_id);
1685 buf.write(self.status_seq_no);
1686 }
1687}
1688
1689impl Decodable for PathStatusAvailable {
1690 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1691 Ok(Self {
1692 path_id: bytes.get()?,
1693 status_seq_no: bytes.get()?,
1694 })
1695 }
1696}
1697
1698#[derive(Debug, PartialEq, Eq)]
1699pub(crate) struct PathStatusBackup {
1700 pub(crate) path_id: PathId,
1701 pub(crate) status_seq_no: VarInt,
1702}
1703
1704impl PathStatusBackup {
1705 const TYPE: FrameType = FrameType::PathStatusBackup;
1706}
1707
1708impl Encodable for PathStatusBackup {
1709 fn encode<W: BufMut>(&self, buf: &mut W) {
1710 buf.write(Self::TYPE);
1711 buf.write(self.path_id);
1712 buf.write(self.status_seq_no);
1713 }
1714}
1715
1716impl Decodable for PathStatusBackup {
1717 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1718 Ok(Self {
1719 path_id: bytes.get()?,
1720 status_seq_no: bytes.get()?,
1721 })
1722 }
1723}
1724
1725#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
1730#[allow(dead_code)]
1732pub(crate) struct AddAddress {
1733 pub(crate) seq_no: VarInt,
1736 pub(crate) ip: IpAddr,
1738 pub(crate) port: u16,
1740}
1741
1742#[allow(dead_code)]
1744impl AddAddress {
1745 pub(crate) const SIZE_BOUND: usize = Self {
1747 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST),
1748 port: u16::MAX,
1749 seq_no: VarInt::MAX,
1750 }
1751 .size();
1752
1753 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self {
1754 Self { ip, port, seq_no }
1755 }
1756
1757 pub(crate) const fn get_type(&self) -> FrameType {
1759 if self.ip.is_ipv6() {
1760 FrameType::AddIpv6Address
1761 } else {
1762 FrameType::AddIpv4Address
1763 }
1764 }
1765
1766 pub(crate) const fn size(&self) -> usize {
1768 let type_size = self.get_type().size();
1769 let seq_no_bytes = self.seq_no.size();
1770 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
1771 let port_bytes = 2;
1772 type_size + seq_no_bytes + ip_bytes + port_bytes
1773 }
1774
1775 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
1780 let seq_no = bytes.get()?;
1781 let ip = if is_ipv6 {
1782 IpAddr::V6(bytes.get()?)
1783 } else {
1784 IpAddr::V4(bytes.get()?)
1785 };
1786 let port = bytes.get()?;
1787 Ok(Self { seq_no, ip, port })
1788 }
1789
1790 pub(crate) fn socket_addr(&self) -> SocketAddr {
1792 self.ip_port().into()
1793 }
1794
1795 pub(crate) fn ip_port(&self) -> (IpAddr, u16) {
1796 (self.ip, self.port)
1797 }
1798}
1799
1800impl Encodable for AddAddress {
1801 fn encode<W: BufMut>(&self, buf: &mut W) {
1802 buf.write(self.get_type());
1803 buf.write(self.seq_no);
1804 match self.ip {
1805 IpAddr::V4(ipv4_addr) => {
1806 buf.write(ipv4_addr);
1807 }
1808 IpAddr::V6(ipv6_addr) => {
1809 buf.write(ipv6_addr);
1810 }
1811 }
1812 buf.write::<u16>(self.port);
1813 }
1814}
1815
1816#[derive(Debug, PartialEq, Eq, Clone)]
1819#[allow(dead_code)]
1821pub(crate) struct ReachOut {
1822 pub(crate) round: VarInt,
1824 pub(crate) ip: IpAddr,
1826 pub(crate) port: u16,
1828}
1829
1830#[allow(dead_code)]
1832impl ReachOut {
1833 pub(crate) const SIZE_BOUND: usize = Self {
1835 round: VarInt::MAX,
1836 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST),
1837 port: u16::MAX,
1838 }
1839 .size();
1840
1841 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self {
1842 Self { round, ip, port }
1843 }
1844
1845 pub(crate) const fn get_type(&self) -> FrameType {
1847 if self.ip.is_ipv6() {
1848 FrameType::ReachOutAtIpv6
1849 } else {
1850 FrameType::ReachOutAtIpv4
1851 }
1852 }
1853
1854 pub(crate) const fn size(&self) -> usize {
1856 let type_size = self.get_type().size();
1857 let round_bytes = self.round.size();
1858 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
1859 let port_bytes = 2;
1860 type_size + round_bytes + ip_bytes + port_bytes
1861 }
1862
1863 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
1868 let round = bytes.get()?;
1869 let ip = if is_ipv6 {
1870 IpAddr::V6(bytes.get()?)
1871 } else {
1872 IpAddr::V4(bytes.get()?)
1873 };
1874 let port = bytes.get()?;
1875 Ok(Self { round, ip, port })
1876 }
1877
1878 pub(crate) fn socket_addr(&self) -> SocketAddr {
1880 (self.ip, self.port).into()
1881 }
1882}
1883
1884impl Encodable for ReachOut {
1885 fn encode<W: BufMut>(&self, buf: &mut W) {
1886 buf.write(self.get_type());
1887 buf.write(self.round);
1888 match self.ip {
1889 IpAddr::V4(ipv4_addr) => {
1890 buf.write(ipv4_addr);
1891 }
1892 IpAddr::V6(ipv6_addr) => {
1893 buf.write(ipv6_addr);
1894 }
1895 }
1896 buf.write::<u16>(self.port);
1897 }
1898}
1899
1900#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
1902#[allow(dead_code)]
1904pub(crate) struct RemoveAddress {
1905 pub(crate) seq_no: VarInt,
1907}
1908
1909#[allow(dead_code)]
1911impl RemoveAddress {
1912 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress;
1914
1915 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size();
1917
1918 pub(crate) const fn new(seq_no: VarInt) -> Self {
1919 Self { seq_no }
1920 }
1921
1922 pub(crate) const fn size(&self) -> usize {
1924 let type_size = Self::TYPE.size();
1925 let seq_no_bytes = self.seq_no.size();
1926 type_size + seq_no_bytes
1927 }
1928
1929 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1934 Ok(Self {
1935 seq_no: bytes.get()?,
1936 })
1937 }
1938}
1939
1940impl Encodable for RemoveAddress {
1941 fn encode<W: BufMut>(&self, buf: &mut W) {
1942 buf.write(Self::TYPE);
1943 buf.write(self.seq_no);
1944 }
1945}
1946
1947#[cfg(test)]
1948mod test {
1949 use super::*;
1950 use crate::coding::Encodable;
1951 use assert_matches::assert_matches;
1952
1953 #[track_caller]
1954 fn frames(buf: Vec<u8>) -> Vec<Frame> {
1955 Iter::new(Bytes::from(buf))
1956 .unwrap()
1957 .collect::<Result<Vec<_>, _>>()
1958 .unwrap()
1959 }
1960
1961 #[test]
1962 fn ack_coding() {
1963 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
1964 let mut ranges = ArrayRangeSet::new();
1965 for &packet in PACKETS {
1966 ranges.insert(packet..packet + 1);
1967 }
1968 let mut buf = Vec::new();
1969 const ECN: EcnCounts = EcnCounts {
1970 ect0: 42,
1971 ect1: 24,
1972 ce: 12,
1973 };
1974 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf);
1975 let frames = frames(buf);
1976 assert_eq!(frames.len(), 1);
1977 match frames[0] {
1978 Frame::Ack(ref ack) => {
1979 let mut packets = ack.iter().flatten().collect::<Vec<_>>();
1980 packets.sort_unstable();
1981 assert_eq!(&packets[..], PACKETS);
1982 assert_eq!(ack.ecn, Some(ECN));
1983 }
1984 ref x => panic!("incorrect frame {x:?}"),
1985 }
1986 }
1987
1988 #[test]
1989 #[allow(clippy::range_plus_one)]
1990 fn path_ack_coding() {
1991 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
1992 let mut ranges = ArrayRangeSet::new();
1993 for &packet in PACKETS {
1994 ranges.insert(packet..packet + 1);
1995 }
1996 let mut buf = Vec::new();
1997 const ECN: EcnCounts = EcnCounts {
1998 ect0: 42,
1999 ect1: 24,
2000 ce: 12,
2001 };
2002 const PATH_ID: PathId = PathId::MAX;
2003 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf);
2004 let frames = frames(buf);
2005 assert_eq!(frames.len(), 1);
2006 match frames[0] {
2007 Frame::PathAck(ref ack) => {
2008 assert_eq!(ack.path_id, PATH_ID);
2009 let mut packets = ack.into_iter().flatten().collect::<Vec<_>>();
2010 packets.sort_unstable();
2011 assert_eq!(&packets[..], PACKETS);
2012 assert_eq!(ack.ecn, Some(ECN));
2013 }
2014 ref x => panic!("incorrect frame {x:?}"),
2015 }
2016 }
2017
2018 #[test]
2019 fn ack_frequency_coding() {
2020 let mut buf = Vec::new();
2021 let original = AckFrequency {
2022 sequence: VarInt(42),
2023 ack_eliciting_threshold: VarInt(20),
2024 request_max_ack_delay: VarInt(50_000),
2025 reordering_threshold: VarInt(1),
2026 };
2027 original.encode(&mut buf);
2028 let frames = frames(buf);
2029 assert_eq!(frames.len(), 1);
2030 match &frames[0] {
2031 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original),
2032 x => panic!("incorrect frame {x:?}"),
2033 }
2034 }
2035
2036 #[test]
2037 fn immediate_ack_coding() {
2038 let mut buf = Vec::new();
2039 FrameType::ImmediateAck.encode(&mut buf);
2040 let frames = frames(buf);
2041 assert_eq!(frames.len(), 1);
2042 assert_matches!(&frames[0], Frame::ImmediateAck);
2043 }
2044
2045 #[test]
2047 fn test_observed_addr_roundrip() {
2048 let observed_addr = ObservedAddr {
2049 seq_no: VarInt(42),
2050 ip: std::net::Ipv4Addr::LOCALHOST.into(),
2051 port: 4242,
2052 };
2053 let mut buf = Vec::with_capacity(observed_addr.size());
2054 observed_addr.encode(&mut buf);
2055
2056 assert_eq!(
2057 observed_addr.size(),
2058 buf.len(),
2059 "expected written bytes and actual size differ"
2060 );
2061
2062 let mut decoded = frames(buf);
2063 assert_eq!(decoded.len(), 1);
2064 match decoded.pop().expect("non empty") {
2065 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr),
2066 x => panic!("incorrect frame {x:?}"),
2067 }
2068 }
2069
2070 #[test]
2071 fn test_path_abandon_roundtrip() {
2072 let abandon = PathAbandon {
2073 path_id: PathId(42),
2074 error_code: TransportErrorCode::NO_ERROR,
2075 };
2076 let mut buf = Vec::new();
2077 abandon.encode(&mut buf);
2078
2079 let mut decoded = frames(buf);
2080 assert_eq!(decoded.len(), 1);
2081 match decoded.pop().expect("non empty") {
2082 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon),
2083 x => panic!("incorrect frame {x:?}"),
2084 }
2085 }
2086
2087 #[test]
2088 fn test_path_status_available_roundtrip() {
2089 let path_status_available = PathStatusAvailable {
2090 path_id: PathId(42),
2091 status_seq_no: VarInt(73),
2092 };
2093 let mut buf = Vec::new();
2094 path_status_available.encode(&mut buf);
2095
2096 let mut decoded = frames(buf);
2097 assert_eq!(decoded.len(), 1);
2098 match decoded.pop().expect("non empty") {
2099 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available),
2100 x => panic!("incorrect frame {x:?}"),
2101 }
2102 }
2103
2104 #[test]
2105 fn test_path_status_backup_roundtrip() {
2106 let path_status_backup = PathStatusBackup {
2107 path_id: PathId(42),
2108 status_seq_no: VarInt(73),
2109 };
2110 let mut buf = Vec::new();
2111 path_status_backup.encode(&mut buf);
2112
2113 let mut decoded = frames(buf);
2114 assert_eq!(decoded.len(), 1);
2115 match decoded.pop().expect("non empty") {
2116 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup),
2117 x => panic!("incorrect frame {x:?}"),
2118 }
2119 }
2120
2121 #[test]
2122 fn test_path_new_connection_id_roundtrip() {
2123 let cid = NewConnectionId {
2124 path_id: Some(PathId(22)),
2125 sequence: 31,
2126 retire_prior_to: 13,
2127 id: ConnectionId::new(&[0xAB; 8]),
2128 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]),
2129 };
2130 let mut buf = Vec::new();
2131 cid.encode(&mut buf);
2132
2133 let mut decoded = frames(buf);
2134 assert_eq!(decoded.len(), 1);
2135 match decoded.pop().expect("non empty") {
2136 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid),
2137 x => panic!("incorrect frame {x:?}"),
2138 }
2139 }
2140
2141 #[test]
2142 fn test_path_retire_connection_id_roundtrip() {
2143 let retire_cid = RetireConnectionId {
2144 path_id: Some(PathId(22)),
2145 sequence: 31,
2146 };
2147 let mut buf = Vec::new();
2148 retire_cid.encode(&mut buf);
2149
2150 let mut decoded = frames(buf);
2151 assert_eq!(decoded.len(), 1);
2152 match decoded.pop().expect("non empty") {
2153 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid),
2154 x => panic!("incorrect frame {x:?}"),
2155 }
2156 }
2157
2158 #[test]
2159 fn test_paths_blocked_path_cids_blocked_roundtrip() {
2160 let mut buf = Vec::new();
2161
2162 let frame0 = PathsBlocked(PathId(22));
2163 frame0.encode(&mut buf);
2164 let frame1 = PathCidsBlocked {
2165 path_id: PathId(23),
2166 next_seq: VarInt(32),
2167 };
2168 frame1.encode(&mut buf);
2169
2170 let mut decoded = frames(buf);
2171 assert_eq!(decoded.len(), 2);
2172 match decoded.pop().expect("non empty") {
2173 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1),
2174 x => panic!("incorrect frame {x:?}"),
2175 }
2176 match decoded.pop().expect("non empty") {
2177 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0),
2178 x => panic!("incorrect frame {x:?}"),
2179 }
2180 }
2181
2182 #[test]
2184 fn test_add_address_roundrip() {
2185 let add_address = AddAddress {
2186 seq_no: VarInt(42),
2187 ip: std::net::Ipv4Addr::LOCALHOST.into(),
2188 port: 4242,
2189 };
2190 let mut buf = Vec::with_capacity(add_address.size());
2191 add_address.encode(&mut buf);
2192
2193 assert_eq!(
2194 add_address.size(),
2195 buf.len(),
2196 "expected written bytes and actual size differ"
2197 );
2198
2199 let mut decoded = frames(buf);
2200 assert_eq!(decoded.len(), 1);
2201 match decoded.pop().expect("non empty") {
2202 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address),
2203 x => panic!("incorrect frame {x:?}"),
2204 }
2205 }
2206
2207 #[test]
2209 fn test_reach_out_roundrip() {
2210 let reach_out = ReachOut {
2211 round: VarInt(42),
2212 ip: std::net::Ipv6Addr::LOCALHOST.into(),
2213 port: 4242,
2214 };
2215 let mut buf = Vec::with_capacity(reach_out.size());
2216 reach_out.encode(&mut buf);
2217
2218 assert_eq!(
2219 reach_out.size(),
2220 buf.len(),
2221 "expected written bytes and actual size differ"
2222 );
2223
2224 let mut decoded = frames(buf);
2225 assert_eq!(decoded.len(), 1);
2226 match decoded.pop().expect("non empty") {
2227 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out),
2228 x => panic!("incorrect frame {x:?}"),
2229 }
2230 }
2231
2232 #[test]
2234 fn test_remove_address_roundrip() {
2235 let remove_addr = RemoveAddress::new(VarInt(10));
2236 let mut buf = Vec::with_capacity(remove_addr.size());
2237 remove_addr.encode(&mut buf);
2238
2239 assert_eq!(
2240 remove_addr.size(),
2241 buf.len(),
2242 "expected written bytes and actual size differ"
2243 );
2244
2245 let mut decoded = frames(buf);
2246 assert_eq!(decoded.len(), 1);
2247 match decoded.pop().expect("non empty") {
2248 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr),
2249 x => panic!("incorrect frame {x:?}"),
2250 }
2251 }
2252}