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