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}