use std::{fmt::Debug, io};
use bytes::{BufMut, BytesMut};
use netlink_packet_core::{
NetlinkBuffer,
NetlinkDeserializable,
NetlinkMessage,
NetlinkSerializable,
};
pub trait NetlinkMessageCodec {
fn decode<T>(src: &mut BytesMut) -> io::Result<Option<NetlinkMessage<T>>>
where
T: NetlinkDeserializable + Debug;
fn encode<T>(msg: NetlinkMessage<T>, buf: &mut BytesMut) -> io::Result<()>
where
T: NetlinkSerializable + Debug;
}
pub struct NetlinkCodec {
_private: (),
}
impl NetlinkMessageCodec for NetlinkCodec {
fn decode<T>(src: &mut BytesMut) -> io::Result<Option<NetlinkMessage<T>>>
where
T: NetlinkDeserializable + Debug,
{
debug!("NetlinkCodec: decoding next message");
loop {
if src.is_empty() {
trace!("buffer is empty");
return Ok(None);
}
let len = match NetlinkBuffer::new_checked(src.as_ref()) {
Ok(buf) => buf.length() as usize,
Err(e) => {
error!(
"failed to decode datagram, clearing buffer: {:?}: {:#x?}.",
e,
src.as_ref()
);
src.clear();
return Ok(None);
}
};
let bytes = src.split_to(len);
let parsed = NetlinkMessage::<T>::deserialize(&bytes);
match parsed {
Ok(packet) => {
trace!("<<< {:?}", packet);
return Ok(Some(packet));
}
Err(e) => {
error!("failed to decode packet {:#x?}: {}", &bytes, e);
}
}
}
}
fn encode<T>(msg: NetlinkMessage<T>, buf: &mut BytesMut) -> io::Result<()>
where
T: Debug + NetlinkSerializable,
{
let msg_len = msg.buffer_len();
if buf.remaining_mut() < msg_len {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"message is {} bytes, but only {} bytes left in the buffer",
msg_len,
buf.remaining_mut()
),
));
}
let old_len = buf.len();
let new_len = old_len + msg_len;
buf.resize(new_len, 0);
msg.serialize(&mut buf[old_len..][..msg_len]);
trace!(">>> {:?}", msg);
Ok(())
}
}