1#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5#[cfg(feature = "frozen-abi")]
6use atlas_frozen_abi_macro::AbiExample;
7#[cfg(feature = "bincode")]
8use {
9 bincode::{Options, Result},
10 std::io::Write,
11};
12use {
13 bitflags::bitflags,
14 atlas_pubkey::Pubkey,
15 std::{
16 fmt,
17 net::{IpAddr, Ipv4Addr, SocketAddr},
18 slice::SliceIndex,
19 },
20};
21#[cfg(feature = "serde")]
22use {
23 serde_derive::{Deserialize, Serialize},
24 serde_with::{serde_as, Bytes},
25};
26
27#[cfg(test)]
28static_assertions::const_assert_eq!(PACKET_DATA_SIZE, 1232);
29pub const PACKET_DATA_SIZE: usize = 1280 - 40 - 8;
34
35#[cfg(feature = "bincode")]
36pub trait Encode {
37 fn encode<W: Write>(&self, writer: W) -> Result<()>;
38}
39
40#[cfg(feature = "bincode")]
41impl<T: ?Sized + serde::Serialize> Encode for T {
42 fn encode<W: Write>(&self, writer: W) -> Result<()> {
43 bincode::serialize_into::<W, T>(writer, self)
44 }
45}
46
47bitflags! {
48 #[repr(C)]
49 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
50 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
51 pub struct PacketFlags: u8 {
52 const DISCARD = 0b0000_0001;
53 const FORWARDED = 0b0000_0010;
54 const REPAIR = 0b0000_0100;
55 const SIMPLE_VOTE_TX = 0b0000_1000;
56 const UNUSED_0 = 0b0001_0000;
58 const UNUSED_1 = 0b0010_0000;
60 const PERF_TRACK_PACKET = 0b0100_0000;
62 const FROM_STAKED_NODE = 0b1000_0000;
64 }
65}
66
67#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
68#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
69#[derive(Clone, Debug, PartialEq, Eq)]
70#[repr(C)]
71pub struct Meta {
72 pub size: usize,
73 pub addr: IpAddr,
74 pub port: u16,
75 pub flags: PacketFlags,
76 remote_pubkey: Pubkey,
77}
78
79#[cfg(feature = "frozen-abi")]
80impl ::atlas_frozen_abi::abi_example::AbiExample for PacketFlags {
81 fn example() -> Self {
82 Self::empty()
83 }
84}
85
86#[cfg(feature = "frozen-abi")]
87impl ::atlas_frozen_abi::abi_example::TransparentAsHelper for PacketFlags {}
88
89#[cfg(feature = "frozen-abi")]
90impl ::atlas_frozen_abi::abi_example::EvenAsOpaque for PacketFlags {
91 const TYPE_NAME_MATCHER: &'static str = "::_::InternalBitFlags";
92}
93
94#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
123#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
124#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
125#[derive(Clone, Eq)]
126#[repr(C)]
127pub struct Packet {
128 #[cfg_attr(feature = "serde", serde_as(as = "Bytes"))]
131 buffer: [u8; PACKET_DATA_SIZE],
132 meta: Meta,
133}
134
135impl Packet {
136 pub fn new(buffer: [u8; PACKET_DATA_SIZE], meta: Meta) -> Self {
137 Self { buffer, meta }
138 }
139
140 #[inline]
146 pub fn data<I>(&self, index: I) -> Option<&<I as SliceIndex<[u8]>>::Output>
147 where
148 I: SliceIndex<[u8]>,
149 {
150 if self.meta.discard() {
154 None
155 } else {
156 self.buffer.get(..self.meta.size)?.get(index)
157 }
158 }
159
160 #[inline]
164 pub fn buffer_mut(&mut self) -> &mut [u8] {
165 debug_assert!(!self.meta.discard());
166 &mut self.buffer[..]
167 }
168
169 #[inline]
170 pub fn meta(&self) -> &Meta {
171 &self.meta
172 }
173
174 #[inline]
175 pub fn meta_mut(&mut self) -> &mut Meta {
176 &mut self.meta
177 }
178
179 #[cfg(feature = "bincode")]
180 pub fn from_data<T: Encode>(dest: Option<&SocketAddr>, data: T) -> Result<Self> {
181 let mut packet = Self::default();
182 Self::populate_packet(&mut packet, dest, &data)?;
183 Ok(packet)
184 }
185
186 #[cfg(feature = "bincode")]
187 pub fn populate_packet<T: Encode>(
188 &mut self,
189 dest: Option<&SocketAddr>,
190 data: &T,
191 ) -> Result<()> {
192 debug_assert!(!self.meta.discard());
193 let mut wr = std::io::Cursor::new(self.buffer_mut());
194 <T as Encode>::encode(data, &mut wr)?;
195 self.meta.size = wr.position() as usize;
196 if let Some(dest) = dest {
197 self.meta.set_socket_addr(dest);
198 }
199 Ok(())
200 }
201
202 #[cfg(feature = "bincode")]
203 pub fn deserialize_slice<T, I>(&self, index: I) -> Result<T>
204 where
205 T: serde::de::DeserializeOwned,
206 I: SliceIndex<[u8], Output = [u8]>,
207 {
208 let bytes = self.data(index).ok_or(bincode::ErrorKind::SizeLimit)?;
209 bincode::options()
210 .with_limit(PACKET_DATA_SIZE as u64)
211 .with_fixint_encoding()
212 .reject_trailing_bytes()
213 .deserialize(bytes)
214 }
215}
216
217impl fmt::Debug for Packet {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 write!(
220 f,
221 "Packet {{ size: {:?}, addr: {:?} }}",
222 self.meta.size,
223 self.meta.socket_addr()
224 )
225 }
226}
227
228#[allow(clippy::uninit_assumed_init)]
229impl Default for Packet {
230 fn default() -> Self {
231 let buffer = std::mem::MaybeUninit::<[u8; PACKET_DATA_SIZE]>::uninit();
232 Self {
233 buffer: unsafe { buffer.assume_init() },
234 meta: Meta::default(),
235 }
236 }
237}
238
239impl PartialEq for Packet {
240 fn eq(&self, other: &Self) -> bool {
241 self.meta() == other.meta() && self.data(..) == other.data(..)
242 }
243}
244
245impl Meta {
246 pub fn new(
247 size: usize,
248 addr: IpAddr,
249 port: u16,
250 flags: PacketFlags,
251 remote_pubkey: Option<Pubkey>,
252 ) -> Self {
253 Self {
254 size,
255 addr,
256 port,
257 flags,
258 remote_pubkey: remote_pubkey.unwrap_or_default(),
259 }
260 }
261
262 pub fn socket_addr(&self) -> SocketAddr {
263 SocketAddr::new(self.addr, self.port)
264 }
265
266 pub fn set_socket_addr(&mut self, socket_addr: &SocketAddr) {
267 self.addr = socket_addr.ip();
268 self.port = socket_addr.port();
269 }
270
271 pub fn set_from_staked_node(&mut self, from_staked_node: bool) {
272 self.flags
273 .set(PacketFlags::FROM_STAKED_NODE, from_staked_node);
274 }
275
276 #[inline]
277 pub fn discard(&self) -> bool {
278 self.flags.contains(PacketFlags::DISCARD)
279 }
280
281 #[inline]
282 pub fn set_discard(&mut self, discard: bool) {
283 self.flags.set(PacketFlags::DISCARD, discard);
284 }
285
286 #[inline]
287 pub fn set_track_performance(&mut self, is_performance_track: bool) {
288 self.flags
289 .set(PacketFlags::PERF_TRACK_PACKET, is_performance_track);
290 }
291
292 #[inline]
293 pub fn set_simple_vote(&mut self, is_simple_vote: bool) {
294 self.flags.set(PacketFlags::SIMPLE_VOTE_TX, is_simple_vote);
295 }
296
297 #[inline]
298 pub fn forwarded(&self) -> bool {
299 self.flags.contains(PacketFlags::FORWARDED)
300 }
301
302 #[inline]
303 pub fn repair(&self) -> bool {
304 self.flags.contains(PacketFlags::REPAIR)
305 }
306
307 #[inline]
308 pub fn is_simple_vote_tx(&self) -> bool {
309 self.flags.contains(PacketFlags::SIMPLE_VOTE_TX)
310 }
311
312 #[inline]
313 pub fn is_perf_track_packet(&self) -> bool {
314 self.flags.contains(PacketFlags::PERF_TRACK_PACKET)
315 }
316
317 #[inline]
318 pub fn is_from_staked_node(&self) -> bool {
319 self.flags.contains(PacketFlags::FROM_STAKED_NODE)
320 }
321
322 #[inline]
323 pub fn remote_pubkey(&self) -> Option<Pubkey> {
324 if self.remote_pubkey == Pubkey::default() {
325 None
326 } else {
327 Some(self.remote_pubkey)
328 }
329 }
330
331 #[inline]
333 pub fn set_remote_pubkey(&mut self, pubkey: Pubkey) {
334 self.remote_pubkey = pubkey;
335 }
336}
337
338impl Default for Meta {
339 fn default() -> Self {
340 Self {
341 size: 0,
342 addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
343 port: 0,
344 flags: PacketFlags::empty(),
345 remote_pubkey: Pubkey::default(),
346 }
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 use super::*;
353
354 #[test]
355 fn test_deserialize_slice() {
356 let p = Packet::from_data(None, u32::MAX).unwrap();
357 assert_eq!(p.deserialize_slice(..).ok(), Some(u32::MAX));
358 assert_eq!(p.deserialize_slice(0..4).ok(), Some(u32::MAX));
359 assert_eq!(
360 p.deserialize_slice::<u16, _>(0..4)
361 .map_err(|e| e.to_string()),
362 Err("Slice had bytes remaining after deserialization".to_string()),
363 );
364 assert_eq!(
365 p.deserialize_slice::<u32, _>(0..0)
366 .map_err(|e| e.to_string()),
367 Err("io error: unexpected end of file".to_string()),
368 );
369 assert_eq!(
370 p.deserialize_slice::<u32, _>(0..1)
371 .map_err(|e| e.to_string()),
372 Err("io error: unexpected end of file".to_string()),
373 );
374 assert_eq!(
375 p.deserialize_slice::<u32, _>(0..5)
376 .map_err(|e| e.to_string()),
377 Err("the size limit has been reached".to_string()),
378 );
379 #[allow(clippy::reversed_empty_ranges)]
380 let reversed_empty_range = 4..0;
381 assert_eq!(
382 p.deserialize_slice::<u32, _>(reversed_empty_range)
383 .map_err(|e| e.to_string()),
384 Err("the size limit has been reached".to_string()),
385 );
386 assert_eq!(
387 p.deserialize_slice::<u32, _>(4..5)
388 .map_err(|e| e.to_string()),
389 Err("the size limit has been reached".to_string()),
390 );
391 }
392
393 #[test]
394 fn test_remote_pubkey() {
395 let mut meta = Meta::default();
396 assert!(meta.remote_pubkey().is_none());
397 let pubkey = Pubkey::new_unique();
398 meta.set_remote_pubkey(pubkey);
399 assert_eq!(meta.remote_pubkey(), Some(pubkey));
400 let pubkey = Pubkey::default();
401 meta.set_remote_pubkey(pubkey);
402 assert!(meta.remote_pubkey().is_none());
403 }
404
405 #[test]
406 fn test_meta_new() {
407 let size = 1024;
408 let addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
409 let port = 8080;
410 let flags = PacketFlags::FROM_STAKED_NODE | PacketFlags::REPAIR;
411 let pubkey = Pubkey::new_unique();
412
413 let meta = Meta::new(size, addr, port, flags, Some(pubkey));
414
415 assert_eq!(meta.size, size);
416 assert_eq!(meta.addr, addr);
417 assert_eq!(meta.port, port);
418 assert_eq!(meta.flags, flags);
419 assert_eq!(meta.remote_pubkey, pubkey);
420 assert_eq!(meta.remote_pubkey(), Some(pubkey));
421 let meta = Meta::new(size, addr, port, flags, None);
422 assert_eq!(meta.remote_pubkey, Pubkey::default());
423 assert_eq!(meta.remote_pubkey(), None);
424 }
425}