mio_uds/listener.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
use std::io;
use std::os::unix::net;
use std::os::unix::prelude::*;
use std::path::Path;
use libc;
use mio::event::Evented;
use mio::unix::EventedFd;
use mio::{Poll, PollOpt, Ready, Token};
use UnixStream;
use cvt;
use socket::{sockaddr_un, Socket};
/// A structure representing a Unix domain socket server.
///
/// This listener can be used to accept new streams connected to a remote
/// endpoint, through which the `read` and `write` methods can be used to
/// communicate.
#[derive(Debug)]
pub struct UnixListener {
inner: net::UnixListener,
}
impl UnixListener {
/// Creates a new `UnixListener` bound to the specified socket.
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
UnixListener::_bind(path.as_ref())
}
fn _bind(path: &Path) -> io::Result<UnixListener> {
unsafe {
let (addr, len) = try!(sockaddr_un(path));
let fd = try!(Socket::new(libc::SOCK_STREAM));
let addr = &addr as *const _ as *const _;
try!(cvt(libc::bind(fd.fd(), addr, len)));
try!(cvt(libc::listen(fd.fd(), 128)));
Ok(UnixListener::from_raw_fd(fd.into_fd()))
}
}
/// Consumes a standard library `UnixListener` and returns a wrapped
/// `UnixListener` compatible with mio.
///
/// The returned stream is moved into nonblocking mode and is otherwise
/// ready to get associated with an event loop.
pub fn from_listener(stream: net::UnixListener) -> io::Result<UnixListener> {
try!(stream.set_nonblocking(true));
Ok(UnixListener { inner: stream })
}
/// Accepts a new incoming connection to this listener.
///
/// When established, the corresponding `UnixStream` and the remote peer's
/// address will be returned as `Ok(Some(...))`. If there is no connection
/// waiting to be accepted, then `Ok(None)` is returned.
///
/// If an error happens while accepting, `Err` is returned.
pub fn accept(&self) -> io::Result<Option<(UnixStream, net::SocketAddr)>> {
match try!(self.accept_std()) {
Some((stream, addr)) => Ok(Some((UnixStream::from_stream(stream)?, addr))),
None => Ok(None),
}
}
/// Accepts a new incoming connection to this listener.
///
/// This method is the same as `accept`, except that it returns a `net::UnixStream` *in blocking mode*
/// which isn't bound to a `mio` type. This can later be converted to a `mio` type, if
/// necessary.
///
/// If an error happens while accepting, `Err` is returned.
pub fn accept_std(&self) -> io::Result<Option<(net::UnixStream, net::SocketAddr)>> {
match self.inner.accept() {
Ok((socket, addr)) => Ok(Some(unsafe {
(net::UnixStream::from_raw_fd(socket.into_raw_fd()), addr)
})),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Ok(None),
Err(e) => Err(e),
}
}
/// Creates a new independently owned handle to the underlying socket.
///
/// The returned `UnixListener` is a reference to the same socket that this
/// object references. Both handles can be used to accept incoming
/// connections and options set on one listener will affect the other.
pub fn try_clone(&self) -> io::Result<UnixListener> {
self.inner.try_clone().map(|l| UnixListener { inner: l })
}
/// Returns the local socket address of this listener.
pub fn local_addr(&self) -> io::Result<net::SocketAddr> {
self.inner.local_addr()
}
/// Returns the value of the `SO_ERROR` option.
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.inner.take_error()
}
}
impl Evented for UnixListener {
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 AsRawFd for UnixListener {
fn as_raw_fd(&self) -> i32 {
self.inner.as_raw_fd()
}
}
impl IntoRawFd for UnixListener {
fn into_raw_fd(self) -> i32 {
self.inner.into_raw_fd()
}
}
impl FromRawFd for UnixListener {
unsafe fn from_raw_fd(fd: i32) -> UnixListener {
UnixListener {
inner: net::UnixListener::from_raw_fd(fd),
}
}
}