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