Move unix_socket_abstract feature API to SocketAddrExt.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
use crate::ffi::OsStr;
|
||||
#[cfg(any(doc, target_os = "android", target_os = "linux"))]
|
||||
use crate::os::net::linux_ext;
|
||||
use crate::os::unix::ffi::OsStrExt;
|
||||
use crate::path::Path;
|
||||
use crate::sealed::Sealed;
|
||||
use crate::sys::cvt;
|
||||
use crate::{fmt, io, mem, ptr};
|
||||
|
||||
@@ -224,31 +227,6 @@ impl SocketAddr {
|
||||
if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None }
|
||||
}
|
||||
|
||||
/// Returns the contents of this address if it is an abstract namespace
|
||||
/// without the leading null byte.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(unix_socket_abstract)]
|
||||
/// use std::os::unix::net::{UnixListener, SocketAddr};
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let namespace = b"hidden";
|
||||
/// let namespace_addr = SocketAddr::from_abstract_namespace(&namespace[..])?;
|
||||
/// let socket = UnixListener::bind_addr(&namespace_addr)?;
|
||||
/// let local_addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// assert_eq!(local_addr.as_abstract_namespace(), Some(&namespace[..]));
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[doc(cfg(any(target_os = "android", target_os = "linux")))]
|
||||
#[cfg(any(doc, target_os = "android", target_os = "linux",))]
|
||||
#[unstable(feature = "unix_socket_abstract", issue = "85410")]
|
||||
pub fn as_abstract_namespace(&self) -> Option<&[u8]> {
|
||||
if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None }
|
||||
}
|
||||
|
||||
fn address(&self) -> AddressKind<'_> {
|
||||
let len = self.len as usize - sun_path_offset(&self.addr);
|
||||
let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
|
||||
@@ -265,62 +243,41 @@ impl SocketAddr {
|
||||
AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an abstract domain socket address from a namespace
|
||||
///
|
||||
/// An abstract address does not create a file unlike traditional path-based
|
||||
/// Unix sockets. The advantage of this is that the address will disappear when
|
||||
/// the socket bound to it is closed, so no filesystem clean up is required.
|
||||
///
|
||||
/// The leading null byte for the abstract namespace is automatically added.
|
||||
///
|
||||
/// This is a Linux-specific extension. See more at [`unix(7)`].
|
||||
///
|
||||
/// [`unix(7)`]: https://man7.org/linux/man-pages/man7/unix.7.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This will return an error if the given namespace is too long
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(unix_socket_abstract)]
|
||||
/// use std::os::unix::net::{UnixListener, SocketAddr};
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let addr = SocketAddr::from_abstract_namespace(b"hidden")?;
|
||||
/// let listener = match UnixListener::bind_addr(&addr) {
|
||||
/// Ok(sock) => sock,
|
||||
/// Err(err) => {
|
||||
/// println!("Couldn't bind: {err:?}");
|
||||
/// return Err(err);
|
||||
/// }
|
||||
/// };
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[doc(cfg(any(target_os = "android", target_os = "linux")))]
|
||||
#[cfg(any(doc, target_os = "android", target_os = "linux",))]
|
||||
#[unstable(feature = "unix_socket_abstract", issue = "85410")]
|
||||
pub fn from_abstract_namespace(namespace: &[u8]) -> io::Result<SocketAddr> {
|
||||
#[unstable(feature = "unix_socket_abstract", issue = "85410")]
|
||||
impl Sealed for SocketAddr {}
|
||||
|
||||
#[doc(cfg(any(target_os = "android", target_os = "linux")))]
|
||||
#[cfg(any(doc, target_os = "android", target_os = "linux"))]
|
||||
#[unstable(feature = "unix_socket_abstract", issue = "85410")]
|
||||
impl linux_ext::addr::SocketAddrExt for SocketAddr {
|
||||
fn as_abstract_name(&self) -> Option<&[u8]> {
|
||||
if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None }
|
||||
}
|
||||
|
||||
fn from_abstract_name<N>(name: &N) -> crate::io::Result<Self>
|
||||
where
|
||||
N: AsRef<[u8]>,
|
||||
{
|
||||
let name = name.as_ref();
|
||||
unsafe {
|
||||
let mut addr: libc::sockaddr_un = mem::zeroed();
|
||||
addr.sun_family = libc::AF_UNIX as libc::sa_family_t;
|
||||
|
||||
if namespace.len() + 1 > addr.sun_path.len() {
|
||||
if name.len() + 1 > addr.sun_path.len() {
|
||||
return Err(io::const_io_error!(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"namespace must be shorter than SUN_LEN",
|
||||
"abstract socket name must be shorter than SUN_LEN",
|
||||
));
|
||||
}
|
||||
|
||||
crate::ptr::copy_nonoverlapping(
|
||||
namespace.as_ptr(),
|
||||
name.as_ptr(),
|
||||
addr.sun_path.as_mut_ptr().add(1) as *mut u8,
|
||||
namespace.len(),
|
||||
name.len(),
|
||||
);
|
||||
let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t;
|
||||
let len = (sun_path_offset(&addr) + 1 + name.len()) as libc::socklen_t;
|
||||
SocketAddr::from_parts(addr, len)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user