about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Millikin <john@john-millikin.com>2022-09-18 16:20:11 +0900
committerJohn Millikin <john@john-millikin.com>2022-09-18 16:20:11 +0900
commit8f1e6eba343452ac48412f11d57aa7d206c8c3dd (patch)
tree079a3ebd2d6530bd01823b5c01abeb8e1f4504ad
parentfc380ecd13f0a16519ebf1df64648d006a4985fc (diff)
downloadrust-8f1e6eba343452ac48412f11d57aa7d206c8c3dd.tar.gz
rust-8f1e6eba343452ac48412f11d57aa7d206c8c3dd.zip
Move `unix_socket_abstract` feature API to `SocketAddrExt`.
-rw-r--r--library/std/src/os/android/net.rs5
-rw-r--r--library/std/src/os/linux/net.rs5
-rw-r--r--library/std/src/os/net/linux_ext/addr.rs64
-rw-r--r--library/std/src/os/net/linux_ext/mod.rs3
-rw-r--r--library/std/src/os/unix/net/addr.rs93
-rw-r--r--library/std/src/os/unix/net/tests.rs36
6 files changed, 123 insertions, 83 deletions
diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs
index 53ef7e114c0..7cecd1bbfaa 100644
--- a/library/std/src/os/android/net.rs
+++ b/library/std/src/os/android/net.rs
@@ -1,4 +1,9 @@
 //! Android-specific networking functionality.
 
 #![unstable(feature = "tcp_quickack", issue = "96256")]
+
+#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+pub use crate::os::net::linux_ext::addr::SocketAddrExt;
+
+#[unstable(feature = "tcp_quickack", issue = "96256")]
 pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs
index d67b369be27..94081c8dd31 100644
--- a/library/std/src/os/linux/net.rs
+++ b/library/std/src/os/linux/net.rs
@@ -1,4 +1,9 @@
 //! Linux-specific networking functionality.
 
 #![unstable(feature = "tcp_quickack", issue = "96256")]
+
+#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+pub use crate::os::net::linux_ext::addr::SocketAddrExt;
+
+#[unstable(feature = "tcp_quickack", issue = "96256")]
 pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/net/linux_ext/addr.rs b/library/std/src/os/net/linux_ext/addr.rs
new file mode 100644
index 00000000000..df3fc8e6a3b
--- /dev/null
+++ b/library/std/src/os/net/linux_ext/addr.rs
@@ -0,0 +1,64 @@
+//! Linux and Android-specific extensions to socket addresses.
+
+use crate::os::unix::net::SocketAddr;
+use crate::sealed::Sealed;
+
+/// Platform-specific extensions to [`SocketAddr`].
+#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+pub trait SocketAddrExt: Sealed {
+    /// Creates a Unix socket address in the abstract namespace.
+    ///
+    /// The abstract namespace is a Linux-specific extension that allows Unix
+    /// sockets to be bound without creating an entry in the filesystem.
+    /// Abstract sockets are unaffected by filesystem layout or permissions,
+    /// and no cleanup is necessary when the socket is closed.
+    ///
+    /// An abstract socket address name may contain any bytes, including zero.
+    ///
+    /// # Errors
+    ///
+    /// Returns an error if the name is longer than `SUN_LEN - 1`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_abstract)]
+    /// use std::os::unix::net::{UnixListener, SocketAddr};
+    /// use std::os::linux::net::SocketAddrExt;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let addr = SocketAddr::from_abstract_name(b"hidden")?;
+    ///     let listener = match UnixListener::bind_addr(&addr) {
+    ///         Ok(sock) => sock,
+    ///         Err(err) => {
+    ///             println!("Couldn't bind: {err:?}");
+    ///             return Err(err);
+    ///         }
+    ///     };
+    ///     Ok(())
+    /// }
+    /// ```
+    fn from_abstract_name<N>(name: &N) -> crate::io::Result<SocketAddr>
+    where
+        N: AsRef<[u8]>;
+
+    /// Returns the contents of this address if it is in the abstract namespace.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_abstract)]
+    /// use std::os::unix::net::{UnixListener, SocketAddr};
+    /// use std::os::linux::net::SocketAddrExt;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let name = b"hidden";
+    ///     let name_addr = SocketAddr::from_abstract_name(name)?;
+    ///     let socket = UnixListener::bind_addr(&name_addr)?;
+    ///     let local_addr = socket.local_addr().expect("Couldn't get local address");
+    ///     assert_eq!(local_addr.as_abstract_name(), Some(&name[..]));
+    ///     Ok(())
+    /// }
+    /// ```
+    fn as_abstract_name(&self) -> Option<&[u8]>;
+}
diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs
index 9bd66f3bb80..318ebacfd7a 100644
--- a/library/std/src/os/net/linux_ext/mod.rs
+++ b/library/std/src/os/net/linux_ext/mod.rs
@@ -2,6 +2,9 @@
 
 #![doc(cfg(any(target_os = "linux", target_os = "android")))]
 
+#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+pub(crate) mod addr;
+
 #[unstable(feature = "tcp_quickack", issue = "96256")]
 pub(crate) mod tcp;
 
diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs
index 094085e1942..81ac829d21b 100644
--- a/library/std/src/os/unix/net/addr.rs
+++ b/library/std/src/os/unix/net/addr.rs
@@ -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)
         }
     }
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index e4499f9b6a6..37fcfa8446b 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -7,6 +7,12 @@ use crate::sys_common::io::test::tmpdir;
 use crate::thread;
 use crate::time::Duration;
 
+#[cfg(target_os = "android")]
+use crate::os::android::net::SocketAddrExt;
+
+#[cfg(target_os = "linux")]
+use crate::os::linux::net::SocketAddrExt;
+
 macro_rules! or_panic {
     ($e:expr) => {
         match $e {
@@ -404,7 +410,7 @@ fn test_abstract_stream_connect() {
     let msg1 = b"hello";
     let msg2 = b"world";
 
-    let socket_addr = or_panic!(SocketAddr::from_abstract_namespace(b"namespace"));
+    let socket_addr = or_panic!(SocketAddr::from_abstract_name(b"name"));
     let listener = or_panic!(UnixListener::bind_addr(&socket_addr));
 
     let thread = thread::spawn(move || {
@@ -418,7 +424,7 @@ fn test_abstract_stream_connect() {
     let mut stream = or_panic!(UnixStream::connect_addr(&socket_addr));
 
     let peer = or_panic!(stream.peer_addr());
-    assert_eq!(peer.as_abstract_namespace().unwrap(), b"namespace");
+    assert_eq!(peer.as_abstract_name().unwrap(), b"name");
 
     or_panic!(stream.write_all(msg1));
     let mut buf = vec![];
@@ -432,7 +438,7 @@ fn test_abstract_stream_connect() {
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 fn test_abstract_stream_iter() {
-    let addr = or_panic!(SocketAddr::from_abstract_namespace(b"hidden"));
+    let addr = or_panic!(SocketAddr::from_abstract_name(b"hidden"));
     let listener = or_panic!(UnixListener::bind_addr(&addr));
 
     let thread = thread::spawn(move || {
@@ -454,13 +460,13 @@ fn test_abstract_stream_iter() {
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 fn test_abstract_datagram_bind_send_to_addr() {
-    let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns1"));
+    let addr1 = or_panic!(SocketAddr::from_abstract_name(b"ns1"));
     let sock1 = or_panic!(UnixDatagram::bind_addr(&addr1));
 
     let local = or_panic!(sock1.local_addr());
-    assert_eq!(local.as_abstract_namespace().unwrap(), b"ns1");
+    assert_eq!(local.as_abstract_name().unwrap(), b"ns1");
 
-    let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns2"));
+    let addr2 = or_panic!(SocketAddr::from_abstract_name(b"ns2"));
     let sock2 = or_panic!(UnixDatagram::bind_addr(&addr2));
 
     let msg = b"hello world";
@@ -469,13 +475,13 @@ fn test_abstract_datagram_bind_send_to_addr() {
     let (len, addr) = or_panic!(sock2.recv_from(&mut buf));
     assert_eq!(msg, &buf[..]);
     assert_eq!(len, 11);
-    assert_eq!(addr.as_abstract_namespace().unwrap(), b"ns1");
+    assert_eq!(addr.as_abstract_name().unwrap(), b"ns1");
 }
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 fn test_abstract_datagram_connect_addr() {
-    let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns3"));
+    let addr1 = or_panic!(SocketAddr::from_abstract_name(b"ns3"));
     let bsock1 = or_panic!(UnixDatagram::bind_addr(&addr1));
 
     let sock = or_panic!(UnixDatagram::unbound());
@@ -489,7 +495,7 @@ fn test_abstract_datagram_connect_addr() {
     assert_eq!(addr.is_unnamed(), true);
     assert_eq!(msg, &buf[..]);
 
-    let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns4"));
+    let addr2 = or_panic!(SocketAddr::from_abstract_name(b"ns4"));
     let bsock2 = or_panic!(UnixDatagram::bind_addr(&addr2));
 
     or_panic!(sock.connect_addr(&addr2));
@@ -499,8 +505,8 @@ fn test_abstract_datagram_connect_addr() {
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
-fn test_abstract_namespace_too_long() {
-    match SocketAddr::from_abstract_namespace(
+fn test_abstract_name_too_long() {
+    match SocketAddr::from_abstract_name(
         b"abcdefghijklmnopqrstuvwxyzabcdefghijklmn\
         opqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi\
         jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
@@ -513,11 +519,11 @@ fn test_abstract_namespace_too_long() {
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
-fn test_abstract_namespace_no_pathname_and_not_unnamed() {
-    let namespace = b"local";
-    let addr = or_panic!(SocketAddr::from_abstract_namespace(&namespace[..]));
+fn test_abstract_no_pathname_and_not_unnamed() {
+    let name = b"local";
+    let addr = or_panic!(SocketAddr::from_abstract_name(name));
     assert_eq!(addr.as_pathname(), None);
-    assert_eq!(addr.as_abstract_namespace(), Some(&namespace[..]));
+    assert_eq!(addr.as_abstract_name(), Some(&name[..]));
     assert_eq!(addr.is_unnamed(), false);
 }