use std::{error::Error, fmt};
use netlink_packet_core::{
NetlinkDeserializable, NetlinkHeader, NetlinkMessage, NetlinkPayload,
NetlinkSerializable,
};
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PingPongMessage {
Ping(Vec<u8>),
Pong(Vec<u8>),
}
pub const PING_MESSAGE: u16 = 18;
pub const PONG_MESSAGE: u16 = 20;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DeserializeError(&'static str);
impl Error for DeserializeError {
fn description(&self) -> &str {
self.0
}
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
}
impl fmt::Display for DeserializeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl NetlinkDeserializable for PingPongMessage {
type Error = DeserializeError;
fn deserialize(
header: &NetlinkHeader,
payload: &[u8],
) -> Result<Self, Self::Error> {
match header.message_type {
PING_MESSAGE => Ok(PingPongMessage::Ping(payload.to_vec())),
PONG_MESSAGE => Ok(PingPongMessage::Pong(payload.to_vec())),
_ => Err(DeserializeError(
"invalid ping-pong message: invalid message type",
)),
}
}
}
impl NetlinkSerializable for PingPongMessage {
fn message_type(&self) -> u16 {
match self {
PingPongMessage::Ping(_) => PING_MESSAGE,
PingPongMessage::Pong(_) => PONG_MESSAGE,
}
}
fn buffer_len(&self) -> usize {
match self {
PingPongMessage::Ping(vec) | PingPongMessage::Pong(vec) => {
vec.len()
}
}
}
fn serialize(&self, buffer: &mut [u8]) {
match self {
PingPongMessage::Ping(vec) | PingPongMessage::Pong(vec) => {
buffer.copy_from_slice(&vec[..])
}
}
}
}
impl From<PingPongMessage> for NetlinkPayload<PingPongMessage> {
fn from(message: PingPongMessage) -> Self {
NetlinkPayload::InnerMessage(message)
}
}
fn main() {
let ping_pong_message = PingPongMessage::Ping(vec![0, 1, 2, 3]);
let mut packet = NetlinkMessage::from(ping_pong_message);
packet.finalize();
let mut buf = vec![0; packet.header.length as usize];
packet.serialize(&mut buf[..]);
let deserialized_packet =
NetlinkMessage::<PingPongMessage>::deserialize(&buf)
.expect("Failed to deserialize message");
assert_eq!(deserialized_packet, packet);
println!("{packet:?}");
}