use std::cmp;
use std::io;
use std::io::prelude::*;
use std::net::Shutdown;
use std::os::unix::net;
use std::os::unix::prelude::*;
use std::path::Path;
use crate::event::Evented;
use crate::unix::EventedFd;
use crate::{Poll, PollOpt, Ready, Token};
use iovec::{
unix::{as_os_slice, as_os_slice_mut},
IoVec,
};
use crate::socket::{sockaddr_un, Socket};
fn cvt(i: libc::c_int) -> io::Result<libc::c_int> {
if i == -1 {
Err(io::Error::last_os_error())
} else {
Ok(i)
}
}
#[derive(Debug)]
pub struct UnixStream {
inner: net::UnixStream,
}
impl UnixStream {
pub fn connect<P: AsRef<Path>>(p: P) -> io::Result<UnixStream> {
UnixStream::_connect(p.as_ref())
}
fn _connect(path: &Path) -> io::Result<UnixStream> {
unsafe {
let (addr, len) = sockaddr_un(path)?;
let socket = Socket::new(libc::SOCK_STREAM)?;
let addr = &addr as *const _ as *const _;
match cvt(libc::connect(socket.fd(), addr, len)) {
Ok(_) => {}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
Err(e) => return Err(e),
}
Ok(UnixStream::from_raw_fd(socket.into_fd()))
}
}
pub fn from_stream(stream: net::UnixStream) -> io::Result<UnixStream> {
stream.set_nonblocking(true)?;
Ok(UnixStream { inner: stream })
}
pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
Socket::pair(libc::SOCK_STREAM).map(|(a, b)| unsafe {
(
UnixStream::from_raw_fd(a.into_fd()),
UnixStream::from_raw_fd(b.into_fd()),
)
})
}
pub fn try_clone(&self) -> io::Result<UnixStream> {
self.inner.try_clone().map(|s| UnixStream { inner: s })
}
pub fn local_addr(&self) -> io::Result<net::SocketAddr> {
self.inner.local_addr()
}
pub fn peer_addr(&self) -> io::Result<net::SocketAddr> {
self.inner.peer_addr()
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.inner.take_error()
}
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.inner.shutdown(how)
}
pub fn read_bufs(&self, bufs: &mut [&mut IoVec]) -> io::Result<usize> {
unsafe {
let slice = as_os_slice_mut(bufs);
let len = cmp::min(<libc::c_int>::MAX as usize, slice.len());
let rc =
libc::readv(self.inner.as_raw_fd(), slice.as_ptr(), len as libc::c_int);
if rc < 0 {
Err(io::Error::last_os_error())
} else {
Ok(rc as usize)
}
}
}
pub fn write_bufs(&self, bufs: &[&IoVec]) -> io::Result<usize> {
unsafe {
let slice = as_os_slice(bufs);
let len = cmp::min(<libc::c_int>::MAX as usize, slice.len());
let rc =
libc::writev(self.inner.as_raw_fd(), slice.as_ptr(), len as libc::c_int);
if rc < 0 {
Err(io::Error::last_os_error())
} else {
Ok(rc as usize)
}
}
}
}
impl Evented for UnixStream {
fn register(
&self,
poll: &Poll,
token: Token,
events: Ready,
opts: PollOpt,
) -> io::Result<()> {
EventedFd(&self.as_raw_fd()).register(poll, token, events, opts)
}
fn reregister(
&self,
poll: &Poll,
token: Token,
events: Ready,
opts: PollOpt,
) -> io::Result<()> {
EventedFd(&self.as_raw_fd()).reregister(poll, token, events, opts)
}
fn deregister(&self, poll: &Poll) -> io::Result<()> {
EventedFd(&self.as_raw_fd()).deregister(poll)
}
}
impl Read for UnixStream {
fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
self.inner.read(bytes)
}
}
impl Read for &UnixStream {
fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
(&self.inner).read(bytes)
}
}
impl Write for UnixStream {
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
self.inner.write(bytes)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}
impl Write for &UnixStream {
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
(&self.inner).write(bytes)
}
fn flush(&mut self) -> io::Result<()> {
(&self.inner).flush()
}
}
impl AsRawFd for UnixStream {
fn as_raw_fd(&self) -> i32 {
self.inner.as_raw_fd()
}
}
impl IntoRawFd for UnixStream {
fn into_raw_fd(self) -> i32 {
self.inner.into_raw_fd()
}
}
impl FromRawFd for UnixStream {
unsafe fn from_raw_fd(fd: i32) -> UnixStream {
UnixStream {
inner: net::UnixStream::from_raw_fd(fd),
}
}
}