Skip to main content

std/os/windows/net/
listener.rs

1#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")]
2use crate::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
3use crate::os::windows::net::{SocketAddr, UnixStream};
4use crate::path::Path;
5#[cfg(not(doc))]
6use crate::sys::c::{AF_UNIX, SOCK_STREAM, SOCKADDR_UN, bind, getsockname, listen};
7use crate::sys::net::Socket;
8#[cfg(not(doc))]
9use crate::sys::winsock::startup;
10use crate::sys::{AsInner, cvt_nz};
11use crate::{fmt, io};
12
13/// A structure representing a Unix domain socket server.
14///
15/// Under Windows, it will only work starting from Windows 10 17063.
16///
17/// # Examples
18///
19/// ```no_run
20/// #![feature(windows_unix_domain_sockets)]
21/// use std::thread;
22/// use std::os::windows::net::{UnixStream, UnixListener};
23///
24/// fn handle_client(stream: UnixStream) {
25///     // ...
26/// }
27///
28/// fn main() -> std::io::Result<()> {
29///     let listener = UnixListener::bind("/path/to/the/socket")?;
30///
31///     // accept connections and process them, spawning a new thread for each one
32///     for stream in listener.incoming() {
33///         match stream {
34///             Ok(stream) => {
35///                 /* connection succeeded */
36///                 thread::spawn(|| handle_client(stream));
37///             }
38///             Err(err) => {
39///                 /* connection failed */
40///                 break;
41///             }
42///         }
43///     }
44///     Ok(())
45/// }
46/// ```
47pub struct UnixListener(Socket);
48
49impl fmt::Debug for UnixListener {
50    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
51        let mut builder = fmt.debug_struct("UnixListener");
52        builder.field("sock", self.0.as_inner());
53        if let Ok(addr) = self.local_addr() {
54            builder.field("local", &addr);
55        }
56        builder.finish()
57    }
58}
59impl UnixListener {
60    /// Creates a new `UnixListener` bound to the specified socket.
61    ///
62    /// # Examples
63    ///
64    /// ```no_run
65    /// #![feature(windows_unix_domain_sockets)]
66    /// use std::os::windows::net::UnixListener;
67    ///
68    /// let listener = match UnixListener::bind("/path/to/the/socket") {
69    ///     Ok(sock) => sock,
70    ///     Err(e) => {
71    ///         println!("Couldn't connect: {e:?}");
72    ///         return
73    ///     }
74    /// };
75    /// ```
76    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
77        let socket_addr = SocketAddr::from_pathname(path)?;
78        Self::bind_addr(&socket_addr)
79    }
80
81    /// Creates a new `UnixListener` bound to the specified [`socket address`].
82    ///
83    /// [`socket address`]: crate::os::windows::net::SocketAddr
84    ///
85    /// # Examples
86    ///
87    /// ```no_run
88    /// #![feature(windows_unix_domain_sockets)]
89    /// use std::os::windows::net::{UnixListener};
90    ///
91    /// fn main() -> std::io::Result<()> {
92    ///     let listener1 = UnixListener::bind("path/to/socket")?;
93    ///     let addr = listener1.local_addr()?;
94    ///
95    ///     let listener2 = match UnixListener::bind_addr(&addr) {
96    ///         Ok(sock) => sock,
97    ///         Err(err) => {
98    ///             println!("Couldn't bind: {err:?}");
99    ///             return Err(err);
100    ///         }
101    ///     };
102    ///     Ok(())
103    /// }
104    /// ```
105    pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> {
106        startup();
107        let inner = Socket::new(AF_UNIX as _, SOCK_STREAM)?;
108        unsafe {
109            cvt_nz(bind(inner.as_raw(), &raw const socket_addr.addr as _, socket_addr.len as _))?;
110            cvt_nz(listen(inner.as_raw(), 128))?;
111        }
112        Ok(UnixListener(inner))
113    }
114
115    /// Accepts a new incoming connection to this listener.
116    ///
117    /// This function will block the calling thread until a new Unix connection
118    /// is established. When established, the corresponding [`UnixStream`] and
119    /// the remote peer's address will be returned.
120    ///
121    /// [`UnixStream`]: crate::os::windows::net::UnixStream
122    ///
123    /// # Examples
124    ///
125    /// ```no_run
126    /// #![feature(windows_unix_domain_sockets)]
127    /// use std::os::windows::net::UnixListener;
128    ///
129    /// fn main() -> std::io::Result<()> {
130    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
131    ///
132    ///     match listener.accept() {
133    ///         Ok((socket, addr)) => println!("Got a client: {addr:?}"),
134    ///         Err(e) => println!("accept function failed: {e:?}"),
135    ///     }
136    ///     Ok(())
137    /// }
138    /// ```
139    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
140        let mut storage = SOCKADDR_UN::default();
141        let mut len = size_of::<SOCKADDR_UN>() as _;
142        let inner = self.0.accept(&raw mut storage as *mut _, &raw mut len)?;
143        let addr = SocketAddr::from_parts(storage, len)?;
144        Ok((UnixStream(inner), addr))
145    }
146
147    /// Returns the local socket address of this listener.
148    ///
149    /// # Examples
150    ///
151    /// ```no_run
152    /// #![feature(windows_unix_domain_sockets)]
153    /// use std::os::windows::net::UnixListener;
154    ///
155    /// fn main() -> std::io::Result<()> {
156    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
157    ///     let addr = listener.local_addr().expect("Couldn't get local address");
158    ///     Ok(())
159    /// }
160    /// ```
161    pub fn local_addr(&self) -> io::Result<SocketAddr> {
162        SocketAddr::new(|addr, len| unsafe { getsockname(self.0.as_raw(), addr, len) })
163    }
164
165    /// Creates a new independently owned handle to the underlying socket.
166    ///
167    /// The returned `UnixListener` is a reference to the same socket that this
168    /// object references. Both handles can be used to accept incoming
169    /// connections and options set on one listener will affect the other.
170    ///
171    /// # Examples
172    ///
173    /// ```no_run
174    /// #![feature(windows_unix_domain_sockets)]
175    /// use std::os::windows::net::UnixListener;
176    ///
177    /// fn main() -> std::io::Result<()> {
178    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
179    ///     let listener_copy = listener.try_clone().expect("try_clone failed");
180    ///     Ok(())
181    /// }
182    /// ```
183    pub fn try_clone(&self) -> io::Result<UnixListener> {
184        self.0.duplicate().map(UnixListener)
185    }
186
187    /// Moves the socket into or out of nonblocking mode.
188    ///
189    /// This will result in the `accept` operation becoming nonblocking,
190    /// i.e., immediately returning from their calls. If the IO operation is
191    /// successful, `Ok` is returned and no further action is required. If the
192    /// IO operation could not be completed and needs to be retried, an error
193    /// with kind [`io::ErrorKind::WouldBlock`] is returned.
194    ///
195    /// # Examples
196    ///
197    /// ```no_run
198    /// #![feature(windows_unix_domain_sockets)]
199    /// use std::os::windows::net::UnixListener;
200    ///
201    /// fn main() -> std::io::Result<()> {
202    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
203    ///     listener.set_nonblocking(true).expect("Couldn't set non blocking");
204    ///     Ok(())
205    /// }
206    /// ```
207    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
208        self.0.set_nonblocking(nonblocking)
209    }
210
211    /// Returns the value of the `SO_ERROR` option.
212    ///
213    /// # Examples
214    ///
215    /// ```no_run
216    /// #![feature(windows_unix_domain_sockets)]
217    /// use std::os::windows::net::UnixListener;
218    ///
219    /// fn main() -> std::io::Result<()> {
220    ///     let listener = UnixListener::bind("/tmp/sock")?;
221    ///
222    ///     if let Ok(Some(err)) = listener.take_error() {
223    ///         println!("Got error: {err:?}");
224    ///     }
225    ///     Ok(())
226    /// }
227    /// ```
228    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
229        self.0.take_error()
230    }
231
232    /// Returns an iterator over incoming connections.
233    ///
234    /// The iterator will never return [`None`] and will also not yield the
235    /// peer's [`SocketAddr`] structure.
236    ///
237    /// # Examples
238    ///
239    /// ```no_run
240    /// #![feature(windows_unix_domain_sockets)]
241    /// use std::thread;
242    /// use std::os::windows::net::{UnixStream, UnixListener};
243    ///
244    /// fn handle_client(stream: UnixStream) {
245    ///     // ...
246    /// }
247    ///
248    /// fn main() -> std::io::Result<()> {
249    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
250    ///
251    ///     for stream in listener.incoming() {
252    ///         match stream {
253    ///             Ok(stream) => {
254    ///                 thread::spawn(|| handle_client(stream));
255    ///             }
256    ///             Err(err) => {
257    ///                 break;
258    ///             }
259    ///         }
260    ///     }
261    ///     Ok(())
262    /// }
263    /// ```
264    pub fn incoming(&self) -> Incoming<'_> {
265        Incoming { listener: self }
266    }
267}
268
269/// An iterator over incoming connections to a [`UnixListener`].
270///
271/// It will never return [`None`].
272///
273/// # Examples
274///
275/// ```no_run
276/// #![feature(windows_unix_domain_sockets)]
277/// use std::thread;
278/// use std::os::windows::net::{UnixStream, UnixListener};
279///
280/// fn handle_client(stream: UnixStream) {
281///     // ...
282/// }
283///
284/// fn main() -> std::io::Result<()> {
285///     let listener = UnixListener::bind("/path/to/the/socket")?;
286///
287///     for stream in listener.incoming() {
288///         match stream {
289///             Ok(stream) => {
290///                 thread::spawn(|| handle_client(stream));
291///             }
292///             Err(err) => {
293///                 break;
294///             }
295///         }
296///     }
297///     Ok(())
298/// }
299/// ```
300pub struct Incoming<'a> {
301    listener: &'a UnixListener,
302}
303
304impl<'a> Iterator for Incoming<'a> {
305    type Item = io::Result<UnixStream>;
306
307    fn next(&mut self) -> Option<io::Result<UnixStream>> {
308        Some(self.listener.accept().map(|s| s.0))
309    }
310
311    fn size_hint(&self) -> (usize, Option<usize>) {
312        (usize::MAX, None)
313    }
314}
315
316impl AsRawSocket for UnixListener {
317    #[inline]
318    fn as_raw_socket(&self) -> RawSocket {
319        self.0.as_raw_socket()
320    }
321}
322
323impl FromRawSocket for UnixListener {
324    #[inline]
325    unsafe fn from_raw_socket(sock: RawSocket) -> Self {
326        UnixListener(unsafe { Socket::from_raw_socket(sock) })
327    }
328}
329
330impl IntoRawSocket for UnixListener {
331    #[inline]
332    fn into_raw_socket(self) -> RawSocket {
333        self.0.into_raw_socket()
334    }
335}
336
337impl<'a> IntoIterator for &'a UnixListener {
338    type Item = io::Result<UnixStream>;
339    type IntoIter = Incoming<'a>;
340
341    fn into_iter(self) -> Incoming<'a> {
342        self.incoming()
343    }
344}