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}