Rollup merge of #140482 - devnexen:tcp_deferaccept_toduration, r=joboet

std::net: update tcp deferaccept delay type to Duration.

See comment [here](https://github.com/rust-lang/rust/issues/119639#issuecomment-2839330337).
This commit is contained in:
Matthias Krüger 2025-09-28 18:13:10 +02:00 committed by GitHub
commit 322dca8551
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 17 deletions

View file

@ -4,6 +4,8 @@
use crate::sealed::Sealed;
use crate::sys_common::AsInner;
#[cfg(target_os = "linux")]
use crate::time::Duration;
use crate::{io, net};
/// Os-specific extensions for [`TcpStream`]
@ -59,11 +61,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 +77,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 +97,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<u32>;
fn deferaccept(&self) -> io::Result<Duration>;
}
#[stable(feature = "tcp_quickack", since = "1.89.0")]
@ -117,12 +123,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<u32> {
fn deferaccept(&self) -> io::Result<Duration> {
self.as_inner().as_inner().deferaccept()
}
}

View file

@ -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);
}

View file

@ -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<u32> {
pub fn deferaccept(&self) -> io::Result<Duration> {
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"))]