netlink-sys: Async sockets don't return bytes received
jordanisaacs opened this issue · comments
See https://docs.rs/netlink-sys/0.8.2/netlink_sys/trait.AsyncSocket.html#tymethod.poll_recv
the buffer will have advanced by the amount read
You probably should just use bytes::BytesMut
, as is done in the audit netlink-sys example.
The idea is that you need a "buffer type" that knows the length of initialized bytes if you don't want to initialize the buffer to read into - at least in a non-unsafe
interface. To make sure one doesn't use ugly (unsafe/UB) workarounds the length is only returned through the buffer (i.e. the type implementing bytes::BufMut
).
The standard library is working on a similar concept std::io::ReadBuf
.
Ah that makes sense. I saw the comment about the buffer advancement but didn't understand how I could retrieve the information. So from my understanding this would be the preferred version:
let mut responses = vec![];
let mut buf = bytes::BytesMut::with_capacity(MAX_NETLINK_BUFFER_LENGTH);
loop {
buf.clear();
socket.recv(&mut buf).await?;
let mut offset = 0;
loop {
let bytes = &buf[offset..];
let response = NetlinkMessage::<I>::deserialize(bytes)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
match response.payload {
NetlinkPayload::Ack(_) | NetlinkPayload::Done => return Ok(responses),
NetlinkPayload::Error(e) => return Err(e.into()),
_ => (),
}
responses.push(response.clone());
offset += response.header.length as usize;
if offset == buf.len() || response.header.length == 0 {
// Fully parsed the datagram, but there may be more datagrams
// with additional netlink response parts
break;
}
}
}
Not quite sure whether I'd trust offset not to grow beyond buf.len()
- I'd probably check offset >= buf.len()
instead, but looking good regarding the buffer handling otherwise, yes.
Great thanks for the help!