Skip to content

Commit ee285ea

Browse files
committed
Auto merge of rust-lang#96324 - berendjan:set_tcp_quickack, r=dtolnay
Add setter and getter for TCP_QUICKACK on TcpStream for Linux Reference issue rust-lang#96256 Setting TCP_QUICKACK on TcpStream for Linux
2 parents 3fdd578 + 786e875 commit ee285ea

File tree

11 files changed

+138
-2
lines changed

11 files changed

+138
-2
lines changed

library/std/src/net/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ mod ip;
4141
mod parser;
4242
mod tcp;
4343
#[cfg(test)]
44-
mod test;
44+
pub(crate) mod test;
4545
mod udp;
4646

4747
/// Possible values which can be passed to the [`TcpStream::shutdown`] method.

library/std/src/os/android/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
#![stable(feature = "raw_ext", since = "1.1.0")]
44

55
pub mod fs;
6+
pub mod net;
67
pub mod raw;

library/std/src/os/android/net.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! Linux and Android-specific definitions for socket options.
2+
3+
#![unstable(feature = "tcp_quickack", issue = "96256")]
4+
pub use crate::os::net::tcp::TcpStreamExt;

library/std/src/os/linux/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
#![doc(cfg(target_os = "linux"))]
55

66
pub mod fs;
7+
pub mod net;
78
pub mod process;
89
pub mod raw;

library/std/src/os/linux/net.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! Linux and Android-specific definitions for socket options.
2+
3+
#![unstable(feature = "tcp_quickack", issue = "96256")]
4+
pub use crate::os::net::tcp::TcpStreamExt;

library/std/src/os/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,6 @@ pub mod vxworks;
148148

149149
#[cfg(any(unix, target_os = "wasi", doc))]
150150
mod fd;
151+
152+
#[cfg(any(target_os = "linux", target_os = "android", doc))]
153+
mod net;

library/std/src/os/net/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! Linux and Android-specific definitions for socket options.
2+
3+
#![unstable(feature = "tcp_quickack", issue = "96256")]
4+
#![doc(cfg(any(target_os = "linux", target_os = "android",)))]
5+
pub mod tcp;
6+
#[cfg(test)]
7+
mod tests;

library/std/src/os/net/tcp.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//! Linux and Android-specific tcp extensions to primitives in the [`std::net`] module.
2+
//!
3+
//! [`std::net`]: crate::net
4+
5+
use crate::io;
6+
use crate::net;
7+
use crate::sealed::Sealed;
8+
use crate::sys_common::AsInner;
9+
10+
/// Os-specific extensions for [`TcpStream`]
11+
///
12+
/// [`TcpStream`]: net::TcpStream
13+
#[unstable(feature = "tcp_quickack", issue = "96256")]
14+
pub trait TcpStreamExt: Sealed {
15+
/// Enable or disable `TCP_QUICKACK`.
16+
///
17+
/// This flag causes Linux to eagerly send ACKs rather than delaying them.
18+
/// Linux may reset this flag after further operations on the socket.
19+
///
20+
/// See [`man 7 tcp`](https://man7.org/linux/man-pages/man7/tcp.7.html) and
21+
/// [TCP delayed acknowledgement](https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment)
22+
/// for more information.
23+
///
24+
/// # Examples
25+
///
26+
/// ```no_run
27+
/// #![feature(tcp_quickack)]
28+
/// use std::net::TcpStream;
29+
/// use std::os::linux::net::TcpStreamExt;
30+
///
31+
/// let stream = TcpStream::connect("127.0.0.1:8080")
32+
/// .expect("Couldn't connect to the server...");
33+
/// stream.set_quickack(true).expect("set_quickack call failed");
34+
/// ```
35+
#[unstable(feature = "tcp_quickack", issue = "96256")]
36+
fn set_quickack(&self, quickack: bool) -> io::Result<()>;
37+
38+
/// Gets the value of the `TCP_QUICKACK` option on this socket.
39+
///
40+
/// For more information about this option, see [`TcpStreamExt::set_quickack`].
41+
///
42+
/// # Examples
43+
///
44+
/// ```no_run
45+
/// #![feature(tcp_quickack)]
46+
/// use std::net::TcpStream;
47+
/// use std::os::linux::net::TcpStreamExt;
48+
///
49+
/// let stream = TcpStream::connect("127.0.0.1:8080")
50+
/// .expect("Couldn't connect to the server...");
51+
/// stream.set_quickack(true).expect("set_quickack call failed");
52+
/// assert_eq!(stream.quickack().unwrap_or(false), true);
53+
/// ```
54+
#[unstable(feature = "tcp_quickack", issue = "96256")]
55+
fn quickack(&self) -> io::Result<bool>;
56+
}
57+
58+
#[unstable(feature = "tcp_quickack", issue = "96256")]
59+
impl Sealed for net::TcpStream {}
60+
61+
#[unstable(feature = "tcp_quickack", issue = "96256")]
62+
impl TcpStreamExt for net::TcpStream {
63+
fn set_quickack(&self, quickack: bool) -> io::Result<()> {
64+
self.as_inner().as_inner().set_quickack(quickack)
65+
}
66+
67+
fn quickack(&self) -> io::Result<bool> {
68+
self.as_inner().as_inner().quickack()
69+
}
70+
}

library/std/src/os/net/tests.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#[cfg(any(target_os = "android", target_os = "linux",))]
2+
#[test]
3+
fn quickack() {
4+
use crate::{
5+
net::{test::next_test_ip4, TcpListener, TcpStream},
6+
os::net::tcp::TcpStreamExt,
7+
};
8+
9+
macro_rules! t {
10+
($e:expr) => {
11+
match $e {
12+
Ok(t) => t,
13+
Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
14+
}
15+
};
16+
}
17+
18+
let addr = next_test_ip4();
19+
let _listener = t!(TcpListener::bind(&addr));
20+
21+
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
22+
23+
t!(stream.set_quickack(false));
24+
assert_eq!(false, t!(stream.quickack()));
25+
t!(stream.set_quickack(true));
26+
assert_eq!(true, t!(stream.quickack()));
27+
t!(stream.set_quickack(false));
28+
assert_eq!(false, t!(stream.quickack()));
29+
}

library/std/src/sys/unix/net.rs

+11
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,17 @@ impl Socket {
392392
Ok(raw != 0)
393393
}
394394

395+
#[cfg(any(target_os = "android", target_os = "linux",))]
396+
pub fn set_quickack(&self, quickack: bool) -> io::Result<()> {
397+
setsockopt(self, libc::IPPROTO_TCP, libc::TCP_QUICKACK, quickack as c_int)
398+
}
399+
400+
#[cfg(any(target_os = "android", target_os = "linux",))]
401+
pub fn quickack(&self) -> io::Result<bool> {
402+
let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_QUICKACK)?;
403+
Ok(raw != 0)
404+
}
405+
395406
#[cfg(any(target_os = "android", target_os = "linux",))]
396407
pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
397408
setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)

library/std/src/sys_common/net.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
1010
use crate::ptr;
1111
use crate::sys::net::netc as c;
1212
use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
13-
use crate::sys_common::{FromInner, IntoInner};
13+
use crate::sys_common::{AsInner, FromInner, IntoInner};
1414
use crate::time::Duration;
1515

1616
use libc::{c_int, c_void};
@@ -345,6 +345,12 @@ impl TcpStream {
345345
}
346346
}
347347

348+
impl AsInner<Socket> for TcpStream {
349+
fn as_inner(&self) -> &Socket {
350+
&self.inner
351+
}
352+
}
353+
348354
impl FromInner<Socket> for TcpStream {
349355
fn from_inner(socket: Socket) -> TcpStream {
350356
TcpStream { inner: socket }

0 commit comments

Comments
 (0)