mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
os::net: expanding TcpStreamExt for Linux with tcp_deferaccept
.
allows for socket to process only when there is data to process, the option sets a number of seconds until the data is ready.
This commit is contained in:
parent
f8131a48a4
commit
85bf4439e6
@ -53,6 +53,51 @@ pub trait TcpStreamExt: Sealed {
|
||||
/// ```
|
||||
#[unstable(feature = "tcp_quickack", issue = "96256")]
|
||||
fn quickack(&self) -> io::Result<bool>;
|
||||
|
||||
/// A socket listener will be awakened solely when data arrives.
|
||||
///
|
||||
/// The `accept` argument set the delay in seconds 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.
|
||||
///
|
||||
/// See [`man 7 tcp`](https://man7.org/linux/man-pages/man7/tcp.7.html)
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no run
|
||||
/// #![feature(tcp_deferaccept)]
|
||||
/// use std::net::TcpStream;
|
||||
/// use std::os::linux::net::TcpStreamExt;
|
||||
///
|
||||
/// 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");
|
||||
/// ```
|
||||
#[unstable(feature = "tcp_deferaccept", issue = "119639")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn set_deferaccept(&self, accept: u32) -> io::Result<()>;
|
||||
|
||||
/// Gets the accept delay value (in seconds) of the `TCP_DEFER_ACCEPT` option.
|
||||
///
|
||||
/// For more information about this option, see [`TcpStreamExt::set_deferaccept`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(tcp_deferaccept)]
|
||||
/// use std::net::TcpStream;
|
||||
/// use std::os::linux::net::TcpStreamExt;
|
||||
///
|
||||
/// 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);
|
||||
/// ```
|
||||
#[unstable(feature = "tcp_deferaccept", issue = "119639")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn deferaccept(&self) -> io::Result<u32>;
|
||||
}
|
||||
|
||||
#[unstable(feature = "tcp_quickack", issue = "96256")]
|
||||
@ -67,4 +112,14 @@ impl TcpStreamExt for net::TcpStream {
|
||||
fn quickack(&self) -> io::Result<bool> {
|
||||
self.as_inner().as_inner().quickack()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn set_deferaccept(&self, accept: u32) -> io::Result<()> {
|
||||
self.as_inner().as_inner().set_deferaccept(accept)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn deferaccept(&self) -> io::Result<u32> {
|
||||
self.as_inner().as_inner().deferaccept()
|
||||
}
|
||||
}
|
||||
|
@ -26,3 +26,29 @@ fn quickack() {
|
||||
t!(stream.set_quickack(false));
|
||||
assert_eq!(false, t!(stream.quickack()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn deferaccept() {
|
||||
use crate::{
|
||||
net::{test::next_test_ip4, TcpListener, TcpStream},
|
||||
os::net::linux_ext::tcp::TcpStreamExt,
|
||||
};
|
||||
|
||||
macro_rules! t {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Ok(t) => t,
|
||||
Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let addr = next_test_ip4();
|
||||
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);
|
||||
}
|
||||
|
@ -441,6 +441,18 @@ impl Socket {
|
||||
Ok(raw != 0)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn deferaccept(&self) -> io::Result<u32> {
|
||||
let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_DEFER_ACCEPT)?;
|
||||
Ok(raw as u32)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux",))]
|
||||
pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
|
||||
setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)
|
||||
|
Loading…
Reference in New Issue
Block a user