From c0de794949f652b368fa107c3b52d0515f1f3859 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 29 Apr 2025 19:01:08 +0100 Subject: [PATCH 1/2] std::net: update tcp deferaccept delay type to Duration. --- library/std/src/os/net/linux_ext/tcp.rs | 23 +++++++++++-------- library/std/src/os/net/linux_ext/tests.rs | 11 +++++---- .../std/src/sys/net/connection/socket/unix.rs | 9 ++++---- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs index fde53ec4257bd..dbefc91a979a5 100644 --- a/library/std/src/os/net/linux_ext/tcp.rs +++ b/library/std/src/os/net/linux_ext/tcp.rs @@ -4,6 +4,7 @@ use crate::sealed::Sealed; use crate::sys_common::AsInner; +use crate::time::Duration; use crate::{io, net}; /// Os-specific extensions for [`TcpStream`] @@ -59,11 +60,13 @@ pub trait TcpStreamExt: Sealed { /// A socket listener will be awakened solely when data arrives. /// - /// The `accept` argument set the delay in seconds until the + /// The `accept` argument set the maximum delay until the /// data is available to read, reducing the number of short lived /// connections without data to process. /// Contrary to other platforms `SO_ACCEPTFILTER` feature equivalent, there is /// no necessity to set it after the `listen` call. + /// Note that the delay is expressed as Duration from user's perspective + /// the call rounds it down to the nearest second expressible as a `c_int`. /// /// See [`man 7 tcp`](https://man7.org/linux/man-pages/man7/tcp.7.html) /// @@ -73,16 +76,17 @@ pub trait TcpStreamExt: Sealed { /// #![feature(tcp_deferaccept)] /// use std::net::TcpStream; /// use std::os::linux::net::TcpStreamExt; + /// use std::time::Duration; /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); - /// stream.set_deferaccept(1).expect("set_deferaccept call failed"); + /// stream.set_deferaccept(Duration::from_secs(1u64)).expect("set_deferaccept call failed"); /// ``` #[unstable(feature = "tcp_deferaccept", issue = "119639")] #[cfg(target_os = "linux")] - fn set_deferaccept(&self, accept: u32) -> io::Result<()>; + fn set_deferaccept(&self, accept: Duration) -> io::Result<()>; - /// Gets the accept delay value (in seconds) of the `TCP_DEFER_ACCEPT` option. + /// Gets the accept delay value of the `TCP_DEFER_ACCEPT` option. /// /// For more information about this option, see [`TcpStreamExt::set_deferaccept`]. /// @@ -92,15 +96,16 @@ pub trait TcpStreamExt: Sealed { /// #![feature(tcp_deferaccept)] /// use std::net::TcpStream; /// use std::os::linux::net::TcpStreamExt; + /// use std::time::Duration; /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); - /// stream.set_deferaccept(1).expect("set_deferaccept call failed"); - /// assert_eq!(stream.deferaccept().unwrap_or(0), 1); + /// stream.set_deferaccept(Duration::from_secs(1u64)).expect("set_deferaccept call failed"); + /// assert_eq!(stream.deferaccept().unwrap(), Duration::from_secs(1u64)); /// ``` #[unstable(feature = "tcp_deferaccept", issue = "119639")] #[cfg(target_os = "linux")] - fn deferaccept(&self) -> io::Result; + fn deferaccept(&self) -> io::Result; } #[stable(feature = "tcp_quickack", since = "1.89.0")] @@ -117,12 +122,12 @@ impl TcpStreamExt for net::TcpStream { } #[cfg(target_os = "linux")] - fn set_deferaccept(&self, accept: u32) -> io::Result<()> { + fn set_deferaccept(&self, accept: Duration) -> io::Result<()> { self.as_inner().as_inner().set_deferaccept(accept) } #[cfg(target_os = "linux")] - fn deferaccept(&self) -> io::Result { + fn deferaccept(&self) -> io::Result { self.as_inner().as_inner().deferaccept() } } diff --git a/library/std/src/os/net/linux_ext/tests.rs b/library/std/src/os/net/linux_ext/tests.rs index 12f35696abc5c..0758b426ccc59 100644 --- a/library/std/src/os/net/linux_ext/tests.rs +++ b/library/std/src/os/net/linux_ext/tests.rs @@ -32,6 +32,7 @@ fn deferaccept() { use crate::net::test::next_test_ip4; use crate::net::{TcpListener, TcpStream}; use crate::os::net::linux_ext::tcp::TcpStreamExt; + use crate::time::Duration; macro_rules! t { ($e:expr) => { @@ -43,10 +44,12 @@ fn deferaccept() { } let addr = next_test_ip4(); + let one = Duration::from_secs(1u64); + let zero = Duration::from_secs(0u64); let _listener = t!(TcpListener::bind(&addr)); let stream = t!(TcpStream::connect(&("localhost", addr.port()))); - stream.set_deferaccept(1).expect("set_deferaccept failed"); - assert_eq!(stream.deferaccept().unwrap(), 1); - stream.set_deferaccept(0).expect("set_deferaccept failed"); - assert_eq!(stream.deferaccept().unwrap(), 0); + stream.set_deferaccept(one).expect("set_deferaccept failed"); + assert_eq!(stream.deferaccept().unwrap(), one); + stream.set_deferaccept(zero).expect("set_deferaccept failed"); + assert_eq!(stream.deferaccept().unwrap(), zero); } diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index 8b5970d1494e5..86b966242bf38 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -485,14 +485,15 @@ impl Socket { // bionic libc makes no use of this flag #[cfg(target_os = "linux")] - pub fn set_deferaccept(&self, accept: u32) -> io::Result<()> { - setsockopt(self, libc::IPPROTO_TCP, libc::TCP_DEFER_ACCEPT, accept as c_int) + pub fn set_deferaccept(&self, accept: Duration) -> io::Result<()> { + let val = cmp::min(accept.as_secs(), c_int::MAX as u64) as c_int; + setsockopt(self, libc::IPPROTO_TCP, libc::TCP_DEFER_ACCEPT, val) } #[cfg(target_os = "linux")] - pub fn deferaccept(&self) -> io::Result { + pub fn deferaccept(&self) -> io::Result { let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_DEFER_ACCEPT)?; - Ok(raw as u32) + Ok(Duration::from_secs(raw as _)) } #[cfg(any(target_os = "freebsd", target_os = "netbsd"))] From 19d0e728496afa1ba6a5f9817201b7d57337c14c Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 27 Sep 2025 20:38:45 +0100 Subject: [PATCH 2/2] fix build for android --- library/std/src/os/net/linux_ext/tcp.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs index dbefc91a979a5..3f9b2bd3f4b43 100644 --- a/library/std/src/os/net/linux_ext/tcp.rs +++ b/library/std/src/os/net/linux_ext/tcp.rs @@ -4,6 +4,7 @@ use crate::sealed::Sealed; use crate::sys_common::AsInner; +#[cfg(target_os = "linux")] use crate::time::Duration; use crate::{io, net};