little-dude / netlink

netlink libraries for rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

netlink-sys: Async sockets don't return bytes received

jordanisaacs opened this issue · comments

Is there a reason async sockets don't return the bytes received when calling recv using the extended traits? See the here.

I am trying to adapt this code to be async which utilizes the bytes received. I am new to socket programming so forgive me if there is something I am missing.

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!