From d390bbdbbcccfb24f53a1fec1e9fa602d4eff433 Mon Sep 17 00:00:00 2001 From: rklaehn Date: Mon, 19 Jan 2026 16:42:11 +0000 Subject: [PATCH] deploy: 0199bade53cbf7f46cb24e890e51cc119acf408c --- pr/340/docs/help.html | 2 +- .../coding/trait.Encodable.html | 2 +- .../iroh_quinn_proto/struct.Datagram.html | 4 +- pr/340/docs/settings.html | 2 +- .../docs/src/iroh_quinn_proto/frame.rs.html | 3726 +++++++++-------- .../range_set/array_range_set.rs.html | 2 +- 6 files changed, 1872 insertions(+), 1866 deletions(-) diff --git a/pr/340/docs/help.html b/pr/340/docs/help.html index 99d8cb979..cda0c7f93 100644 --- a/pr/340/docs/help.html +++ b/pr/340/docs/help.html @@ -1 +1 @@ -Help

All

Rustdoc help

Back
\ No newline at end of file +Help

All

Rustdoc help

Back
\ No newline at end of file diff --git a/pr/340/docs/iroh_quinn_proto/coding/trait.Encodable.html b/pr/340/docs/iroh_quinn_proto/coding/trait.Encodable.html index 58e2959a7..15abe79cf 100644 --- a/pr/340/docs/iroh_quinn_proto/coding/trait.Encodable.html +++ b/pr/340/docs/iroh_quinn_proto/coding/trait.Encodable.html @@ -3,4 +3,4 @@ fn encode<B: BufMut>(&self, buf: &mut B); }
Expand description

Infallible encoding of QUIC primitives.

Required Methods§

Source

fn encode<B: BufMut>(&self, buf: &mut B)

Append the encoding of self to the provided buffer.

-

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Encodable for u8

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u16

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u32

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u64

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv4Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv6Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Implementors§

Source§

impl Encodable for FrameType

Source§

impl Encodable for MaybeFrame

Source§

impl Encodable for Datagram

Source§

impl Encodable for PathId

Source§

impl Encodable for StreamId

Source§

impl Encodable for Code

Source§

impl Encodable for VarInt

\ No newline at end of file +

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Encodable for u8

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u16

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u32

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u64

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv4Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv6Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Implementors§

Source§

impl Encodable for FrameType

Source§

impl Encodable for MaybeFrame

Source§

impl Encodable for Datagram

Source§

impl Encodable for PathId

Source§

impl Encodable for StreamId

Source§

impl Encodable for Code

Source§

impl Encodable for VarInt

\ No newline at end of file diff --git a/pr/340/docs/iroh_quinn_proto/struct.Datagram.html b/pr/340/docs/iroh_quinn_proto/struct.Datagram.html index ed210214b..5471fe7fa 100644 --- a/pr/340/docs/iroh_quinn_proto/struct.Datagram.html +++ b/pr/340/docs/iroh_quinn_proto/struct.Datagram.html @@ -1,8 +1,8 @@ -Datagram in iroh_quinn_proto - Rust

Datagram

Struct Datagram 

Source
pub struct Datagram {
+Datagram in iroh_quinn_proto - Rust

Datagram

Struct Datagram 

Source
pub struct Datagram {
     pub data: Bytes,
 }
Expand description

An unreliable datagram

Fields§

§data: Bytes

Payload

-

Trait Implementations§

Source§

impl Clone for Datagram

Source§

fn clone(&self) -> Datagram

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Datagram

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Datagram

Source§

fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Encodable for Datagram

Source§

fn encode<B: BufMut>(&self, out: &mut B)

Append the encoding of self to the provided buffer.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for Datagram

Source§

fn clone(&self) -> Datagram

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Datagram

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Datagram

Source§

fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Encodable for Datagram

Source§

fn encode<B: BufMut>(&self, out: &mut B)

Append the encoding of self to the provided buffer.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/340/docs/settings.html b/pr/340/docs/settings.html index abf467830..1adf3f67d 100644 --- a/pr/340/docs/settings.html +++ b/pr/340/docs/settings.html @@ -1 +1 @@ -Settings

All

Rustdoc settings

Back
\ No newline at end of file +Settings

All

Rustdoc settings

Back
\ No newline at end of file diff --git a/pr/340/docs/src/iroh_quinn_proto/frame.rs.html b/pr/340/docs/src/iroh_quinn_proto/frame.rs.html index f6a52cdce..08cdf39f5 100644 --- a/pr/340/docs/src/iroh_quinn_proto/frame.rs.html +++ b/pr/340/docs/src/iroh_quinn_proto/frame.rs.html @@ -1001,1905 +1001,1911 @@ 1001 any::<ArrayRangeSet>(), 1002 any::<Option<EcnCounts>>(), 1003 ) -1004 .prop_map(|(path_id, delay, ranges, ecn)| Self { -1005 path_id, -1006 largest: ranges.max().unwrap(), -1007 delay, -1008 ranges, -1009 ecn, -1010 }) -1011 .boxed() -1012 } -1013} -1014 -1015impl PathAck { -1016 pub(crate) fn into_ack(self) -> (Ack, PathId) { -1017 let ack = Ack { -1018 largest: self.largest, -1019 delay: self.delay, -1020 ranges: self.ranges, -1021 ecn: self.ecn, -1022 }; -1023 -1024 (ack, self.path_id) -1025 } +1004 .prop_filter("ranges must be non empty", |(_, _, ranges, _)| { +1005 !ranges.is_empty() +1006 }) +1007 .prop_map(|(path_id, delay, ranges, ecn)| Self { +1008 path_id, +1009 largest: ranges.max().expect("ranges must be non empty"), +1010 delay, +1011 ranges, +1012 ecn, +1013 }) +1014 .boxed() +1015 } +1016} +1017 +1018impl PathAck { +1019 pub(crate) fn into_ack(self) -> (Ack, PathId) { +1020 let ack = Ack { +1021 largest: self.largest, +1022 delay: self.delay, +1023 ranges: self.ranges, +1024 ecn: self.ecn, +1025 }; 1026 -1027 fn get_type(&self) -> FrameType { -1028 if self.ecn.is_some() { -1029 FrameType::PathAckEcn -1030 } else { -1031 FrameType::PathAck -1032 } -1033 } -1034 -1035 pub(crate) fn encoder<'a>( -1036 path_id: PathId, -1037 delay: u64, -1038 ranges: &'a ArrayRangeSet, -1039 ecn: Option<&'a EcnCounts>, -1040 ) -> PathAckEncoder<'a> { -1041 PathAckEncoder { -1042 path_id, -1043 delay, -1044 ranges, -1045 ecn, -1046 } -1047 } -1048} -1049 -1050#[derive(derive_more::Display)] -1051#[display("{} path_id: {path_id} ranges: {ranges:?} delay: {delay}µs", self.get_type())] -1052pub(crate) struct PathAckEncoder<'a> { -1053 pub(super) path_id: PathId, -1054 pub(super) delay: u64, -1055 pub(super) ranges: &'a ArrayRangeSet, -1056 pub(super) ecn: Option<&'a EcnCounts>, -1057} -1058 -1059impl<'a> PathAckEncoder<'a> { -1060 const fn get_type(&self) -> FrameType { -1061 match self.ecn.is_some() { -1062 true => FrameType::PathAckEcn, -1063 false => FrameType::PathAck, -1064 } -1065 } -1066} -1067 -1068impl<'a> Encodable for PathAckEncoder<'a> { -1069 /// Encode [`Self`] into the given buffer -1070 /// -1071 /// The [`FrameType`] will be either [`FrameType::PathAckEcn`] or [`FrameType::PathAck`] -1072 /// depending on whether [`EcnCounts`] are provided. +1027 (ack, self.path_id) +1028 } +1029 +1030 fn get_type(&self) -> FrameType { +1031 if self.ecn.is_some() { +1032 FrameType::PathAckEcn +1033 } else { +1034 FrameType::PathAck +1035 } +1036 } +1037 +1038 pub(crate) fn encoder<'a>( +1039 path_id: PathId, +1040 delay: u64, +1041 ranges: &'a ArrayRangeSet, +1042 ecn: Option<&'a EcnCounts>, +1043 ) -> PathAckEncoder<'a> { +1044 PathAckEncoder { +1045 path_id, +1046 delay, +1047 ranges, +1048 ecn, +1049 } +1050 } +1051} +1052 +1053#[derive(derive_more::Display)] +1054#[display("{} path_id: {path_id} ranges: {ranges:?} delay: {delay}µs", self.get_type())] +1055pub(crate) struct PathAckEncoder<'a> { +1056 pub(super) path_id: PathId, +1057 pub(super) delay: u64, +1058 pub(super) ranges: &'a ArrayRangeSet, +1059 pub(super) ecn: Option<&'a EcnCounts>, +1060} +1061 +1062impl<'a> PathAckEncoder<'a> { +1063 const fn get_type(&self) -> FrameType { +1064 match self.ecn.is_some() { +1065 true => FrameType::PathAckEcn, +1066 false => FrameType::PathAck, +1067 } +1068 } +1069} +1070 +1071impl<'a> Encodable for PathAckEncoder<'a> { +1072 /// Encode [`Self`] into the given buffer 1073 /// -1074 /// PANICS: if `ranges` is empty. -1075 fn encode<W: BufMut>(&self, buf: &mut W) { -1076 let PathAckEncoder { -1077 path_id, -1078 delay, -1079 ranges, -1080 ecn, -1081 } = self; -1082 let mut rest = ranges.iter().rev(); -1083 let first = rest -1084 .next() -1085 .expect("Caller has verified ranges is non empty"); -1086 let largest = first.end - 1; -1087 let first_size = first.end - first.start; -1088 let kind = match ecn.is_some() { -1089 true => FrameType::PathAckEcn, -1090 false => FrameType::PathAck, -1091 }; -1092 buf.write(kind); -1093 buf.write(*path_id); -1094 buf.write_var(largest); -1095 buf.write_var(*delay); -1096 buf.write_var(ranges.len() as u64 - 1); -1097 buf.write_var(first_size - 1); -1098 let mut prev = first.start; -1099 for block in rest { -1100 let size = block.end - block.start; -1101 buf.write_var(prev - block.end - 1); -1102 buf.write_var(size - 1); -1103 prev = block.start; -1104 } -1105 if let Some(x) = ecn { -1106 x.encode(buf) +1074 /// The [`FrameType`] will be either [`FrameType::PathAckEcn`] or [`FrameType::PathAck`] +1075 /// depending on whether [`EcnCounts`] are provided. +1076 /// +1077 /// PANICS: if `ranges` is empty. +1078 fn encode<W: BufMut>(&self, buf: &mut W) { +1079 let PathAckEncoder { +1080 path_id, +1081 delay, +1082 ranges, +1083 ecn, +1084 } = self; +1085 let mut rest = ranges.iter().rev(); +1086 let first = rest +1087 .next() +1088 .expect("Caller has verified ranges is non empty"); +1089 let largest = first.end - 1; +1090 let first_size = first.end - first.start; +1091 let kind = match ecn.is_some() { +1092 true => FrameType::PathAckEcn, +1093 false => FrameType::PathAck, +1094 }; +1095 buf.write(kind); +1096 buf.write(*path_id); +1097 buf.write_var(largest); +1098 buf.write_var(*delay); +1099 buf.write_var(ranges.len() as u64 - 1); +1100 buf.write_var(first_size - 1); +1101 let mut prev = first.start; +1102 for block in rest { +1103 let size = block.end - block.start; +1104 buf.write_var(prev - block.end - 1); +1105 buf.write_var(size - 1); +1106 prev = block.start; 1107 } -1108 } -1109} -1110 -1111#[derive(Debug, Clone, Eq, PartialEq)] -1112pub(crate) struct Ack { -1113 pub largest: u64, -1114 pub delay: u64, -1115 pub ranges: ArrayRangeSet, -1116 pub ecn: Option<EcnCounts>, -1117} -1118 -1119#[cfg(test)] -1120impl proptest::arbitrary::Arbitrary for Ack { -1121 type Parameters = (); -1122 type Strategy = proptest::strategy::BoxedStrategy<Self>; -1123 -1124 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { -1125 use proptest::prelude::*; -1126 ( -1127 varint_u64(), -1128 any::<ArrayRangeSet>(), -1129 any::<Option<EcnCounts>>(), -1130 ) -1131 .prop_map(|(delay, ranges, ecn)| Self { -1132 largest: ranges.max().unwrap(), -1133 delay, -1134 ranges, -1135 ecn, +1108 if let Some(x) = ecn { +1109 x.encode(buf) +1110 } +1111 } +1112} +1113 +1114#[derive(Debug, Clone, Eq, PartialEq)] +1115pub(crate) struct Ack { +1116 pub largest: u64, +1117 pub delay: u64, +1118 pub ranges: ArrayRangeSet, +1119 pub ecn: Option<EcnCounts>, +1120} +1121 +1122#[cfg(test)] +1123impl proptest::arbitrary::Arbitrary for Ack { +1124 type Parameters = (); +1125 type Strategy = proptest::strategy::BoxedStrategy<Self>; +1126 +1127 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { +1128 use proptest::prelude::*; +1129 ( +1130 varint_u64(), +1131 any::<ArrayRangeSet>(), +1132 any::<Option<EcnCounts>>(), +1133 ) +1134 .prop_filter("ranges must be non empty", |(_, ranges, _)| { +1135 !ranges.is_empty() 1136 }) -1137 .boxed() -1138 } -1139} -1140 -1141impl Ack { -1142 pub(crate) fn encoder<'a>( -1143 delay: u64, -1144 ranges: &'a ArrayRangeSet, -1145 ecn: Option<&'a EcnCounts>, -1146 ) -> AckEncoder<'a> { -1147 AckEncoder { delay, ranges, ecn } -1148 } -1149 -1150 pub(crate) fn iter(&self) -> impl DoubleEndedIterator<Item = Range<u64>> + '_ { -1151 self.ranges.iter() -1152 } -1153 -1154 pub(crate) const fn get_type(&self) -> FrameType { -1155 if self.ecn.is_some() { -1156 FrameType::AckEcn -1157 } else { -1158 FrameType::Ack -1159 } -1160 } -1161} -1162 -1163#[derive(derive_more::Display)] -1164#[display("{} ranges: {ranges:?} delay: {delay}µs", self.get_type())] -1165pub(crate) struct AckEncoder<'a> { -1166 pub(crate) delay: u64, -1167 pub(crate) ranges: &'a ArrayRangeSet, -1168 pub(crate) ecn: Option<&'a EcnCounts>, -1169} -1170 -1171impl<'a> AckEncoder<'a> { -1172 const fn get_type(&self) -> FrameType { -1173 match self.ecn.is_some() { -1174 true => FrameType::AckEcn, -1175 false => FrameType::Ack, -1176 } -1177 } -1178} -1179 -1180impl<'a> Encodable for AckEncoder<'a> { -1181 fn encode<W: BufMut>(&self, buf: &mut W) { -1182 let AckEncoder { delay, ranges, ecn } = self; -1183 let mut rest = ranges.iter().rev(); -1184 let first = rest.next().unwrap(); -1185 let largest = first.end - 1; -1186 let first_size = first.end - first.start; -1187 let kind = match ecn.is_some() { -1188 true => FrameType::AckEcn, -1189 false => FrameType::Ack, -1190 }; -1191 buf.write(kind); -1192 buf.write_var(largest); -1193 buf.write_var(*delay); -1194 buf.write_var(ranges.len() as u64 - 1); -1195 buf.write_var(first_size - 1); -1196 let mut prev = first.start; -1197 for block in rest { -1198 let size = block.end - block.start; -1199 buf.write_var(prev - block.end - 1); -1200 buf.write_var(size - 1); -1201 prev = block.start; -1202 } -1203 if let Some(x) = ecn { -1204 x.encode(buf) -1205 } -1206 } -1207} -1208 -1209#[cfg_attr(test, derive(Arbitrary))] -1210#[derive(Debug, Copy, Clone, Eq, PartialEq)] -1211pub(crate) struct EcnCounts { -1212 #[cfg_attr(test, strategy(varint_u64()))] -1213 pub ect0: u64, -1214 #[cfg_attr(test, strategy(varint_u64()))] -1215 pub ect1: u64, -1216 #[cfg_attr(test, strategy(varint_u64()))] -1217 pub ce: u64, -1218} -1219 -1220impl std::ops::AddAssign<EcnCodepoint> for EcnCounts { -1221 fn add_assign(&mut self, rhs: EcnCodepoint) { -1222 match rhs { -1223 EcnCodepoint::Ect0 => { -1224 self.ect0 += 1; -1225 } -1226 EcnCodepoint::Ect1 => { -1227 self.ect1 += 1; -1228 } -1229 EcnCodepoint::Ce => { -1230 self.ce += 1; +1137 .prop_map(|(delay, ranges, ecn)| Self { +1138 largest: ranges.max().expect("ranges must be non empty"), +1139 delay, +1140 ranges, +1141 ecn, +1142 }) +1143 .boxed() +1144 } +1145} +1146 +1147impl Ack { +1148 pub(crate) fn encoder<'a>( +1149 delay: u64, +1150 ranges: &'a ArrayRangeSet, +1151 ecn: Option<&'a EcnCounts>, +1152 ) -> AckEncoder<'a> { +1153 AckEncoder { delay, ranges, ecn } +1154 } +1155 +1156 pub(crate) fn iter(&self) -> impl DoubleEndedIterator<Item = Range<u64>> + '_ { +1157 self.ranges.iter() +1158 } +1159 +1160 pub(crate) const fn get_type(&self) -> FrameType { +1161 if self.ecn.is_some() { +1162 FrameType::AckEcn +1163 } else { +1164 FrameType::Ack +1165 } +1166 } +1167} +1168 +1169#[derive(derive_more::Display)] +1170#[display("{} ranges: {ranges:?} delay: {delay}µs", self.get_type())] +1171pub(crate) struct AckEncoder<'a> { +1172 pub(crate) delay: u64, +1173 pub(crate) ranges: &'a ArrayRangeSet, +1174 pub(crate) ecn: Option<&'a EcnCounts>, +1175} +1176 +1177impl<'a> AckEncoder<'a> { +1178 const fn get_type(&self) -> FrameType { +1179 match self.ecn.is_some() { +1180 true => FrameType::AckEcn, +1181 false => FrameType::Ack, +1182 } +1183 } +1184} +1185 +1186impl<'a> Encodable for AckEncoder<'a> { +1187 fn encode<W: BufMut>(&self, buf: &mut W) { +1188 let AckEncoder { delay, ranges, ecn } = self; +1189 let mut rest = ranges.iter().rev(); +1190 let first = rest.next().unwrap(); +1191 let largest = first.end - 1; +1192 let first_size = first.end - first.start; +1193 let kind = match ecn.is_some() { +1194 true => FrameType::AckEcn, +1195 false => FrameType::Ack, +1196 }; +1197 buf.write(kind); +1198 buf.write_var(largest); +1199 buf.write_var(*delay); +1200 buf.write_var(ranges.len() as u64 - 1); +1201 buf.write_var(first_size - 1); +1202 let mut prev = first.start; +1203 for block in rest { +1204 let size = block.end - block.start; +1205 buf.write_var(prev - block.end - 1); +1206 buf.write_var(size - 1); +1207 prev = block.start; +1208 } +1209 if let Some(x) = ecn { +1210 x.encode(buf) +1211 } +1212 } +1213} +1214 +1215#[cfg_attr(test, derive(Arbitrary))] +1216#[derive(Debug, Copy, Clone, Eq, PartialEq)] +1217pub(crate) struct EcnCounts { +1218 #[cfg_attr(test, strategy(varint_u64()))] +1219 pub ect0: u64, +1220 #[cfg_attr(test, strategy(varint_u64()))] +1221 pub ect1: u64, +1222 #[cfg_attr(test, strategy(varint_u64()))] +1223 pub ce: u64, +1224} +1225 +1226impl std::ops::AddAssign<EcnCodepoint> for EcnCounts { +1227 fn add_assign(&mut self, rhs: EcnCodepoint) { +1228 match rhs { +1229 EcnCodepoint::Ect0 => { +1230 self.ect0 += 1; 1231 } -1232 } -1233 } -1234} -1235 -1236impl EcnCounts { -1237 pub(crate) const ZERO: Self = Self { -1238 ect0: 0, -1239 ect1: 0, -1240 ce: 0, -1241 }; -1242} -1243 -1244impl Encodable for EcnCounts { -1245 fn encode<W: BufMut>(&self, out: &mut W) { -1246 out.write_var(self.ect0); -1247 out.write_var(self.ect1); -1248 out.write_var(self.ce); -1249 } -1250} -1251 -1252#[derive(Debug, Clone)] -1253#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] -1254pub(crate) struct Stream { -1255 pub(crate) id: StreamId, -1256 #[cfg_attr(test, strategy(varint_u64()))] -1257 pub(crate) offset: u64, -1258 pub(crate) fin: bool, -1259 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..100), Bytes::from)))] -1260 pub(crate) data: Bytes, -1261} -1262 -1263impl FrameStruct for Stream { -1264 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -1265} -1266 -1267/// Metadata from a stream frame -1268#[derive(Debug, Clone, derive_more::Display)] -1269#[display("STREAM id: {id} off: {} len: {} fin: {fin}", offsets.start, offsets.end - offsets.start)] -1270pub(crate) struct StreamMeta { -1271 pub(crate) id: StreamId, -1272 pub(crate) offsets: Range<u64>, -1273 pub(crate) fin: bool, -1274} -1275 -1276// This manual implementation exists because `Default` is not implemented for `StreamId` -1277impl Default for StreamMeta { -1278 fn default() -> Self { -1279 Self { -1280 id: StreamId(0), -1281 offsets: 0..0, -1282 fin: false, -1283 } -1284 } -1285} -1286 -1287impl StreamMeta { -1288 pub(crate) fn encoder(self, encode_length: bool) -> StreamMetaEncoder { -1289 StreamMetaEncoder { -1290 meta: self, -1291 encode_length, -1292 } -1293 } -1294 -1295 const fn get_type(&self, encode_length: bool) -> StreamInfo { -1296 let mut ty = *StreamInfo::VALUES.start(); -1297 if self.offsets.start != 0 { -1298 ty |= 0x04; -1299 } -1300 if encode_length { -1301 ty |= 0x02; -1302 } -1303 if self.fin { -1304 ty |= 0x01; +1232 EcnCodepoint::Ect1 => { +1233 self.ect1 += 1; +1234 } +1235 EcnCodepoint::Ce => { +1236 self.ce += 1; +1237 } +1238 } +1239 } +1240} +1241 +1242impl EcnCounts { +1243 pub(crate) const ZERO: Self = Self { +1244 ect0: 0, +1245 ect1: 0, +1246 ce: 0, +1247 }; +1248} +1249 +1250impl Encodable for EcnCounts { +1251 fn encode<W: BufMut>(&self, out: &mut W) { +1252 out.write_var(self.ect0); +1253 out.write_var(self.ect1); +1254 out.write_var(self.ce); +1255 } +1256} +1257 +1258#[derive(Debug, Clone)] +1259#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] +1260pub(crate) struct Stream { +1261 pub(crate) id: StreamId, +1262 #[cfg_attr(test, strategy(varint_u64()))] +1263 pub(crate) offset: u64, +1264 pub(crate) fin: bool, +1265 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..100), Bytes::from)))] +1266 pub(crate) data: Bytes, +1267} +1268 +1269impl FrameStruct for Stream { +1270 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +1271} +1272 +1273/// Metadata from a stream frame +1274#[derive(Debug, Clone, derive_more::Display)] +1275#[display("STREAM id: {id} off: {} len: {} fin: {fin}", offsets.start, offsets.end - offsets.start)] +1276pub(crate) struct StreamMeta { +1277 pub(crate) id: StreamId, +1278 pub(crate) offsets: Range<u64>, +1279 pub(crate) fin: bool, +1280} +1281 +1282// This manual implementation exists because `Default` is not implemented for `StreamId` +1283impl Default for StreamMeta { +1284 fn default() -> Self { +1285 Self { +1286 id: StreamId(0), +1287 offsets: 0..0, +1288 fin: false, +1289 } +1290 } +1291} +1292 +1293impl StreamMeta { +1294 pub(crate) fn encoder(self, encode_length: bool) -> StreamMetaEncoder { +1295 StreamMetaEncoder { +1296 meta: self, +1297 encode_length, +1298 } +1299 } +1300 +1301 const fn get_type(&self, encode_length: bool) -> StreamInfo { +1302 let mut ty = *StreamInfo::VALUES.start(); +1303 if self.offsets.start != 0 { +1304 ty |= 0x04; 1305 } -1306 StreamInfo(ty as u8) -1307 } -1308} -1309 -1310#[derive(derive_more::Display)] -1311#[display("{meta}")] -1312pub(crate) struct StreamMetaEncoder { -1313 pub(crate) meta: StreamMeta, -1314 encode_length: bool, -1315} -1316 -1317impl StreamMetaEncoder { -1318 const fn get_type(&self) -> FrameType { -1319 FrameType::Stream(self.meta.get_type(self.encode_length)) -1320 } +1306 if encode_length { +1307 ty |= 0x02; +1308 } +1309 if self.fin { +1310 ty |= 0x01; +1311 } +1312 StreamInfo(ty as u8) +1313 } +1314} +1315 +1316#[derive(derive_more::Display)] +1317#[display("{meta}")] +1318pub(crate) struct StreamMetaEncoder { +1319 pub(crate) meta: StreamMeta, +1320 encode_length: bool, 1321} 1322 -1323impl Encodable for StreamMetaEncoder { -1324 fn encode<W: BufMut>(&self, out: &mut W) { -1325 let Self { -1326 meta, -1327 encode_length, -1328 } = self; -1329 out.write_var(meta.get_type(*encode_length).0 as u64); // 1 byte -1330 out.write(meta.id); // <=8 bytes -1331 if meta.offsets.start != 0 { -1332 out.write_var(meta.offsets.start); // <=8 bytes -1333 } -1334 if *encode_length { -1335 out.write_var(meta.offsets.end - meta.offsets.start); // <=8 bytes -1336 } -1337 } -1338} -1339 -1340/// A vector of [`StreamMeta`] with optimization for the single element case -1341pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>; -1342 -1343#[derive(Debug, Clone, derive_more::Display)] -1344#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] -1345#[display("CRYPTO off: {offset} len = {}", data.len())] -1346pub(crate) struct Crypto { -1347 #[cfg_attr(test, strategy(varint_u64()))] -1348 pub(crate) offset: u64, -1349 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..1024), Bytes::from)))] -1350 pub(crate) data: Bytes, -1351} -1352 -1353impl Crypto { -1354 pub(crate) const SIZE_BOUND: usize = 17; -1355 -1356 const fn get_type(&self) -> FrameType { -1357 FrameType::Crypto -1358 } -1359} -1360 -1361impl Encodable for Crypto { -1362 fn encode<W: BufMut>(&self, out: &mut W) { -1363 out.write(FrameType::Crypto); -1364 out.write_var(self.offset); -1365 out.write_var(self.data.len() as u64); -1366 out.put_slice(&self.data); -1367 } -1368} -1369 -1370#[derive(Debug, Clone, derive_more::Display)] -1371#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] -1372#[display("NEW_TOKEN")] -1373pub(crate) struct NewToken { -1374 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..1024), Bytes::from)))] -1375 pub(crate) token: Bytes, -1376} -1377 -1378impl Encodable for NewToken { -1379 fn encode<W: BufMut>(&self, out: &mut W) { -1380 out.write(FrameType::NewToken); -1381 out.write_var(self.token.len() as u64); -1382 out.put_slice(&self.token); -1383 } -1384} -1385 -1386impl NewToken { -1387 pub(crate) fn size(&self) -> usize { -1388 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len() +1323impl StreamMetaEncoder { +1324 const fn get_type(&self) -> FrameType { +1325 FrameType::Stream(self.meta.get_type(self.encode_length)) +1326 } +1327} +1328 +1329impl Encodable for StreamMetaEncoder { +1330 fn encode<W: BufMut>(&self, out: &mut W) { +1331 let Self { +1332 meta, +1333 encode_length, +1334 } = self; +1335 out.write_var(meta.get_type(*encode_length).0 as u64); // 1 byte +1336 out.write(meta.id); // <=8 bytes +1337 if meta.offsets.start != 0 { +1338 out.write_var(meta.offsets.start); // <=8 bytes +1339 } +1340 if *encode_length { +1341 out.write_var(meta.offsets.end - meta.offsets.start); // <=8 bytes +1342 } +1343 } +1344} +1345 +1346/// A vector of [`StreamMeta`] with optimization for the single element case +1347pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>; +1348 +1349#[derive(Debug, Clone, derive_more::Display)] +1350#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] +1351#[display("CRYPTO off: {offset} len = {}", data.len())] +1352pub(crate) struct Crypto { +1353 #[cfg_attr(test, strategy(varint_u64()))] +1354 pub(crate) offset: u64, +1355 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..1024), Bytes::from)))] +1356 pub(crate) data: Bytes, +1357} +1358 +1359impl Crypto { +1360 pub(crate) const SIZE_BOUND: usize = 17; +1361 +1362 const fn get_type(&self) -> FrameType { +1363 FrameType::Crypto +1364 } +1365} +1366 +1367impl Encodable for Crypto { +1368 fn encode<W: BufMut>(&self, out: &mut W) { +1369 out.write(FrameType::Crypto); +1370 out.write_var(self.offset); +1371 out.write_var(self.data.len() as u64); +1372 out.put_slice(&self.data); +1373 } +1374} +1375 +1376#[derive(Debug, Clone, derive_more::Display)] +1377#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] +1378#[display("NEW_TOKEN")] +1379pub(crate) struct NewToken { +1380 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..1024), Bytes::from)))] +1381 pub(crate) token: Bytes, +1382} +1383 +1384impl Encodable for NewToken { +1385 fn encode<W: BufMut>(&self, out: &mut W) { +1386 out.write(FrameType::NewToken); +1387 out.write_var(self.token.len() as u64); +1388 out.put_slice(&self.token); 1389 } -1390 -1391 const fn get_type(&self) -> FrameType { -1392 FrameType::NewToken -1393 } -1394} -1395 -1396#[derive(Debug, Clone, derive_more::Display)] -1397#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] -1398#[display("MAX_PATH_ID path_id: {_0}")] -1399pub(crate) struct MaxPathId(pub(crate) PathId); -1400 -1401impl MaxPathId { -1402 pub(crate) const SIZE_BOUND: usize = -1403 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size(); -1404 -1405 const fn get_type(&self) -> FrameType { -1406 FrameType::MaxPathId -1407 } -1408} -1409 -1410impl Decodable for MaxPathId { -1411 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -1412 Ok(Self(buf.get()?)) +1390} +1391 +1392impl NewToken { +1393 pub(crate) fn size(&self) -> usize { +1394 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len() +1395 } +1396 +1397 const fn get_type(&self) -> FrameType { +1398 FrameType::NewToken +1399 } +1400} +1401 +1402#[derive(Debug, Clone, derive_more::Display)] +1403#[cfg_attr(test, derive(Arbitrary, PartialEq, Eq))] +1404#[display("MAX_PATH_ID path_id: {_0}")] +1405pub(crate) struct MaxPathId(pub(crate) PathId); +1406 +1407impl MaxPathId { +1408 pub(crate) const SIZE_BOUND: usize = +1409 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size(); +1410 +1411 const fn get_type(&self) -> FrameType { +1412 FrameType::MaxPathId 1413 } 1414} 1415 -1416impl Encodable for MaxPathId { -1417 fn encode<B: BufMut>(&self, buf: &mut B) { -1418 buf.write(FrameType::MaxPathId); -1419 buf.write(self.0); -1420 } -1421} -1422 -1423#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] -1424#[cfg_attr(test, derive(Arbitrary))] -1425#[display("PATHS_BLOCKED remote_max_path_id: {_0}")] -1426pub(crate) struct PathsBlocked(pub(crate) PathId); -1427 -1428impl PathsBlocked { -1429 pub(crate) const SIZE_BOUND: usize = -1430 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size(); -1431 -1432 const fn get_type(&self) -> FrameType { -1433 FrameType::PathsBlocked -1434 } -1435} -1436 -1437impl Encodable for PathsBlocked { -1438 fn encode<B: BufMut>(&self, buf: &mut B) { -1439 buf.write(FrameType::PathsBlocked); -1440 buf.write(self.0); -1441 } -1442} -1443 -1444impl Decodable for PathsBlocked { -1445 /// Decode [`Self`] from the buffer, provided that the frame type has been verified -1446 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -1447 Ok(Self(buf.get()?)) -1448 } -1449} -1450 -1451#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] -1452#[cfg_attr(test, derive(Arbitrary))] -1453#[display("PATH_CIDS_BLOCKED path_id: {path_id} next_seq: {next_seq}")] -1454pub(crate) struct PathCidsBlocked { -1455 pub(crate) path_id: PathId, -1456 pub(crate) next_seq: VarInt, -1457} -1458 -1459impl PathCidsBlocked { -1460 pub(crate) const SIZE_BOUND: usize = -1461 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size(); -1462 -1463 const fn get_type(&self) -> FrameType { -1464 FrameType::PathCidsBlocked -1465 } -1466} -1467 -1468impl Decodable for PathCidsBlocked { -1469 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> { -1470 Ok(Self { -1471 path_id: buf.get()?, -1472 next_seq: buf.get()?, -1473 }) -1474 } -1475} -1476 -1477impl Encodable for PathCidsBlocked { -1478 fn encode<W: BufMut>(&self, buf: &mut W) { -1479 buf.write(FrameType::PathCidsBlocked); -1480 buf.write(self.path_id); -1481 buf.write(self.next_seq); -1482 } -1483} -1484 -1485pub(crate) struct Iter { -1486 bytes: Bytes, -1487 last_ty: MaybeFrame, -1488} -1489 -1490impl Iter { -1491 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> { -1492 if payload.is_empty() { -1493 // "An endpoint MUST treat receipt of a packet containing no frames as a -1494 // connection error of type PROTOCOL_VIOLATION." -1495 // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types -1496 return Err(TransportError::PROTOCOL_VIOLATION( -1497 "packet payload is empty", -1498 )); -1499 } -1500 -1501 Ok(Self { -1502 bytes: payload, -1503 last_ty: MaybeFrame::None, -1504 }) -1505 } +1416impl Decodable for MaxPathId { +1417 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +1418 Ok(Self(buf.get()?)) +1419 } +1420} +1421 +1422impl Encodable for MaxPathId { +1423 fn encode<B: BufMut>(&self, buf: &mut B) { +1424 buf.write(FrameType::MaxPathId); +1425 buf.write(self.0); +1426 } +1427} +1428 +1429#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] +1430#[cfg_attr(test, derive(Arbitrary))] +1431#[display("PATHS_BLOCKED remote_max_path_id: {_0}")] +1432pub(crate) struct PathsBlocked(pub(crate) PathId); +1433 +1434impl PathsBlocked { +1435 pub(crate) const SIZE_BOUND: usize = +1436 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size(); +1437 +1438 const fn get_type(&self) -> FrameType { +1439 FrameType::PathsBlocked +1440 } +1441} +1442 +1443impl Encodable for PathsBlocked { +1444 fn encode<B: BufMut>(&self, buf: &mut B) { +1445 buf.write(FrameType::PathsBlocked); +1446 buf.write(self.0); +1447 } +1448} +1449 +1450impl Decodable for PathsBlocked { +1451 /// Decode [`Self`] from the buffer, provided that the frame type has been verified +1452 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +1453 Ok(Self(buf.get()?)) +1454 } +1455} +1456 +1457#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] +1458#[cfg_attr(test, derive(Arbitrary))] +1459#[display("PATH_CIDS_BLOCKED path_id: {path_id} next_seq: {next_seq}")] +1460pub(crate) struct PathCidsBlocked { +1461 pub(crate) path_id: PathId, +1462 pub(crate) next_seq: VarInt, +1463} +1464 +1465impl PathCidsBlocked { +1466 pub(crate) const SIZE_BOUND: usize = +1467 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size(); +1468 +1469 const fn get_type(&self) -> FrameType { +1470 FrameType::PathCidsBlocked +1471 } +1472} +1473 +1474impl Decodable for PathCidsBlocked { +1475 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> { +1476 Ok(Self { +1477 path_id: buf.get()?, +1478 next_seq: buf.get()?, +1479 }) +1480 } +1481} +1482 +1483impl Encodable for PathCidsBlocked { +1484 fn encode<W: BufMut>(&self, buf: &mut W) { +1485 buf.write(FrameType::PathCidsBlocked); +1486 buf.write(self.path_id); +1487 buf.write(self.next_seq); +1488 } +1489} +1490 +1491pub(crate) struct Iter { +1492 bytes: Bytes, +1493 last_ty: MaybeFrame, +1494} +1495 +1496impl Iter { +1497 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> { +1498 if payload.is_empty() { +1499 // "An endpoint MUST treat receipt of a packet containing no frames as a +1500 // connection error of type PROTOCOL_VIOLATION." +1501 // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types +1502 return Err(TransportError::PROTOCOL_VIOLATION( +1503 "packet payload is empty", +1504 )); +1505 } 1506 -1507 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> { -1508 let len = self.bytes.get_var()?; -1509 if len > self.bytes.remaining() as u64 { -1510 return Err(UnexpectedEnd); -1511 } -1512 Ok(self.bytes.split_to(len as usize)) -1513 } -1514 -1515 #[track_caller] -1516 fn try_next(&mut self) -> Result<Frame, IterErr> { -1517 self.last_ty = self.bytes.get()?; -1518 -1519 let ty = match self.last_ty { -1520 MaybeFrame::None => FrameType::Padding, -1521 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId), -1522 MaybeFrame::Known(frame_type) => frame_type, -1523 }; -1524 Ok(match ty { -1525 FrameType::Padding => Frame::Padding, -1526 FrameType::ResetStream => Frame::ResetStream(ResetStream { -1527 id: self.bytes.get()?, -1528 error_code: self.bytes.get()?, -1529 final_offset: self.bytes.get()?, -1530 }), -1531 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose { -1532 error_code: self.bytes.get()?, -1533 frame_type: self.bytes.get()?, -1534 reason: self.take_len()?, -1535 })), -1536 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose { -1537 error_code: self.bytes.get()?, -1538 reason: self.take_len()?, -1539 })), -1540 FrameType::MaxData => Frame::MaxData(self.bytes.get()?), -1541 FrameType::MaxStreamData => Frame::MaxStreamData(self.bytes.get()?), -1542 FrameType::MaxStreamsBidi => Frame::MaxStreams(MaxStreams { -1543 dir: Dir::Bi, -1544 count: self.bytes.get_var()?, -1545 }), -1546 FrameType::MaxStreamsUni => Frame::MaxStreams(MaxStreams { -1547 dir: Dir::Uni, -1548 count: self.bytes.get_var()?, -1549 }), -1550 FrameType::Ping => Frame::Ping, -1551 FrameType::DataBlocked => Frame::DataBlocked(DataBlocked(self.bytes.get_var()?)), -1552 FrameType::StreamDataBlocked => Frame::StreamDataBlocked(StreamDataBlocked { -1553 id: self.bytes.get()?, -1554 offset: self.bytes.get_var()?, +1507 Ok(Self { +1508 bytes: payload, +1509 last_ty: MaybeFrame::None, +1510 }) +1511 } +1512 +1513 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> { +1514 let len = self.bytes.get_var()?; +1515 if len > self.bytes.remaining() as u64 { +1516 return Err(UnexpectedEnd); +1517 } +1518 Ok(self.bytes.split_to(len as usize)) +1519 } +1520 +1521 #[track_caller] +1522 fn try_next(&mut self) -> Result<Frame, IterErr> { +1523 self.last_ty = self.bytes.get()?; +1524 +1525 let ty = match self.last_ty { +1526 MaybeFrame::None => FrameType::Padding, +1527 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId), +1528 MaybeFrame::Known(frame_type) => frame_type, +1529 }; +1530 Ok(match ty { +1531 FrameType::Padding => Frame::Padding, +1532 FrameType::ResetStream => Frame::ResetStream(ResetStream { +1533 id: self.bytes.get()?, +1534 error_code: self.bytes.get()?, +1535 final_offset: self.bytes.get()?, +1536 }), +1537 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose { +1538 error_code: self.bytes.get()?, +1539 frame_type: self.bytes.get()?, +1540 reason: self.take_len()?, +1541 })), +1542 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose { +1543 error_code: self.bytes.get()?, +1544 reason: self.take_len()?, +1545 })), +1546 FrameType::MaxData => Frame::MaxData(self.bytes.get()?), +1547 FrameType::MaxStreamData => Frame::MaxStreamData(self.bytes.get()?), +1548 FrameType::MaxStreamsBidi => Frame::MaxStreams(MaxStreams { +1549 dir: Dir::Bi, +1550 count: self.bytes.get_var()?, +1551 }), +1552 FrameType::MaxStreamsUni => Frame::MaxStreams(MaxStreams { +1553 dir: Dir::Uni, +1554 count: self.bytes.get_var()?, 1555 }), -1556 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked(StreamsBlocked { -1557 dir: Dir::Bi, -1558 limit: self.bytes.get_var()?, -1559 }), -1560 FrameType::StreamsBlockedUni => Frame::StreamsBlocked(StreamsBlocked { -1561 dir: Dir::Uni, -1562 limit: self.bytes.get_var()?, -1563 }), -1564 FrameType::StopSending => Frame::StopSending(StopSending { -1565 id: self.bytes.get()?, -1566 error_code: self.bytes.get()?, -1567 }), -1568 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => { -1569 Frame::RetireConnectionId(RetireConnectionId::decode( -1570 &mut self.bytes, -1571 ty == FrameType::PathRetireConnectionId, -1572 )?) -1573 } -1574 FrameType::Ack => { -1575 let largest = self.bytes.get_var()?; -1576 let delay = self.bytes.get_var()?; -1577 let ranges = read_ack_blocks(&mut self.bytes, largest)?; -1578 Frame::Ack(Ack { -1579 delay, -1580 largest, -1581 ranges, -1582 ecn: None, -1583 }) -1584 } -1585 FrameType::AckEcn => { -1586 let largest = self.bytes.get_var()?; -1587 let delay = self.bytes.get_var()?; -1588 let ranges = read_ack_blocks(&mut self.bytes, largest)?; -1589 let ecn = Some(EcnCounts { -1590 ect0: self.bytes.get_var()?, -1591 ect1: self.bytes.get_var()?, -1592 ce: self.bytes.get_var()?, -1593 }); -1594 -1595 Frame::Ack(Ack { -1596 delay, -1597 largest, -1598 ranges, -1599 ecn, -1600 }) -1601 } -1602 FrameType::PathAck => { -1603 let path_id = self.bytes.get()?; -1604 let largest = self.bytes.get_var()?; -1605 let delay = self.bytes.get_var()?; -1606 let ranges = read_ack_blocks(&mut self.bytes, largest)?; -1607 Frame::PathAck(PathAck { -1608 path_id, -1609 delay, -1610 largest, -1611 ranges, -1612 ecn: None, -1613 }) -1614 } -1615 FrameType::PathAckEcn => { -1616 let path_id = self.bytes.get()?; -1617 let largest = self.bytes.get_var()?; -1618 let delay = self.bytes.get_var()?; -1619 let ranges = read_ack_blocks(&mut self.bytes, largest)?; -1620 let ecn = Some(EcnCounts { -1621 ect0: self.bytes.get_var()?, -1622 ect1: self.bytes.get_var()?, -1623 ce: self.bytes.get_var()?, -1624 }); -1625 Frame::PathAck(PathAck { -1626 path_id, -1627 delay, -1628 largest, -1629 ranges, -1630 ecn, -1631 }) -1632 } -1633 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?), -1634 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?), -1635 FrameType::NewConnectionId | FrameType::PathNewConnectionId => { -1636 let read_path = ty == FrameType::PathNewConnectionId; -1637 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?) +1556 FrameType::Ping => Frame::Ping, +1557 FrameType::DataBlocked => Frame::DataBlocked(DataBlocked(self.bytes.get_var()?)), +1558 FrameType::StreamDataBlocked => Frame::StreamDataBlocked(StreamDataBlocked { +1559 id: self.bytes.get()?, +1560 offset: self.bytes.get_var()?, +1561 }), +1562 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked(StreamsBlocked { +1563 dir: Dir::Bi, +1564 limit: self.bytes.get_var()?, +1565 }), +1566 FrameType::StreamsBlockedUni => Frame::StreamsBlocked(StreamsBlocked { +1567 dir: Dir::Uni, +1568 limit: self.bytes.get_var()?, +1569 }), +1570 FrameType::StopSending => Frame::StopSending(StopSending { +1571 id: self.bytes.get()?, +1572 error_code: self.bytes.get()?, +1573 }), +1574 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => { +1575 Frame::RetireConnectionId(RetireConnectionId::decode( +1576 &mut self.bytes, +1577 ty == FrameType::PathRetireConnectionId, +1578 )?) +1579 } +1580 FrameType::Ack => { +1581 let largest = self.bytes.get_var()?; +1582 let delay = self.bytes.get_var()?; +1583 let ranges = read_ack_blocks(&mut self.bytes, largest)?; +1584 Frame::Ack(Ack { +1585 delay, +1586 largest, +1587 ranges, +1588 ecn: None, +1589 }) +1590 } +1591 FrameType::AckEcn => { +1592 let largest = self.bytes.get_var()?; +1593 let delay = self.bytes.get_var()?; +1594 let ranges = read_ack_blocks(&mut self.bytes, largest)?; +1595 let ecn = Some(EcnCounts { +1596 ect0: self.bytes.get_var()?, +1597 ect1: self.bytes.get_var()?, +1598 ce: self.bytes.get_var()?, +1599 }); +1600 +1601 Frame::Ack(Ack { +1602 delay, +1603 largest, +1604 ranges, +1605 ecn, +1606 }) +1607 } +1608 FrameType::PathAck => { +1609 let path_id = self.bytes.get()?; +1610 let largest = self.bytes.get_var()?; +1611 let delay = self.bytes.get_var()?; +1612 let ranges = read_ack_blocks(&mut self.bytes, largest)?; +1613 Frame::PathAck(PathAck { +1614 path_id, +1615 delay, +1616 largest, +1617 ranges, +1618 ecn: None, +1619 }) +1620 } +1621 FrameType::PathAckEcn => { +1622 let path_id = self.bytes.get()?; +1623 let largest = self.bytes.get_var()?; +1624 let delay = self.bytes.get_var()?; +1625 let ranges = read_ack_blocks(&mut self.bytes, largest)?; +1626 let ecn = Some(EcnCounts { +1627 ect0: self.bytes.get_var()?, +1628 ect1: self.bytes.get_var()?, +1629 ce: self.bytes.get_var()?, +1630 }); +1631 Frame::PathAck(PathAck { +1632 path_id, +1633 delay, +1634 largest, +1635 ranges, +1636 ecn, +1637 }) 1638 } -1639 FrameType::Crypto => Frame::Crypto(Crypto { -1640 offset: self.bytes.get_var()?, -1641 data: self.take_len()?, -1642 }), -1643 FrameType::NewToken => Frame::NewToken(NewToken { -1644 token: self.take_len()?, -1645 }), -1646 FrameType::HandshakeDone => Frame::HandshakeDone, -1647 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency { -1648 sequence: self.bytes.get()?, -1649 ack_eliciting_threshold: self.bytes.get()?, -1650 request_max_ack_delay: self.bytes.get()?, -1651 reordering_threshold: self.bytes.get()?, -1652 }), -1653 FrameType::ImmediateAck => Frame::ImmediateAck, -1654 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => { -1655 let is_ipv6 = ty == FrameType::ObservedIpv6Addr; -1656 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?; -1657 Frame::ObservedAddr(observed) -1658 } -1659 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?), -1660 FrameType::PathStatusAvailable => { -1661 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?) -1662 } -1663 FrameType::PathStatusBackup => { -1664 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?) -1665 } -1666 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?), -1667 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?), -1668 FrameType::PathCidsBlocked => { -1669 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?) -1670 } -1671 FrameType::AddIpv4Address | FrameType::AddIpv6Address => { -1672 let is_ipv6 = ty == FrameType::AddIpv6Address; -1673 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?; -1674 Frame::AddAddress(add_address) -1675 } -1676 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => { -1677 let is_ipv6 = ty == FrameType::ReachOutAtIpv6; -1678 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?; -1679 Frame::ReachOut(reach_out) -1680 } -1681 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?), -1682 FrameType::Stream(s) => Frame::Stream(Stream { -1683 id: self.bytes.get()?, -1684 offset: if s.off() { self.bytes.get_var()? } else { 0 }, -1685 fin: s.fin(), -1686 data: if s.len() { -1687 self.take_len()? -1688 } else { -1689 self.take_remaining() -1690 }, -1691 }), -1692 FrameType::Datagram(d) => Frame::Datagram(Datagram { -1693 data: if d.len() { -1694 self.take_len()? -1695 } else { -1696 self.take_remaining() -1697 }, -1698 }), -1699 }) -1700 } -1701 -1702 fn take_remaining(&mut self) -> Bytes { -1703 mem::take(&mut self.bytes) -1704 } -1705} -1706 -1707impl Iterator for Iter { -1708 type Item = Result<Frame, InvalidFrame>; -1709 fn next(&mut self) -> Option<Self::Item> { -1710 if !self.bytes.has_remaining() { -1711 return None; -1712 } -1713 match self.try_next() { -1714 Ok(x) => Some(Ok(x)), -1715 Err(e) => { -1716 // Corrupt frame, skip it and everything that follows -1717 self.bytes.clear(); -1718 Some(Err(InvalidFrame { -1719 ty: self.last_ty, -1720 reason: e.reason(), -1721 })) -1722 } -1723 } -1724 } -1725} -1726 -1727#[derive(Debug)] -1728pub(crate) struct InvalidFrame { -1729 pub(crate) ty: MaybeFrame, -1730 pub(crate) reason: &'static str, +1639 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?), +1640 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?), +1641 FrameType::NewConnectionId | FrameType::PathNewConnectionId => { +1642 let read_path = ty == FrameType::PathNewConnectionId; +1643 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?) +1644 } +1645 FrameType::Crypto => Frame::Crypto(Crypto { +1646 offset: self.bytes.get_var()?, +1647 data: self.take_len()?, +1648 }), +1649 FrameType::NewToken => Frame::NewToken(NewToken { +1650 token: self.take_len()?, +1651 }), +1652 FrameType::HandshakeDone => Frame::HandshakeDone, +1653 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency { +1654 sequence: self.bytes.get()?, +1655 ack_eliciting_threshold: self.bytes.get()?, +1656 request_max_ack_delay: self.bytes.get()?, +1657 reordering_threshold: self.bytes.get()?, +1658 }), +1659 FrameType::ImmediateAck => Frame::ImmediateAck, +1660 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => { +1661 let is_ipv6 = ty == FrameType::ObservedIpv6Addr; +1662 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?; +1663 Frame::ObservedAddr(observed) +1664 } +1665 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?), +1666 FrameType::PathStatusAvailable => { +1667 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?) +1668 } +1669 FrameType::PathStatusBackup => { +1670 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?) +1671 } +1672 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?), +1673 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?), +1674 FrameType::PathCidsBlocked => { +1675 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?) +1676 } +1677 FrameType::AddIpv4Address | FrameType::AddIpv6Address => { +1678 let is_ipv6 = ty == FrameType::AddIpv6Address; +1679 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?; +1680 Frame::AddAddress(add_address) +1681 } +1682 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => { +1683 let is_ipv6 = ty == FrameType::ReachOutAtIpv6; +1684 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?; +1685 Frame::ReachOut(reach_out) +1686 } +1687 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?), +1688 FrameType::Stream(s) => Frame::Stream(Stream { +1689 id: self.bytes.get()?, +1690 offset: if s.off() { self.bytes.get_var()? } else { 0 }, +1691 fin: s.fin(), +1692 data: if s.len() { +1693 self.take_len()? +1694 } else { +1695 self.take_remaining() +1696 }, +1697 }), +1698 FrameType::Datagram(d) => Frame::Datagram(Datagram { +1699 data: if d.len() { +1700 self.take_len()? +1701 } else { +1702 self.take_remaining() +1703 }, +1704 }), +1705 }) +1706 } +1707 +1708 fn take_remaining(&mut self) -> Bytes { +1709 mem::take(&mut self.bytes) +1710 } +1711} +1712 +1713impl Iterator for Iter { +1714 type Item = Result<Frame, InvalidFrame>; +1715 fn next(&mut self) -> Option<Self::Item> { +1716 if !self.bytes.has_remaining() { +1717 return None; +1718 } +1719 match self.try_next() { +1720 Ok(x) => Some(Ok(x)), +1721 Err(e) => { +1722 // Corrupt frame, skip it and everything that follows +1723 self.bytes.clear(); +1724 Some(Err(InvalidFrame { +1725 ty: self.last_ty, +1726 reason: e.reason(), +1727 })) +1728 } +1729 } +1730 } 1731} 1732 -1733impl From<InvalidFrame> for TransportError { -1734 fn from(err: InvalidFrame) -> Self { -1735 let mut te = Self::FRAME_ENCODING_ERROR(err.reason); -1736 te.frame = err.ty; -1737 te -1738 } -1739} -1740 -1741/// Decodes the ACK Ranges from the given buffer. -1742/// This means, reading these three values -1743/// -1744/// - ACK Range Count -1745/// - First ACK Range -1746/// - ACK Ranges -1747/// -1748/// Ref <https://www.rfc-editor.org/rfc/rfc9000.html#name-ack-ranges> -1749fn read_ack_blocks(buf: &mut Bytes, mut largest: u64) -> Result<ArrayRangeSet, IterErr> { -1750 // Ack Range Count -1751 let num_blocks = buf.get_var()?; -1752 -1753 let mut out = ArrayRangeSet::new(); -1754 let mut block_to_block; -1755 let mut range; -1756 -1757 for num_block in 0..num_blocks + 1 { -1758 range = buf.get_var()?; -1759 range += 1; -1760 -1761 let start = (largest + 1).checked_sub(range).ok_or(IterErr::Malformed)?; +1733#[derive(Debug)] +1734pub(crate) struct InvalidFrame { +1735 pub(crate) ty: MaybeFrame, +1736 pub(crate) reason: &'static str, +1737} +1738 +1739impl From<InvalidFrame> for TransportError { +1740 fn from(err: InvalidFrame) -> Self { +1741 let mut te = Self::FRAME_ENCODING_ERROR(err.reason); +1742 te.frame = err.ty; +1743 te +1744 } +1745} +1746 +1747/// Decodes the ACK Ranges from the given buffer. +1748/// This means, reading these three values +1749/// +1750/// - ACK Range Count +1751/// - First ACK Range +1752/// - ACK Ranges +1753/// +1754/// Ref <https://www.rfc-editor.org/rfc/rfc9000.html#name-ack-ranges> +1755fn read_ack_blocks(buf: &mut Bytes, mut largest: u64) -> Result<ArrayRangeSet, IterErr> { +1756 // Ack Range Count +1757 let num_blocks = buf.get_var()?; +1758 +1759 let mut out = ArrayRangeSet::new(); +1760 let mut block_to_block; +1761 let mut range; 1762 -1763 if range > 0 { -1764 out.insert(start..largest + 1); -1765 } +1763 for num_block in 0..num_blocks + 1 { +1764 range = buf.get_var()?; +1765 range += 1; 1766 -1767 // no gap on the last "block" -1768 if num_block < num_blocks { -1769 // skip the gap -1770 block_to_block = buf.get_var()?; -1771 block_to_block += 1; -1772 block_to_block += range; -1773 -1774 largest = largest -1775 .checked_sub(block_to_block) -1776 .ok_or(IterErr::Malformed)?; -1777 } -1778 } +1767 let start = (largest + 1).checked_sub(range).ok_or(IterErr::Malformed)?; +1768 +1769 if range > 0 { +1770 out.insert(start..largest + 1); +1771 } +1772 +1773 // no gap on the last "block" +1774 if num_block < num_blocks { +1775 // skip the gap +1776 block_to_block = buf.get_var()?; +1777 block_to_block += 1; +1778 block_to_block += range; 1779 -1780 Ok(out) -1781} -1782 -1783#[derive(Debug)] -1784enum IterErr { -1785 UnexpectedEnd, -1786 InvalidFrameId, -1787 Malformed, -1788} -1789 -1790impl IterErr { -1791 fn reason(&self) -> &'static str { -1792 use IterErr::*; -1793 match *self { -1794 UnexpectedEnd => "unexpected end", -1795 InvalidFrameId => "invalid frame ID", -1796 Malformed => "malformed", -1797 } -1798 } -1799} -1800 -1801impl From<UnexpectedEnd> for IterErr { -1802 fn from(_: UnexpectedEnd) -> Self { -1803 Self::UnexpectedEnd +1780 largest = largest +1781 .checked_sub(block_to_block) +1782 .ok_or(IterErr::Malformed)?; +1783 } +1784 } +1785 +1786 Ok(out) +1787} +1788 +1789#[derive(Debug)] +1790enum IterErr { +1791 UnexpectedEnd, +1792 InvalidFrameId, +1793 Malformed, +1794} +1795 +1796impl IterErr { +1797 fn reason(&self) -> &'static str { +1798 use IterErr::*; +1799 match *self { +1800 UnexpectedEnd => "unexpected end", +1801 InvalidFrameId => "invalid frame ID", +1802 Malformed => "malformed", +1803 } 1804 } 1805} 1806 -1807#[allow(unreachable_pub)] // fuzzing only -1808#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -1809#[cfg_attr(test, derive(Arbitrary))] -1810#[derive(Debug, Copy, Clone, derive_more::Display)] -1811#[display("RESET_STREAM id: {id}")] -1812pub struct ResetStream { -1813 pub(crate) id: StreamId, -1814 pub(crate) error_code: VarInt, -1815 pub(crate) final_offset: VarInt, -1816} -1817 -1818impl ResetStream { -1819 const fn get_type(&self) -> FrameType { -1820 FrameType::ResetStream -1821 } +1807impl From<UnexpectedEnd> for IterErr { +1808 fn from(_: UnexpectedEnd) -> Self { +1809 Self::UnexpectedEnd +1810 } +1811} +1812 +1813#[allow(unreachable_pub)] // fuzzing only +1814#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +1815#[cfg_attr(test, derive(Arbitrary))] +1816#[derive(Debug, Copy, Clone, derive_more::Display)] +1817#[display("RESET_STREAM id: {id}")] +1818pub struct ResetStream { +1819 pub(crate) id: StreamId, +1820 pub(crate) error_code: VarInt, +1821 pub(crate) final_offset: VarInt, 1822} 1823 -1824impl FrameStruct for ResetStream { -1825 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -1826} -1827 -1828impl Encodable for ResetStream { -1829 fn encode<W: BufMut>(&self, out: &mut W) { -1830 out.write(FrameType::ResetStream); // 1 byte -1831 out.write(self.id); // <= 8 bytes -1832 out.write(self.error_code); // <= 8 bytes -1833 out.write(self.final_offset); // <= 8 bytes -1834 } -1835} -1836 -1837#[cfg_attr(test, derive(Arbitrary))] -1838#[derive(Debug, Copy, Clone, derive_more::Display)] -1839#[display("STOP_SENDING id: {id}")] -1840pub(crate) struct StopSending { -1841 pub(crate) id: StreamId, -1842 pub(crate) error_code: VarInt, -1843} -1844 -1845impl FrameStruct for StopSending { -1846 const SIZE_BOUND: usize = 1 + 8 + 8; -1847} -1848 -1849impl StopSending { -1850 const fn get_type(&self) -> FrameType { -1851 FrameType::StopSending -1852 } +1824impl ResetStream { +1825 const fn get_type(&self) -> FrameType { +1826 FrameType::ResetStream +1827 } +1828} +1829 +1830impl FrameStruct for ResetStream { +1831 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +1832} +1833 +1834impl Encodable for ResetStream { +1835 fn encode<W: BufMut>(&self, out: &mut W) { +1836 out.write(FrameType::ResetStream); // 1 byte +1837 out.write(self.id); // <= 8 bytes +1838 out.write(self.error_code); // <= 8 bytes +1839 out.write(self.final_offset); // <= 8 bytes +1840 } +1841} +1842 +1843#[cfg_attr(test, derive(Arbitrary))] +1844#[derive(Debug, Copy, Clone, derive_more::Display)] +1845#[display("STOP_SENDING id: {id}")] +1846pub(crate) struct StopSending { +1847 pub(crate) id: StreamId, +1848 pub(crate) error_code: VarInt, +1849} +1850 +1851impl FrameStruct for StopSending { +1852 const SIZE_BOUND: usize = 1 + 8 + 8; 1853} 1854 -1855impl Encodable for StopSending { -1856 fn encode<W: BufMut>(&self, out: &mut W) { -1857 out.write(FrameType::StopSending); // 1 byte -1858 out.write(self.id); // <= 8 bytes -1859 out.write(self.error_code) // <= 8 bytes -1860 } -1861} -1862 -1863#[derive(Debug, Copy, Clone, PartialEq, Eq, derive_more::Display)] -1864#[display("{} {} seq: {sequence} id: {id}", self.get_type(), DisplayOption::new("path_id", path_id.as_ref()))] -1865pub(crate) struct NewConnectionId { -1866 pub(crate) path_id: Option<PathId>, -1867 pub(crate) sequence: u64, -1868 pub(crate) retire_prior_to: u64, -1869 pub(crate) id: ConnectionId, -1870 pub(crate) reset_token: ResetToken, -1871} -1872 -1873#[cfg(test)] -1874fn connection_id_and_reset_token() -> impl Strategy<Value = (crate::ConnectionId, ResetToken)> { -1875 (any::<ConnectionId>(), any::<[u8; 64]>()).prop_map(|(id, reset_key)| { -1876 #[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))] -1877 use aws_lc_rs::hmac; -1878 #[cfg(feature = "ring")] -1879 use ring::hmac; -1880 let key = hmac::Key::new(hmac::HMAC_SHA256, &reset_key); -1881 (id, ResetToken::new(&key, id)) -1882 }) -1883} -1884 -1885#[cfg(test)] -1886impl proptest::arbitrary::Arbitrary for NewConnectionId { -1887 type Parameters = (); -1888 type Strategy = proptest::strategy::BoxedStrategy<Self>; -1889 -1890 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { -1891 use proptest::prelude::*; -1892 ( -1893 any::<Option<PathId>>(), -1894 varint_u64(), -1895 varint_u64(), -1896 connection_id_and_reset_token(), -1897 ) -1898 .prop_map(|(path_id, a, b, (id, reset_token))| { -1899 let sequence = std::cmp::max(a, b); -1900 let retire_prior_to = std::cmp::min(a, b); -1901 Self { -1902 path_id, -1903 sequence, -1904 retire_prior_to, -1905 id, -1906 reset_token, -1907 } -1908 }) -1909 .boxed() -1910 } -1911} -1912 -1913impl NewConnectionId { -1914 /// Maximum size of this frame when the frame type is [`FrameType::NewConnectionId`], -1915 pub(crate) const SIZE_BOUND: usize = { -1916 let type_len = FrameType::NewConnectionId.size(); -1917 let seq_max_len = 8usize; -1918 let retire_prior_to_max_len = 8usize; -1919 let cid_len_len = 1; -1920 let cid_len = 160; -1921 let reset_token_len = 16; -1922 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len -1923 }; -1924 -1925 /// Maximum size of this frame when the frame type is [`FrameType::PathNewConnectionId`], -1926 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { -1927 let type_len = FrameType::PathNewConnectionId.size(); -1928 let path_id_len = VarInt::from_u32(u32::MAX).size(); -1929 let seq_max_len = 8usize; -1930 let retire_prior_to_max_len = 8usize; -1931 let cid_len_len = 1; -1932 let cid_len = 160; -1933 let reset_token_len = 16; -1934 type_len -1935 + path_id_len -1936 + seq_max_len -1937 + retire_prior_to_max_len -1938 + cid_len_len -1939 + cid_len -1940 + reset_token_len -1941 }; -1942 -1943 const fn get_type(&self) -> FrameType { -1944 if self.path_id.is_some() { -1945 FrameType::PathNewConnectionId -1946 } else { -1947 FrameType::NewConnectionId -1948 } -1949 } -1950 -1951 /// Returns the maximum encoded size on the wire. -1952 /// -1953 /// This is a rough upper estimate, does not squeeze every last byte out. -1954 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize { -1955 let upper_bound = match path_new_cid { -1956 true => Self::SIZE_BOUND_MULTIPATH, -1957 false => Self::SIZE_BOUND, -1958 }; -1959 // instead of using the maximum cid len, use the provided one -1960 upper_bound - 160 + cid_len -1961 } -1962 -1963 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> { -1964 let path_id = if read_path { Some(bytes.get()?) } else { None }; -1965 let sequence = bytes.get_var()?; -1966 let retire_prior_to = bytes.get_var()?; -1967 if retire_prior_to > sequence { -1968 return Err(IterErr::Malformed); -1969 } -1970 let length = bytes.get::<u8>()? as usize; -1971 if length > MAX_CID_SIZE || length == 0 { -1972 return Err(IterErr::Malformed); -1973 } -1974 if length > bytes.remaining() { -1975 return Err(IterErr::UnexpectedEnd); -1976 } -1977 let mut stage = [0; MAX_CID_SIZE]; -1978 bytes.copy_to_slice(&mut stage[0..length]); -1979 let id = ConnectionId::new(&stage[..length]); -1980 if bytes.remaining() < 16 { +1855impl StopSending { +1856 const fn get_type(&self) -> FrameType { +1857 FrameType::StopSending +1858 } +1859} +1860 +1861impl Encodable for StopSending { +1862 fn encode<W: BufMut>(&self, out: &mut W) { +1863 out.write(FrameType::StopSending); // 1 byte +1864 out.write(self.id); // <= 8 bytes +1865 out.write(self.error_code) // <= 8 bytes +1866 } +1867} +1868 +1869#[derive(Debug, Copy, Clone, PartialEq, Eq, derive_more::Display)] +1870#[display("{} {} seq: {sequence} id: {id}", self.get_type(), DisplayOption::new("path_id", path_id.as_ref()))] +1871pub(crate) struct NewConnectionId { +1872 pub(crate) path_id: Option<PathId>, +1873 pub(crate) sequence: u64, +1874 pub(crate) retire_prior_to: u64, +1875 pub(crate) id: ConnectionId, +1876 pub(crate) reset_token: ResetToken, +1877} +1878 +1879#[cfg(test)] +1880fn connection_id_and_reset_token() -> impl Strategy<Value = (crate::ConnectionId, ResetToken)> { +1881 (any::<ConnectionId>(), any::<[u8; 64]>()).prop_map(|(id, reset_key)| { +1882 #[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))] +1883 use aws_lc_rs::hmac; +1884 #[cfg(feature = "ring")] +1885 use ring::hmac; +1886 let key = hmac::Key::new(hmac::HMAC_SHA256, &reset_key); +1887 (id, ResetToken::new(&key, id)) +1888 }) +1889} +1890 +1891#[cfg(test)] +1892impl proptest::arbitrary::Arbitrary for NewConnectionId { +1893 type Parameters = (); +1894 type Strategy = proptest::strategy::BoxedStrategy<Self>; +1895 +1896 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { +1897 use proptest::prelude::*; +1898 ( +1899 any::<Option<PathId>>(), +1900 varint_u64(), +1901 varint_u64(), +1902 connection_id_and_reset_token(), +1903 ) +1904 .prop_map(|(path_id, a, b, (id, reset_token))| { +1905 let sequence = std::cmp::max(a, b); +1906 let retire_prior_to = std::cmp::min(a, b); +1907 Self { +1908 path_id, +1909 sequence, +1910 retire_prior_to, +1911 id, +1912 reset_token, +1913 } +1914 }) +1915 .boxed() +1916 } +1917} +1918 +1919impl NewConnectionId { +1920 /// Maximum size of this frame when the frame type is [`FrameType::NewConnectionId`], +1921 pub(crate) const SIZE_BOUND: usize = { +1922 let type_len = FrameType::NewConnectionId.size(); +1923 let seq_max_len = 8usize; +1924 let retire_prior_to_max_len = 8usize; +1925 let cid_len_len = 1; +1926 let cid_len = 160; +1927 let reset_token_len = 16; +1928 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len +1929 }; +1930 +1931 /// Maximum size of this frame when the frame type is [`FrameType::PathNewConnectionId`], +1932 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { +1933 let type_len = FrameType::PathNewConnectionId.size(); +1934 let path_id_len = VarInt::from_u32(u32::MAX).size(); +1935 let seq_max_len = 8usize; +1936 let retire_prior_to_max_len = 8usize; +1937 let cid_len_len = 1; +1938 let cid_len = 160; +1939 let reset_token_len = 16; +1940 type_len +1941 + path_id_len +1942 + seq_max_len +1943 + retire_prior_to_max_len +1944 + cid_len_len +1945 + cid_len +1946 + reset_token_len +1947 }; +1948 +1949 const fn get_type(&self) -> FrameType { +1950 if self.path_id.is_some() { +1951 FrameType::PathNewConnectionId +1952 } else { +1953 FrameType::NewConnectionId +1954 } +1955 } +1956 +1957 /// Returns the maximum encoded size on the wire. +1958 /// +1959 /// This is a rough upper estimate, does not squeeze every last byte out. +1960 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize { +1961 let upper_bound = match path_new_cid { +1962 true => Self::SIZE_BOUND_MULTIPATH, +1963 false => Self::SIZE_BOUND, +1964 }; +1965 // instead of using the maximum cid len, use the provided one +1966 upper_bound - 160 + cid_len +1967 } +1968 +1969 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> { +1970 let path_id = if read_path { Some(bytes.get()?) } else { None }; +1971 let sequence = bytes.get_var()?; +1972 let retire_prior_to = bytes.get_var()?; +1973 if retire_prior_to > sequence { +1974 return Err(IterErr::Malformed); +1975 } +1976 let length = bytes.get::<u8>()? as usize; +1977 if length > MAX_CID_SIZE || length == 0 { +1978 return Err(IterErr::Malformed); +1979 } +1980 if length > bytes.remaining() { 1981 return Err(IterErr::UnexpectedEnd); 1982 } -1983 let mut reset_token = [0; RESET_TOKEN_SIZE]; -1984 bytes.copy_to_slice(&mut reset_token); -1985 Ok(Self { -1986 path_id, -1987 sequence, -1988 retire_prior_to, -1989 id, -1990 reset_token: reset_token.into(), -1991 }) -1992 } -1993 -1994 pub(crate) fn issued(&self) -> crate::shared::IssuedCid { -1995 crate::shared::IssuedCid { -1996 path_id: self.path_id.unwrap_or_default(), -1997 sequence: self.sequence, -1998 id: self.id, -1999 reset_token: self.reset_token, -2000 } -2001 } -2002} -2003 -2004impl Encodable for NewConnectionId { -2005 fn encode<W: BufMut>(&self, out: &mut W) { -2006 out.write(self.get_type()); -2007 if let Some(id) = self.path_id { -2008 out.write(id); -2009 } -2010 out.write_var(self.sequence); -2011 out.write_var(self.retire_prior_to); -2012 out.write(self.id.len() as u8); -2013 out.put_slice(&self.id); -2014 out.put_slice(&self.reset_token); -2015 } -2016} -2017 -2018impl FrameStruct for NewConnectionId { -2019 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE; -2020} -2021 -2022/// An unreliable datagram -2023#[derive(Debug, Clone, derive_more::Display)] -2024#[cfg_attr(test, derive(Arbitrary))] -2025#[display("DATAGRAM len: {}", data.len())] -2026pub struct Datagram { -2027 /// Payload -2028 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..100), Bytes::from)))] -2029 pub data: Bytes, -2030} -2031 -2032impl FrameStruct for Datagram { -2033 const SIZE_BOUND: usize = 1 + 8; -2034} -2035 -2036impl Datagram { -2037 pub(crate) fn size(&self, length: bool) -> usize { -2038 1 + if length { -2039 VarInt::from_u64(self.data.len() as u64).unwrap().size() -2040 } else { -2041 0 -2042 } + self.data.len() -2043 } -2044 -2045 const fn get_type(&self) -> FrameType { -2046 FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)) -2047 } -2048} -2049 -2050impl Encodable for Datagram { -2051 fn encode<B: BufMut>(&self, out: &mut B) { -2052 // A datagram is encoded only after this is verified. -2053 const ENCODE_LEN: bool = true; -2054 out.write(FrameType::Datagram(DatagramInfo( -2055 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN), -2056 ))); // 1 byte -2057 // Safe to unwrap because we check length sanity before queueing datagrams -2058 out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); // <= 8 bytes -2059 out.put_slice(&self.data); -2060 } -2061} -2062 -2063#[derive(Debug, Copy, Clone, PartialEq, Eq, derive_more::Display)] -2064#[cfg_attr(test, derive(Arbitrary))] -2065#[display("ACK_FREQUENCY max_ack_delay: {}µs", request_max_ack_delay.0)] -2066pub(crate) struct AckFrequency { -2067 pub(crate) sequence: VarInt, -2068 pub(crate) ack_eliciting_threshold: VarInt, -2069 pub(crate) request_max_ack_delay: VarInt, -2070 pub(crate) reordering_threshold: VarInt, -2071} -2072 -2073impl AckFrequency { -2074 const fn get_type(&self) -> FrameType { -2075 FrameType::AckFrequency -2076 } +1983 let mut stage = [0; MAX_CID_SIZE]; +1984 bytes.copy_to_slice(&mut stage[0..length]); +1985 let id = ConnectionId::new(&stage[..length]); +1986 if bytes.remaining() < 16 { +1987 return Err(IterErr::UnexpectedEnd); +1988 } +1989 let mut reset_token = [0; RESET_TOKEN_SIZE]; +1990 bytes.copy_to_slice(&mut reset_token); +1991 Ok(Self { +1992 path_id, +1993 sequence, +1994 retire_prior_to, +1995 id, +1996 reset_token: reset_token.into(), +1997 }) +1998 } +1999 +2000 pub(crate) fn issued(&self) -> crate::shared::IssuedCid { +2001 crate::shared::IssuedCid { +2002 path_id: self.path_id.unwrap_or_default(), +2003 sequence: self.sequence, +2004 id: self.id, +2005 reset_token: self.reset_token, +2006 } +2007 } +2008} +2009 +2010impl Encodable for NewConnectionId { +2011 fn encode<W: BufMut>(&self, out: &mut W) { +2012 out.write(self.get_type()); +2013 if let Some(id) = self.path_id { +2014 out.write(id); +2015 } +2016 out.write_var(self.sequence); +2017 out.write_var(self.retire_prior_to); +2018 out.write(self.id.len() as u8); +2019 out.put_slice(&self.id); +2020 out.put_slice(&self.reset_token); +2021 } +2022} +2023 +2024impl FrameStruct for NewConnectionId { +2025 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE; +2026} +2027 +2028/// An unreliable datagram +2029#[derive(Debug, Clone, derive_more::Display)] +2030#[cfg_attr(test, derive(Arbitrary))] +2031#[display("DATAGRAM len: {}", data.len())] +2032pub struct Datagram { +2033 /// Payload +2034 #[cfg_attr(test, strategy(Strategy::prop_map(collection::vec(any::<u8>(), 0..100), Bytes::from)))] +2035 pub data: Bytes, +2036} +2037 +2038impl FrameStruct for Datagram { +2039 const SIZE_BOUND: usize = 1 + 8; +2040} +2041 +2042impl Datagram { +2043 pub(crate) fn size(&self, length: bool) -> usize { +2044 1 + if length { +2045 VarInt::from_u64(self.data.len() as u64).unwrap().size() +2046 } else { +2047 0 +2048 } + self.data.len() +2049 } +2050 +2051 const fn get_type(&self) -> FrameType { +2052 FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)) +2053 } +2054} +2055 +2056impl Encodable for Datagram { +2057 fn encode<B: BufMut>(&self, out: &mut B) { +2058 // A datagram is encoded only after this is verified. +2059 const ENCODE_LEN: bool = true; +2060 out.write(FrameType::Datagram(DatagramInfo( +2061 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN), +2062 ))); // 1 byte +2063 // Safe to unwrap because we check length sanity before queueing datagrams +2064 out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); // <= 8 bytes +2065 out.put_slice(&self.data); +2066 } +2067} +2068 +2069#[derive(Debug, Copy, Clone, PartialEq, Eq, derive_more::Display)] +2070#[cfg_attr(test, derive(Arbitrary))] +2071#[display("ACK_FREQUENCY max_ack_delay: {}µs", request_max_ack_delay.0)] +2072pub(crate) struct AckFrequency { +2073 pub(crate) sequence: VarInt, +2074 pub(crate) ack_eliciting_threshold: VarInt, +2075 pub(crate) request_max_ack_delay: VarInt, +2076 pub(crate) reordering_threshold: VarInt, 2077} 2078 -2079impl Encodable for AckFrequency { -2080 fn encode<W: BufMut>(&self, buf: &mut W) { -2081 buf.write(FrameType::AckFrequency); -2082 buf.write(self.sequence); -2083 buf.write(self.ack_eliciting_threshold); -2084 buf.write(self.request_max_ack_delay); -2085 buf.write(self.reordering_threshold); -2086 } -2087} -2088 -2089/* Address Discovery https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/ */ -2090 -2091/// Conjunction of the information contained in the address discovery frames -2092/// ([`FrameType::ObservedIpv4Addr`], [`FrameType::ObservedIpv6Addr`]). -2093#[derive(Debug, PartialEq, Eq, Clone, derive_more::Display)] -2094#[display("{} seq_no: {seq_no} addr: {}", self.get_type(), self.socket_addr())] -2095pub(crate) struct ObservedAddr { -2096 /// Monotonically increasing integer within the same connection. -2097 pub(crate) seq_no: VarInt, -2098 /// Reported observed address. -2099 pub(crate) ip: IpAddr, -2100 /// Reported observed port. -2101 pub(crate) port: u16, -2102} -2103 -2104#[cfg(test)] -2105impl proptest::arbitrary::Arbitrary for ObservedAddr { -2106 type Parameters = (); -2107 type Strategy = proptest::strategy::BoxedStrategy<Self>; -2108 -2109 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { -2110 use proptest::prelude::*; -2111 (any::<VarInt>(), any::<IpAddr>(), any::<u16>()) -2112 .prop_map(|(seq_no, ip, port)| Self { seq_no, ip, port }) -2113 .boxed() -2114 } -2115} -2116 -2117impl ObservedAddr { -2118 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self { -2119 Self { -2120 ip: remote.ip(), -2121 port: remote.port(), -2122 seq_no: seq_no.into(), -2123 } -2124 } -2125 -2126 /// Get the [`FrameType`] for this frame. -2127 const fn get_type(&self) -> FrameType { -2128 if self.ip.is_ipv6() { -2129 FrameType::ObservedIpv6Addr -2130 } else { -2131 FrameType::ObservedIpv4Addr -2132 } -2133 } -2134 -2135 /// Compute the number of bytes needed to encode the frame. -2136 pub(crate) fn size(&self) -> usize { -2137 let type_size = self.get_type().size(); -2138 let req_id_bytes = self.seq_no.size(); -2139 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -2140 let port_bytes = 2; -2141 type_size + req_id_bytes + ip_bytes + port_bytes -2142 } -2143 -2144 /// Reads the frame contents from the buffer. -2145 /// -2146 /// Should only be called when the frame type has been identified as -2147 /// [`FrameType::ObservedIpv4Addr`] or [`FrameType::ObservedIpv6Addr`]. -2148 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -2149 let seq_no = bytes.get()?; -2150 let ip = if is_ipv6 { -2151 IpAddr::V6(bytes.get()?) -2152 } else { -2153 IpAddr::V4(bytes.get()?) -2154 }; -2155 let port = bytes.get()?; -2156 Ok(Self { seq_no, ip, port }) -2157 } -2158 -2159 /// Gives the [`SocketAddr`] reported in the frame. -2160 pub(crate) fn socket_addr(&self) -> SocketAddr { -2161 (self.ip, self.port).into() -2162 } -2163} +2079impl AckFrequency { +2080 const fn get_type(&self) -> FrameType { +2081 FrameType::AckFrequency +2082 } +2083} +2084 +2085impl Encodable for AckFrequency { +2086 fn encode<W: BufMut>(&self, buf: &mut W) { +2087 buf.write(FrameType::AckFrequency); +2088 buf.write(self.sequence); +2089 buf.write(self.ack_eliciting_threshold); +2090 buf.write(self.request_max_ack_delay); +2091 buf.write(self.reordering_threshold); +2092 } +2093} +2094 +2095/* Address Discovery https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/ */ +2096 +2097/// Conjunction of the information contained in the address discovery frames +2098/// ([`FrameType::ObservedIpv4Addr`], [`FrameType::ObservedIpv6Addr`]). +2099#[derive(Debug, PartialEq, Eq, Clone, derive_more::Display)] +2100#[display("{} seq_no: {seq_no} addr: {}", self.get_type(), self.socket_addr())] +2101pub(crate) struct ObservedAddr { +2102 /// Monotonically increasing integer within the same connection. +2103 pub(crate) seq_no: VarInt, +2104 /// Reported observed address. +2105 pub(crate) ip: IpAddr, +2106 /// Reported observed port. +2107 pub(crate) port: u16, +2108} +2109 +2110#[cfg(test)] +2111impl proptest::arbitrary::Arbitrary for ObservedAddr { +2112 type Parameters = (); +2113 type Strategy = proptest::strategy::BoxedStrategy<Self>; +2114 +2115 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { +2116 use proptest::prelude::*; +2117 (any::<VarInt>(), any::<IpAddr>(), any::<u16>()) +2118 .prop_map(|(seq_no, ip, port)| Self { seq_no, ip, port }) +2119 .boxed() +2120 } +2121} +2122 +2123impl ObservedAddr { +2124 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self { +2125 Self { +2126 ip: remote.ip(), +2127 port: remote.port(), +2128 seq_no: seq_no.into(), +2129 } +2130 } +2131 +2132 /// Get the [`FrameType`] for this frame. +2133 const fn get_type(&self) -> FrameType { +2134 if self.ip.is_ipv6() { +2135 FrameType::ObservedIpv6Addr +2136 } else { +2137 FrameType::ObservedIpv4Addr +2138 } +2139 } +2140 +2141 /// Compute the number of bytes needed to encode the frame. +2142 pub(crate) fn size(&self) -> usize { +2143 let type_size = self.get_type().size(); +2144 let req_id_bytes = self.seq_no.size(); +2145 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +2146 let port_bytes = 2; +2147 type_size + req_id_bytes + ip_bytes + port_bytes +2148 } +2149 +2150 /// Reads the frame contents from the buffer. +2151 /// +2152 /// Should only be called when the frame type has been identified as +2153 /// [`FrameType::ObservedIpv4Addr`] or [`FrameType::ObservedIpv6Addr`]. +2154 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +2155 let seq_no = bytes.get()?; +2156 let ip = if is_ipv6 { +2157 IpAddr::V6(bytes.get()?) +2158 } else { +2159 IpAddr::V4(bytes.get()?) +2160 }; +2161 let port = bytes.get()?; +2162 Ok(Self { seq_no, ip, port }) +2163 } 2164 -2165impl Encodable for ObservedAddr { -2166 fn encode<W: BufMut>(&self, buf: &mut W) { -2167 buf.write(self.get_type()); -2168 buf.write(self.seq_no); -2169 match self.ip { -2170 IpAddr::V4(ipv4_addr) => { -2171 buf.write(ipv4_addr); -2172 } -2173 IpAddr::V6(ipv6_addr) => { -2174 buf.write(ipv6_addr); -2175 } -2176 } -2177 buf.write::<u16>(self.port); -2178 } -2179} -2180 -2181/* Multipath <https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/> */ -2182 -2183#[derive(Debug, PartialEq, Eq, derive_more::Display)] -2184#[cfg_attr(test, derive(Arbitrary))] -2185#[display("PATH_ABANDON path_id: {path_id}")] -2186pub(crate) struct PathAbandon { -2187 pub(crate) path_id: PathId, -2188 pub(crate) error_code: TransportErrorCode, -2189} -2190 -2191impl PathAbandon { -2192 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8; -2193 -2194 const fn get_type(&self) -> FrameType { -2195 FrameType::PathAbandon -2196 } -2197} -2198 -2199impl Encodable for PathAbandon { -2200 fn encode<W: BufMut>(&self, buf: &mut W) { -2201 buf.write(FrameType::PathAbandon); -2202 buf.write(self.path_id); -2203 buf.write(self.error_code); -2204 } -2205} -2206 -2207impl Decodable for PathAbandon { -2208 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -2209 Ok(Self { -2210 path_id: bytes.get()?, -2211 error_code: bytes.get()?, -2212 }) -2213 } -2214} -2215 -2216#[derive(Debug, PartialEq, Eq, derive_more::Display)] -2217#[cfg_attr(test, derive(Arbitrary))] -2218#[display("PATH_STATUS_AVAILABLE path_id: {path_id} seq_no: {status_seq_no}")] -2219pub(crate) struct PathStatusAvailable { -2220 pub(crate) path_id: PathId, -2221 pub(crate) status_seq_no: VarInt, -2222} -2223 -2224impl PathStatusAvailable { -2225 const TYPE: FrameType = FrameType::PathStatusAvailable; -2226 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8; -2227 -2228 const fn get_type(&self) -> FrameType { -2229 FrameType::PathStatusAvailable -2230 } -2231} -2232 -2233impl Encodable for PathStatusAvailable { -2234 fn encode<W: BufMut>(&self, buf: &mut W) { -2235 buf.write(Self::TYPE); -2236 buf.write(self.path_id); -2237 buf.write(self.status_seq_no); -2238 } -2239} -2240 -2241impl Decodable for PathStatusAvailable { -2242 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -2243 Ok(Self { -2244 path_id: bytes.get()?, -2245 status_seq_no: bytes.get()?, -2246 }) -2247 } -2248} -2249 -2250#[derive(Debug, PartialEq, Eq, derive_more::Display)] -2251#[cfg_attr(test, derive(Arbitrary))] -2252#[display("PATH_STATUS_BACKUP path_id: {path_id} seq_no: {status_seq_no}")] -2253pub(crate) struct PathStatusBackup { -2254 pub(crate) path_id: PathId, -2255 pub(crate) status_seq_no: VarInt, -2256} -2257 -2258impl PathStatusBackup { -2259 const TYPE: FrameType = FrameType::PathStatusBackup; -2260 -2261 const fn get_type(&self) -> FrameType { -2262 FrameType::PathStatusBackup -2263 } -2264} -2265 -2266impl Encodable for PathStatusBackup { -2267 fn encode<W: BufMut>(&self, buf: &mut W) { -2268 buf.write(Self::TYPE); -2269 buf.write(self.path_id); -2270 buf.write(self.status_seq_no); -2271 } -2272} -2273 -2274impl Decodable for PathStatusBackup { -2275 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -2276 Ok(Self { -2277 path_id: bytes.get()?, -2278 status_seq_no: bytes.get()?, -2279 }) -2280 } -2281} -2282 -2283/* Nat traversal frames */ -2284 -2285/// Conjunction of the information contained in the add address frames -2286/// ([`FrameType::AddIpv4Address`], [`FrameType::AddIpv6Address`]). -2287#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, derive_more::Display)] -2288#[display("{} seq_no: {seq_no} addr: {}", self.get_type(), self.socket_addr())] -2289pub(crate) struct AddAddress { -2290 /// Monotonically increasing integer within the same connection -2291 // TODO(@divma): both assumed, the draft has no mention of this but it's standard -2292 pub(crate) seq_no: VarInt, -2293 /// Address to include in the known set -2294 pub(crate) ip: IpAddr, -2295 /// Port to use with this address -2296 pub(crate) port: u16, -2297} -2298 -2299#[cfg(test)] -2300impl proptest::arbitrary::Arbitrary for AddAddress { -2301 type Parameters = (); -2302 type Strategy = proptest::strategy::BoxedStrategy<Self>; -2303 -2304 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { -2305 use proptest::prelude::*; -2306 (any::<VarInt>(), any::<IpAddr>(), any::<u16>()) -2307 .prop_map(|(seq_no, ip, port)| Self { seq_no, ip, port }) -2308 .boxed() -2309 } -2310} -2311 -2312// TODO(@divma): remove -2313#[allow(dead_code)] -2314impl AddAddress { -2315 /// Smallest number of bytes this type of frame is guaranteed to fit within. -2316 pub(crate) const SIZE_BOUND: usize = Self { -2317 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), -2318 port: u16::MAX, -2319 seq_no: VarInt::MAX, -2320 } -2321 .size(); -2322 -2323 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self { -2324 Self { ip, port, seq_no } -2325 } -2326 -2327 /// Get the [`FrameType`] for this frame. -2328 const fn get_type(&self) -> FrameType { -2329 if self.ip.is_ipv6() { -2330 FrameType::AddIpv6Address -2331 } else { -2332 FrameType::AddIpv4Address -2333 } -2334 } -2335 -2336 /// Compute the number of bytes needed to encode the frame -2337 pub(crate) const fn size(&self) -> usize { -2338 let type_size = self.get_type().size(); -2339 let seq_no_bytes = self.seq_no.size(); -2340 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -2341 let port_bytes = 2; -2342 type_size + seq_no_bytes + ip_bytes + port_bytes -2343 } -2344 -2345 /// Read the frame contents from the buffer -2346 /// -2347 /// Should only be called when the frame type has been identified as -2348 /// [`FrameType::AddIpv4Address`] or [`FrameType::AddIpv6Address`]. -2349 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -2350 let seq_no = bytes.get()?; -2351 let ip = if is_ipv6 { -2352 IpAddr::V6(bytes.get()?) -2353 } else { -2354 IpAddr::V4(bytes.get()?) -2355 }; -2356 let port = bytes.get()?; -2357 Ok(Self { seq_no, ip, port }) -2358 } -2359 -2360 /// Give the [`SocketAddr`] encoded in the frame -2361 pub(crate) fn socket_addr(&self) -> SocketAddr { -2362 self.ip_port().into() -2363 } -2364 -2365 pub(crate) fn ip_port(&self) -> (IpAddr, u16) { -2366 (self.ip, self.port) -2367 } -2368} -2369 -2370impl Encodable for AddAddress { -2371 fn encode<W: BufMut>(&self, buf: &mut W) { -2372 buf.write(self.get_type()); -2373 buf.write(self.seq_no); -2374 match self.ip { -2375 IpAddr::V4(ipv4_addr) => { -2376 buf.write(ipv4_addr); -2377 } -2378 IpAddr::V6(ipv6_addr) => { -2379 buf.write(ipv6_addr); -2380 } -2381 } -2382 buf.write::<u16>(self.port); -2383 } -2384} -2385 -2386/// Conjunction of the information contained in the reach out frames -2387/// ([`FrameType::ReachOutAtIpv4`], [`FrameType::ReachOutAtIpv6`]) -2388#[derive(Debug, PartialEq, Eq, Clone, derive_more::Display)] -2389#[display("REACH_OUT round: {round} local_addr: {}", self.socket_addr())] -2390pub(crate) struct ReachOut { -2391 /// The sequence number of the NAT Traversal attempts -2392 pub(crate) round: VarInt, -2393 /// Address to use -2394 pub(crate) ip: IpAddr, -2395 /// Port to use with this address -2396 pub(crate) port: u16, -2397} -2398 -2399#[cfg(test)] -2400impl proptest::arbitrary::Arbitrary for ReachOut { -2401 type Parameters = (); -2402 type Strategy = proptest::strategy::BoxedStrategy<Self>; -2403 -2404 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { -2405 use proptest::prelude::*; -2406 (any::<VarInt>(), any::<IpAddr>(), any::<u16>()) -2407 .prop_map(|(round, ip, port)| Self { round, ip, port }) -2408 .boxed() -2409 } -2410} -2411 -2412// TODO(@divma): remove -2413#[allow(dead_code)] -2414impl ReachOut { -2415 /// Smallest number of bytes this type of frame is guaranteed to fit within -2416 pub(crate) const SIZE_BOUND: usize = Self { -2417 round: VarInt::MAX, -2418 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), -2419 port: u16::MAX, -2420 } -2421 .size(); -2422 -2423 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self { -2424 Self { round, ip, port } -2425 } -2426 -2427 /// Get the [`FrameType`] for this frame -2428 pub(crate) const fn get_type(&self) -> FrameType { -2429 if self.ip.is_ipv6() { -2430 FrameType::ReachOutAtIpv6 -2431 } else { -2432 FrameType::ReachOutAtIpv4 -2433 } -2434 } -2435 -2436 /// Compute the number of bytes needed to encode the frame -2437 pub(crate) const fn size(&self) -> usize { -2438 let type_size = self.get_type().size(); -2439 let round_bytes = self.round.size(); -2440 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -2441 let port_bytes = 2; -2442 type_size + round_bytes + ip_bytes + port_bytes -2443 } -2444 -2445 /// Read the frame contents from the buffer -2446 /// -2447 /// Should only be called when the frame type has been identified as -2448 /// [`FrameType::ReachOutAtIpv4`] or [`FrameType::ReachOutAtIpv6`]. -2449 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -2450 let round = bytes.get()?; -2451 let ip = if is_ipv6 { -2452 IpAddr::V6(bytes.get()?) -2453 } else { -2454 IpAddr::V4(bytes.get()?) -2455 }; -2456 let port = bytes.get()?; -2457 Ok(Self { round, ip, port }) -2458 } -2459 -2460 /// Give the [`SocketAddr`] encoded in the frame -2461 pub(crate) fn socket_addr(&self) -> SocketAddr { -2462 (self.ip, self.port).into() -2463 } -2464} +2165 /// Gives the [`SocketAddr`] reported in the frame. +2166 pub(crate) fn socket_addr(&self) -> SocketAddr { +2167 (self.ip, self.port).into() +2168 } +2169} +2170 +2171impl Encodable for ObservedAddr { +2172 fn encode<W: BufMut>(&self, buf: &mut W) { +2173 buf.write(self.get_type()); +2174 buf.write(self.seq_no); +2175 match self.ip { +2176 IpAddr::V4(ipv4_addr) => { +2177 buf.write(ipv4_addr); +2178 } +2179 IpAddr::V6(ipv6_addr) => { +2180 buf.write(ipv6_addr); +2181 } +2182 } +2183 buf.write::<u16>(self.port); +2184 } +2185} +2186 +2187/* Multipath <https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/> */ +2188 +2189#[derive(Debug, PartialEq, Eq, derive_more::Display)] +2190#[cfg_attr(test, derive(Arbitrary))] +2191#[display("PATH_ABANDON path_id: {path_id}")] +2192pub(crate) struct PathAbandon { +2193 pub(crate) path_id: PathId, +2194 pub(crate) error_code: TransportErrorCode, +2195} +2196 +2197impl PathAbandon { +2198 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8; +2199 +2200 const fn get_type(&self) -> FrameType { +2201 FrameType::PathAbandon +2202 } +2203} +2204 +2205impl Encodable for PathAbandon { +2206 fn encode<W: BufMut>(&self, buf: &mut W) { +2207 buf.write(FrameType::PathAbandon); +2208 buf.write(self.path_id); +2209 buf.write(self.error_code); +2210 } +2211} +2212 +2213impl Decodable for PathAbandon { +2214 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +2215 Ok(Self { +2216 path_id: bytes.get()?, +2217 error_code: bytes.get()?, +2218 }) +2219 } +2220} +2221 +2222#[derive(Debug, PartialEq, Eq, derive_more::Display)] +2223#[cfg_attr(test, derive(Arbitrary))] +2224#[display("PATH_STATUS_AVAILABLE path_id: {path_id} seq_no: {status_seq_no}")] +2225pub(crate) struct PathStatusAvailable { +2226 pub(crate) path_id: PathId, +2227 pub(crate) status_seq_no: VarInt, +2228} +2229 +2230impl PathStatusAvailable { +2231 const TYPE: FrameType = FrameType::PathStatusAvailable; +2232 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8; +2233 +2234 const fn get_type(&self) -> FrameType { +2235 FrameType::PathStatusAvailable +2236 } +2237} +2238 +2239impl Encodable for PathStatusAvailable { +2240 fn encode<W: BufMut>(&self, buf: &mut W) { +2241 buf.write(Self::TYPE); +2242 buf.write(self.path_id); +2243 buf.write(self.status_seq_no); +2244 } +2245} +2246 +2247impl Decodable for PathStatusAvailable { +2248 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +2249 Ok(Self { +2250 path_id: bytes.get()?, +2251 status_seq_no: bytes.get()?, +2252 }) +2253 } +2254} +2255 +2256#[derive(Debug, PartialEq, Eq, derive_more::Display)] +2257#[cfg_attr(test, derive(Arbitrary))] +2258#[display("PATH_STATUS_BACKUP path_id: {path_id} seq_no: {status_seq_no}")] +2259pub(crate) struct PathStatusBackup { +2260 pub(crate) path_id: PathId, +2261 pub(crate) status_seq_no: VarInt, +2262} +2263 +2264impl PathStatusBackup { +2265 const TYPE: FrameType = FrameType::PathStatusBackup; +2266 +2267 const fn get_type(&self) -> FrameType { +2268 FrameType::PathStatusBackup +2269 } +2270} +2271 +2272impl Encodable for PathStatusBackup { +2273 fn encode<W: BufMut>(&self, buf: &mut W) { +2274 buf.write(Self::TYPE); +2275 buf.write(self.path_id); +2276 buf.write(self.status_seq_no); +2277 } +2278} +2279 +2280impl Decodable for PathStatusBackup { +2281 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +2282 Ok(Self { +2283 path_id: bytes.get()?, +2284 status_seq_no: bytes.get()?, +2285 }) +2286 } +2287} +2288 +2289/* Nat traversal frames */ +2290 +2291/// Conjunction of the information contained in the add address frames +2292/// ([`FrameType::AddIpv4Address`], [`FrameType::AddIpv6Address`]). +2293#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, derive_more::Display)] +2294#[display("{} seq_no: {seq_no} addr: {}", self.get_type(), self.socket_addr())] +2295pub(crate) struct AddAddress { +2296 /// Monotonically increasing integer within the same connection +2297 // TODO(@divma): both assumed, the draft has no mention of this but it's standard +2298 pub(crate) seq_no: VarInt, +2299 /// Address to include in the known set +2300 pub(crate) ip: IpAddr, +2301 /// Port to use with this address +2302 pub(crate) port: u16, +2303} +2304 +2305#[cfg(test)] +2306impl proptest::arbitrary::Arbitrary for AddAddress { +2307 type Parameters = (); +2308 type Strategy = proptest::strategy::BoxedStrategy<Self>; +2309 +2310 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { +2311 use proptest::prelude::*; +2312 (any::<VarInt>(), any::<IpAddr>(), any::<u16>()) +2313 .prop_map(|(seq_no, ip, port)| Self { seq_no, ip, port }) +2314 .boxed() +2315 } +2316} +2317 +2318// TODO(@divma): remove +2319#[allow(dead_code)] +2320impl AddAddress { +2321 /// Smallest number of bytes this type of frame is guaranteed to fit within. +2322 pub(crate) const SIZE_BOUND: usize = Self { +2323 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), +2324 port: u16::MAX, +2325 seq_no: VarInt::MAX, +2326 } +2327 .size(); +2328 +2329 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self { +2330 Self { ip, port, seq_no } +2331 } +2332 +2333 /// Get the [`FrameType`] for this frame. +2334 const fn get_type(&self) -> FrameType { +2335 if self.ip.is_ipv6() { +2336 FrameType::AddIpv6Address +2337 } else { +2338 FrameType::AddIpv4Address +2339 } +2340 } +2341 +2342 /// Compute the number of bytes needed to encode the frame +2343 pub(crate) const fn size(&self) -> usize { +2344 let type_size = self.get_type().size(); +2345 let seq_no_bytes = self.seq_no.size(); +2346 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +2347 let port_bytes = 2; +2348 type_size + seq_no_bytes + ip_bytes + port_bytes +2349 } +2350 +2351 /// Read the frame contents from the buffer +2352 /// +2353 /// Should only be called when the frame type has been identified as +2354 /// [`FrameType::AddIpv4Address`] or [`FrameType::AddIpv6Address`]. +2355 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +2356 let seq_no = bytes.get()?; +2357 let ip = if is_ipv6 { +2358 IpAddr::V6(bytes.get()?) +2359 } else { +2360 IpAddr::V4(bytes.get()?) +2361 }; +2362 let port = bytes.get()?; +2363 Ok(Self { seq_no, ip, port }) +2364 } +2365 +2366 /// Give the [`SocketAddr`] encoded in the frame +2367 pub(crate) fn socket_addr(&self) -> SocketAddr { +2368 self.ip_port().into() +2369 } +2370 +2371 pub(crate) fn ip_port(&self) -> (IpAddr, u16) { +2372 (self.ip, self.port) +2373 } +2374} +2375 +2376impl Encodable for AddAddress { +2377 fn encode<W: BufMut>(&self, buf: &mut W) { +2378 buf.write(self.get_type()); +2379 buf.write(self.seq_no); +2380 match self.ip { +2381 IpAddr::V4(ipv4_addr) => { +2382 buf.write(ipv4_addr); +2383 } +2384 IpAddr::V6(ipv6_addr) => { +2385 buf.write(ipv6_addr); +2386 } +2387 } +2388 buf.write::<u16>(self.port); +2389 } +2390} +2391 +2392/// Conjunction of the information contained in the reach out frames +2393/// ([`FrameType::ReachOutAtIpv4`], [`FrameType::ReachOutAtIpv6`]) +2394#[derive(Debug, PartialEq, Eq, Clone, derive_more::Display)] +2395#[display("REACH_OUT round: {round} local_addr: {}", self.socket_addr())] +2396pub(crate) struct ReachOut { +2397 /// The sequence number of the NAT Traversal attempts +2398 pub(crate) round: VarInt, +2399 /// Address to use +2400 pub(crate) ip: IpAddr, +2401 /// Port to use with this address +2402 pub(crate) port: u16, +2403} +2404 +2405#[cfg(test)] +2406impl proptest::arbitrary::Arbitrary for ReachOut { +2407 type Parameters = (); +2408 type Strategy = proptest::strategy::BoxedStrategy<Self>; +2409 +2410 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { +2411 use proptest::prelude::*; +2412 (any::<VarInt>(), any::<IpAddr>(), any::<u16>()) +2413 .prop_map(|(round, ip, port)| Self { round, ip, port }) +2414 .boxed() +2415 } +2416} +2417 +2418// TODO(@divma): remove +2419#[allow(dead_code)] +2420impl ReachOut { +2421 /// Smallest number of bytes this type of frame is guaranteed to fit within +2422 pub(crate) const SIZE_BOUND: usize = Self { +2423 round: VarInt::MAX, +2424 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), +2425 port: u16::MAX, +2426 } +2427 .size(); +2428 +2429 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self { +2430 Self { round, ip, port } +2431 } +2432 +2433 /// Get the [`FrameType`] for this frame +2434 pub(crate) const fn get_type(&self) -> FrameType { +2435 if self.ip.is_ipv6() { +2436 FrameType::ReachOutAtIpv6 +2437 } else { +2438 FrameType::ReachOutAtIpv4 +2439 } +2440 } +2441 +2442 /// Compute the number of bytes needed to encode the frame +2443 pub(crate) const fn size(&self) -> usize { +2444 let type_size = self.get_type().size(); +2445 let round_bytes = self.round.size(); +2446 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +2447 let port_bytes = 2; +2448 type_size + round_bytes + ip_bytes + port_bytes +2449 } +2450 +2451 /// Read the frame contents from the buffer +2452 /// +2453 /// Should only be called when the frame type has been identified as +2454 /// [`FrameType::ReachOutAtIpv4`] or [`FrameType::ReachOutAtIpv6`]. +2455 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +2456 let round = bytes.get()?; +2457 let ip = if is_ipv6 { +2458 IpAddr::V6(bytes.get()?) +2459 } else { +2460 IpAddr::V4(bytes.get()?) +2461 }; +2462 let port = bytes.get()?; +2463 Ok(Self { round, ip, port }) +2464 } 2465 -2466impl Encodable for ReachOut { -2467 fn encode<W: BufMut>(&self, buf: &mut W) { -2468 buf.write(self.get_type()); -2469 buf.write(self.round); -2470 match self.ip { -2471 IpAddr::V4(ipv4_addr) => { -2472 buf.write(ipv4_addr); -2473 } -2474 IpAddr::V6(ipv6_addr) => { -2475 buf.write(ipv6_addr); -2476 } -2477 } -2478 buf.write::<u16>(self.port); -2479 } -2480} -2481 -2482/// Frame signaling an address is no longer being advertised -2483#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, derive_more::Display)] -2484#[cfg_attr(test, derive(Arbitrary))] -2485#[display("REMOVE_ADDRESS seq_no: {seq_no}")] -2486pub(crate) struct RemoveAddress { -2487 /// The sequence number of the address advertisement to be removed -2488 pub(crate) seq_no: VarInt, -2489} -2490 -2491// TODO(@divma): remove -2492#[allow(dead_code)] -2493impl RemoveAddress { -2494 /// [`FrameType`] of this frame -2495 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress; +2466 /// Give the [`SocketAddr`] encoded in the frame +2467 pub(crate) fn socket_addr(&self) -> SocketAddr { +2468 (self.ip, self.port).into() +2469 } +2470} +2471 +2472impl Encodable for ReachOut { +2473 fn encode<W: BufMut>(&self, buf: &mut W) { +2474 buf.write(self.get_type()); +2475 buf.write(self.round); +2476 match self.ip { +2477 IpAddr::V4(ipv4_addr) => { +2478 buf.write(ipv4_addr); +2479 } +2480 IpAddr::V6(ipv6_addr) => { +2481 buf.write(ipv6_addr); +2482 } +2483 } +2484 buf.write::<u16>(self.port); +2485 } +2486} +2487 +2488/// Frame signaling an address is no longer being advertised +2489#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, derive_more::Display)] +2490#[cfg_attr(test, derive(Arbitrary))] +2491#[display("REMOVE_ADDRESS seq_no: {seq_no}")] +2492pub(crate) struct RemoveAddress { +2493 /// The sequence number of the address advertisement to be removed +2494 pub(crate) seq_no: VarInt, +2495} 2496 -2497 /// Smallest number of bytes this type of frame is guaranteed to fit within -2498 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size(); -2499 -2500 pub(crate) const fn new(seq_no: VarInt) -> Self { -2501 Self { seq_no } -2502 } -2503 -2504 /// Compute the number of bytes needed to encode the frame -2505 pub(crate) const fn size(&self) -> usize { -2506 let type_size = Self::TYPE.size(); -2507 let seq_no_bytes = self.seq_no.size(); -2508 type_size + seq_no_bytes -2509 } -2510 -2511 /// Read the frame contents from the buffer -2512 /// -2513 /// Should only be called when the frame type has been identified as -2514 /// [`FrameType::RemoveAddress`]. -2515 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -2516 Ok(Self { -2517 seq_no: bytes.get()?, -2518 }) -2519 } -2520 -2521 const fn get_type(&self) -> FrameType { -2522 FrameType::RemoveAddress -2523 } -2524} -2525 -2526impl Encodable for RemoveAddress { -2527 fn encode<W: BufMut>(&self, buf: &mut W) { -2528 buf.write(Self::TYPE); -2529 buf.write(self.seq_no); -2530 } -2531} -2532 -2533/// Helper struct for display implementations. -2534// NOTE: Due to lifetimes in fmt::Arguments it's not possible to make this a simple function that -2535// avoids allocations. -2536struct DisplayOption<T: Display> { -2537 field_name: &'static str, -2538 op: Option<T>, -2539} -2540 -2541impl<T: Display> DisplayOption<T> { -2542 fn new(field_name: &'static str, op: Option<T>) -> Self { -2543 Self { field_name, op } -2544 } +2497// TODO(@divma): remove +2498#[allow(dead_code)] +2499impl RemoveAddress { +2500 /// [`FrameType`] of this frame +2501 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress; +2502 +2503 /// Smallest number of bytes this type of frame is guaranteed to fit within +2504 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size(); +2505 +2506 pub(crate) const fn new(seq_no: VarInt) -> Self { +2507 Self { seq_no } +2508 } +2509 +2510 /// Compute the number of bytes needed to encode the frame +2511 pub(crate) const fn size(&self) -> usize { +2512 let type_size = Self::TYPE.size(); +2513 let seq_no_bytes = self.seq_no.size(); +2514 type_size + seq_no_bytes +2515 } +2516 +2517 /// Read the frame contents from the buffer +2518 /// +2519 /// Should only be called when the frame type has been identified as +2520 /// [`FrameType::RemoveAddress`]. +2521 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +2522 Ok(Self { +2523 seq_no: bytes.get()?, +2524 }) +2525 } +2526 +2527 const fn get_type(&self) -> FrameType { +2528 FrameType::RemoveAddress +2529 } +2530} +2531 +2532impl Encodable for RemoveAddress { +2533 fn encode<W: BufMut>(&self, buf: &mut W) { +2534 buf.write(Self::TYPE); +2535 buf.write(self.seq_no); +2536 } +2537} +2538 +2539/// Helper struct for display implementations. +2540// NOTE: Due to lifetimes in fmt::Arguments it's not possible to make this a simple function that +2541// avoids allocations. +2542struct DisplayOption<T: Display> { +2543 field_name: &'static str, +2544 op: Option<T>, 2545} 2546 -2547impl<T: Display> Display for DisplayOption<T> { -2548 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -2549 if let Some(x) = self.op.as_ref() { -2550 write!(f, "{}: {x}", self.field_name) -2551 } else { -2552 fmt::Result::Ok(()) -2553 } -2554 } -2555} -2556 -2557#[cfg(test)] -2558mod test { -2559 use super::*; -2560 use crate::coding::Encodable; -2561 use assert_matches::assert_matches; +2547impl<T: Display> DisplayOption<T> { +2548 fn new(field_name: &'static str, op: Option<T>) -> Self { +2549 Self { field_name, op } +2550 } +2551} +2552 +2553impl<T: Display> Display for DisplayOption<T> { +2554 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +2555 if let Some(x) = self.op.as_ref() { +2556 write!(f, "{}: {x}", self.field_name) +2557 } else { +2558 fmt::Result::Ok(()) +2559 } +2560 } +2561} 2562 -2563 #[test] -2564 fn frame_type() { -2565 assert_eq!( -2566 FrameType::try_from(FrameType::Padding.to_u64()), -2567 Ok(FrameType::Padding), -2568 ); -2569 -2570 assert_eq!( -2571 FrameType::try_from(FrameType::Datagram(DatagramInfo(0x30)).to_u64()), -2572 Ok(FrameType::Datagram(DatagramInfo(0x30))), -2573 ); -2574 -2575 assert_eq!( -2576 FrameType::try_from(FrameType::Stream(StreamInfo(0x08)).to_u64()), -2577 Ok(FrameType::Stream(StreamInfo(0x08))), -2578 ); -2579 } +2563#[cfg(test)] +2564mod test { +2565 use super::*; +2566 use crate::coding::Encodable; +2567 use assert_matches::assert_matches; +2568 +2569 #[test] +2570 fn frame_type() { +2571 assert_eq!( +2572 FrameType::try_from(FrameType::Padding.to_u64()), +2573 Ok(FrameType::Padding), +2574 ); +2575 +2576 assert_eq!( +2577 FrameType::try_from(FrameType::Datagram(DatagramInfo(0x30)).to_u64()), +2578 Ok(FrameType::Datagram(DatagramInfo(0x30))), +2579 ); 2580 -2581 #[track_caller] -2582 fn frames(buf: Vec<u8>) -> Vec<Frame> { -2583 Iter::new(Bytes::from(buf)) -2584 .unwrap() -2585 .collect::<Result<Vec<_>, _>>() -2586 .unwrap() -2587 } -2588 -2589 #[test] -2590 fn ack_coding() { -2591 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; -2592 let mut ranges = ArrayRangeSet::new(); -2593 for &packet in PACKETS { -2594 ranges.insert(packet..packet + 1); -2595 } -2596 let mut buf = Vec::new(); -2597 const ECN: EcnCounts = EcnCounts { -2598 ect0: 42, -2599 ect1: 24, -2600 ce: 12, -2601 }; -2602 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf); -2603 let frames = frames(buf); -2604 assert_eq!(frames.len(), 1); -2605 match frames[0] { -2606 Frame::Ack(ref ack) => { -2607 let mut packets = ack.iter().flatten().collect::<Vec<_>>(); -2608 packets.sort_unstable(); -2609 assert_eq!(&packets[..], PACKETS); -2610 assert_eq!(ack.ecn, Some(ECN)); -2611 } -2612 ref x => panic!("incorrect frame {x:?}"), -2613 } -2614 } -2615 -2616 #[test] -2617 #[allow(clippy::range_plus_one)] -2618 fn path_ack_coding_with_ecn() { -2619 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; -2620 let mut ranges = ArrayRangeSet::new(); -2621 for &packet in PACKETS { -2622 ranges.insert(packet..packet + 1); -2623 } -2624 let mut buf = Vec::new(); -2625 const ECN: EcnCounts = EcnCounts { -2626 ect0: 42, -2627 ect1: 24, -2628 ce: 12, -2629 }; -2630 const PATH_ID: PathId = PathId::MAX; -2631 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf); -2632 let frames = frames(buf); -2633 assert_eq!(frames.len(), 1); -2634 match frames[0] { -2635 Frame::PathAck(ref ack) => { -2636 assert_eq!(ack.path_id, PATH_ID); -2637 let mut packets = ack.ranges.iter().flatten().collect::<Vec<_>>(); -2638 packets.sort_unstable(); -2639 assert_eq!(&packets[..], PACKETS); -2640 assert_eq!(ack.ecn, Some(ECN)); -2641 } -2642 ref x => panic!("incorrect frame {x:?}"), -2643 } -2644 } -2645 -2646 #[test] -2647 #[allow(clippy::range_plus_one)] -2648 fn path_ack_coding_no_ecn() { -2649 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; -2650 let mut ranges = ArrayRangeSet::new(); -2651 for &packet in PACKETS { -2652 ranges.insert(packet..packet + 1); -2653 } -2654 let mut buf = Vec::new(); -2655 const PATH_ID: PathId = PathId::MAX; -2656 PathAck::encoder(PATH_ID, 42, &ranges, None).encode(&mut buf); -2657 let frames = frames(buf); -2658 assert_eq!(frames.len(), 1); -2659 match frames[0] { -2660 Frame::PathAck(ref ack) => { -2661 assert_eq!(ack.path_id, PATH_ID); -2662 let mut packets = ack.ranges.iter().flatten().collect::<Vec<_>>(); -2663 packets.sort_unstable(); -2664 assert_eq!(&packets[..], PACKETS); -2665 assert_eq!(ack.ecn, None); -2666 } -2667 ref x => panic!("incorrect frame {x:?}"), -2668 } -2669 } -2670 -2671 #[test] -2672 fn ack_frequency_coding() { -2673 let mut buf = Vec::new(); -2674 let original = AckFrequency { -2675 sequence: VarInt(42), -2676 ack_eliciting_threshold: VarInt(20), -2677 request_max_ack_delay: VarInt(50_000), -2678 reordering_threshold: VarInt(1), -2679 }; -2680 original.encode(&mut buf); -2681 let frames = frames(buf); -2682 assert_eq!(frames.len(), 1); -2683 match &frames[0] { -2684 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original), -2685 x => panic!("incorrect frame {x:?}"), -2686 } -2687 } -2688 -2689 #[test] -2690 fn immediate_ack_coding() { -2691 let mut buf = Vec::new(); -2692 FrameType::ImmediateAck.encode(&mut buf); -2693 let frames = frames(buf); -2694 assert_eq!(frames.len(), 1); -2695 assert_matches!(&frames[0], Frame::ImmediateAck); -2696 } -2697 -2698 /// Test that encoding and decoding [`ObservedAddr`] produces the same result. -2699 #[test] -2700 fn test_observed_addr_roundrip() { -2701 let observed_addr = ObservedAddr { -2702 seq_no: VarInt(42), -2703 ip: std::net::Ipv4Addr::LOCALHOST.into(), -2704 port: 4242, -2705 }; -2706 let mut buf = Vec::with_capacity(observed_addr.size()); -2707 observed_addr.encode(&mut buf); -2708 -2709 assert_eq!( -2710 observed_addr.size(), -2711 buf.len(), -2712 "expected written bytes and actual size differ" -2713 ); +2581 assert_eq!( +2582 FrameType::try_from(FrameType::Stream(StreamInfo(0x08)).to_u64()), +2583 Ok(FrameType::Stream(StreamInfo(0x08))), +2584 ); +2585 } +2586 +2587 #[track_caller] +2588 fn frames(buf: Vec<u8>) -> Vec<Frame> { +2589 Iter::new(Bytes::from(buf)) +2590 .unwrap() +2591 .collect::<Result<Vec<_>, _>>() +2592 .unwrap() +2593 } +2594 +2595 #[test] +2596 fn ack_coding() { +2597 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; +2598 let mut ranges = ArrayRangeSet::new(); +2599 for &packet in PACKETS { +2600 ranges.insert(packet..packet + 1); +2601 } +2602 let mut buf = Vec::new(); +2603 const ECN: EcnCounts = EcnCounts { +2604 ect0: 42, +2605 ect1: 24, +2606 ce: 12, +2607 }; +2608 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf); +2609 let frames = frames(buf); +2610 assert_eq!(frames.len(), 1); +2611 match frames[0] { +2612 Frame::Ack(ref ack) => { +2613 let mut packets = ack.iter().flatten().collect::<Vec<_>>(); +2614 packets.sort_unstable(); +2615 assert_eq!(&packets[..], PACKETS); +2616 assert_eq!(ack.ecn, Some(ECN)); +2617 } +2618 ref x => panic!("incorrect frame {x:?}"), +2619 } +2620 } +2621 +2622 #[test] +2623 #[allow(clippy::range_plus_one)] +2624 fn path_ack_coding_with_ecn() { +2625 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; +2626 let mut ranges = ArrayRangeSet::new(); +2627 for &packet in PACKETS { +2628 ranges.insert(packet..packet + 1); +2629 } +2630 let mut buf = Vec::new(); +2631 const ECN: EcnCounts = EcnCounts { +2632 ect0: 42, +2633 ect1: 24, +2634 ce: 12, +2635 }; +2636 const PATH_ID: PathId = PathId::MAX; +2637 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf); +2638 let frames = frames(buf); +2639 assert_eq!(frames.len(), 1); +2640 match frames[0] { +2641 Frame::PathAck(ref ack) => { +2642 assert_eq!(ack.path_id, PATH_ID); +2643 let mut packets = ack.ranges.iter().flatten().collect::<Vec<_>>(); +2644 packets.sort_unstable(); +2645 assert_eq!(&packets[..], PACKETS); +2646 assert_eq!(ack.ecn, Some(ECN)); +2647 } +2648 ref x => panic!("incorrect frame {x:?}"), +2649 } +2650 } +2651 +2652 #[test] +2653 #[allow(clippy::range_plus_one)] +2654 fn path_ack_coding_no_ecn() { +2655 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; +2656 let mut ranges = ArrayRangeSet::new(); +2657 for &packet in PACKETS { +2658 ranges.insert(packet..packet + 1); +2659 } +2660 let mut buf = Vec::new(); +2661 const PATH_ID: PathId = PathId::MAX; +2662 PathAck::encoder(PATH_ID, 42, &ranges, None).encode(&mut buf); +2663 let frames = frames(buf); +2664 assert_eq!(frames.len(), 1); +2665 match frames[0] { +2666 Frame::PathAck(ref ack) => { +2667 assert_eq!(ack.path_id, PATH_ID); +2668 let mut packets = ack.ranges.iter().flatten().collect::<Vec<_>>(); +2669 packets.sort_unstable(); +2670 assert_eq!(&packets[..], PACKETS); +2671 assert_eq!(ack.ecn, None); +2672 } +2673 ref x => panic!("incorrect frame {x:?}"), +2674 } +2675 } +2676 +2677 #[test] +2678 fn ack_frequency_coding() { +2679 let mut buf = Vec::new(); +2680 let original = AckFrequency { +2681 sequence: VarInt(42), +2682 ack_eliciting_threshold: VarInt(20), +2683 request_max_ack_delay: VarInt(50_000), +2684 reordering_threshold: VarInt(1), +2685 }; +2686 original.encode(&mut buf); +2687 let frames = frames(buf); +2688 assert_eq!(frames.len(), 1); +2689 match &frames[0] { +2690 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original), +2691 x => panic!("incorrect frame {x:?}"), +2692 } +2693 } +2694 +2695 #[test] +2696 fn immediate_ack_coding() { +2697 let mut buf = Vec::new(); +2698 FrameType::ImmediateAck.encode(&mut buf); +2699 let frames = frames(buf); +2700 assert_eq!(frames.len(), 1); +2701 assert_matches!(&frames[0], Frame::ImmediateAck); +2702 } +2703 +2704 /// Test that encoding and decoding [`ObservedAddr`] produces the same result. +2705 #[test] +2706 fn test_observed_addr_roundrip() { +2707 let observed_addr = ObservedAddr { +2708 seq_no: VarInt(42), +2709 ip: std::net::Ipv4Addr::LOCALHOST.into(), +2710 port: 4242, +2711 }; +2712 let mut buf = Vec::with_capacity(observed_addr.size()); +2713 observed_addr.encode(&mut buf); 2714 -2715 let mut decoded = frames(buf); -2716 assert_eq!(decoded.len(), 1); -2717 match decoded.pop().expect("non empty") { -2718 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr), -2719 x => panic!("incorrect frame {x:?}"), -2720 } -2721 } -2722 -2723 #[test] -2724 fn test_path_abandon_roundtrip() { -2725 let abandon = PathAbandon { -2726 path_id: PathId(42), -2727 error_code: TransportErrorCode::NO_ERROR, -2728 }; -2729 let mut buf = Vec::new(); -2730 abandon.encode(&mut buf); -2731 -2732 let mut decoded = frames(buf); -2733 assert_eq!(decoded.len(), 1); -2734 match decoded.pop().expect("non empty") { -2735 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon), -2736 x => panic!("incorrect frame {x:?}"), -2737 } -2738 } -2739 -2740 #[test] -2741 fn test_path_status_available_roundtrip() { -2742 let path_status_available = PathStatusAvailable { -2743 path_id: PathId(42), -2744 status_seq_no: VarInt(73), -2745 }; -2746 let mut buf = Vec::new(); -2747 path_status_available.encode(&mut buf); -2748 -2749 let mut decoded = frames(buf); -2750 assert_eq!(decoded.len(), 1); -2751 match decoded.pop().expect("non empty") { -2752 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available), -2753 x => panic!("incorrect frame {x:?}"), -2754 } -2755 } -2756 -2757 #[test] -2758 fn test_path_status_backup_roundtrip() { -2759 let path_status_backup = PathStatusBackup { -2760 path_id: PathId(42), -2761 status_seq_no: VarInt(73), -2762 }; -2763 let mut buf = Vec::new(); -2764 path_status_backup.encode(&mut buf); -2765 -2766 let mut decoded = frames(buf); -2767 assert_eq!(decoded.len(), 1); -2768 match decoded.pop().expect("non empty") { -2769 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup), -2770 x => panic!("incorrect frame {x:?}"), -2771 } -2772 } -2773 -2774 #[test] -2775 fn test_path_new_connection_id_roundtrip() { -2776 let cid = NewConnectionId { -2777 path_id: Some(PathId(22)), -2778 sequence: 31, -2779 retire_prior_to: 13, -2780 id: ConnectionId::new(&[0xAB; 8]), -2781 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]), -2782 }; -2783 let mut buf = Vec::new(); -2784 cid.encode(&mut buf); -2785 -2786 let mut decoded = frames(buf); -2787 assert_eq!(decoded.len(), 1); -2788 match decoded.pop().expect("non empty") { -2789 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid), -2790 x => panic!("incorrect frame {x:?}"), -2791 } -2792 } -2793 -2794 #[test] -2795 fn test_path_retire_connection_id_roundtrip() { -2796 let retire_cid = RetireConnectionId { -2797 path_id: Some(PathId(22)), -2798 sequence: 31, -2799 }; -2800 let mut buf = Vec::new(); -2801 retire_cid.encode(&mut buf); -2802 -2803 let mut decoded = frames(buf); -2804 assert_eq!(decoded.len(), 1); -2805 match decoded.pop().expect("non empty") { -2806 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid), -2807 x => panic!("incorrect frame {x:?}"), -2808 } -2809 } -2810 -2811 #[test] -2812 fn test_paths_blocked_path_cids_blocked_roundtrip() { -2813 let mut buf = Vec::new(); -2814 -2815 let frame0 = PathsBlocked(PathId(22)); -2816 frame0.encode(&mut buf); -2817 let frame1 = PathCidsBlocked { -2818 path_id: PathId(23), -2819 next_seq: VarInt(32), -2820 }; -2821 frame1.encode(&mut buf); -2822 -2823 let mut decoded = frames(buf); -2824 assert_eq!(decoded.len(), 2); -2825 match decoded.pop().expect("non empty") { -2826 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1), -2827 x => panic!("incorrect frame {x:?}"), -2828 } -2829 match decoded.pop().expect("non empty") { -2830 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0), -2831 x => panic!("incorrect frame {x:?}"), -2832 } -2833 } -2834 -2835 /// Test that encoding and decoding [`AddAddress`] produces the same result -2836 #[test] -2837 fn test_add_address_roundrip() { -2838 let add_address = AddAddress { -2839 seq_no: VarInt(42), -2840 ip: std::net::Ipv4Addr::LOCALHOST.into(), -2841 port: 4242, -2842 }; -2843 let mut buf = Vec::with_capacity(add_address.size()); -2844 add_address.encode(&mut buf); -2845 -2846 assert_eq!( -2847 add_address.size(), -2848 buf.len(), -2849 "expected written bytes and actual size differ" -2850 ); +2715 assert_eq!( +2716 observed_addr.size(), +2717 buf.len(), +2718 "expected written bytes and actual size differ" +2719 ); +2720 +2721 let mut decoded = frames(buf); +2722 assert_eq!(decoded.len(), 1); +2723 match decoded.pop().expect("non empty") { +2724 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr), +2725 x => panic!("incorrect frame {x:?}"), +2726 } +2727 } +2728 +2729 #[test] +2730 fn test_path_abandon_roundtrip() { +2731 let abandon = PathAbandon { +2732 path_id: PathId(42), +2733 error_code: TransportErrorCode::NO_ERROR, +2734 }; +2735 let mut buf = Vec::new(); +2736 abandon.encode(&mut buf); +2737 +2738 let mut decoded = frames(buf); +2739 assert_eq!(decoded.len(), 1); +2740 match decoded.pop().expect("non empty") { +2741 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon), +2742 x => panic!("incorrect frame {x:?}"), +2743 } +2744 } +2745 +2746 #[test] +2747 fn test_path_status_available_roundtrip() { +2748 let path_status_available = PathStatusAvailable { +2749 path_id: PathId(42), +2750 status_seq_no: VarInt(73), +2751 }; +2752 let mut buf = Vec::new(); +2753 path_status_available.encode(&mut buf); +2754 +2755 let mut decoded = frames(buf); +2756 assert_eq!(decoded.len(), 1); +2757 match decoded.pop().expect("non empty") { +2758 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available), +2759 x => panic!("incorrect frame {x:?}"), +2760 } +2761 } +2762 +2763 #[test] +2764 fn test_path_status_backup_roundtrip() { +2765 let path_status_backup = PathStatusBackup { +2766 path_id: PathId(42), +2767 status_seq_no: VarInt(73), +2768 }; +2769 let mut buf = Vec::new(); +2770 path_status_backup.encode(&mut buf); +2771 +2772 let mut decoded = frames(buf); +2773 assert_eq!(decoded.len(), 1); +2774 match decoded.pop().expect("non empty") { +2775 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup), +2776 x => panic!("incorrect frame {x:?}"), +2777 } +2778 } +2779 +2780 #[test] +2781 fn test_path_new_connection_id_roundtrip() { +2782 let cid = NewConnectionId { +2783 path_id: Some(PathId(22)), +2784 sequence: 31, +2785 retire_prior_to: 13, +2786 id: ConnectionId::new(&[0xAB; 8]), +2787 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]), +2788 }; +2789 let mut buf = Vec::new(); +2790 cid.encode(&mut buf); +2791 +2792 let mut decoded = frames(buf); +2793 assert_eq!(decoded.len(), 1); +2794 match decoded.pop().expect("non empty") { +2795 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid), +2796 x => panic!("incorrect frame {x:?}"), +2797 } +2798 } +2799 +2800 #[test] +2801 fn test_path_retire_connection_id_roundtrip() { +2802 let retire_cid = RetireConnectionId { +2803 path_id: Some(PathId(22)), +2804 sequence: 31, +2805 }; +2806 let mut buf = Vec::new(); +2807 retire_cid.encode(&mut buf); +2808 +2809 let mut decoded = frames(buf); +2810 assert_eq!(decoded.len(), 1); +2811 match decoded.pop().expect("non empty") { +2812 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid), +2813 x => panic!("incorrect frame {x:?}"), +2814 } +2815 } +2816 +2817 #[test] +2818 fn test_paths_blocked_path_cids_blocked_roundtrip() { +2819 let mut buf = Vec::new(); +2820 +2821 let frame0 = PathsBlocked(PathId(22)); +2822 frame0.encode(&mut buf); +2823 let frame1 = PathCidsBlocked { +2824 path_id: PathId(23), +2825 next_seq: VarInt(32), +2826 }; +2827 frame1.encode(&mut buf); +2828 +2829 let mut decoded = frames(buf); +2830 assert_eq!(decoded.len(), 2); +2831 match decoded.pop().expect("non empty") { +2832 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1), +2833 x => panic!("incorrect frame {x:?}"), +2834 } +2835 match decoded.pop().expect("non empty") { +2836 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0), +2837 x => panic!("incorrect frame {x:?}"), +2838 } +2839 } +2840 +2841 /// Test that encoding and decoding [`AddAddress`] produces the same result +2842 #[test] +2843 fn test_add_address_roundrip() { +2844 let add_address = AddAddress { +2845 seq_no: VarInt(42), +2846 ip: std::net::Ipv4Addr::LOCALHOST.into(), +2847 port: 4242, +2848 }; +2849 let mut buf = Vec::with_capacity(add_address.size()); +2850 add_address.encode(&mut buf); 2851 -2852 let mut decoded = frames(buf); -2853 assert_eq!(decoded.len(), 1); -2854 match decoded.pop().expect("non empty") { -2855 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address), -2856 x => panic!("incorrect frame {x:?}"), -2857 } -2858 } -2859 -2860 /// Test that encoding and decoding [`AddAddress`] produces the same result -2861 #[test] -2862 fn test_reach_out_roundrip() { -2863 let reach_out = ReachOut { -2864 round: VarInt(42), -2865 ip: std::net::Ipv6Addr::LOCALHOST.into(), -2866 port: 4242, -2867 }; -2868 let mut buf = Vec::with_capacity(reach_out.size()); -2869 reach_out.encode(&mut buf); -2870 -2871 assert_eq!( -2872 reach_out.size(), -2873 buf.len(), -2874 "expected written bytes and actual size differ" -2875 ); +2852 assert_eq!( +2853 add_address.size(), +2854 buf.len(), +2855 "expected written bytes and actual size differ" +2856 ); +2857 +2858 let mut decoded = frames(buf); +2859 assert_eq!(decoded.len(), 1); +2860 match decoded.pop().expect("non empty") { +2861 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address), +2862 x => panic!("incorrect frame {x:?}"), +2863 } +2864 } +2865 +2866 /// Test that encoding and decoding [`AddAddress`] produces the same result +2867 #[test] +2868 fn test_reach_out_roundrip() { +2869 let reach_out = ReachOut { +2870 round: VarInt(42), +2871 ip: std::net::Ipv6Addr::LOCALHOST.into(), +2872 port: 4242, +2873 }; +2874 let mut buf = Vec::with_capacity(reach_out.size()); +2875 reach_out.encode(&mut buf); 2876 -2877 let mut decoded = frames(buf); -2878 assert_eq!(decoded.len(), 1); -2879 match decoded.pop().expect("non empty") { -2880 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out), -2881 x => panic!("incorrect frame {x:?}"), -2882 } -2883 } -2884 -2885 /// Test that encoding and decoding [`RemoveAddress`] produces the same result -2886 #[test] -2887 fn test_remove_address_roundrip() { -2888 let remove_addr = RemoveAddress::new(VarInt(10)); -2889 let mut buf = Vec::with_capacity(remove_addr.size()); -2890 remove_addr.encode(&mut buf); -2891 -2892 assert_eq!( -2893 remove_addr.size(), -2894 buf.len(), -2895 "expected written bytes and actual size differ" -2896 ); +2877 assert_eq!( +2878 reach_out.size(), +2879 buf.len(), +2880 "expected written bytes and actual size differ" +2881 ); +2882 +2883 let mut decoded = frames(buf); +2884 assert_eq!(decoded.len(), 1); +2885 match decoded.pop().expect("non empty") { +2886 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out), +2887 x => panic!("incorrect frame {x:?}"), +2888 } +2889 } +2890 +2891 /// Test that encoding and decoding [`RemoveAddress`] produces the same result +2892 #[test] +2893 fn test_remove_address_roundrip() { +2894 let remove_addr = RemoveAddress::new(VarInt(10)); +2895 let mut buf = Vec::with_capacity(remove_addr.size()); +2896 remove_addr.encode(&mut buf); 2897 -2898 let mut decoded = frames(buf); -2899 assert_eq!(decoded.len(), 1); -2900 match decoded.pop().expect("non empty") { -2901 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr), -2902 x => panic!("incorrect frame {x:?}"), -2903 } -2904 } -2905}

\ No newline at end of file +2898 assert_eq!( +2899 remove_addr.size(), +2900 buf.len(), +2901 "expected written bytes and actual size differ" +2902 ); +2903 +2904 let mut decoded = frames(buf); +2905 assert_eq!(decoded.len(), 1); +2906 match decoded.pop().expect("non empty") { +2907 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr), +2908 x => panic!("incorrect frame {x:?}"), +2909 } +2910 } +2911} \ No newline at end of file diff --git a/pr/340/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html b/pr/340/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html index d58c407d1..a8ccd40d8 100644 --- a/pr/340/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html +++ b/pr/340/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html @@ -236,7 +236,7 @@ 236 use proptest::prelude::*; 237 // Generate 1-8 ranges. Each range is defined by a gap from the previous and a size. 238 // We use small values to keep encoding reasonable. -239 prop::collection::vec((1u64..100, 1u64..50), 1..=8) +239 prop::collection::vec((1u64..100, 1u64..50), 0..8) 240 .prop_map(|gaps_and_sizes| { 241 let mut ranges = Self::new(); 242 let mut pos = 0u64;