Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
fc380ec
Adjust `tcp_quickack` feature to allow other `os::linux::net` features.
jmillikin Sep 18, 2022
8f1e6eb
Move `unix_socket_abstract` feature API to `SocketAddrExt`.
jmillikin Sep 18, 2022
12c15a2
Split out from_u32_unchecked from const_char_convert
est31 Sep 29, 2022
176c44c
Stabilize const_char_convert
est31 Sep 29, 2022
d8c0fef
Fixed some `_i32` notation in `maybe_uninit`’s doc
Elarcis Nov 12, 2022
56dfb70
use `EXE_EXTENSION` while searching for python
SparkyPotato Nov 13, 2022
8e81cc2
rustdoc: Resolve doc links in external traits having local impls
petrochenkov Nov 13, 2022
d634c1c
avoid rustc_llvm rebuilds when LD_LIBRARY_PATH changes
RalfJung Nov 13, 2022
6de5f62
Bump chalk to v0.87
compiler-errors Nov 13, 2022
36a1068
Make rustc build with new chalk
compiler-errors Nov 13, 2022
2de7581
Rollup merge of #101967 - jmillikin:linux-abstract-socket-addr, r=jos…
matthiaskrgr Nov 14, 2022
ab87c4c
Rollup merge of #102470 - est31:stabilize_const_char_convert, r=josht…
matthiaskrgr Nov 14, 2022
95ea4f0
Rollup merge of #104332 - Elarcis:maybe_uninit_doc_fix, r=m-ou-se
matthiaskrgr Nov 14, 2022
5e2785f
Rollup merge of #104350 - SparkyPotato:fix-x-wrapper, r=jyn514
matthiaskrgr Nov 14, 2022
7bb7bf7
Rollup merge of #104364 - petrochenkov:docice2, r=GuillaumeGomez
matthiaskrgr Nov 14, 2022
4c8b7b3
Rollup merge of #104375 - RalfJung:rustc_llvm_rebuild, r=jyn514,Mark-…
matthiaskrgr Nov 14, 2022
d403505
Rollup merge of #104378 - compiler-errors:chalk-up, r=jackh726
matthiaskrgr Nov 14, 2022
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move unix_socket_abstract feature API to SocketAddrExt.
  • Loading branch information
jmillikin committed Sep 18, 2022
commit 8f1e6eba343452ac48412f11d57aa7d206c8c3dd
5 changes: 5 additions & 0 deletions library/std/src/os/android/net.rs
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions library/std/src/os/linux/net.rs
Original file line number Diff line number Diff line change
@@ -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;
64 changes: 64 additions & 0 deletions library/std/src/os/net/linux_ext/addr.rs
Original file line number Diff line number Diff line change
@@ -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]>;
}
3 changes: 3 additions & 0 deletions library/std/src/os/net/linux_ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
93 changes: 25 additions & 68 deletions library/std/src/os/unix/net/addr.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -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) };
Expand All @@ -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)
}
}
Expand Down
36 changes: 21 additions & 15 deletions library/std/src/os/unix/net/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 || {
Expand All @@ -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![];
Expand All @@ -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 || {
Expand All @@ -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";
Expand All @@ -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());
Expand All @@ -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));
Expand All @@ -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",
Expand All @@ -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);
}

Expand Down