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