1#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5#[cfg(feature = "frozen-abi")]
6use solana_frozen_abi_macro::{frozen_abi, AbiExample, StableAbi, StableAbiSample};
7#[cfg(feature = "bincode")]
8use {
9 bincode::{Options, Result},
10 std::io::Write,
11};
12use {
13 bitflags::bitflags,
14 solana_pubkey::Pubkey,
15 std::{
16 fmt,
17 net::{IpAddr, Ipv4Addr, SocketAddr},
18 slice::SliceIndex,
19 },
20};
21#[cfg(feature = "wincode")]
22use {
23 core::mem::MaybeUninit,
24 wincode::{
25 config::ConfigCore,
26 io::{Reader, Writer},
27 ReadResult, SchemaRead, SchemaWrite, TypeMeta, WriteResult,
28 },
29};
30#[cfg(feature = "serde")]
31use {
32 serde_derive::{Deserialize, Serialize},
33 serde_with::{serde_as, Bytes},
34};
35
36#[cfg(test)]
37static_assertions::const_assert_eq!(PACKET_DATA_SIZE, 1232);
38pub const PACKET_DATA_SIZE: usize = 1280 - 40 - 8;
43
44#[cfg(feature = "bincode")]
45pub trait Encode {
46 fn encode<W: Write>(&self, writer: W) -> Result<()>;
47}
48
49#[cfg(feature = "bincode")]
50impl<T: ?Sized + serde::Serialize> Encode for T {
51 fn encode<W: Write>(&self, writer: W) -> Result<()> {
52 bincode::serialize_into::<W, T>(writer, self)
53 }
54}
55
56bitflags! {
57 #[repr(C)]
58 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
59 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
60 pub struct PacketFlags: u8 {
61 const DISCARD = 0b0000_0001;
62 const FORWARDED = 0b0000_0010;
63 const REPAIR = 0b0000_0100;
64 const SIMPLE_VOTE_TX = 0b0000_1000;
65 const UNUSED_0 = 0b0001_0000;
67 const UNUSED_1 = 0b0010_0000;
69 const PERF_TRACK_PACKET = 0b0100_0000;
71 const FROM_STAKED_NODE = 0b1000_0000;
73 }
74}
75
76#[cfg_attr(feature = "frozen-abi", derive(AbiExample, StableAbi, StableAbiSample))]
77#[cfg_attr(feature = "wincode", derive(SchemaWrite, SchemaRead))]
78#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
79#[derive(Clone, Debug, PartialEq, Eq)]
80#[repr(C)]
81pub struct Meta {
82 pub size: usize,
83 pub addr: IpAddr,
84 pub port: u16,
85 #[cfg_attr(feature = "wincode", wincode(with = "PodPacketFlags"))]
86 pub flags: PacketFlags,
87 remote_pubkey: Pubkey,
88}
89
90#[cfg(feature = "frozen-abi")]
91impl ::solana_frozen_abi::abi_example::AbiExample for PacketFlags {
92 fn example() -> Self {
93 Self::empty()
94 }
95}
96
97#[cfg(feature = "frozen-abi")]
98impl ::solana_frozen_abi::abi_example::TransparentAsHelper for PacketFlags {}
99
100#[cfg(feature = "frozen-abi")]
101impl ::solana_frozen_abi::abi_example::EvenAsOpaque for PacketFlags {
102 const TYPE_NAME_MATCHER: &'static str = "::_::InternalBitFlags";
103}
104
105#[cfg(feature = "frozen-abi")]
106impl ::solana_frozen_abi::stable_abi::StableAbi for PacketFlags {
107 fn random_with_context(
108 rng: &mut (impl ::solana_frozen_abi::rand::RngCore + ?Sized),
109 _ctx: (),
110 ) -> Self {
111 Self::from_bits_truncate(::solana_frozen_abi::rand::Rng::random(rng))
113 }
114}
115
116#[cfg(feature = "wincode")]
119wincode::pod_wrapper! {
120 unsafe struct PodPacketFlags(PacketFlags);
121}
122
123#[cfg(feature = "wincode")]
127struct LenPrefixedByteArray<const N: usize>;
128
129#[cfg(feature = "wincode")]
130unsafe impl<const N: usize, C: ConfigCore> SchemaWrite<C> for LenPrefixedByteArray<N> {
131 type Src = [u8; N];
132
133 const TYPE_META: TypeMeta = TypeMeta::join_types([
134 <u64 as SchemaWrite<C>>::TYPE_META,
135 <[u8; N] as SchemaWrite<C>>::TYPE_META,
136 ])
137 .keep_zero_copy(false);
138
139 fn size_of(src: &Self::Src) -> WriteResult<usize> {
140 Ok(<u64 as SchemaWrite<C>>::size_of(&(N as u64))?
141 .saturating_add(<[u8; N] as SchemaWrite<C>>::size_of(src)?))
142 }
143
144 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
145 <u64 as SchemaWrite<C>>::write(writer.by_ref(), &(N as u64))?;
146 <[u8; N] as SchemaWrite<C>>::write(writer, src)
147 }
148}
149
150#[cfg(feature = "wincode")]
151unsafe impl<'de, const N: usize, C: ConfigCore> SchemaRead<'de, C> for LenPrefixedByteArray<N> {
152 type Dst = [u8; N];
153
154 const TYPE_META: TypeMeta = TypeMeta::join_types([
155 <u64 as SchemaRead<'de, C>>::TYPE_META,
156 <[u8; N] as SchemaRead<'de, C>>::TYPE_META,
157 ])
158 .keep_zero_copy(false);
159
160 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
161 let len = <u64 as SchemaRead<'de, C>>::get(reader.by_ref())?;
162 if len != N as u64 {
163 return Err(wincode::error::invalid_value(
164 "unexpected packet buffer length",
165 ));
166 }
167 <[u8; N] as SchemaRead<'de, C>>::read(reader, dst)
168 }
169}
170
171#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
200#[cfg_attr(
201 feature = "frozen-abi",
202 derive(AbiExample, StableAbi, StableAbiSample),
203 frozen_abi(
204 abi_digest = "5MtHLJ3g6mJfsz9KfxnUgjksRUXSETinR9jZZiYuE7fh",
205 abi_serializer = ["bincode", "wincode"],
206 test_roundtrip = "eq_and_wire"
207 )
208)]
209#[cfg_attr(feature = "wincode", derive(SchemaWrite, SchemaRead))]
210#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
211#[derive(Clone, Eq)]
212#[repr(C)]
213pub struct Packet {
214 #[cfg_attr(feature = "serde", serde_as(as = "Bytes"))]
217 #[cfg_attr(
218 feature = "wincode",
219 wincode(with = "LenPrefixedByteArray<PACKET_DATA_SIZE>")
220 )]
221 buffer: [u8; PACKET_DATA_SIZE],
222 meta: Meta,
223}
224
225impl Packet {
226 pub fn new(buffer: [u8; PACKET_DATA_SIZE], meta: Meta) -> Self {
227 Self { buffer, meta }
228 }
229
230 #[inline]
236 pub fn data<I>(&self, index: I) -> Option<&<I as SliceIndex<[u8]>>::Output>
237 where
238 I: SliceIndex<[u8]>,
239 {
240 if self.meta.discard() {
244 None
245 } else {
246 self.buffer.get(..self.meta.size)?.get(index)
247 }
248 }
249
250 #[inline]
254 pub fn buffer_mut(&mut self) -> &mut [u8] {
255 debug_assert!(!self.meta.discard());
256 &mut self.buffer[..]
257 }
258
259 #[inline]
260 pub fn meta(&self) -> &Meta {
261 &self.meta
262 }
263
264 #[inline]
265 pub fn meta_mut(&mut self) -> &mut Meta {
266 &mut self.meta
267 }
268
269 #[cfg(feature = "bincode")]
270 pub fn from_data<T: Encode>(dest: Option<&SocketAddr>, data: T) -> Result<Self> {
271 let mut packet = Self::default();
272 Self::populate_packet(&mut packet, dest, &data)?;
273 Ok(packet)
274 }
275
276 #[cfg(feature = "bincode")]
277 pub fn populate_packet<T: Encode>(
278 &mut self,
279 dest: Option<&SocketAddr>,
280 data: &T,
281 ) -> Result<()> {
282 debug_assert!(!self.meta.discard());
283 let mut wr = std::io::Cursor::new(self.buffer_mut());
284 <T as Encode>::encode(data, &mut wr)?;
285 self.meta.size = wr.position() as usize;
286 if let Some(dest) = dest {
287 self.meta.set_socket_addr(dest);
288 }
289 Ok(())
290 }
291
292 #[cfg(feature = "bincode")]
293 pub fn deserialize_slice<T, I>(&self, index: I) -> Result<T>
294 where
295 T: serde::de::DeserializeOwned,
296 I: SliceIndex<[u8], Output = [u8]>,
297 {
298 let bytes = self.data(index).ok_or(bincode::ErrorKind::SizeLimit)?;
299 bincode::options()
300 .with_limit(PACKET_DATA_SIZE as u64)
301 .with_fixint_encoding()
302 .reject_trailing_bytes()
303 .deserialize(bytes)
304 }
305}
306
307impl fmt::Debug for Packet {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 write!(
310 f,
311 "Packet {{ size: {:?}, addr: {:?} }}",
312 self.meta.size,
313 self.meta.socket_addr()
314 )
315 }
316}
317
318impl Default for Packet {
319 fn default() -> Self {
320 Self {
321 buffer: [0; PACKET_DATA_SIZE],
322 meta: Meta::default(),
323 }
324 }
325}
326
327impl PartialEq for Packet {
328 fn eq(&self, other: &Self) -> bool {
329 self.meta() == other.meta() && self.data(..) == other.data(..)
330 }
331}
332
333impl Meta {
334 pub fn new(
335 size: usize,
336 addr: IpAddr,
337 port: u16,
338 flags: PacketFlags,
339 remote_pubkey: Option<Pubkey>,
340 ) -> Self {
341 Self {
342 size,
343 addr,
344 port,
345 flags,
346 remote_pubkey: remote_pubkey.unwrap_or_default(),
347 }
348 }
349
350 pub fn socket_addr(&self) -> SocketAddr {
351 SocketAddr::new(self.addr, self.port)
352 }
353
354 pub fn set_socket_addr(&mut self, socket_addr: &SocketAddr) {
355 self.addr = socket_addr.ip();
356 self.port = socket_addr.port();
357 }
358
359 pub fn set_from_staked_node(&mut self, from_staked_node: bool) {
360 self.flags
361 .set(PacketFlags::FROM_STAKED_NODE, from_staked_node);
362 }
363
364 #[inline]
365 pub fn discard(&self) -> bool {
366 self.flags.contains(PacketFlags::DISCARD)
367 }
368
369 #[inline]
370 pub fn set_discard(&mut self, discard: bool) {
371 self.flags.set(PacketFlags::DISCARD, discard);
372 }
373
374 #[deprecated(since = "4.2.0", note = "Not in use anymore")]
375 #[inline]
376 pub fn set_track_performance(&mut self, is_performance_track: bool) {
377 self.flags
378 .set(PacketFlags::PERF_TRACK_PACKET, is_performance_track);
379 }
380
381 #[inline]
382 pub fn set_simple_vote(&mut self, is_simple_vote: bool) {
383 self.flags.set(PacketFlags::SIMPLE_VOTE_TX, is_simple_vote);
384 }
385
386 #[inline]
387 pub fn forwarded(&self) -> bool {
388 self.flags.contains(PacketFlags::FORWARDED)
389 }
390
391 #[inline]
392 pub fn repair(&self) -> bool {
393 self.flags.contains(PacketFlags::REPAIR)
394 }
395
396 #[inline]
397 pub fn is_simple_vote_tx(&self) -> bool {
398 self.flags.contains(PacketFlags::SIMPLE_VOTE_TX)
399 }
400
401 #[deprecated(since = "4.2.0", note = "Not in use anymore")]
402 #[inline]
403 pub fn is_perf_track_packet(&self) -> bool {
404 self.flags.contains(PacketFlags::PERF_TRACK_PACKET)
405 }
406
407 #[inline]
408 pub fn is_from_staked_node(&self) -> bool {
409 self.flags.contains(PacketFlags::FROM_STAKED_NODE)
410 }
411
412 #[inline]
413 pub fn remote_pubkey(&self) -> Option<Pubkey> {
414 if self.remote_pubkey == Pubkey::default() {
415 None
416 } else {
417 Some(self.remote_pubkey)
418 }
419 }
420
421 #[inline]
423 pub fn set_remote_pubkey(&mut self, pubkey: Pubkey) {
424 self.remote_pubkey = pubkey;
425 }
426}
427
428impl Default for Meta {
429 fn default() -> Self {
430 Self {
431 size: 0,
432 addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
433 port: 0,
434 flags: PacketFlags::empty(),
435 remote_pubkey: Pubkey::default(),
436 }
437 }
438}
439
440#[cfg(test)]
441mod tests {
442 use super::*;
443
444 #[test]
445 fn test_deserialize_slice() {
446 let p = Packet::from_data(None, u32::MAX).unwrap();
447 assert_eq!(p.deserialize_slice(..).ok(), Some(u32::MAX));
448 assert_eq!(p.deserialize_slice(0..4).ok(), Some(u32::MAX));
449 assert_eq!(
450 p.deserialize_slice::<u16, _>(0..4)
451 .map_err(|e| e.to_string()),
452 Err("Slice had bytes remaining after deserialization".to_string()),
453 );
454 assert_eq!(
455 p.deserialize_slice::<u32, _>(0..0)
456 .map_err(|e| e.to_string()),
457 Err("io error: unexpected end of file".to_string()),
458 );
459 assert_eq!(
460 p.deserialize_slice::<u32, _>(0..1)
461 .map_err(|e| e.to_string()),
462 Err("io error: unexpected end of file".to_string()),
463 );
464 assert_eq!(
465 p.deserialize_slice::<u32, _>(0..5)
466 .map_err(|e| e.to_string()),
467 Err("the size limit has been reached".to_string()),
468 );
469 #[allow(clippy::reversed_empty_ranges)]
470 let reversed_empty_range = 4..0;
471 assert_eq!(
472 p.deserialize_slice::<u32, _>(reversed_empty_range)
473 .map_err(|e| e.to_string()),
474 Err("the size limit has been reached".to_string()),
475 );
476 assert_eq!(
477 p.deserialize_slice::<u32, _>(4..5)
478 .map_err(|e| e.to_string()),
479 Err("the size limit has been reached".to_string()),
480 );
481 }
482
483 #[test]
484 fn test_remote_pubkey() {
485 let mut meta = Meta::default();
486 assert!(meta.remote_pubkey().is_none());
487 let pubkey = Pubkey::new_unique();
488 meta.set_remote_pubkey(pubkey);
489 assert_eq!(meta.remote_pubkey(), Some(pubkey));
490 let pubkey = Pubkey::default();
491 meta.set_remote_pubkey(pubkey);
492 assert!(meta.remote_pubkey().is_none());
493 }
494
495 #[test]
496 fn test_meta_new() {
497 let size = 1024;
498 let addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
499 let port = 8080;
500 let flags = PacketFlags::FROM_STAKED_NODE | PacketFlags::REPAIR;
501 let pubkey = Pubkey::new_unique();
502
503 let meta = Meta::new(size, addr, port, flags, Some(pubkey));
504
505 assert_eq!(meta.size, size);
506 assert_eq!(meta.addr, addr);
507 assert_eq!(meta.port, port);
508 assert_eq!(meta.flags, flags);
509 assert_eq!(meta.remote_pubkey, pubkey);
510 assert_eq!(meta.remote_pubkey(), Some(pubkey));
511 let meta = Meta::new(size, addr, port, flags, None);
512 assert_eq!(meta.remote_pubkey, Pubkey::default());
513 assert_eq!(meta.remote_pubkey(), None);
514 }
515}