aboutsummaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-11-16 17:42:39 -0800
committerHaibo Huang <hhb@google.com>2020-11-16 17:42:39 -0800
commitb871bf78acdb643f7b39ac9d1110ab94d886d7d1 (patch)
tree9953974f4f90698632f6dcdcb001e8f962af4dbd /src/net
parent8414138e74aa469015108049230e70b0a325c6e9 (diff)
downloadmio-b871bf78acdb643f7b39ac9d1110ab94d886d7d1.tar.gz
Upgrade rust/crates/mio to 0.7.6
Test: make Change-Id: I26de17b65a22ec1ba472a61c51b55681afdb8ffa
Diffstat (limited to 'src/net')
-rw-r--r--src/net/mod.rs21
-rw-r--r--src/net/tcp/listener.rs3
-rw-r--r--src/net/tcp/mod.rs2
-rw-r--r--src/net/tcp/socket.rs336
-rw-r--r--src/net/tcp/stream.rs5
-rw-r--r--src/net/udp.rs25
6 files changed, 355 insertions, 37 deletions
diff --git a/src/net/mod.rs b/src/net/mod.rs
index 91804ec..4df701d 100644
--- a/src/net/mod.rs
+++ b/src/net/mod.rs
@@ -1,4 +1,4 @@
-//! Networking primitives
+//! Networking primitives.
//!
//! The types provided in this module are non-blocking by default and are
//! designed to be portable across all supported Mio platforms. As long as the
@@ -7,18 +7,13 @@
//!
//! [portability guidelines]: ../struct.Poll.html#portability
-cfg_tcp! {
- mod tcp;
- pub use self::tcp::{TcpListener, TcpSocket, TcpStream};
-}
+mod tcp;
+pub use self::tcp::{TcpListener, TcpSocket, TcpStream, TcpKeepalive};
-cfg_udp! {
- mod udp;
- pub use self::udp::UdpSocket;
-}
+mod udp;
+pub use self::udp::UdpSocket;
#[cfg(unix)]
-cfg_uds! {
- mod uds;
- pub use self::uds::{SocketAddr, UnixDatagram, UnixListener, UnixStream};
-}
+mod uds;
+#[cfg(unix)]
+pub use self::uds::{SocketAddr, UnixDatagram, UnixListener, UnixStream};
diff --git a/src/net/tcp/listener.rs b/src/net/tcp/listener.rs
index b6f5736..da276f3 100644
--- a/src/net/tcp/listener.rs
+++ b/src/net/tcp/listener.rs
@@ -13,7 +13,8 @@ use crate::{event, sys, Interest, Registry, Token};
///
/// # Examples
///
-/// ```
+#[cfg_attr(feature = "os-poll", doc = "```")]
+#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Events, Interest, Poll, Token};
diff --git a/src/net/tcp/mod.rs b/src/net/tcp/mod.rs
index b39b909..4e47aee 100644
--- a/src/net/tcp/mod.rs
+++ b/src/net/tcp/mod.rs
@@ -2,7 +2,7 @@ mod listener;
pub use self::listener::TcpListener;
mod socket;
-pub use self::socket::TcpSocket;
+pub use self::socket::{TcpSocket, TcpKeepalive};
mod stream;
pub use self::stream::TcpStream;
diff --git a/src/net/tcp/socket.rs b/src/net/tcp/socket.rs
index f3e27c3..35a589c 100644
--- a/src/net/tcp/socket.rs
+++ b/src/net/tcp/socket.rs
@@ -1,14 +1,14 @@
-use crate::net::{TcpStream, TcpListener};
-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, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
+use std::time::Duration;
+
+use crate::net::{TcpListener, TcpStream};
+use crate::sys;
/// A non-blocking TCP socket used to configure a stream or listener.
///
@@ -22,23 +22,42 @@ pub struct TcpSocket {
sys: sys::tcp::TcpSocket,
}
+/// Configures a socket's TCP keepalive parameters.
+#[derive(Debug, Default, Clone)]
+pub struct TcpKeepalive {
+ pub(crate) time: Option<Duration>,
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "windows",
+ ))]
+ pub(crate) interval: Option<Duration>,
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ ))]
+ pub(crate) retries: Option<u32>,
+}
+
impl TcpSocket {
/// Create a new IPv4 TCP socket.
///
/// 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> {
@@ -106,6 +125,201 @@ impl TcpSocket {
sys::tcp::set_linger(self.sys, dur)
}
+ /// Gets the value of `SO_LINGER` on this socket
+ pub fn get_linger(&self) -> io::Result<Option<Duration>> {
+ sys::tcp::get_linger(self.sys)
+ }
+
+ /// Sets the value of `SO_RCVBUF` on this socket.
+ pub fn set_recv_buffer_size(&self, size: u32) -> io::Result<()> {
+ sys::tcp::set_recv_buffer_size(self.sys, size)
+ }
+
+ /// Get the value of `SO_RCVBUF` set on this socket.
+ ///
+ /// Note that if [`set_recv_buffer_size`] has been called on this socket
+ /// previously, the value returned by this function may not be the same as
+ /// the argument provided to `set_recv_buffer_size`. This is for the
+ /// following reasons:
+ ///
+ /// * Most operating systems have minimum and maximum allowed sizes for the
+ /// receive buffer, and will clamp the provided value if it is below the
+ /// minimum or above the maximum. The minimum and maximum buffer sizes are
+ /// OS-dependent.
+ /// * Linux will double the buffer size to account for internal bookkeeping
+ /// data, and returns the doubled value from `getsockopt(2)`. As per `man
+ /// 7 socket`:
+ /// > Sets or gets the maximum socket receive buffer in bytes. The
+ /// > kernel doubles this value (to allow space for bookkeeping
+ /// > overhead) when it is set using `setsockopt(2)`, and this doubled
+ /// > value is returned by `getsockopt(2)`.
+ ///
+ /// [`set_recv_buffer_size`]: #method.set_recv_buffer_size
+ pub fn get_recv_buffer_size(&self) -> io::Result<u32> {
+ sys::tcp::get_recv_buffer_size(self.sys)
+ }
+
+ /// Sets the value of `SO_SNDBUF` on this socket.
+ pub fn set_send_buffer_size(&self, size: u32) -> io::Result<()> {
+ sys::tcp::set_send_buffer_size(self.sys, size)
+ }
+
+ /// Get the value of `SO_SNDBUF` set on this socket.
+ ///
+ /// Note that if [`set_send_buffer_size`] has been called on this socket
+ /// previously, the value returned by this function may not be the same as
+ /// the argument provided to `set_send_buffer_size`. This is for the
+ /// following reasons:
+ ///
+ /// * Most operating systems have minimum and maximum allowed sizes for the
+ /// receive buffer, and will clamp the provided value if it is below the
+ /// minimum or above the maximum. The minimum and maximum buffer sizes are
+ /// OS-dependent.
+ /// * Linux will double the buffer size to account for internal bookkeeping
+ /// data, and returns the doubled value from `getsockopt(2)`. As per `man
+ /// 7 socket`:
+ /// > Sets or gets the maximum socket send buffer in bytes. The
+ /// > kernel doubles this value (to allow space for bookkeeping
+ /// > overhead) when it is set using `setsockopt(2)`, and this doubled
+ /// > value is returned by `getsockopt(2)`.
+ ///
+ /// [`set_send_buffer_size`]: #method.set_send_buffer_size
+ 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.
+ ///
+ /// 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 parameters configuring TCP keepalive probes for this socket.
+ ///
+ /// The supported parameters depend on the operating system, and are
+ /// configured using the [`TcpKeepalive`] struct. At a minimum, all systems
+ /// support configuring the [keepalive time]: the time after which the OS
+ /// will start sending keepalive messages on an idle connection.
+ ///
+ /// # Notes
+ ///
+ /// * This will enable TCP keepalive on this socket, if it is not already
+ /// enabled.
+ /// * On some platforms, such as Windows, any keepalive parameters *not*
+ /// configured by the `TcpKeepalive` struct passed to this function may be
+ /// overwritten with their default values. Therefore, this function should
+ /// either only be called once per socket, or the same parameters should
+ /// be passed every time it is called.
+ ///
+ /// # Examples
+ /// ```
+ /// use mio::net::{TcpSocket, TcpKeepalive};
+ /// use std::time::Duration;
+ ///
+ /// # fn main() -> Result<(), std::io::Error> {
+ /// let socket = TcpSocket::new_v6()?;
+ /// let keepalive = TcpKeepalive::default()
+ /// .with_time(Duration::from_secs(4));
+ /// // Depending on the target operating system, we may also be able to
+ /// // configure the keepalive probe interval and/or the number of retries
+ /// // here as well.
+ ///
+ /// socket.set_keepalive_params(keepalive)?;
+ /// # Ok(()) }
+ /// ```
+ ///
+ /// [`TcpKeepalive`]: ../struct.TcpKeepalive.html
+ /// [keepalive time]: ../struct.TcpKeepalive.html#method.with_time
+ pub fn set_keepalive_params(&self, keepalive: TcpKeepalive) -> io::Result<()> {
+ self.set_keepalive(true)?;
+ sys::tcp::set_keepalive_params(self.sys, keepalive)
+ }
+
+ /// 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, it is not possible to
+ /// access the value of TCP keepalive parameters after they have been set.
+ ///
+ /// Some platforms specify this value in seconds, so sub-second
+ /// specifications may be omitted.
+ #[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
+ #[cfg(not(target_os = "windows"))]
+ pub fn get_keepalive_time(&self) -> io::Result<Option<Duration>> {
+ sys::tcp::get_keepalive_time(self.sys)
+ }
+
+ /// 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, it is not possible to access the value of TCP
+ /// keepalive parameters after they have been set..
+ ///
+ /// Some platforms specify this value in seconds, so sub-second
+ /// specifications may be omitted.
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ )))
+ )]
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ ))]
+ pub fn get_keepalive_interval(&self) -> io::Result<Option<Duration>> {
+ sys::tcp::get_keepalive_interval(self.sys)
+ }
+
+ /// 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. On Windows, it is not possible to access the value
+ /// of TCP keepalive parameters after they have been set.
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ )))
+ )]
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ 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
///
/// Will return `Err` result in windows if called before calling `bind`
@@ -121,6 +335,16 @@ impl Drop for TcpSocket {
}
#[cfg(unix)]
+impl IntoRawFd for TcpSocket {
+ fn into_raw_fd(self) -> RawFd {
+ let ret = self.sys;
+ // Avoid closing the socket
+ mem::forget(self);
+ ret
+ }
+}
+
+#[cfg(unix)]
impl AsRawFd for TcpSocket {
fn as_raw_fd(&self) -> RawFd {
self.sys
@@ -172,6 +396,94 @@ 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,
+ }
+ }
+}
+
+impl TcpKeepalive {
+ // Sets the amount of time after which TCP keepalive probes will be sent
+ /// on idle connections.
+ ///
+ /// This will set 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 with_time(self, time: Duration) -> Self {
+ Self {
+ time: Some(time),
+ ..self
+ }
+ }
+
+ /// Sets the time interval between TCP keepalive probes.
+ /// 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.
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "windows"
+ )))
+ )]
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "windows"
+ ))]
+ pub fn with_interval(self, interval: Duration) -> Self {
+ Self {
+ interval: Some(interval),
+ ..self
+ }
+ }
+
+ /// 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 will set the value of `TCP_KEEPCNT` on Unix operating systems that
+ /// support this option.
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ )))
+ )]
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ ))]
+ pub fn with_retries(self, retries: u32) -> Self {
+ Self {
+ retries: Some(retries),
+ ..self
+ }
+ }
+
+ /// Returns a new, empty set of TCP keepalive parameters.
+ pub fn new() -> Self {
+ Self::default()
}
}
diff --git a/src/net/tcp/stream.rs b/src/net/tcp/stream.rs
index 86f674c..cdbd46a 100644
--- a/src/net/tcp/stream.rs
+++ b/src/net/tcp/stream.rs
@@ -7,8 +7,8 @@ use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use crate::io_source::IoSource;
-use crate::{event, Interest, Registry, Token};
use crate::net::TcpSocket;
+use crate::{event, Interest, Registry, Token};
/// A non-blocking TCP stream between a local socket and a remote socket.
///
@@ -16,7 +16,8 @@ use crate::net::TcpSocket;
///
/// # Examples
///
-/// ```
+#[cfg_attr(feature = "os-poll", doc = "```")]
+#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::net::{TcpListener, SocketAddr};
/// # use std::error::Error;
/// #
diff --git a/src/net/udp.rs b/src/net/udp.rs
index 164315a..436b4cc 100644
--- a/src/net/udp.rs
+++ b/src/net/udp.rs
@@ -27,7 +27,8 @@ use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}
///
/// # Examples
///
-/// ```
+#[cfg_attr(feature = "os-poll", doc = "```")]
+#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
@@ -96,7 +97,8 @@ impl UdpSocket {
///
/// # Examples
///
- /// ```
+ #[cfg_attr(feature = "os-poll", doc = "```")]
+ #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
@@ -139,8 +141,11 @@ impl UdpSocket {
// This assertion is almost, but not quite, universal. It fails on
// shared-IP FreeBSD jails. It's hard for mio to know whether we're jailed,
// so simply disable the test on FreeBSD.
- #[cfg_attr(not(target_os = "freebsd"), doc = " ```")]
- #[cfg_attr(target_os = "freebsd", doc = " ```no_run")]
+ #[cfg_attr(all(feature = "os-poll", not(target_os = "freebsd")), doc = "```")]
+ #[cfg_attr(
+ any(not(feature = "os-poll"), target_os = "freebsd"),
+ doc = "```ignore"
+ )]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
@@ -303,7 +308,8 @@ impl UdpSocket {
///
/// # Examples
///
- /// ```
+ #[cfg_attr(feature = "os-poll", doc = "```")]
+ #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
@@ -332,7 +338,8 @@ impl UdpSocket {
///
/// # Examples
///
- /// ```
+ #[cfg_attr(feature = "os-poll", doc = "```")]
+ #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
@@ -412,7 +419,8 @@ impl UdpSocket {
///
/// # Examples
///
- /// ```
+ #[cfg_attr(feature = "os-poll", doc = "```")]
+ #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
@@ -440,7 +448,8 @@ impl UdpSocket {
///
/// # Examples
///
- /// ```
+ #[cfg_attr(feature = "os-poll", doc = "```")]
+ #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {