Skip to content

Commit

Permalink
tcp: add separate APIs for every keepalive option
Browse files Browse the repository at this point in the history
Signed-off-by: Eliza Weisman <[email protected]>
  • Loading branch information
hawkw committed Nov 3, 2020
1 parent 0f52a28 commit 13cdfe0
Show file tree
Hide file tree
Showing 5 changed files with 450 additions and 97 deletions.
130 changes: 107 additions & 23 deletions src/net/tcp/socket.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::net::{TcpStream, TcpListener};
use crate::net::{TcpListener, TcpStream};
use crate::sys;

use std::io;
use std::mem;
use std::net::SocketAddr;
use std::time::Duration;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::time::Duration;

/// A non-blocking TCP socket used to configure a stream or listener.
///
Expand All @@ -27,18 +27,14 @@ impl TcpSocket {
///
/// This calls `socket(2)`.
pub fn new_v4() -> io::Result<TcpSocket> {
sys::tcp::new_v4_socket().map(|sys| TcpSocket {
sys
})
sys::tcp::new_v4_socket().map(|sys| TcpSocket { sys })
}

/// Create a new IPv6 TCP socket.
///
/// This calls `socket(2)`.
pub fn new_v6() -> io::Result<TcpSocket> {
sys::tcp::new_v6_socket().map(|sys| TcpSocket {
sys
})
sys::tcp::new_v6_socket().map(|sys| TcpSocket { sys })
}

pub(crate) fn new_for_addr(addr: SocketAddr) -> io::Result<TcpSocket> {
Expand Down Expand Up @@ -163,32 +159,118 @@ impl TcpSocket {
pub fn get_send_buffer_size(&self) -> io::Result<u32> {
sys::tcp::get_send_buffer_size(self.sys)
}

/// Sets whether keepalive messages are enabled to be sent on this socket.
///
/// On Unix, this option will set the `SO_KEEPALIVE` as well as the
/// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
/// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
/// This will set the `SO_KEEPALIVE` option on this socket.
pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
sys::tcp::set_keepalive(self.sys, keepalive)
}

/// Returns whether or not TCP keepalive probes will be sent by this socket.
pub fn get_keepalive(&self) -> io::Result<bool> {
sys::tcp::get_keepalive(self.sys)
}

/// Sets the amount of time after which TCP keepalive probes will be sent
/// on idle connections, if TCP keepalive is enabled on this socket.
///
/// If `None` is specified then keepalive messages are disabled, otherwise
/// the duration specified will be the time to remain idle before sending a
/// TCP keepalive probe.
/// This sets the value of `SO_KEEPALIVE` + `IPPROTO_TCP` on OpenBSD,
/// NetBSD, and Haiku, `TCP_KEEPALIVE` on macOS and iOS, and `TCP_KEEPIDLE`
/// on all other Unix operating systems. On Windows, this sets the value of
/// the `tcp_keepalive` struct's `keepalivetime` field.
///
/// Some platforms specify this value in seconds, so sub-second
/// specifications may be omitted.
pub fn set_keepalive(&self, dur: Option<Duration>) -> io::Result<()> {
sys::tcp::set_keepalive(self.sys, dur)
///
/// The OS may return an error if TCP keepalive was not already enabled by
/// calling `set_keepalive(true)` on this socket.
pub fn set_keepalive_time(&self, time: Duration) -> io::Result<()> {
sys::tcp::set_keepalive_time(self.sys, time)
}

/// Returns the duration after which TCP keepalive probes will be sent, if
/// keepalive messages are enabled to be sent on this socket.
/// Returns the amount of time after which TCP keepalive probes will be sent
/// on idle connections.
///
/// If `None`, then keepalive messages are disabled.
///
/// This returns the value of `SO_KEEPALIVE` + `IPPROTO_TCP` on OpenBSD,
/// NetBSD, and Haiku, `TCP_KEEPALIVE` on macOS and iOS, and `TCP_KEEPIDLE`
/// on all other Unix operating systems. On Windows, this returns the value of
/// the `tcp_keepalive` struct's `keepalivetime` field.
///
/// Some platforms specify this value in seconds, so sub-second
/// specifications may be omitted.
pub fn get_keepalive(&self) -> io::Result<Option<Duration>> {
sys::tcp::get_keepalive(self.sys)
pub fn get_keepalive_time(&self) -> io::Result<Option<Duration>> {
sys::tcp::get_keepalive_time(self.sys)
}

/// Sets the time interval between TCP keepalive probes, if TCP keepalive is
/// enabled on this socket.
///
/// This sets the value of `TCP_KEEPINTVL` on supported Unix operating
/// systems. On Windows, this sets the value of the `tcp_keepalive` struct's
/// `keepaliveinterval` field.
///
/// Some platforms specify this value in seconds, so sub-second
/// specifications may be omitted.
///
/// The OS may return an error if TCP keepalive was not already enabled by
/// calling `set_keepalive(true)` on this socket.
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "windows"
))]
pub fn set_keepalive_interval(&self, interval: Duration) -> io::Result<()> {
sys::tcp::set_keepalive_interval(self.sys, interval)
}

/// Returns the time interval between TCP keepalive probes, if TCP keepalive is
/// enabled on this socket.
///
/// If `None`, then keepalive messages are disabled.
///
/// This returns the value of `TCP_KEEPINTVL` on supported Unix operating
/// systems. On Windows, this sets the value of the `tcp_keepalive` struct's
/// `keepaliveinterval` field.
///
/// Some platforms specify this value in seconds, so sub-second
/// specifications may be omitted.
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "windows"
))]
pub fn get_keepalive_interval(&self) -> io::Result<Option<Duration>> {
sys::tcp::get_keepalive_interval(self.sys)
}

/// Sets the maximum number of TCP keepalive probes that will be sent before
/// dropping a connection, if TCP keepalive is enabled on this socket.
///
/// This sets the value of `TCP_KEEPCNT` on Unix operating systems that
/// support this option.
///
/// The OS may return an error if TCP keepalive was not already enabled by
/// calling `set_keepalive(true)` on this socket.
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd",))]
pub fn set_keepalive_retries(&self, retries: u32) -> io::Result<()> {
sys::tcp::set_keepalive_retries(self.sys, retries)
}

/// Returns the maximum number of TCP keepalive probes that will be sent before
/// dropping a connection, if TCP keepalive is enabled on this socket.
///
/// If `None`, then keepalive messages are disabled.
///
/// This returns the value of `TCP_KEEPCNT` on Unix operating systems that
/// support this option.
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd",))]
pub fn get_keepalive_retries(&self) -> io::Result<Option<u32>> {
sys::tcp::get_keepalive_retries(self.sys)
}

/// Returns the local address of this socket
Expand Down Expand Up @@ -257,6 +339,8 @@ impl FromRawSocket for TcpSocket {
/// The caller is responsible for ensuring that the socket is in
/// non-blocking mode.
unsafe fn from_raw_socket(socket: RawSocket) -> TcpSocket {
TcpSocket { sys: socket as sys::tcp::TcpSocket }
TcpSocket {
sys: socket as sys::tcp::TcpSocket,
}
}
}
54 changes: 52 additions & 2 deletions src/sys/shell/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,64 @@ pub(crate) fn set_send_buffer_size(_: TcpSocket, _: u32) -> io::Result<()> {
pub(crate) fn get_send_buffer_size(_: TcpSocket) -> io::Result<u32> {
os_required!();
}
pub(crate) fn set_keepalive(_: TcpSocket, _: Option<Duration>) -> io::Result<()> {

pub(crate) fn set_keepalive(_: TcpSocket, _: bool) -> io::Result<()> {
os_required!();
}

pub(crate) fn get_keepalive(_: TcpSocket) -> io::Result<bool> {
os_required!();
}

pub(crate) fn get_keepalive(_: TcpSocket) -> io::Result<Option<Duration>> {
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "windows"
))]
pub(crate) fn set_keepalive_time(_: TcpSocket, _: Duration) -> io::Result<()> {
os_required!();
}

#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "windows"
))]
pub(crate) fn get_keepalive_time(_: TcpSocket) -> io::Result<Option<Duration>> {
os_required!()
}

#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "windows"
))]
pub(crate) fn set_keepalive_interval(_: TcpSocket, _: Duration) -> io::Result<()> {
os_required!()
}

#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "windows"
))]
pub(crate) fn get_keepalive_interval(_: TcpSocket) -> io::Result<Option<Duration>> {
os_required!()
}

#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"))]
pub(crate) fn set_keepalive_retries(_: TcpSocket, _: u32) -> io::Result<()> {
os_required!()
}

#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"))]
pub(crate) fn get_keepalive_retries(socket: TcpSocket) -> io::Result<Option<u32>> {
os_required!()
}

pub fn accept(_: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> {
os_required!();
Expand Down
Loading

0 comments on commit 13cdfe0

Please sign in to comment.