1 use crate::io::{Interest, PollEvented}; 2 use crate::net::unix::{SocketAddr, UnixStream}; 3 4 use std::convert::TryFrom; 5 use std::fmt; 6 use std::io; 7 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 8 use std::os::unix::net; 9 use std::path::Path; 10 use std::task::{Context, Poll}; 11 12 cfg_net_unix! { 13 /// A Unix socket which can accept connections from other Unix sockets. 14 /// 15 /// You can accept a new connection by using the [`accept`](`UnixListener::accept`) method. 16 /// 17 /// A `UnixListener` can be turned into a `Stream` with [`UnixListenerStream`]. 18 /// 19 /// [`UnixListenerStream`]: https://docs.rs/tokio-stream/0.1/tokio_stream/wrappers/struct.UnixListenerStream.html 20 /// 21 /// # Errors 22 /// 23 /// Note that accepting a connection can lead to various errors and not all 24 /// of them are necessarily fatal ‒ for example having too many open file 25 /// descriptors or the other side closing the connection while it waits in 26 /// an accept queue. These would terminate the stream if not handled in any 27 /// way. 28 /// 29 /// # Examples 30 /// 31 /// ```no_run 32 /// use tokio::net::UnixListener; 33 /// 34 /// #[tokio::main] 35 /// async fn main() { 36 /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); 37 /// loop { 38 /// match listener.accept().await { 39 /// Ok((stream, _addr)) => { 40 /// println!("new client!"); 41 /// } 42 /// Err(e) => { /* connection failed */ } 43 /// } 44 /// } 45 /// } 46 /// ``` 47 pub struct UnixListener { 48 io: PollEvented<mio::net::UnixListener>, 49 } 50 } 51 52 impl UnixListener { 53 /// Creates a new `UnixListener` bound to the specified path. 54 /// 55 /// # Panics 56 /// 57 /// This function panics if thread-local runtime is not set. 58 /// 59 /// The runtime is usually set implicitly when this function is called 60 /// from a future driven by a tokio runtime, otherwise runtime can be set 61 /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function. bind<P>(path: P) -> io::Result<UnixListener> where P: AsRef<Path>,62 pub fn bind<P>(path: P) -> io::Result<UnixListener> 63 where 64 P: AsRef<Path>, 65 { 66 let listener = mio::net::UnixListener::bind(path)?; 67 let io = PollEvented::new(listener)?; 68 Ok(UnixListener { io }) 69 } 70 71 /// Creates new `UnixListener` from a `std::os::unix::net::UnixListener `. 72 /// 73 /// This function is intended to be used to wrap a UnixListener from the 74 /// standard library in the Tokio equivalent. The conversion assumes 75 /// nothing about the underlying listener; it is left up to the user to set 76 /// it in non-blocking mode. 77 /// 78 /// # Panics 79 /// 80 /// This function panics if thread-local runtime is not set. 81 /// 82 /// The runtime is usually set implicitly when this function is called 83 /// from a future driven by a tokio runtime, otherwise runtime can be set 84 /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function. from_std(listener: net::UnixListener) -> io::Result<UnixListener>85 pub fn from_std(listener: net::UnixListener) -> io::Result<UnixListener> { 86 let listener = mio::net::UnixListener::from_std(listener); 87 let io = PollEvented::new(listener)?; 88 Ok(UnixListener { io }) 89 } 90 91 /// Turns a [`tokio::net::UnixListener`] into a [`std::os::unix::net::UnixListener`]. 92 /// 93 /// The returned [`std::os::unix::net::UnixListener`] will have nonblocking mode 94 /// set as `true`. Use [`set_nonblocking`] to change the blocking mode if needed. 95 /// 96 /// # Examples 97 /// 98 /// ```rust,no_run 99 /// use std::error::Error; 100 /// 101 /// #[tokio::main] 102 /// async fn main() -> Result<(), Box<dyn Error>> { 103 /// let tokio_listener = tokio::net::UnixListener::bind("127.0.0.1:0")?; 104 /// let std_listener = tokio_listener.into_std()?; 105 /// std_listener.set_nonblocking(false)?; 106 /// Ok(()) 107 /// } 108 /// ``` 109 /// 110 /// [`tokio::net::UnixListener`]: UnixListener 111 /// [`std::os::unix::net::UnixListener`]: std::os::unix::net::UnixListener 112 /// [`set_nonblocking`]: fn@std::os::unix::net::UnixListener::set_nonblocking into_std(self) -> io::Result<std::os::unix::net::UnixListener>113 pub fn into_std(self) -> io::Result<std::os::unix::net::UnixListener> { 114 self.io 115 .into_inner() 116 .map(|io| io.into_raw_fd()) 117 .map(|raw_fd| unsafe { net::UnixListener::from_raw_fd(raw_fd) }) 118 } 119 120 /// Returns the local socket address of this listener. local_addr(&self) -> io::Result<SocketAddr>121 pub fn local_addr(&self) -> io::Result<SocketAddr> { 122 self.io.local_addr().map(SocketAddr) 123 } 124 125 /// Returns the value of the `SO_ERROR` option. take_error(&self) -> io::Result<Option<io::Error>>126 pub fn take_error(&self) -> io::Result<Option<io::Error>> { 127 self.io.take_error() 128 } 129 130 /// Accepts a new incoming connection to this listener. 131 /// 132 /// # Cancel safety 133 /// 134 /// This method is cancel safe. If the method is used as the event in a 135 /// [`tokio::select!`](crate::select) statement and some other branch 136 /// completes first, then it is guaranteed that no new connections were 137 /// accepted by this method. accept(&self) -> io::Result<(UnixStream, SocketAddr)>138 pub async fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { 139 let (mio, addr) = self 140 .io 141 .registration() 142 .async_io(Interest::READABLE, || self.io.accept()) 143 .await?; 144 145 let addr = SocketAddr(addr); 146 let stream = UnixStream::new(mio)?; 147 Ok((stream, addr)) 148 } 149 150 /// Polls to accept a new incoming connection to this listener. 151 /// 152 /// If there is no connection to accept, `Poll::Pending` is returned and the 153 /// current task will be notified by a waker. Note that on multiple calls 154 /// to `poll_accept`, only the `Waker` from the `Context` passed to the most 155 /// recent call is scheduled to receive a wakeup. poll_accept(&self, cx: &mut Context<'_>) -> Poll<io::Result<(UnixStream, SocketAddr)>>156 pub fn poll_accept(&self, cx: &mut Context<'_>) -> Poll<io::Result<(UnixStream, SocketAddr)>> { 157 let (sock, addr) = ready!(self.io.registration().poll_read_io(cx, || self.io.accept()))?; 158 let addr = SocketAddr(addr); 159 let sock = UnixStream::new(sock)?; 160 Poll::Ready(Ok((sock, addr))) 161 } 162 } 163 164 impl TryFrom<std::os::unix::net::UnixListener> for UnixListener { 165 type Error = io::Error; 166 167 /// Consumes stream, returning the tokio I/O object. 168 /// 169 /// This is equivalent to 170 /// [`UnixListener::from_std(stream)`](UnixListener::from_std). try_from(stream: std::os::unix::net::UnixListener) -> io::Result<Self>171 fn try_from(stream: std::os::unix::net::UnixListener) -> io::Result<Self> { 172 Self::from_std(stream) 173 } 174 } 175 176 impl fmt::Debug for UnixListener { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 178 self.io.fmt(f) 179 } 180 } 181 182 impl AsRawFd for UnixListener { as_raw_fd(&self) -> RawFd183 fn as_raw_fd(&self) -> RawFd { 184 self.io.as_raw_fd() 185 } 186 } 187