1use super::{Error, Result, be32, put_be32};
6
7pub const PEER_ERROR_FILE_SYSTEM: u32 = 4000;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize))]
14pub struct KeepAlivePacket {
15 pub timestamp: u32,
17 pub dest_socket_id: u32,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize))]
25pub struct CongestionWarningPacket {
26 pub timestamp: u32,
28 pub dest_socket_id: u32,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize))]
35pub struct ShutdownPacket {
36 pub timestamp: u32,
38 pub dest_socket_id: u32,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
44#[cfg_attr(feature = "serde", derive(serde::Serialize))]
45pub struct AckAckPacket {
46 pub ack_number: u32,
48 pub timestamp: u32,
50 pub dest_socket_id: u32,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
56#[cfg_attr(feature = "serde", derive(serde::Serialize))]
57pub struct DropReqPacket {
58 pub message_number: u32,
61 pub timestamp: u32,
63 pub dest_socket_id: u32,
65 pub first_seq: u32,
67 pub last_seq: u32,
69}
70
71impl DropReqPacket {
72 pub(crate) fn parse_cif(
73 message_number: u32,
74 timestamp: u32,
75 dest_socket_id: u32,
76 cif: &[u8],
77 ) -> Result<Self> {
78 if cif.len() != 8 {
79 return Err(Error::BufferTooShort {
80 need: 8,
81 have: cif.len(),
82 what: "drop request CIF",
83 });
84 }
85 Ok(DropReqPacket {
86 message_number,
87 timestamp,
88 dest_socket_id,
89 first_seq: be32(cif, 0),
90 last_seq: be32(cif, 4),
91 })
92 }
93
94 pub(crate) fn cif_len(&self) -> usize {
95 8
96 }
97
98 pub(crate) fn write_cif(&self, buf: &mut [u8]) {
99 put_be32(buf, 0, self.first_seq);
100 put_be32(buf, 4, self.last_seq);
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
106#[cfg_attr(feature = "serde", derive(serde::Serialize))]
107pub struct PeerErrorPacket {
108 pub error_code: u32,
110 pub timestamp: u32,
112 pub dest_socket_id: u32,
114}
115
116#[cfg(test)]
117mod tests {
118 use alloc::vec::Vec;
119
120 use super::super::control::ControlPacket;
121 use super::*;
122
123 #[test]
124 fn drop_req_round_trips() {
125 let d = DropReqPacket {
126 message_number: 7,
127 timestamp: 100,
128 dest_socket_id: 200,
129 first_seq: 10,
130 last_seq: 20,
131 };
132 let pkt = ControlPacket::DropReq(d);
133 let mut buf = [0u8; 24];
134 let n = pkt.serialize_into(&mut buf).unwrap();
135 assert_eq!(n, 24);
136 assert_eq!(&buf[4..8], &7u32.to_be_bytes()); assert_eq!(&buf[16..20], &10u32.to_be_bytes());
138 assert_eq!(&buf[20..24], &20u32.to_be_bytes());
139 let parsed = ControlPacket::parse(&buf).unwrap();
140 assert_eq!(parsed, pkt);
141 }
142
143 #[test]
144 fn keepalive_congestion_shutdown_ackack_peererror_round_trip() {
145 let cases: Vec<ControlPacket> = alloc::vec![
146 ControlPacket::KeepAlive(KeepAlivePacket {
147 timestamp: 1,
148 dest_socket_id: 2
149 }),
150 ControlPacket::CongestionWarning(CongestionWarningPacket {
151 timestamp: 3,
152 dest_socket_id: 4
153 }),
154 ControlPacket::Shutdown(ShutdownPacket {
155 timestamp: 5,
156 dest_socket_id: 6
157 }),
158 ControlPacket::AckAck(AckAckPacket {
159 ack_number: 9,
160 timestamp: 7,
161 dest_socket_id: 8
162 }),
163 ControlPacket::PeerError(PeerErrorPacket {
164 error_code: PEER_ERROR_FILE_SYSTEM,
165 timestamp: 11,
166 dest_socket_id: 12
167 }),
168 ];
169 for pkt in cases {
170 let mut buf = [0u8; 16];
171 let n = pkt.serialize_into(&mut buf).unwrap();
172 assert_eq!(n, 16);
173 let parsed = ControlPacket::parse(&buf).unwrap();
174 assert_eq!(parsed, pkt);
175 }
176 }
177
178 #[test]
179 fn keepalive_rejects_trailing_bytes() {
180 let mut buf = [0u8; 17];
181 buf[0] = 0x80; buf[1] = 0x01; assert!(matches!(
184 ControlPacket::parse(&buf),
185 Err(Error::UnexpectedTrailingBytes { .. })
186 ));
187 }
188}