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