From b871bf78acdb643f7b39ac9d1110ab94d886d7d1 Mon Sep 17 00:00:00 2001 From: Haibo Huang Date: Mon, 16 Nov 2020 17:42:39 -0800 Subject: Upgrade rust/crates/mio to 0.7.6 Test: make Change-Id: I26de17b65a22ec1ba472a61c51b55681afdb8ffa --- src/net/mod.rs | 21 ++- src/net/tcp/listener.rs | 3 +- src/net/tcp/mod.rs | 2 +- src/net/tcp/socket.rs | 336 ++++++++++++++++++++++++++++++++++++++++++++++-- src/net/tcp/stream.rs | 5 +- src/net/udp.rs | 25 ++-- 6 files changed, 355 insertions(+), 37 deletions(-) (limited to 'src/net') 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> { /// 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, + #[cfg(any( + target_os = "linux", + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "netbsd", + target_os = "windows", + ))] + pub(crate) interval: Option, + #[cfg(any( + target_os = "linux", + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "netbsd", + ))] + pub(crate) retries: Option, +} + impl TcpSocket { /// Create a new IPv4 TCP socket. /// /// This calls `socket(2)`. pub fn new_v4() -> io::Result { - 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 { - 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 { @@ -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> { + 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 { + 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 { + 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 { + 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> { + 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> { + 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> { + 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` @@ -120,6 +334,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 { @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> { -- cgit v1.2.3