about summary refs log tree commit diff
path: root/library/std
diff options
context:
space:
mode:
Diffstat (limited to 'library/std')
-rw-r--r--library/std/src/io/error.rs3
-rw-r--r--library/std/src/net/mod.rs21
-rw-r--r--library/std/src/net/tcp.rs4
-rw-r--r--library/std/src/net/tcp/tests.rs2
-rw-r--r--library/std/src/net/udp.rs4
-rw-r--r--library/std/src/net/udp/tests.rs1
-rw-r--r--library/std/src/sync/barrier.rs4
-rw-r--r--library/std/src/sys/net/connection/mod.rs57
-rw-r--r--library/std/src/sys/net/connection/sgx.rs81
-rw-r--r--library/std/src/sys/net/connection/socket/mod.rs (renamed from library/std/src/sys/net/connection/socket.rs)108
-rw-r--r--library/std/src/sys/net/connection/uefi/mod.rs27
-rw-r--r--library/std/src/sys/net/connection/unsupported.rs10
-rw-r--r--library/std/src/sys/net/connection/wasip1.rs10
-rw-r--r--library/std/src/sys/net/connection/xous/tcplistener.rs26
-rw-r--r--library/std/src/sys/net/connection/xous/tcpstream.rs9
-rw-r--r--library/std/src/sys/net/connection/xous/udp.rs81
-rw-r--r--library/std/src/sys/net/mod.rs48
-rw-r--r--library/std/tests/sync/barrier.rs9
18 files changed, 289 insertions, 216 deletions
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 57a980d6acd..21e82d43a80 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -95,6 +95,9 @@ impl Error {
 
     pub(crate) const ZERO_TIMEOUT: Self =
         const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout");
+
+    pub(crate) const NO_ADDRESSES: Self =
+        const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses");
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs
index ddd3b68dd2d..40f1a93e39d 100644
--- a/library/std/src/net/mod.rs
+++ b/library/std/src/net/mod.rs
@@ -34,7 +34,6 @@ pub use self::tcp::IntoIncoming;
 pub use self::tcp::{Incoming, TcpListener, TcpStream};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::udp::UdpSocket;
-use crate::io::{self, ErrorKind};
 
 mod ip_addr;
 mod socket_addr;
@@ -67,23 +66,3 @@ pub enum Shutdown {
     #[stable(feature = "rust1", since = "1.0.0")]
     Both,
 }
-
-fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
-where
-    F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>,
-{
-    let addrs = match addr.to_socket_addrs() {
-        Ok(addrs) => addrs,
-        Err(e) => return f(Err(e)),
-    };
-    let mut last_err = None;
-    for addr in addrs {
-        match f(Ok(&addr)) {
-            Ok(l) => return Ok(l),
-            Err(e) => last_err = Some(e),
-        }
-    }
-    Err(last_err.unwrap_or_else(|| {
-        io::const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses")
-    }))
-}
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 10685b49319..ae50f531a71 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -167,7 +167,7 @@ impl TcpStream {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
-        super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream)
+        net_imp::TcpStream::connect(addr).map(TcpStream)
     }
 
     /// Opens a TCP connection to a remote host with a timeout.
@@ -782,7 +782,7 @@ impl TcpListener {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
-        super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener)
+        net_imp::TcpListener::bind(addr).map(TcpListener)
     }
 
     /// Returns the local socket address of this listener.
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index 03003037b29..7c7ef7b2f70 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -1,5 +1,5 @@
 use crate::io::prelude::*;
-use crate::io::{BorrowedBuf, IoSlice, IoSliceMut};
+use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut};
 use crate::mem::MaybeUninit;
 use crate::net::test::{next_test_ip4, next_test_ip6};
 use crate::net::*;
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index a97b3299774..72e292e3d15 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -120,7 +120,7 @@ impl UdpSocket {
     /// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`].
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
-        super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
+        net_imp::UdpSocket::bind(addr).map(UdpSocket)
     }
 
     /// Receives a single datagram message on the socket. On success, returns the number
@@ -677,7 +677,7 @@ impl UdpSocket {
     /// on the platform.
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
-        super::each_addr(addr, |addr| self.0.connect(addr))
+        self.0.connect(addr)
     }
 
     /// Sends data on the socket to the remote address to which it is connected.
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
index 91da3135f97..0638b36c54f 100644
--- a/library/std/src/net/udp/tests.rs
+++ b/library/std/src/net/udp/tests.rs
@@ -1,3 +1,4 @@
+use crate::io::ErrorKind;
 use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6};
 use crate::net::*;
 use crate::sync::mpsc::channel;
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index 712ce03f90b..8988126bd90 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -1,4 +1,5 @@
 use crate::fmt;
+use crate::panic::RefUnwindSafe;
 use crate::sync::nonpoison::{Condvar, Mutex};
 
 /// A barrier enables multiple threads to synchronize the beginning
@@ -31,6 +32,9 @@ pub struct Barrier {
     num_threads: usize,
 }
 
+#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
+impl RefUnwindSafe for Barrier {}
+
 // The inner state of a double barrier
 struct BarrierState {
     count: usize,
diff --git a/library/std/src/sys/net/connection/mod.rs b/library/std/src/sys/net/connection/mod.rs
new file mode 100644
index 00000000000..7f9636a8ccf
--- /dev/null
+++ b/library/std/src/sys/net/connection/mod.rs
@@ -0,0 +1,57 @@
+cfg_select! {
+    any(
+        all(target_family = "unix", not(target_os = "l4re")),
+        target_os = "windows",
+        target_os = "hermit",
+        all(target_os = "wasi", target_env = "p2"),
+        target_os = "solid_asp3",
+    ) => {
+        mod socket;
+        pub use socket::*;
+    }
+    all(target_vendor = "fortanix", target_env = "sgx") => {
+        mod sgx;
+        pub use sgx::*;
+    }
+    all(target_os = "wasi", target_env = "p1") => {
+        mod wasip1;
+        pub use wasip1::*;
+    }
+    target_os = "xous" => {
+        mod xous;
+        pub use xous::*;
+    }
+    target_os = "uefi" => {
+        mod uefi;
+        pub use uefi::*;
+    }
+    _ => {
+        mod unsupported;
+        pub use unsupported::*;
+    }
+}
+
+#[cfg_attr(
+    // Make sure that this is used on some platforms at least.
+    not(any(target_os = "linux", target_os = "windows")),
+    allow(dead_code)
+)]
+fn each_addr<A: crate::net::ToSocketAddrs, F, T>(addr: A, mut f: F) -> crate::io::Result<T>
+where
+    F: FnMut(&crate::net::SocketAddr) -> crate::io::Result<T>,
+{
+    use crate::io::Error;
+
+    let mut last_err = None;
+    for addr in addr.to_socket_addrs()? {
+        match f(&addr) {
+            Ok(l) => return Ok(l),
+            Err(e) => last_err = Some(e),
+        }
+    }
+
+    match last_err {
+        Some(err) => Err(err),
+        None => Err(Error::NO_ADDRESSES),
+    }
+}
diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs
index 2389fd1bcb6..9b54571997d 100644
--- a/library/std/src/sys/net/connection/sgx.rs
+++ b/library/std/src/sys/net/connection/sgx.rs
@@ -1,3 +1,5 @@
+use crate::error;
+use crate::fmt::{self, Write};
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
 use crate::sync::Arc;
@@ -5,7 +7,6 @@ use crate::sys::abi::usercalls;
 use crate::sys::fd::FileDesc;
 use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported};
 use crate::time::Duration;
-use crate::{error, fmt};
 
 const DEFAULT_FAKE_TTL: u32 = 64;
 
@@ -63,18 +64,52 @@ impl fmt::Debug for TcpStream {
     }
 }
 
-fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
-    match result {
-        Ok(saddr) => Ok(saddr.to_string()),
-        // need to downcast twice because io::Error::into_inner doesn't return the original
-        // value if the conversion fails
-        Err(e) => {
-            if e.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()).is_some() {
-                Ok(e.into_inner().unwrap().downcast::<NonIpSockAddr>().unwrap().host)
-            } else {
-                Err(e)
+/// Converts each address in `addr` into a hostname.
+///
+/// SGX doesn't support DNS resolution but rather accepts hostnames in
+/// the same place as socket addresses. So, to make e.g.
+/// ```rust
+/// TcpStream::connect("example.com:80")`
+/// ```
+/// work, the DNS lookup returns a special error (`NonIpSockAddr`) instead,
+/// which contains the hostname being looked up. When `.to_socket_addrs()`
+/// fails, we inspect the error and try recover the hostname from it. If that
+/// succeeds, we thus continue with the hostname.
+///
+/// This is a terrible hack and leads to buggy code. For instance, when users
+/// use the result of `.to_socket_addrs()` in their own `ToSocketAddrs`
+/// implementation to select from a list of possible URLs, the only URL used
+/// will be that of the last item tried.
+// FIXME: This is a terrible, terrible hack. Fixing this requires Fortanix to
+// add a method for resolving addresses.
+fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
+where
+    F: FnMut(&str) -> io::Result<T>,
+{
+    match addr.to_socket_addrs() {
+        Ok(addrs) => {
+            let mut last_err = None;
+            let mut encoded = String::new();
+            for addr in addrs {
+                // Format the IP address as a string, reusing the buffer.
+                encoded.clear();
+                write!(encoded, "{}", &addr).unwrap();
+
+                match f(&encoded) {
+                    Ok(val) => return Ok(val),
+                    Err(err) => last_err = Some(err),
+                }
+            }
+
+            match last_err {
+                Some(err) => Err(err),
+                None => Err(io::Error::NO_ADDRESSES),
             }
         }
+        Err(err) => match err.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()) {
+            Some(NonIpSockAddr { host }) => f(host),
+            None => Err(err),
+        },
     }
 }
 
@@ -86,17 +121,18 @@ fn addr_to_sockaddr(addr: Option<&str>) -> io::Result<SocketAddr> {
 }
 
 impl TcpStream {
-    pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
-        let addr = io_err_to_addr(addr)?;
-        let (fd, local_addr, peer_addr) = usercalls::connect_stream(&addr)?;
-        Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
+    pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
+        each_addr(addr, |addr| {
+            let (fd, local_addr, peer_addr) = usercalls::connect_stream(addr)?;
+            Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
+        })
     }
 
     pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
         if dur == Duration::default() {
             return Err(io::Error::ZERO_TIMEOUT);
         }
-        Self::connect(Ok(addr)) // FIXME: ignoring timeout
+        Self::connect(addr) // FIXME: ignoring timeout
     }
 
     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
@@ -247,10 +283,11 @@ impl fmt::Debug for TcpListener {
 }
 
 impl TcpListener {
-    pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
-        let addr = io_err_to_addr(addr)?;
-        let (fd, local_addr) = usercalls::bind_stream(&addr)?;
-        Ok(TcpListener { inner: Socket::new(fd, local_addr) })
+    pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
+        each_addr(addr, |addr| {
+            let (fd, local_addr) = usercalls::bind_stream(addr)?;
+            Ok(TcpListener { inner: Socket::new(fd, local_addr) })
+        })
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
@@ -316,7 +353,7 @@ impl FromInner<Socket> for TcpListener {
 pub struct UdpSocket(!);
 
 impl UdpSocket {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
+    pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
         unsupported()
     }
 
@@ -436,7 +473,7 @@ impl UdpSocket {
         self.0
     }
 
-    pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
+    pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
         self.0
     }
 }
diff --git a/library/std/src/sys/net/connection/socket.rs b/library/std/src/sys/net/connection/socket/mod.rs
index aa83ed65d4c..564f2e3a01f 100644
--- a/library/std/src/sys/net/connection/socket.rs
+++ b/library/std/src/sys/net/connection/socket/mod.rs
@@ -3,8 +3,11 @@ mod tests;
 
 use crate::ffi::{c_int, c_void};
 use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::net::{
+    Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
+};
 use crate::sys::common::small_c_string::run_with_cstr;
+use crate::sys::net::connection::each_addr;
 use crate::sys_common::{AsInner, FromInner};
 use crate::time::Duration;
 use crate::{cmp, fmt, mem, ptr};
@@ -342,14 +345,15 @@ pub struct TcpStream {
 }
 
 impl TcpStream {
-    pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
-        let addr = addr?;
-
+    pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
         init();
+        return each_addr(addr, inner);
 
-        let sock = Socket::new(addr, c::SOCK_STREAM)?;
-        sock.connect(addr)?;
-        Ok(TcpStream { inner: sock })
+        fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
+            let sock = Socket::new(addr, c::SOCK_STREAM)?;
+            sock.connect(addr)?;
+            Ok(TcpStream { inner: sock })
+        }
     }
 
     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
@@ -512,48 +516,45 @@ pub struct TcpListener {
 }
 
 impl TcpListener {
-    pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
-        let addr = addr?;
-
+    pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
         init();
-
-        let sock = Socket::new(addr, c::SOCK_STREAM)?;
-
-        // On platforms with Berkeley-derived sockets, this allows to quickly
-        // rebind a socket, without needing to wait for the OS to clean up the
-        // previous one.
-        //
-        // On Windows, this allows rebinding sockets which are actively in use,
-        // which allows “socket hijacking”, so we explicitly don't set it here.
-        // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
-        #[cfg(not(windows))]
-        setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
-
-        // Bind our new socket
-        let (addr, len) = socket_addr_to_c(addr);
-        cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
-
-        cfg_select! {
-            target_os = "horizon" => {
+        return each_addr(addr, inner);
+
+        fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
+            let sock = Socket::new(addr, c::SOCK_STREAM)?;
+
+            // On platforms with Berkeley-derived sockets, this allows to quickly
+            // rebind a socket, without needing to wait for the OS to clean up the
+            // previous one.
+            //
+            // On Windows, this allows rebinding sockets which are actively in use,
+            // which allows “socket hijacking”, so we explicitly don't set it here.
+            // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
+            #[cfg(not(windows))]
+            setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
+
+            // Bind our new socket
+            let (addr, len) = socket_addr_to_c(addr);
+            cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
+
+            let backlog = if cfg!(target_os = "horizon") {
                 // The 3DS doesn't support a big connection backlog. Sometimes
                 // it allows up to about 37, but other times it doesn't even
                 // accept 32. There may be a global limitation causing this.
-                let backlog = 20;
-            }
-            target_os = "haiku" => {
+                20
+            } else if cfg!(target_os = "haiku") {
                 // Haiku does not support a queue length > 32
                 // https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
-                let backlog = 32;
-            }
-            _ => {
+                32
+            } else {
                 // The default for all other platforms
-                let backlog = 128;
-            }
-        }
+                128
+            };
 
-        // Start listening
-        cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
-        Ok(TcpListener { inner: sock })
+            // Start listening
+            cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
+            Ok(TcpListener { inner: sock })
+        }
     }
 
     #[inline]
@@ -639,15 +640,16 @@ pub struct UdpSocket {
 }
 
 impl UdpSocket {
-    pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
-        let addr = addr?;
-
+    pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
         init();
+        return each_addr(addr, inner);
 
-        let sock = Socket::new(addr, c::SOCK_DGRAM)?;
-        let (addr, len) = socket_addr_to_c(addr);
-        cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
-        Ok(UdpSocket { inner: sock })
+        fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
+            let sock = Socket::new(addr, c::SOCK_DGRAM)?;
+            let (addr, len) = socket_addr_to_c(addr);
+            cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
+            Ok(UdpSocket { inner: sock })
+        }
     }
 
     #[inline]
@@ -822,9 +824,13 @@ impl UdpSocket {
         Ok(ret as usize)
     }
 
-    pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
-        let (addr, len) = socket_addr_to_c(addr?);
-        cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
+    pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
+        return each_addr(addr, |addr| inner(self, addr));
+
+        fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
+            let (addr, len) = socket_addr_to_c(addr);
+            cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
+        }
     }
 }
 
diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs
index 16e3487a174..00368042873 100644
--- a/library/std/src/sys/net/connection/uefi/mod.rs
+++ b/library/std/src/sys/net/connection/uefi/mod.rs
@@ -1,6 +1,7 @@
+use super::each_addr;
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
 use crate::sync::{Arc, Mutex};
 use crate::sys::unsupported;
 use crate::time::Duration;
@@ -15,13 +16,17 @@ pub struct TcpStream {
 }
 
 impl TcpStream {
-    pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
-        let inner = tcp::Tcp::connect(addr?, None)?;
-        Ok(Self {
-            inner,
-            read_timeout: Arc::new(Mutex::new(None)),
-            write_timeout: Arc::new(Mutex::new(None)),
-        })
+    pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
+        return each_addr(addr, inner);
+
+        fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
+            let inner = tcp::Tcp::connect(addr, None)?;
+            Ok(TcpStream {
+                inner,
+                read_timeout: Arc::new(Mutex::new(None)),
+                write_timeout: Arc::new(Mutex::new(None)),
+            })
+        }
     }
 
     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
@@ -145,7 +150,7 @@ pub struct TcpListener {
 }
 
 impl TcpListener {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
+    pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
         unsupported()
     }
 
@@ -195,7 +200,7 @@ impl fmt::Debug for TcpListener {
 pub struct UdpSocket(!);
 
 impl UdpSocket {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
+    pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
         unsupported()
     }
 
@@ -315,7 +320,7 @@ impl UdpSocket {
         self.0
     }
 
-    pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
+    pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
         self.0
     }
 }
diff --git a/library/std/src/sys/net/connection/unsupported.rs b/library/std/src/sys/net/connection/unsupported.rs
index da217439626..fbc86343272 100644
--- a/library/std/src/sys/net/connection/unsupported.rs
+++ b/library/std/src/sys/net/connection/unsupported.rs
@@ -1,13 +1,13 @@
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
 use crate::sys::unsupported;
 use crate::time::Duration;
 
 pub struct TcpStream(!);
 
 impl TcpStream {
-    pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
+    pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
         unsupported()
     }
 
@@ -121,7 +121,7 @@ impl fmt::Debug for TcpStream {
 pub struct TcpListener(!);
 
 impl TcpListener {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
+    pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
         unsupported()
     }
 
@@ -171,7 +171,7 @@ impl fmt::Debug for TcpListener {
 pub struct UdpSocket(!);
 
 impl UdpSocket {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
+    pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
         unsupported()
     }
 
@@ -291,7 +291,7 @@ impl UdpSocket {
         self.0
     }
 
-    pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
+    pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
         self.0
     }
 }
diff --git a/library/std/src/sys/net/connection/wasip1.rs b/library/std/src/sys/net/connection/wasip1.rs
index 951dc65e5b4..cdfa25c8a44 100644
--- a/library/std/src/sys/net/connection/wasip1.rs
+++ b/library/std/src/sys/net/connection/wasip1.rs
@@ -2,7 +2,7 @@
 
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
 use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
 use crate::sys::fd::WasiFd;
 use crate::sys::{err2io, unsupported};
@@ -60,7 +60,7 @@ impl FromRawFd for Socket {
 }
 
 impl TcpStream {
-    pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
+    pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
         unsupported()
     }
 
@@ -212,7 +212,7 @@ pub struct TcpListener {
 }
 
 impl TcpListener {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
+    pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
         unsupported()
     }
 
@@ -316,7 +316,7 @@ pub struct UdpSocket {
 }
 
 impl UdpSocket {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
+    pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
         unsupported()
     }
 
@@ -436,7 +436,7 @@ impl UdpSocket {
         unsupported()
     }
 
-    pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
+    pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
         unsupported()
     }
 
diff --git a/library/std/src/sys/net/connection/xous/tcplistener.rs b/library/std/src/sys/net/connection/xous/tcplistener.rs
index bdf1fcd9302..8818ef2ca9a 100644
--- a/library/std/src/sys/net/connection/xous/tcplistener.rs
+++ b/library/std/src/sys/net/connection/xous/tcplistener.rs
@@ -2,9 +2,10 @@ use core::convert::TryInto;
 use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering};
 
 use super::*;
-use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
 use crate::os::xous::services;
 use crate::sync::Arc;
+use crate::sys::net::connection::each_addr;
 use crate::{fmt, io};
 
 macro_rules! unimpl {
@@ -25,16 +26,19 @@ pub struct TcpListener {
 }
 
 impl TcpListener {
-    pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
-        let mut addr = *socketaddr?;
-
-        let fd = TcpListener::bind_inner(&mut addr)?;
-        return Ok(TcpListener {
-            fd: Arc::new(AtomicU16::new(fd)),
-            local: addr,
-            handle_count: Arc::new(AtomicUsize::new(1)),
-            nonblocking: Arc::new(AtomicBool::new(false)),
-        });
+    pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
+        return each_addr(addr, inner);
+
+        fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
+            let mut addr = *addr;
+            let fd = TcpListener::bind_inner(&mut addr)?;
+            Ok(TcpListener {
+                fd: Arc::new(AtomicU16::new(fd)),
+                local: addr,
+                handle_count: Arc::new(AtomicUsize::new(1)),
+                nonblocking: Arc::new(AtomicBool::new(false)),
+            })
+        }
     }
 
     /// This returns the raw fd of a Listener, so that it can also be used by the
diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs
index 54524767452..4df75453d1f 100644
--- a/library/std/src/sys/net/connection/xous/tcpstream.rs
+++ b/library/std/src/sys/net/connection/xous/tcpstream.rs
@@ -3,9 +3,12 @@ use core::sync::atomic::{Atomic, AtomicBool, AtomicU32, AtomicUsize, Ordering};
 use super::*;
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
-use crate::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::net::{
+    IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
+};
 use crate::os::xous::services;
 use crate::sync::Arc;
+use crate::sys::net::connection::each_addr;
 use crate::time::Duration;
 
 macro_rules! unimpl {
@@ -79,8 +82,8 @@ impl TcpStream {
         }
     }
 
-    pub fn connect(socketaddr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
-        Self::connect_timeout(socketaddr?, Duration::ZERO)
+    pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
+        each_addr(addr, |addr| Self::connect_timeout(addr, Duration::ZERO))
     }
 
     pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> {
diff --git a/library/std/src/sys/net/connection/xous/udp.rs b/library/std/src/sys/net/connection/xous/udp.rs
index 2127d3267ed..ce54ea3b79e 100644
--- a/library/std/src/sys/net/connection/xous/udp.rs
+++ b/library/std/src/sys/net/connection/xous/udp.rs
@@ -3,9 +3,10 @@ use core::sync::atomic::{Atomic, AtomicUsize, Ordering};
 
 use super::*;
 use crate::cell::Cell;
-use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
 use crate::os::xous::services;
 use crate::sync::Arc;
+use crate::sys::net::connection::each_addr;
 use crate::time::Duration;
 use crate::{fmt, io};
 
@@ -32,40 +33,45 @@ pub struct UdpSocket {
 }
 
 impl UdpSocket {
-    pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
-        let addr = socketaddr?;
-        // Construct the request
-        let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
-
-        // Serialize the StdUdpBind structure. This is done "manually" because we don't want to
-        // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
-        let port_bytes = addr.port().to_le_bytes();
-        connect_request.raw[0] = port_bytes[0];
-        connect_request.raw[1] = port_bytes[1];
-        match addr.ip() {
-            IpAddr::V4(addr) => {
-                connect_request.raw[2] = 4;
-                for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
-                    *dest = src;
+    pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
+        return each_addr(addr, inner);
+
+        fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
+            // Construct the request
+            let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
+
+            // Serialize the StdUdpBind structure. This is done "manually" because we don't want to
+            // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
+            let port_bytes = addr.port().to_le_bytes();
+            connect_request.raw[0] = port_bytes[0];
+            connect_request.raw[1] = port_bytes[1];
+            match addr.ip() {
+                IpAddr::V4(addr) => {
+                    connect_request.raw[2] = 4;
+                    for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+                        *dest = src;
+                    }
                 }
-            }
-            IpAddr::V6(addr) => {
-                connect_request.raw[2] = 6;
-                for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
-                    *dest = src;
+                IpAddr::V6(addr) => {
+                    connect_request.raw[2] = 6;
+                    for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+                        *dest = src;
+                    }
                 }
             }
-        }
 
-        let response = crate::os::xous::ffi::lend_mut(
-            services::net_server(),
-            services::NetLendMut::StdUdpBind.into(),
-            &mut connect_request.raw,
-            0,
-            4096,
-        );
+            let response = crate::os::xous::ffi::lend_mut(
+                services::net_server(),
+                services::NetLendMut::StdUdpBind.into(),
+                &mut connect_request.raw,
+                0,
+                4096,
+            );
+
+            let Ok((_, valid)) = response else {
+                return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response"));
+            };
 
-        if let Ok((_, valid)) = response {
             // The first four bytes should be zero upon success, and will be nonzero
             // for an error.
             let response = connect_request.raw;
@@ -87,8 +93,9 @@ impl UdpSocket {
                     ));
                 }
             }
+
             let fd = response[1] as u16;
-            return Ok(UdpSocket {
+            Ok(UdpSocket {
                 fd,
                 local: *addr,
                 remote: Cell::new(None),
@@ -96,9 +103,8 @@ impl UdpSocket {
                 write_timeout: Cell::new(0),
                 handle_count: Arc::new(AtomicUsize::new(1)),
                 nonblocking: Cell::new(false),
-            });
+            })
         }
-        Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response"))
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
@@ -198,10 +204,11 @@ impl UdpSocket {
         self.peek_from(buf).map(|(len, _addr)| len)
     }
 
-    pub fn connect(&self, maybe_addr: io::Result<&SocketAddr>) -> io::Result<()> {
-        let addr = maybe_addr?;
-        self.remote.set(Some(*addr));
-        Ok(())
+    pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
+        each_addr(addr, |addr| {
+            self.remote.set(Some(*addr));
+            Ok(())
+        })
     }
 
     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
diff --git a/library/std/src/sys/net/mod.rs b/library/std/src/sys/net/mod.rs
index 5df1fe138ab..dffc4ea7f81 100644
--- a/library/std/src/sys/net/mod.rs
+++ b/library/std/src/sys/net/mod.rs
@@ -1,46 +1,4 @@
-cfg_select! {
-    any(
-        all(target_family = "unix", not(target_os = "l4re")),
-        target_os = "windows",
-        target_os = "hermit",
-        all(target_os = "wasi", target_env = "p2"),
-        target_os = "solid_asp3",
-    ) => {
-        mod connection {
-            mod socket;
-            pub use socket::*;
-        }
-    }
-    all(target_vendor = "fortanix", target_env = "sgx") => {
-        mod connection {
-            mod sgx;
-            pub use sgx::*;
-        }
-    }
-    all(target_os = "wasi", target_env = "p1") => {
-        mod connection {
-            mod wasip1;
-            pub use wasip1::*;
-        }
-    }
-    target_os = "xous" => {
-        mod connection {
-            mod xous;
-            pub use xous::*;
-        }
-    }
-    target_os = "uefi" => {
-        mod connection {
-            mod uefi;
-            pub use uefi::*;
-        }
-    }
-    _ => {
-        mod connection {
-            mod unsupported;
-            pub use unsupported::*;
-        }
-    }
-}
-
+/// This module contains the implementations of `TcpStream`, `TcpListener` and
+/// `UdpSocket` as well as related functionality like DNS resolving.
+mod connection;
 pub use connection::*;
diff --git a/library/std/tests/sync/barrier.rs b/library/std/tests/sync/barrier.rs
index 8aefff9d507..a66bd629699 100644
--- a/library/std/tests/sync/barrier.rs
+++ b/library/std/tests/sync/barrier.rs
@@ -1,3 +1,4 @@
+use std::panic::RefUnwindSafe;
 use std::sync::mpsc::{TryRecvError, channel};
 use std::sync::{Arc, Barrier};
 use std::thread;
@@ -33,3 +34,11 @@ fn test_barrier() {
     }
     assert!(leader_found);
 }
+
+/// Asserts that `Barrier` is ref unwind safe.
+///
+/// See <https://github.com/rust-lang/rust/issues/146087>.
+const _: () = {
+    const fn check_ref_unwind_safe<T: RefUnwindSafe>() {}
+    check_ref_unwind_safe::<Barrier>();
+};