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