Packet::from_data is ignoring serialization errors:
https://github.com/solana-labs/solana/blob/d08c3232e/sdk/src/packet.rs#L42-L48
This is likely never useful as the packet will be sent over the wire
taking bandwidth but at the receiving end will either fail to
deserialize or it will be invalid.
This commit will propagate the errors out of the function to the
call-site, allowing the call-site to handle the error.
(cherry picked from commit 73ac104df2
)
Co-authored-by: behzad nouri <behzadnouri@gmail.com>
131 lines
3.5 KiB
Rust
131 lines
3.5 KiB
Rust
use crate::clock::Slot;
|
|
use bincode::Result;
|
|
use serde::Serialize;
|
|
use std::{
|
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
|
{fmt, io},
|
|
};
|
|
|
|
/// Maximum over-the-wire size of a Transaction
|
|
/// 1280 is IPv6 minimum MTU
|
|
/// 40 bytes is the size of the IPv6 header
|
|
/// 8 bytes is the size of the fragment header
|
|
pub const PACKET_DATA_SIZE: usize = 1280 - 40 - 8;
|
|
|
|
#[frozen_abi(digest = "9AiPd36yycNg18hDuCBVGwpTfzjX1VV4QtUKUdqeyAKH")]
|
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, AbiExample)]
|
|
#[repr(C)]
|
|
pub struct Meta {
|
|
pub size: usize,
|
|
pub forward: bool,
|
|
pub repair: bool,
|
|
pub discard: bool,
|
|
pub addr: [u16; 8],
|
|
pub port: u16,
|
|
pub v6: bool,
|
|
pub seed: [u8; 32],
|
|
pub slot: Slot,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
#[repr(C)]
|
|
pub struct Packet {
|
|
pub data: [u8; PACKET_DATA_SIZE],
|
|
pub meta: Meta,
|
|
}
|
|
|
|
impl Packet {
|
|
pub fn new(data: [u8; PACKET_DATA_SIZE], meta: Meta) -> Self {
|
|
Self { data, meta }
|
|
}
|
|
|
|
pub fn from_data<T: Serialize>(dest: &SocketAddr, data: T) -> Result<Self> {
|
|
let mut packet = Packet::default();
|
|
Self::populate_packet(&mut packet, Some(dest), &data)?;
|
|
Ok(packet)
|
|
}
|
|
|
|
pub fn populate_packet<T: Serialize>(
|
|
packet: &mut Packet,
|
|
dest: Option<&SocketAddr>,
|
|
data: &T,
|
|
) -> Result<()> {
|
|
let mut wr = io::Cursor::new(&mut packet.data[..]);
|
|
bincode::serialize_into(&mut wr, data)?;
|
|
let len = wr.position() as usize;
|
|
packet.meta.size = len;
|
|
if let Some(dest) = dest {
|
|
packet.meta.set_addr(dest);
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for Packet {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"Packet {{ size: {:?}, addr: {:?} }}",
|
|
self.meta.size,
|
|
self.meta.addr()
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Default for Packet {
|
|
fn default() -> Packet {
|
|
Packet {
|
|
data: unsafe { std::mem::MaybeUninit::uninit().assume_init() },
|
|
meta: Meta::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Packet {
|
|
fn eq(&self, other: &Packet) -> bool {
|
|
let self_data: &[u8] = self.data.as_ref();
|
|
let other_data: &[u8] = other.data.as_ref();
|
|
self.meta == other.meta && self_data[..self.meta.size] == other_data[..other.meta.size]
|
|
}
|
|
}
|
|
|
|
impl Meta {
|
|
pub fn addr(&self) -> SocketAddr {
|
|
if !self.v6 {
|
|
let addr = [
|
|
self.addr[0] as u8,
|
|
self.addr[1] as u8,
|
|
self.addr[2] as u8,
|
|
self.addr[3] as u8,
|
|
];
|
|
let ipv4: Ipv4Addr = From::<[u8; 4]>::from(addr);
|
|
SocketAddr::new(IpAddr::V4(ipv4), self.port)
|
|
} else {
|
|
let ipv6: Ipv6Addr = From::<[u16; 8]>::from(self.addr);
|
|
SocketAddr::new(IpAddr::V6(ipv6), self.port)
|
|
}
|
|
}
|
|
|
|
pub fn set_addr(&mut self, a: &SocketAddr) {
|
|
match *a {
|
|
SocketAddr::V4(v4) => {
|
|
let ip = v4.ip().octets();
|
|
self.addr[0] = u16::from(ip[0]);
|
|
self.addr[1] = u16::from(ip[1]);
|
|
self.addr[2] = u16::from(ip[2]);
|
|
self.addr[3] = u16::from(ip[3]);
|
|
self.addr[4] = 0;
|
|
self.addr[5] = 0;
|
|
self.addr[6] = 0;
|
|
self.addr[7] = 0;
|
|
self.v6 = false;
|
|
}
|
|
SocketAddr::V6(v6) => {
|
|
self.addr = v6.ip().segments();
|
|
self.v6 = true;
|
|
}
|
|
}
|
|
self.port = a.port();
|
|
}
|
|
}
|