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