mio_uds/
listener.rs

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