rustunix-socket

How can I create a BufReader and safely continue reading ancillary data from an underlying unix socket?


I'm writing some Rust code where I have a UnixStream socket that I want to receive ancillary messages as well as normal messages.

For the normal messages, it would be useful to use BufReader's convenience functions, like read_line. But I still need to occasionally use the UnixStream socket directly to send or receive ancillary messages.

Is the following code safe or will I lose data?

#![feature(unix_socket_ancillary_data)]
use std::io::BufRead;
use std::io::BufReader;
use std::io::IoSliceMut;
use std::os::unix::net::SocketAncillary;
use std::os::unix::net::UnixStream;

fn main() {
    let mut reader = BufReader::new(UnixStream::connect("/tmp/socket").unwrap());

    // first do some normal reads
    let mut normal_msg = String::new();
    reader.read_line(&mut normal_msg).unwrap();

    // then receive ancillary data
    // see https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.recv_vectored_with_ancillary
    let mut fd_buf = [0; 128];
    let mut ancillary = SocketAncillary::new(&mut fd_buf[..]);
    let mut recv_buf = [0; 128];
    let recv_buf_vector = &mut [IoSliceMut::new(&mut recv_buf[..])][..];

    reader
        .get_ref()
        .recv_vectored_with_ancillary(recv_buf_vector, &mut ancillary)
        .unwrap();
}


Solution

  • Yes, you may lose data that the BufReader prefilled.

    You can access the prefilled data via BufReader::buffer(), but note that coordinating this partially-read data with the to-be-read data may prove challenging.