1use super::{Error, Result, be32, put_be32};
13
14pub const ACK_CIF_LEN_FULL: usize = 28;
16pub const ACK_CIF_LEN_SMALL: usize = 16;
18pub const ACK_CIF_LEN_LIGHT: usize = 4;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize))]
26#[non_exhaustive]
27pub enum AckCif {
28 Full {
30 last_ack_seq: u32,
32 rtt_us: u32,
34 rtt_var_us: u32,
36 avail_buf_size: u32,
38 pkt_recv_rate: u32,
40 est_link_capacity: u32,
42 recv_rate_bps: u32,
44 },
45 Small {
47 last_ack_seq: u32,
49 rtt_us: u32,
51 rtt_var_us: u32,
53 avail_buf_size: u32,
55 },
56 Light {
58 last_ack_seq: u32,
60 },
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize))]
70pub struct AckPacket {
71 pub ack_number: u32,
73 pub timestamp: u32,
75 pub dest_socket_id: u32,
77 pub cif: AckCif,
79}
80
81impl AckPacket {
82 pub(crate) fn parse_cif(
83 ack_number: u32,
84 timestamp: u32,
85 dest_socket_id: u32,
86 cif: &[u8],
87 ) -> Result<Self> {
88 let parsed = match cif.len() {
89 ACK_CIF_LEN_FULL => AckCif::Full {
90 last_ack_seq: be32(cif, 0),
91 rtt_us: be32(cif, 4),
92 rtt_var_us: be32(cif, 8),
93 avail_buf_size: be32(cif, 12),
94 pkt_recv_rate: be32(cif, 16),
95 est_link_capacity: be32(cif, 20),
96 recv_rate_bps: be32(cif, 24),
97 },
98 ACK_CIF_LEN_SMALL => AckCif::Small {
99 last_ack_seq: be32(cif, 0),
100 rtt_us: be32(cif, 4),
101 rtt_var_us: be32(cif, 8),
102 avail_buf_size: be32(cif, 12),
103 },
104 ACK_CIF_LEN_LIGHT => AckCif::Light {
105 last_ack_seq: be32(cif, 0),
106 },
107 other => return Err(Error::InvalidAckLength { len: other }),
108 };
109 Ok(AckPacket {
110 ack_number,
111 timestamp,
112 dest_socket_id,
113 cif: parsed,
114 })
115 }
116
117 pub(crate) fn cif_len(&self) -> usize {
118 match self.cif {
119 AckCif::Full { .. } => ACK_CIF_LEN_FULL,
120 AckCif::Small { .. } => ACK_CIF_LEN_SMALL,
121 AckCif::Light { .. } => ACK_CIF_LEN_LIGHT,
122 }
123 }
124
125 pub(crate) fn write_cif(&self, buf: &mut [u8]) -> Result<()> {
126 match self.cif {
127 AckCif::Full {
128 last_ack_seq,
129 rtt_us,
130 rtt_var_us,
131 avail_buf_size,
132 pkt_recv_rate,
133 est_link_capacity,
134 recv_rate_bps,
135 } => {
136 put_be32(buf, 0, last_ack_seq);
137 put_be32(buf, 4, rtt_us);
138 put_be32(buf, 8, rtt_var_us);
139 put_be32(buf, 12, avail_buf_size);
140 put_be32(buf, 16, pkt_recv_rate);
141 put_be32(buf, 20, est_link_capacity);
142 put_be32(buf, 24, recv_rate_bps);
143 }
144 AckCif::Small {
145 last_ack_seq,
146 rtt_us,
147 rtt_var_us,
148 avail_buf_size,
149 } => {
150 put_be32(buf, 0, last_ack_seq);
151 put_be32(buf, 4, rtt_us);
152 put_be32(buf, 8, rtt_var_us);
153 put_be32(buf, 12, avail_buf_size);
154 }
155 AckCif::Light { last_ack_seq } => {
156 put_be32(buf, 0, last_ack_seq);
157 }
158 }
159 Ok(())
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::super::control::ControlPacket;
166 use super::*;
167
168 #[test]
169 fn full_ack_round_trips_hand_computed_bytes() {
170 let pkt = ControlPacket::Ack(AckPacket {
171 ack_number: 42,
172 timestamp: 1000,
173 dest_socket_id: 2000,
174 cif: AckCif::Full {
175 last_ack_seq: 1,
176 rtt_us: 2,
177 rtt_var_us: 3,
178 avail_buf_size: 4,
179 pkt_recv_rate: 5,
180 est_link_capacity: 6,
181 recv_rate_bps: 7,
182 },
183 });
184 let mut buf = [0u8; 16 + 28];
185 let n = pkt.serialize_into(&mut buf).unwrap();
186 assert_eq!(n, 44);
187 assert_eq!(buf[0], 0x80); assert_eq!(&buf[0..4], &(0x8002_0000u32).to_be_bytes()); assert_eq!(&buf[4..8], &42u32.to_be_bytes());
190 assert_eq!(&buf[16..20], &1u32.to_be_bytes());
191 assert_eq!(&buf[40..44], &7u32.to_be_bytes());
192 assert_eq!(ControlPacket::parse(&buf).unwrap(), pkt);
193 }
194
195 #[test]
196 fn small_and_light_ack_round_trip() {
197 for cif in [
198 AckCif::Small {
199 last_ack_seq: 10,
200 rtt_us: 20,
201 rtt_var_us: 30,
202 avail_buf_size: 40,
203 },
204 AckCif::Light { last_ack_seq: 99 },
205 ] {
206 let pkt = ControlPacket::Ack(AckPacket {
207 ack_number: 0,
208 timestamp: 1,
209 dest_socket_id: 2,
210 cif,
211 });
212 let mut buf = alloc::vec![0u8; pkt.serialized_len()];
213 pkt.serialize_into(&mut buf).unwrap();
214 assert_eq!(ControlPacket::parse(&buf).unwrap(), pkt);
215 }
216 }
217
218 #[test]
219 fn invalid_ack_cif_length_errs() {
220 let mut buf = [0u8; 16 + 5];
221 buf[0] = 0x80;
222 buf[1] = 0x02; assert_eq!(
224 ControlPacket::parse(&buf).unwrap_err(),
225 Error::InvalidAckLength { len: 5 }
226 );
227 }
228
229 #[test]
230 fn mutate_field_changes_bytes() {
231 let mut pkt = AckPacket {
232 ack_number: 1,
233 timestamp: 2,
234 dest_socket_id: 3,
235 cif: AckCif::Light { last_ack_seq: 4 },
236 };
237 let mut buf1 = [0u8; 20];
238 ControlPacket::Ack(pkt).serialize_into(&mut buf1).unwrap();
239 pkt.ack_number = 99;
240 let mut buf2 = [0u8; 20];
241 ControlPacket::Ack(pkt).serialize_into(&mut buf2).unwrap();
242 assert_ne!(buf1, buf2);
243 }
244}