1use {
4 bincode::{Options, Result},
5 bitflags::bitflags,
6 serde::{Deserialize, Serialize},
7 serde_with::{serde_as, Bytes},
8 std::{
9 fmt, io,
10 net::{IpAddr, Ipv4Addr, SocketAddr},
11 slice::SliceIndex,
12 },
13};
14
15#[cfg(test)]
16static_assertions::const_assert_eq!(PACKET_DATA_SIZE, 1232);
17pub const PACKET_DATA_SIZE: usize = 1280 - 40 - 8;
22
23bitflags! {
24 #[repr(C)]
25 #[derive(Serialize, Deserialize)]
26 pub struct PacketFlags: u8 {
27 const DISCARD = 0b0000_0001;
28 const FORWARDED = 0b0000_0010;
29 const REPAIR = 0b0000_0100;
30 const SIMPLE_VOTE_TX = 0b0000_1000;
31 const TRACER_PACKET = 0b0001_0000;
32 }
33}
34
35#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
36#[repr(C)]
37pub struct Meta {
38 pub size: usize,
39 pub addr: IpAddr,
40 pub port: u16,
41 pub flags: PacketFlags,
42 pub sender_stake: u64,
43}
44
45#[serde_as]
71#[derive(Clone, Eq, Serialize, Deserialize)]
72#[repr(C)]
73pub struct Packet {
74 #[serde_as(as = "Bytes")]
77 buffer: [u8; PACKET_DATA_SIZE],
78 meta: Meta,
79}
80
81impl Packet {
82 pub fn new(buffer: [u8; PACKET_DATA_SIZE], meta: Meta) -> Self {
83 Self { buffer, meta }
84 }
85
86 #[inline]
92 pub fn data<I>(&self, index: I) -> Option<&<I as SliceIndex<[u8]>>::Output>
93 where
94 I: SliceIndex<[u8]>,
95 {
96 if self.meta.discard() {
100 None
101 } else {
102 self.buffer.get(..self.meta.size)?.get(index)
103 }
104 }
105
106 #[inline]
110 pub fn buffer_mut(&mut self) -> &mut [u8] {
111 debug_assert!(!self.meta.discard());
112 &mut self.buffer[..]
113 }
114
115 #[inline]
116 pub fn meta(&self) -> &Meta {
117 &self.meta
118 }
119
120 #[inline]
121 pub fn meta_mut(&mut self) -> &mut Meta {
122 &mut self.meta
123 }
124
125 pub fn from_data<T: Serialize>(dest: Option<&SocketAddr>, data: T) -> Result<Self> {
126 let mut packet = Packet::default();
127 Self::populate_packet(&mut packet, dest, &data)?;
128 Ok(packet)
129 }
130
131 pub fn populate_packet<T: Serialize>(
132 &mut self,
133 dest: Option<&SocketAddr>,
134 data: &T,
135 ) -> Result<()> {
136 debug_assert!(!self.meta.discard());
137 let mut wr = io::Cursor::new(self.buffer_mut());
138 bincode::serialize_into(&mut wr, data)?;
139 self.meta.size = wr.position() as usize;
140 if let Some(dest) = dest {
141 self.meta.set_socket_addr(dest);
142 }
143 Ok(())
144 }
145
146 pub fn deserialize_slice<T, I>(&self, index: I) -> Result<T>
147 where
148 T: serde::de::DeserializeOwned,
149 I: SliceIndex<[u8], Output = [u8]>,
150 {
151 let bytes = self.data(index).ok_or(bincode::ErrorKind::SizeLimit)?;
152 bincode::options()
153 .with_limit(PACKET_DATA_SIZE as u64)
154 .with_fixint_encoding()
155 .reject_trailing_bytes()
156 .deserialize(bytes)
157 }
158}
159
160impl fmt::Debug for Packet {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 write!(
163 f,
164 "Packet {{ size: {:?}, addr: {:?} }}",
165 self.meta.size,
166 self.meta.socket_addr()
167 )
168 }
169}
170
171#[allow(clippy::uninit_assumed_init)]
172impl Default for Packet {
173 fn default() -> Packet {
174 let buffer = std::mem::MaybeUninit::<[u8; PACKET_DATA_SIZE]>::uninit();
175 Packet {
176 buffer: unsafe { buffer.assume_init() },
177 meta: Meta::default(),
178 }
179 }
180}
181
182impl PartialEq for Packet {
183 fn eq(&self, other: &Packet) -> bool {
184 self.meta() == other.meta() && self.data(..) == other.data(..)
185 }
186}
187
188impl Meta {
189 pub fn socket_addr(&self) -> SocketAddr {
190 SocketAddr::new(self.addr, self.port)
191 }
192
193 pub fn set_socket_addr(&mut self, socket_addr: &SocketAddr) {
194 self.addr = socket_addr.ip();
195 self.port = socket_addr.port();
196 }
197
198 #[inline]
199 pub fn discard(&self) -> bool {
200 self.flags.contains(PacketFlags::DISCARD)
201 }
202
203 #[inline]
204 pub fn set_discard(&mut self, discard: bool) {
205 self.flags.set(PacketFlags::DISCARD, discard);
206 }
207
208 #[inline]
209 pub fn set_tracer(&mut self, is_tracer: bool) {
210 self.flags.set(PacketFlags::TRACER_PACKET, is_tracer);
211 }
212
213 #[inline]
214 pub fn set_simple_vote(&mut self, is_simple_vote: bool) {
215 self.flags.set(PacketFlags::SIMPLE_VOTE_TX, is_simple_vote);
216 }
217
218 #[inline]
219 pub fn forwarded(&self) -> bool {
220 self.flags.contains(PacketFlags::FORWARDED)
221 }
222
223 #[inline]
224 pub fn repair(&self) -> bool {
225 self.flags.contains(PacketFlags::REPAIR)
226 }
227
228 #[inline]
229 pub fn is_simple_vote_tx(&self) -> bool {
230 self.flags.contains(PacketFlags::SIMPLE_VOTE_TX)
231 }
232
233 #[inline]
234 pub fn is_tracer_packet(&self) -> bool {
235 self.flags.contains(PacketFlags::TRACER_PACKET)
236 }
237}
238
239impl Default for Meta {
240 fn default() -> Self {
241 Self {
242 size: 0,
243 addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
244 port: 0,
245 flags: PacketFlags::empty(),
246 sender_stake: 0,
247 }
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 use super::*;
254
255 #[test]
256 fn test_deserialize_slice() {
257 let p = Packet::from_data(None, u32::MAX).unwrap();
258 assert_eq!(p.deserialize_slice(..).ok(), Some(u32::MAX));
259 assert_eq!(p.deserialize_slice(0..4).ok(), Some(u32::MAX));
260 assert_eq!(
261 p.deserialize_slice::<u16, _>(0..4)
262 .map_err(|e| e.to_string()),
263 Err("Slice had bytes remaining after deserialization".to_string()),
264 );
265 assert_eq!(
266 p.deserialize_slice::<u32, _>(0..0)
267 .map_err(|e| e.to_string()),
268 Err("io error: unexpected end of file".to_string()),
269 );
270 assert_eq!(
271 p.deserialize_slice::<u32, _>(0..1)
272 .map_err(|e| e.to_string()),
273 Err("io error: unexpected end of file".to_string()),
274 );
275 assert_eq!(
276 p.deserialize_slice::<u32, _>(0..5)
277 .map_err(|e| e.to_string()),
278 Err("the size limit has been reached".to_string()),
279 );
280 #[allow(clippy::reversed_empty_ranges)]
281 let reversed_empty_range = 4..0;
282 assert_eq!(
283 p.deserialize_slice::<u32, _>(reversed_empty_range)
284 .map_err(|e| e.to_string()),
285 Err("the size limit has been reached".to_string()),
286 );
287 assert_eq!(
288 p.deserialize_slice::<u32, _>(4..5)
289 .map_err(|e| e.to_string()),
290 Err("the size limit has been reached".to_string()),
291 );
292 }
293}