std/os/unix/net/listener.rs
1use super::{SocketAddr, UnixStream, sockaddr_un};
2use crate::os::unix::io::{
3 AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd, unsafe_impl_fd_asrefs,
4};
5use crate::path::Path;
6use crate::sys::net::Socket;
7use crate::sys::{AsInner, FromInner, IntoInner, cvt};
8use crate::{fmt, io, mem};
9
10/// A structure representing a Unix domain socket server.
11///
12/// # Examples
13///
14#[cfg_attr(target_family = "unix", doc = "```no_run")]
15#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
16/// use std::thread;
17/// use std::os::unix::net::{UnixStream, UnixListener};
18///
19/// fn handle_client(stream: UnixStream) {
20/// // ...
21/// }
22///
23/// fn main() -> std::io::Result<()> {
24/// let listener = UnixListener::bind("/path/to/the/socket")?;
25///
26/// // accept connections and process them, spawning a new thread for each one
27/// for stream in listener.incoming() {
28/// match stream {
29/// Ok(stream) => {
30/// /* connection succeeded */
31/// thread::spawn(|| handle_client(stream));
32/// }
33/// Err(err) => {
34/// /* connection failed */
35/// break;
36/// }
37/// }
38/// }
39/// Ok(())
40/// }
41/// ```
42#[stable(feature = "unix_socket", since = "1.10.0")]
43pub struct UnixListener(Socket);
44
45#[stable(feature = "unix_socket", since = "1.10.0")]
46impl fmt::Debug for UnixListener {
47 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
48 let mut builder = fmt.debug_struct("UnixListener");
49 builder.field("fd", self.0.as_inner());
50 if let Ok(addr) = self.local_addr() {
51 builder.field("local", &addr);
52 }
53 builder.finish()
54 }
55}
56
57impl UnixListener {
58 /// Creates a new `UnixListener` bound to the specified socket.
59 ///
60 /// # Examples
61 ///
62 #[cfg_attr(target_family = "unix", doc = "```no_run")]
63 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
64 /// use std::os::unix::net::UnixListener;
65 ///
66 /// let listener = match UnixListener::bind("/path/to/the/socket") {
67 /// Ok(sock) => sock,
68 /// Err(e) => {
69 /// println!("Couldn't connect: {e:?}");
70 /// return
71 /// }
72 /// };
73 /// ```
74 #[stable(feature = "unix_socket", since = "1.10.0")]
75 pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
76 unsafe {
77 let inner = Socket::new(libc::AF_UNIX, libc::SOCK_STREAM)?;
78 let (addr, len) = sockaddr_un(path.as_ref())?;
79 #[cfg(any(
80 target_os = "windows",
81 target_os = "redox",
82 target_os = "espidf",
83 target_os = "horizon"
84 ))]
85 const backlog: core::ffi::c_int = 128;
86 #[cfg(any(
87 // Silently capped to `/proc/sys/net/core/somaxconn`.
88 target_os = "linux",
89 // Silently capped to `kern.ipc.soacceptqueue`.
90 target_os = "freebsd",
91 // Silently capped to `kern.somaxconn sysctl`.
92 target_os = "openbsd",
93 // Silently capped to the default 128.
94 target_vendor = "apple",
95 ))]
96 const backlog: core::ffi::c_int = -1;
97 #[cfg(not(any(
98 target_os = "windows",
99 target_os = "redox",
100 target_os = "espidf",
101 target_os = "horizon",
102 target_os = "linux",
103 target_os = "freebsd",
104 target_os = "openbsd",
105 target_vendor = "apple",
106 )))]
107 const backlog: libc::c_int = libc::SOMAXCONN;
108
109 cvt(libc::bind(inner.as_inner().as_raw_fd(), (&raw const addr) as *const _, len as _))?;
110 cvt(libc::listen(inner.as_inner().as_raw_fd(), backlog))?;
111
112 Ok(UnixListener(inner))
113 }
114 }
115
116 /// Creates a new `UnixListener` bound to the specified [`socket address`].
117 ///
118 /// [`socket address`]: crate::os::unix::net::SocketAddr
119 ///
120 /// # Examples
121 ///
122 #[cfg_attr(target_family = "unix", doc = "```no_run")]
123 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
124 /// use std::os::unix::net::{SocketAddr, UnixListener};
125 ///
126 /// fn main() -> std::io::Result<()> {
127 /// let addr = SocketAddr::from_pathname("path/to/socket")?;
128 ///
129 /// let listener = match UnixListener::bind_addr(&addr) {
130 /// Ok(sock) => sock,
131 /// Err(err) => {
132 /// println!("Couldn't bind: {err:?}");
133 /// return Err(err);
134 /// }
135 /// };
136 /// Ok(())
137 /// }
138 /// ```
139 #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
140 pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> {
141 unsafe {
142 let inner = Socket::new(libc::AF_UNIX, libc::SOCK_STREAM)?;
143 #[cfg(target_os = "linux")]
144 const backlog: core::ffi::c_int = -1;
145 #[cfg(not(target_os = "linux"))]
146 const backlog: core::ffi::c_int = 128;
147 cvt(libc::bind(
148 inner.as_raw_fd(),
149 (&raw const socket_addr.addr) as *const _,
150 socket_addr.len as _,
151 ))?;
152 cvt(libc::listen(inner.as_raw_fd(), backlog))?;
153 Ok(UnixListener(inner))
154 }
155 }
156
157 /// Accepts a new incoming connection to this listener.
158 ///
159 /// This function will block the calling thread until a new Unix connection
160 /// is established. When established, the corresponding [`UnixStream`] and
161 /// the remote peer's address will be returned.
162 ///
163 /// [`UnixStream`]: crate::os::unix::net::UnixStream
164 ///
165 /// # Examples
166 ///
167 #[cfg_attr(target_family = "unix", doc = "```no_run")]
168 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
169 /// use std::os::unix::net::UnixListener;
170 ///
171 /// fn main() -> std::io::Result<()> {
172 /// let listener = UnixListener::bind("/path/to/the/socket")?;
173 ///
174 /// match listener.accept() {
175 /// Ok((socket, addr)) => println!("Got a client: {addr:?}"),
176 /// Err(e) => println!("accept function failed: {e:?}"),
177 /// }
178 /// Ok(())
179 /// }
180 /// ```
181 #[stable(feature = "unix_socket", since = "1.10.0")]
182 pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
183 let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
184 let mut len = size_of_val(&storage) as libc::socklen_t;
185 let sock = self.0.accept((&raw mut storage) as *mut _, &mut len)?;
186 let addr = SocketAddr::from_parts(storage, len)?;
187 Ok((UnixStream(sock), addr))
188 }
189
190 /// Creates a new independently owned handle to the underlying socket.
191 ///
192 /// The returned `UnixListener` is a reference to the same socket that this
193 /// object references. Both handles can be used to accept incoming
194 /// connections and options set on one listener will affect the other.
195 ///
196 /// # Examples
197 ///
198 #[cfg_attr(target_family = "unix", doc = "```no_run")]
199 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
200 /// use std::os::unix::net::UnixListener;
201 ///
202 /// fn main() -> std::io::Result<()> {
203 /// let listener = UnixListener::bind("/path/to/the/socket")?;
204 /// let listener_copy = listener.try_clone().expect("`UnixListener::try_clone` should not fail");
205 /// Ok(())
206 /// }
207 /// ```
208 #[stable(feature = "unix_socket", since = "1.10.0")]
209 pub fn try_clone(&self) -> io::Result<UnixListener> {
210 self.0.duplicate().map(UnixListener)
211 }
212
213 /// Returns the local socket address of this listener.
214 ///
215 /// # Examples
216 ///
217 #[cfg_attr(target_family = "unix", doc = "```no_run")]
218 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
219 /// use std::os::unix::net::UnixListener;
220 ///
221 /// fn main() -> std::io::Result<()> {
222 /// let listener = UnixListener::bind("/path/to/the/socket")?;
223 /// let addr = listener.local_addr().expect("`UnixListener::local_addr` should not fail");
224 /// Ok(())
225 /// }
226 /// ```
227 #[stable(feature = "unix_socket", since = "1.10.0")]
228 pub fn local_addr(&self) -> io::Result<SocketAddr> {
229 SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.as_raw_fd(), addr, len) })
230 }
231
232 /// Moves the socket into or out of nonblocking mode.
233 ///
234 /// This will result in the `accept` operation becoming nonblocking,
235 /// i.e., immediately returning from their calls. If the IO operation is
236 /// successful, `Ok` is returned and no further action is required. If the
237 /// IO operation could not be completed and needs to be retried, an error
238 /// with kind [`io::ErrorKind::WouldBlock`] is returned.
239 ///
240 /// # Examples
241 ///
242 #[cfg_attr(target_family = "unix", doc = "```no_run")]
243 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
244 /// use std::os::unix::net::UnixListener;
245 ///
246 /// fn main() -> std::io::Result<()> {
247 /// let listener = UnixListener::bind("/path/to/the/socket")?;
248 /// listener.set_nonblocking(true).expect("`UnixListener::set_nonblocking` should not fail");
249 /// Ok(())
250 /// }
251 /// ```
252 #[stable(feature = "unix_socket", since = "1.10.0")]
253 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
254 self.0.set_nonblocking(nonblocking)
255 }
256
257 /// Returns the value of the `SO_ERROR` option.
258 ///
259 /// # Examples
260 ///
261 #[cfg_attr(target_family = "unix", doc = "```no_run")]
262 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
263 /// use std::os::unix::net::UnixListener;
264 ///
265 /// fn main() -> std::io::Result<()> {
266 /// let listener = UnixListener::bind("/tmp/sock")?;
267 ///
268 /// if let Ok(Some(err)) = listener.take_error() {
269 /// println!("Got error: {err:?}");
270 /// }
271 /// Ok(())
272 /// }
273 /// ```
274 ///
275 /// # Platform specific
276 /// On Redox this always returns `None`.
277 #[stable(feature = "unix_socket", since = "1.10.0")]
278 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
279 self.0.take_error()
280 }
281
282 /// Returns an iterator over incoming connections.
283 ///
284 /// The iterator will never return [`None`] and will also not yield the
285 /// peer's [`SocketAddr`] structure.
286 ///
287 /// # Examples
288 ///
289 #[cfg_attr(target_family = "unix", doc = "```no_run")]
290 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
291 /// use std::thread;
292 /// use std::os::unix::net::{UnixStream, UnixListener};
293 ///
294 /// fn handle_client(stream: UnixStream) {
295 /// // ...
296 /// }
297 ///
298 /// fn main() -> std::io::Result<()> {
299 /// let listener = UnixListener::bind("/path/to/the/socket")?;
300 ///
301 /// for stream in listener.incoming() {
302 /// match stream {
303 /// Ok(stream) => {
304 /// thread::spawn(|| handle_client(stream));
305 /// }
306 /// Err(err) => {
307 /// break;
308 /// }
309 /// }
310 /// }
311 /// Ok(())
312 /// }
313 /// ```
314 #[stable(feature = "unix_socket", since = "1.10.0")]
315 pub fn incoming(&self) -> Incoming<'_> {
316 Incoming { listener: self }
317 }
318}
319
320#[stable(feature = "unix_socket", since = "1.10.0")]
321impl AsRawFd for UnixListener {
322 #[inline]
323 fn as_raw_fd(&self) -> RawFd {
324 self.0.as_inner().as_raw_fd()
325 }
326}
327
328#[stable(feature = "unix_socket", since = "1.10.0")]
329impl FromRawFd for UnixListener {
330 #[inline]
331 unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
332 UnixListener(Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))))
333 }
334}
335
336#[stable(feature = "unix_socket", since = "1.10.0")]
337impl IntoRawFd for UnixListener {
338 #[inline]
339 fn into_raw_fd(self) -> RawFd {
340 self.0.into_inner().into_inner().into_raw_fd()
341 }
342}
343
344#[stable(feature = "io_safety", since = "1.63.0")]
345impl AsFd for UnixListener {
346 #[inline]
347 fn as_fd(&self) -> BorrowedFd<'_> {
348 self.0.as_inner().as_fd()
349 }
350}
351
352#[stable(feature = "io_safety", since = "1.63.0")]
353impl From<OwnedFd> for UnixListener {
354 #[inline]
355 fn from(fd: OwnedFd) -> UnixListener {
356 UnixListener(Socket::from_inner(FromInner::from_inner(fd)))
357 }
358}
359
360// SAFETY: It's a tower of 1-field wrappers around OwnedFd.
361// No methods to close the socket, no methods with safety preconditions,
362// other than the fd being valid.
363unsafe_impl_fd_asrefs!(UnixListener);
364
365#[stable(feature = "io_safety", since = "1.63.0")]
366impl From<UnixListener> for OwnedFd {
367 /// Takes ownership of a [`UnixListener`]'s socket file descriptor.
368 #[inline]
369 fn from(listener: UnixListener) -> OwnedFd {
370 listener.0.into_inner().into_inner()
371 }
372}
373
374#[stable(feature = "unix_socket", since = "1.10.0")]
375impl<'a> IntoIterator for &'a UnixListener {
376 type Item = io::Result<UnixStream>;
377 type IntoIter = Incoming<'a>;
378
379 fn into_iter(self) -> Incoming<'a> {
380 self.incoming()
381 }
382}
383
384/// An iterator over incoming connections to a [`UnixListener`].
385///
386/// It will never return [`None`].
387///
388/// # Examples
389///
390#[cfg_attr(target_family = "unix", doc = "```no_run")]
391#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
392/// use std::thread;
393/// use std::os::unix::net::{UnixStream, UnixListener};
394///
395/// fn handle_client(stream: UnixStream) {
396/// // ...
397/// }
398///
399/// fn main() -> std::io::Result<()> {
400/// let listener = UnixListener::bind("/path/to/the/socket")?;
401///
402/// for stream in listener.incoming() {
403/// match stream {
404/// Ok(stream) => {
405/// thread::spawn(|| handle_client(stream));
406/// }
407/// Err(err) => {
408/// break;
409/// }
410/// }
411/// }
412/// Ok(())
413/// }
414/// ```
415#[derive(Debug)]
416#[must_use = "iterators are lazy and do nothing unless consumed"]
417#[stable(feature = "unix_socket", since = "1.10.0")]
418pub struct Incoming<'a> {
419 listener: &'a UnixListener,
420}
421
422#[stable(feature = "unix_socket", since = "1.10.0")]
423impl<'a> Iterator for Incoming<'a> {
424 type Item = io::Result<UnixStream>;
425
426 fn next(&mut self) -> Option<io::Result<UnixStream>> {
427 Some(self.listener.accept().map(|s| s.0))
428 }
429
430 fn size_hint(&self) -> (usize, Option<usize>) {
431 (usize::MAX, None)
432 }
433}