[][src]Struct interprocess::os::unix::udsocket::UdStreamListener

pub struct UdStreamListener { /* fields omitted */ }

A Unix domain byte stream socket server, listening for connections.

All such sockets have the SOCK_STREAM socket type; in other words, this is the Unix domain version of a TCP server.

Examples

Basic server:

use interprocess::os::unix::udsocket::{UdStream, UdStreamListener};
use std::io::{self, prelude::*};

fn handle_error(result: io::Result<UdStream>) -> Option<UdStream> {
    match result {
        Ok(val) => Some(val),
        Err(error) => {
            eprintln!("There was an error with an incoming connection: {}", error);
            None
        }
    }
}

let listener = UdStreamListener::bind("/tmp/example.sock")?;
for mut connection in listener.incoming()
    // Use filter_map to report all errors with connections and skip those connections in the loop,
    // making the actual server loop part much cleaner than if it contained error handling as well.
    .filter_map(handle_error) {
    connection.write_all(b"Hello from server!");
    let mut input_string = String::new();
    connection.read_to_string(&mut input_string);
    println!("Client answered: {}", input_string);
}

Sending and receiving ancillary data:

use interprocess::{
    unnamed_pipe::{pipe, UnnamedPipeReader},
    os::unix::udsocket::{UdStreamListener, UdStream, AncillaryData, AncillaryDataBuf},
};
use std::{
    io::{self, prelude::*},
    fs,
    iter,
    borrow::Cow,
    os::unix::io::{FromRawFd, IntoRawFd},
};

fn handle_error(result: io::Result<UdStream>) -> Option<UdStream> {
    match result {
        Ok(val) => Some(val),
        Err(error) => {
            eprintln!("There was an error with an incoming connection: {}", error);
            None
        }
    }
}

let listener = UdStreamListener::bind("/tmp/example.sock")?;

// Allocate a sufficient buffer for receiving ancillary data.
let mut ancillary_buffer = AncillaryDataBuf::owned_with_capacity(
    AncillaryData::ENCODED_SIZE_OF_CREDENTIALS
  + AncillaryData::encoded_size_of_file_descriptors(1),
);
// Prepare valid credentials.
let credentials = AncillaryData::credentials();

for mut connection in listener.incoming()
    .filter_map(handle_error) {
    // Create the file descriptor which we will be sending.
    let (own_fd, fd_to_send) = pipe()?;
    // Borrow the file descriptor in a slice right away to send it later.
    let fds = [fd_to_send.into_raw_fd()];
    let fd_ancillary = AncillaryData::FileDescriptors(
        Cow::Borrowed(&fds),
    );
     
    connection.send_ancillary(
        b"File descriptor and credentials from the server!",
        iter::once(fd_ancillary),
    );
     
    // The receive buffer size depends on the situation, but since this example
    // mirrors the second one from UdSocket, 64 is sufficient.
    let mut recv_buffer = [0; 64];
    connection.recv_ancillary(
        &mut recv_buffer,
        &mut ancillary_buffer,
    );
     
    println!("Client answered: {}", String::from_utf8_lossy(&recv_buffer));
 
    // Decode the received ancillary data.
    let (mut file_descriptors, mut cred) = (None, None);
    for element in ancillary_buffer.decode() {
        match element {
            AncillaryData::FileDescriptors(fds) => file_descriptors = Some(fds),
            AncillaryData::Credentials {pid, uid, gid} => cred = Some((pid, uid, gid)),
        }
    }
    let mut files = Vec::new();
    if let Some(fds) = file_descriptors {
        // There is a possibility that zero file descriptors were sent — let's account for that.
        for fd in fds.iter().copied() {
            // This is normally unsafe, but since we know that the descriptor is not owned somewhere
            // else in the current process, it's fine to do this:
            let file = unsafe {fs::File::from_raw_fd(fd)};
            files.push(file);
        }
    }
    for mut file in files {
        file.write(b"Hello foreign file descriptor!");
    }
    if let Some(credentials) = cred {
        println!("Client\tPID: {}", credentials.0);
        println!(      "\tUID: {}", credentials.1);
        println!(      "\tGID: {}", credentials.2);
    }
}

Implementations

impl UdStreamListener[src]

pub fn bind<'a>(path: impl ToUdSocketPath<'a>) -> Result<Self>[src]

Creates a new listener socket at the specified address.

If the socket path exceeds the maximum socket path length (which includes the first 0 byte when using the socket namespace), an error is returned. Errors can also be produced for different reasons, i.e. errors should always be handled regardless of whether the path is known to be short enough or not.

Example

See ToUdSocketPath.

System calls

  • socket
  • bind

pub fn accept(&self) -> Result<UdStream>[src]

Listens for incoming connections to the socket, blocking until a client is connected.

See incoming for a convenient way to create a main loop for a server.

Example

use interprocess::os::unix::udsocket::UdStreamListener;

let listener = UdStreamListener::bind("/tmp/example.sock")?;
loop {
    match listener.accept() {
        Ok(connection) => {
            println!("New client!");
        },
        Err(error) => {
            println!("Incoming connection failed: {}", error);
        },
    }
}

System calls

  • accept

pub fn incoming(&self) -> Incoming<'_>

Notable traits for Incoming<'a>

impl<'a> Iterator for Incoming<'a> type Item = Result<UdStream>;
[src]

Creates an infinite iterator which calls accept() with each iteration. Used together with for loops to conveniently create a main loop for a socket server.

Example

use interprocess::os::unix::udsocket::UdStreamListener;

let listener = UdStreamListener::bind("/tmp/example.sock")?;
// Thanks to incoming(), you get a simple self-documenting infinite server loop
for connection in listener.incoming()
    .map(|conn| if let Err(error) = conn {
        eprintln!("Incoming connection failed: {}", error);
    }) {
    eprintln!("New client!");
}

Trait Implementations

impl AsRawFd for UdStreamListener[src]

impl Debug for UdStreamListener[src]

impl<'a> From<&'a UdStreamListener> for Incoming<'a>[src]

impl FromRawFd for UdStreamListener[src]

impl IntoRawFd for UdStreamListener[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.