Skip to content

Commit 5cda414

Browse files
committed
std::net: adding tcp_syncnt feature for Linux/Android.
to control the number of client's attempts to establish a connection.
1 parent 3b370cf commit 5cda414

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

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

+49
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,47 @@ pub trait TcpStreamExt: Sealed {
9898
#[unstable(feature = "tcp_deferaccept", issue = "119639")]
9999
#[cfg(target_os = "linux")]
100100
fn deferaccept(&self) -> io::Result<u32>;
101+
102+
/// Set the number of `SYN` packets to send before giving up establishing a connection.
103+
///
104+
/// In case the server does not repond, a `SYN` packet is sent by the client.
105+
/// This option controls the number of attempts, the default system value
106+
/// can be seen via the `net.ipv4.tcp_syn_retries` sysctl's OID (usually 5 or 6).
107+
/// The maximum valid value is 255.
108+
///
109+
/// See [`man 7 tcp`](https://man7.org/linux/man-pages/man7/tcp.7.html)
110+
///
111+
/// # Examples
112+
///
113+
/// ```no_run
114+
/// #![feature(tcp_syncnt)]
115+
/// use std::net::TcpStream;
116+
/// use std::os::linux::net::TcpStreamExt;
117+
///
118+
/// let stream = TcpStream::connect("127.0.0.1:8080")
119+
/// .expect("Couldn't connect to the server...");
120+
/// stream.set_syncnt(3).expect("set_setcnt call failed");
121+
#[unstable(feature = "tcp_syncnt", issue = "123112")]
122+
fn set_syncnt(&self, count: u8) -> io::Result<()>;
123+
124+
/// Get the number of `SYN` packets to send before giving up establishing a connection.
125+
///
126+
/// For more information about this option, see [`TcpStreamExt::set_syncnt`].
127+
///
128+
/// # Examples
129+
///
130+
/// ```no_run
131+
/// #![feature(tcp_syncnt)]
132+
/// use std::net::TcpStream;
133+
/// use std::os::linux::net::TcpStreamExt;
134+
///
135+
/// let stream = TcpStream::connect("127.0.0.1:8080")
136+
/// .expect("Couldn't connect to the server...");
137+
/// stream.set_syncnt(3).expect("set_syncnt call failed");
138+
/// assert_eq!(stream.syncnt().unwrap_or(0), 3);
139+
/// ```
140+
#[unstable(feature = "tcp_syncnt", issue = "123112")]
141+
fn syncnt(&self) -> io::Result<u8>;
101142
}
102143

103144
#[unstable(feature = "tcp_quickack", issue = "96256")]
@@ -122,4 +163,12 @@ impl TcpStreamExt for net::TcpStream {
122163
fn deferaccept(&self) -> io::Result<u32> {
123164
self.as_inner().as_inner().deferaccept()
124165
}
166+
167+
fn set_syncnt(&self, count: u8) -> io::Result<()> {
168+
self.as_inner().as_inner().set_syncnt(count)
169+
}
170+
171+
fn syncnt(&self) -> io::Result<u8> {
172+
self.as_inner().as_inner().syncnt()
173+
}
125174
}

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

+11
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,17 @@ impl Socket {
453453
Ok(raw as u32)
454454
}
455455

456+
#[cfg(any(target_os = "android", target_os = "linux",))]
457+
pub fn set_syncnt(&self, count: u8) -> io::Result<()> {
458+
setsockopt(self, libc::IPPROTO_TCP, libc::TCP_SYNCNT, count as c_int)
459+
}
460+
461+
#[cfg(any(target_os = "android", target_os = "linux",))]
462+
pub fn syncnt(&self) -> io::Result<u8> {
463+
let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_SYNCNT)?;
464+
Ok(raw as u8)
465+
}
466+
456467
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
457468
pub fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
458469
if !name.to_bytes().is_empty() {

0 commit comments

Comments
 (0)