tokio_uds/
listener.rs

1use {Incoming, UnixStream};
2
3use tokio_reactor::{Handle, PollEvented};
4
5use futures::{Async, Poll};
6use mio::Ready;
7use mio_uds;
8
9use std::fmt;
10use std::io;
11use std::os::unix::io::{AsRawFd, RawFd};
12use std::os::unix::net::{self, SocketAddr};
13use std::path::Path;
14
15/// A Unix socket which can accept connections from other Unix sockets.
16pub struct UnixListener {
17    io: PollEvented<mio_uds::UnixListener>,
18}
19
20impl UnixListener {
21    /// Creates a new `UnixListener` bound to the specified path.
22    pub fn bind<P>(path: P) -> io::Result<UnixListener>
23    where
24        P: AsRef<Path>,
25    {
26        let listener = mio_uds::UnixListener::bind(path)?;
27        let io = PollEvented::new(listener);
28        Ok(UnixListener { io })
29    }
30
31    /// Consumes a `UnixListener` in the standard library and returns a
32    /// nonblocking `UnixListener` from this crate.
33    ///
34    /// The returned listener will be associated with the given event loop
35    /// specified by `handle` and is ready to perform I/O.
36    pub fn from_std(listener: net::UnixListener, handle: &Handle) -> io::Result<UnixListener> {
37        let listener = mio_uds::UnixListener::from_listener(listener)?;
38        let io = PollEvented::new_with_handle(listener, handle)?;
39        Ok(UnixListener { io })
40    }
41
42    /// Returns the local socket address of this listener.
43    pub fn local_addr(&self) -> io::Result<SocketAddr> {
44        self.io.get_ref().local_addr()
45    }
46
47    /// Test whether this socket is ready to be read or not.
48    pub fn poll_read_ready(&self, ready: Ready) -> Poll<Ready, io::Error> {
49        self.io.poll_read_ready(ready)
50    }
51
52    /// Returns the value of the `SO_ERROR` option.
53    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
54        self.io.get_ref().take_error()
55    }
56
57    /// Attempt to accept a connection and create a new connected `UnixStream`
58    /// if successful.
59    ///
60    /// This function will attempt an accept operation, but will not block
61    /// waiting for it to complete. If the operation would block then a "would
62    /// block" error is returned. Additionally, if this method would block, it
63    /// registers the current task to receive a notification when it would
64    /// otherwise not block.
65    ///
66    /// Note that typically for simple usage it's easier to treat incoming
67    /// connections as a `Stream` of `UnixStream`s with the `incoming` method
68    /// below.
69    ///
70    /// # Panics
71    ///
72    /// This function will panic if it is called outside the context of a
73    /// future's task. It's recommended to only call this from the
74    /// implementation of a `Future::poll`, if necessary.
75    pub fn poll_accept(&self) -> Poll<(UnixStream, SocketAddr), io::Error> {
76        let (io, addr) = try_ready!(self.poll_accept_std());
77
78        let io = mio_uds::UnixStream::from_stream(io)?;
79        Ok((UnixStream::new(io), addr).into())
80    }
81
82    /// Attempt to accept a connection and create a new connected `UnixStream`
83    /// if successful.
84    ///
85    /// This function is the same as `poll_accept` above except that it returns a
86    /// `mio_uds::UnixStream` instead of a `tokio_udp::UnixStream`. This in turn
87    /// can then allow for the stream to be associated with a different reactor
88    /// than the one this `UnixListener` is associated with.
89    ///
90    /// This function will attempt an accept operation, but will not block
91    /// waiting for it to complete. If the operation would block then a "would
92    /// block" error is returned. Additionally, if this method would block, it
93    /// registers the current task to receive a notification when it would
94    /// otherwise not block.
95    ///
96    /// Note that typically for simple usage it's easier to treat incoming
97    /// connections as a `Stream` of `UnixStream`s with the `incoming` method
98    /// below.
99    ///
100    /// # Panics
101    ///
102    /// This function will panic if it is called outside the context of a
103    /// future's task. It's recommended to only call this from the
104    /// implementation of a `Future::poll`, if necessary.
105    pub fn poll_accept_std(&self) -> Poll<(net::UnixStream, SocketAddr), io::Error> {
106        loop {
107            try_ready!(self.io.poll_read_ready(Ready::readable()));
108
109            match self.io.get_ref().accept_std() {
110                Ok(None) => {
111                    self.io.clear_read_ready(Ready::readable())?;
112                    return Ok(Async::NotReady);
113                }
114                Ok(Some((sock, addr))) => {
115                    return Ok(Async::Ready((sock, addr)));
116                }
117                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
118                    self.io.clear_read_ready(Ready::readable())?;
119                    return Ok(Async::NotReady);
120                }
121                Err(err) => return Err(err),
122            }
123        }
124    }
125
126    /// Consumes this listener, returning a stream of the sockets this listener
127    /// accepts.
128    ///
129    /// This method returns an implementation of the `Stream` trait which
130    /// resolves to the sockets the are accepted on this listener.
131    pub fn incoming(self) -> Incoming {
132        Incoming::new(self)
133    }
134}
135
136impl fmt::Debug for UnixListener {
137    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138        self.io.get_ref().fmt(f)
139    }
140}
141
142impl AsRawFd for UnixListener {
143    fn as_raw_fd(&self) -> RawFd {
144        self.io.get_ref().as_raw_fd()
145    }
146}