Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions library/std/src/net/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,57 @@ impl TcpStream {
self.0.linger()
}

/// Sets the value of the `SO_KEEPALIVE` option on this socket.
///
/// If set to `true`, the operating system will periodically send keepalive
/// probes on an idle connection to verify that the remote peer is still
/// reachable. If the peer fails to respond after a system-determined number
/// of probes, the connection is considered broken and subsequent I/O calls
/// will return an error.
///
/// This is useful for detecting dead peers on long-lived connections where
/// no application-level traffic is exchanged, such as database or SSH
/// connections.
///
/// The timing and frequency of keepalive probes are controlled by
/// system-level settings and are not configured by this method alone.
///
/// # Examples
///
/// ```no_run
/// #![feature(tcp_keepalive)]
///
/// use std::net::TcpStream;
///
/// let stream = TcpStream::connect("127.0.0.1:8080")
/// .expect("Couldn't connect to the server...");
/// stream.set_keepalive(true).expect("set_keepalive call failed");
#[unstable(feature = "tcp_keepalive", issue = "69774")]
pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
self.0.set_keepalive(keepalive)
}

/// Gets the value of the `SO_KEEPALIVE` option on this socket.
///
/// For more information about this option, see [`TcpStream::set_keepalive`].
///
/// # Examples
///
/// ```no_run
/// #![feature(tcp_keepalive)]
///
/// use std::net::TcpStream;
///
/// let stream = TcpStream::connect("127.0.0.1:8080")
/// .expect("Couldn't connect to the server...");
/// stream.set_keepalive(true).expect("set_keepalive call failed");
/// assert_eq!(stream.keepalive().unwrap_or(false), true);
/// ```
#[unstable(feature = "tcp_keepalive", issue = "69774")]
pub fn keepalive(&self) -> io::Result<bool> {
self.0.keepalive()
}

/// Sets the value of the `TCP_NODELAY` option on this socket.
///
/// If set, this option disables the Nagle algorithm. This means that
Expand Down
15 changes: 15 additions & 0 deletions library/std/src/net/tcp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,21 @@ fn linger() {
assert_eq!(None, t!(stream.linger()));
}

#[test]
#[cfg_attr(target_env = "sgx", ignore)]
#[cfg_attr(target_os = "wasi", ignore)]
fn keepalive() {
let addr = next_test_ip4();
let _listener = t!(TcpListener::bind(&addr));
let stream = t!(TcpStream::connect(&addr));

assert_eq!(false, t!(stream.keepalive()));
t!(stream.set_keepalive(true));
assert_eq!(true, t!(stream.keepalive()));
t!(stream.set_keepalive(false));
assert_eq!(false, t!(stream.keepalive()));
}

#[test]
#[cfg_attr(target_env = "sgx", ignore)]
fn nodelay() {
Expand Down
10 changes: 9 additions & 1 deletion library/std/src/sys/net/connection/motor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::net::SocketAddr::{V4, V6};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::FileDesc;
use crate::sys::{AsInner, FromInner, IntoInner, map_motor_error};
use crate::sys::{AsInner, FromInner, IntoInner, map_motor_error, unsupported};
use crate::time::Duration;

// We want to re-use as much of Rust's stdlib code as possible,
Expand Down Expand Up @@ -127,6 +127,14 @@ impl TcpStream {
moto_rt::net::linger(self.inner.as_raw_fd()).map_err(map_motor_error)
}

pub fn set_keepalive(&self, _: bool) -> io::Result<()> {
unsupported()
}

pub fn keepalive(&self) -> io::Result<bool> {
unsupported()
}

pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
moto_rt::net::set_nodelay(self.inner.as_raw_fd(), nodelay).map_err(map_motor_error)
}
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sys/net/connection/sgx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ impl TcpStream {
sgx_ineffective(None)
}

pub fn set_keepalive(&self, _: bool) -> io::Result<()> {
sgx_ineffective(())
}

pub fn keepalive(&self) -> io::Result<bool> {
sgx_ineffective(false)
}

pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
sgx_ineffective(())
}
Expand Down
9 changes: 9 additions & 0 deletions library/std/src/sys/net/connection/socket/hermit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,15 @@ impl Socket {
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}

pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
unsafe { setsockopt(self, netc::SOL_SOCKET, netc::SO_KEEPALIVE, keepalive as c_int) }
}

pub fn keepalive(&self) -> io::Result<bool> {
let raw: c_int = unsafe { getsockopt(self, netc::SOL_SOCKET, netc::SO_KEEPALIVE)? };
Ok(raw != 0)
}

pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
let value: i32 = if nodelay { 1 } else { 0 };
unsafe { setsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY, value) }
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sys/net/connection/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,14 @@ impl TcpStream {
self.inner.linger()
}

pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
self.inner.set_keepalive(keepalive)
}

pub fn keepalive(&self) -> io::Result<bool> {
self.inner.keepalive()
}

pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
self.inner.set_nodelay(nodelay)
}
Expand Down
9 changes: 9 additions & 0 deletions library/std/src/sys/net/connection/socket/solid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::ffi::CStr;
use crate::io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr};
use crate::os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd};
use crate::sys::pal::unsupported;
use crate::sys::{FromInner, IntoInner, abi};
use crate::time::Duration;
use crate::{cmp, mem, ptr, str};
Expand Down Expand Up @@ -332,6 +333,14 @@ impl Socket {
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}

pub fn set_keepalive(&self, _: bool) -> io::Result<()> {
unsupported()
}

pub fn keepalive(&self) -> io::Result<bool> {
unsupported()
}

pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
unsafe { setsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY, nodelay as c_int) }
}
Expand Down
9 changes: 9 additions & 0 deletions library/std/src/sys/net/connection/socket/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,15 @@ impl Socket {
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}

pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
unsafe { setsockopt(self, libc::SOL_SOCKET, libc::SO_KEEPALIVE, keepalive as c_int) }
}

pub fn keepalive(&self) -> io::Result<bool> {
let raw: c_int = unsafe { getsockopt(self, libc::SOL_SOCKET, libc::SO_KEEPALIVE)? };
Ok(raw != 0)
}

pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
unsafe { setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int) }
}
Expand Down
9 changes: 9 additions & 0 deletions library/std/src/sys/net/connection/socket/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,15 @@ impl Socket {
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}

pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
unsafe { setsockopt(self, c::SOL_SOCKET, c::SO_KEEPALIVE, keepalive as c::BOOL) }
}

pub fn keepalive(&self) -> io::Result<bool> {
let raw: c::BOOL = unsafe { getsockopt(self, c::SOL_SOCKET, c::SO_KEEPALIVE)? };
Ok(raw != 0)
}

pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
unsafe { setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL) }
}
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sys/net/connection/uefi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ impl TcpStream {
unsupported()
}

pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
unsupported()
}

pub fn keepalive(&self) -> io::Result<bool> {
unsupported()
}

pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
unsupported()
}
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sys/net/connection/unsupported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ impl TcpStream {
self.0
}

pub fn set_keepalive(&self, _: bool) -> io::Result<()> {
self.0
}

pub fn keepalive(&self) -> io::Result<bool> {
self.0
}

pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
self.0
}
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sys/net/connection/wasip1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ impl TcpStream {
unsupported()
}

pub fn set_keepalive(&self, _: bool) -> io::Result<()> {
unsupported()
}

pub fn keepalive(&self) -> io::Result<bool> {
unsupported()
}

pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
unsupported()
}
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sys/net/connection/xous/tcpstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,14 @@ impl TcpStream {
unimpl!();
}

pub fn set_keepalive(&self, _: bool) -> io::Result<()> {
unimpl!();
}

pub fn keepalive(&self) -> io::Result<bool> {
unimpl!();
}

pub fn set_nodelay(&self, enabled: bool) -> io::Result<()> {
crate::os::xous::ffi::blocking_scalar(
services::net_server(),
Expand Down
1 change: 1 addition & 0 deletions library/std/src/sys/pal/windows/c/bindings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2388,6 +2388,7 @@ SleepConditionVariableSRW
SleepEx
SO_BROADCAST
SO_ERROR
SO_KEEPALIVE
SO_LINGER
SO_RCVTIMEO
SO_SNDTIMEO
Expand Down
1 change: 1 addition & 0 deletions library/std/src/sys/pal/windows/c/windows_sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3189,6 +3189,7 @@ pub const SOCK_STREAM: WINSOCK_SOCKET_TYPE = 1i32;
pub const SOL_SOCKET: i32 = 65535i32;
pub const SO_BROADCAST: i32 = 32i32;
pub const SO_ERROR: i32 = 4103i32;
pub const SO_KEEPALIVE: i32 = 8i32;
pub const SO_LINGER: i32 = 128i32;
pub const SO_RCVTIMEO: i32 = 4102i32;
pub const SO_SNDTIMEO: i32 = 4101i32;
Expand Down