| 1 | use super::{SocketAddr, UnixStream, sockaddr_un}; |
| 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 | // Silently capped to `/proc/sys/net/core/somaxconn`. |
| 85 | target_os = "linux" , |
| 86 | // Silently capped to `kern.ipc.soacceptqueue`. |
| 87 | target_os = "freebsd" , |
| 88 | // Silently capped to `kern.somaxconn sysctl`. |
| 89 | target_os = "openbsd" , |
| 90 | // Silently capped to the default 128. |
| 91 | target_vendor = "apple" , |
| 92 | ))] |
| 93 | const backlog: core::ffi::c_int = -1; |
| 94 | #[cfg (not(any( |
| 95 | target_os = "windows" , |
| 96 | target_os = "redox" , |
| 97 | target_os = "espidf" , |
| 98 | target_os = "horizon" , |
| 99 | target_os = "linux" , |
| 100 | target_os = "freebsd" , |
| 101 | target_os = "openbsd" , |
| 102 | target_vendor = "apple" , |
| 103 | )))] |
| 104 | const backlog: libc::c_int = libc::SOMAXCONN; |
| 105 | |
| 106 | cvt(libc::bind(inner.as_inner().as_raw_fd(), (&raw const addr) as *const _, len as _))?; |
| 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 | (&raw const 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 = size_of_val(&storage) as libc::socklen_t; |
| 181 | let sock = self.0.accept((&raw 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 | |