ringbahn 0.0.0-experimental.3

an experimental safe API for io-uring
Documentation
mod listener;
mod stream;

use std::alloc::{alloc, Layout};
use std::io;
use std::mem;
use std::net::{SocketAddr, ToSocketAddrs};
use std::os::unix::io::RawFd;
use std::ptr;

pub use listener::{TcpListener, Accept, Close, Incoming};
pub use stream::{TcpStream, Connect};

fn socket<A: ToSocketAddrs>(addr: A) -> io::Result<(RawFd, SocketAddr)> {
    use io::{Error, ErrorKind};

    let mut error = Error::new(ErrorKind::InvalidInput, "could not resolve to any addresses");

    for addr in addr.to_socket_addrs()? {
        let domain = match addr.is_ipv6() {
            true    => libc::AF_INET6,
            false   => libc::AF_INET,
        };

        let ty = libc::SOCK_STREAM | libc::SOCK_CLOEXEC;
        let protocol = libc::IPPROTO_TCP;

        match unsafe { libc::socket(domain, ty, protocol) } {
            fd if fd >= 0   => return Ok((fd, addr)),
            _               => error = io::Error::last_os_error(),
        }
    }

    Err(error)
}

pub(crate) unsafe fn addr_from_c(addr: &libc::sockaddr, len: usize) -> io::Result<SocketAddr> {
    match addr.sa_family as libc::c_int {
        libc::AF_INET   => {
            debug_assert!(len >= mem::size_of::<libc::sockaddr_in>());
            Ok(SocketAddr::V4(mem::transmute_copy(addr)))
        }
        libc::AF_INET6  => {
            debug_assert!(len >= mem::size_of::<libc::sockaddr_in6>());
            Ok(SocketAddr::V6(mem::transmute_copy(addr)))
        }
        _               => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid protocol"))
    }
}

pub(crate) fn addr_to_c(addr: SocketAddr) -> (Box<libc::sockaddr_storage>, libc::socklen_t) {
    unsafe {
        match addr {
            SocketAddr::V4(addr)    => {
                let addr: libc::sockaddr_in = mem::transmute(addr);
                let ptr: *mut u8 = alloc(Layout::new::<libc::sockaddr_storage>());
                ptr::write(ptr as *mut libc::sockaddr_in, addr);
                let len = mem::size_of::<libc::sockaddr_in>() as libc::socklen_t;
                (Box::from_raw(ptr as *mut libc::sockaddr_storage), len)
            }
            SocketAddr::V6(addr)    => {
                let addr: libc::sockaddr_in6 = mem::transmute(addr);
                let ptr: *mut u8 = alloc(Layout::new::<libc::sockaddr_storage>());
                ptr::write(ptr as *mut libc::sockaddr_in6, addr);
                let len = mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t;
                (Box::from_raw(ptr as *mut libc::sockaddr_storage), len)
            }
        }
    }
}