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