summaryrefslogtreecommitdiffstats
path: root/tokio/src/net/unix/listener.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tokio/src/net/unix/listener.rs')
-rw-r--r--tokio/src/net/unix/listener.rs135
1 files changed, 135 insertions, 0 deletions
diff --git a/tokio/src/net/unix/listener.rs b/tokio/src/net/unix/listener.rs
new file mode 100644
index 00000000..3a36dc90
--- /dev/null
+++ b/tokio/src/net/unix/listener.rs
@@ -0,0 +1,135 @@
+use crate::net::unix::UnixStream;
+use crate::net::util::PollEvented;
+
+use futures_core::ready;
+use futures_util::future::poll_fn;
+use mio::Ready;
+use mio_uds;
+use std::convert::TryFrom;
+use std::fmt;
+use std::io;
+use std::os::unix::io::{AsRawFd, RawFd};
+use std::os::unix::net::{self, SocketAddr};
+use std::path::Path;
+use std::task::{Context, Poll};
+
+/// A Unix socket which can accept connections from other Unix sockets.
+pub struct UnixListener {
+ io: PollEvented<mio_uds::UnixListener>,
+}
+
+impl UnixListener {
+ /// Creates a new `UnixListener` bound to the specified path.
+ pub fn bind<P>(path: P) -> io::Result<UnixListener>
+ where
+ P: AsRef<Path>,
+ {
+ let listener = mio_uds::UnixListener::bind(path)?;
+ let io = PollEvented::new(listener)?;
+ Ok(UnixListener { io })
+ }
+
+ /// Consumes a `UnixListener` in the standard library and returns a
+ /// nonblocking `UnixListener` from this crate.
+ ///
+ /// The returned listener will be associated with the given event loop
+ /// specified by `handle` and is ready to perform I/O.
+ pub fn from_std(listener: net::UnixListener) -> io::Result<UnixListener> {
+ let listener = mio_uds::UnixListener::from_listener(listener)?;
+ let io = PollEvented::new(listener)?;
+ Ok(UnixListener { io })
+ }
+
+ /// Returns the local socket address of this listener.
+ pub fn local_addr(&self) -> io::Result<SocketAddr> {
+ self.io.get_ref().local_addr()
+ }
+
+ /// Returns the value of the `SO_ERROR` option.
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ self.io.get_ref().take_error()
+ }
+
+ /// Accepts a new incoming connection to this listener.
+ pub async fn accept(&mut self) -> io::Result<(UnixStream, SocketAddr)> {
+ poll_fn(|cx| self.poll_accept(cx)).await
+ }
+
+ pub(crate) fn poll_accept(
+ &mut self,
+ cx: &mut Context<'_>,
+ ) -> Poll<io::Result<(UnixStream, SocketAddr)>> {
+ let (io, addr) = ready!(self.poll_accept_std(cx))?;
+
+ let io = mio_uds::UnixStream::from_stream(io)?;
+ Ok((UnixStream::new(io)?, addr)).into()
+ }
+
+ fn poll_accept_std(
+ &mut self,
+ cx: &mut Context<'_>,
+ ) -> Poll<io::Result<(net::UnixStream, SocketAddr)>> {
+ ready!(self.io.poll_read_ready(cx, Ready::readable()))?;
+
+ match self.io.get_ref().accept_std() {
+ Ok(None) => {
+ self.io.clear_read_ready(cx, Ready::readable())?;
+ Poll::Pending
+ }
+ Ok(Some((sock, addr))) => Ok((sock, addr)).into(),
+ Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
+ self.io.clear_read_ready(cx, Ready::readable())?;
+ Poll::Pending
+ }
+ Err(err) => Err(err).into(),
+ }
+ }
+
+ /// Consumes this listener, returning a stream of the sockets this listener
+ /// accepts.
+ ///
+ /// This method returns an implementation of the `Stream` trait which
+ /// resolves to the sockets the are accepted on this listener.
+ #[cfg(feature = "async-traits")]
+ pub fn incoming(self) -> super::Incoming {
+ super::Incoming::new(self)
+ }
+}
+
+impl TryFrom<UnixListener> for mio_uds::UnixListener {
+ type Error = io::Error;
+
+ /// Consumes value, returning the mio I/O object.
+ ///
+ /// See [`PollEvented::into_inner`] for more details about
+ /// resource deregistration that happens during the call.
+ ///
+ /// [`PollEvented::into_inner`]: crate::util::PollEvented::into_inner
+ fn try_from(value: UnixListener) -> Result<Self, Self::Error> {
+ value.io.into_inner()
+ }
+}
+
+impl TryFrom<net::UnixListener> for UnixListener {
+ type Error = io::Error;
+
+ /// Consumes stream, returning the tokio I/O object.
+ ///
+ /// This is equivalent to
+ /// [`UnixListener::from_std(stream)`](UnixListener::from_std).
+ fn try_from(stream: net::UnixListener) -> io::Result<Self> {
+ Self::from_std(stream)
+ }
+}
+
+impl fmt::Debug for UnixListener {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.io.get_ref().fmt(f)
+ }
+}
+
+impl AsRawFd for UnixListener {
+ fn as_raw_fd(&self) -> RawFd {
+ self.io.get_ref().as_raw_fd()
+ }
+}