add TcpStream::set_linger
and TcpStream::linger
This commit is contained in:
parent
6cfa773583
commit
3b6777f1ab
12 changed files with 166 additions and 1 deletions
|
@ -321,6 +321,7 @@
|
||||||
#![feature(stdsimd)]
|
#![feature(stdsimd)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
#![feature(str_internals)]
|
#![feature(str_internals)]
|
||||||
|
#![feature(tcp_linger)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(thread_local)]
|
#![feature(thread_local)]
|
||||||
#![feature(thread_local_internals)]
|
#![feature(thread_local_internals)]
|
||||||
|
|
|
@ -401,6 +401,53 @@ impl TcpStream {
|
||||||
self.0.peek(buf)
|
self.0.peek(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the value of the `SO_LINGER` option on this socket.
|
||||||
|
///
|
||||||
|
/// This value controls how the socket is closed when data remains
|
||||||
|
/// to be sent. If `SO_LINGER` is set, the socket will remain open
|
||||||
|
/// for the specified duration as the system attempts to send pending data.
|
||||||
|
/// Otherwise, the system may close the socket immediately, or wait for a
|
||||||
|
/// default timeout.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// #![feature(tcp_linger)]
|
||||||
|
///
|
||||||
|
/// use std::net::TcpStream;
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// let stream = TcpStream::connect("127.0.0.1:8080")
|
||||||
|
/// .expect("Couldn't connect to the server...");
|
||||||
|
/// stream.set_linger(Some(Duration::from_secs(0))).expect("set_linger call failed");
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "tcp_linger", issue = "88494")]
|
||||||
|
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
|
||||||
|
self.0.set_linger(linger)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the value of the `SO_LINGER` option on this socket.
|
||||||
|
///
|
||||||
|
/// For more information about this option, see [`TcpStream::set_linger`].
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// #![feature(tcp_linger)]
|
||||||
|
///
|
||||||
|
/// use std::net::TcpStream;
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// let stream = TcpStream::connect("127.0.0.1:8080")
|
||||||
|
/// .expect("Couldn't connect to the server...");
|
||||||
|
/// stream.set_linger(Some(Duration::from_secs(0))).expect("set_linger call failed");
|
||||||
|
/// assert_eq!(stream.linger().unwrap(), Some(Duration::from_secs(0)));
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "tcp_linger", issue = "88494")]
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
self.0.linger()
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the value of the `TCP_NODELAY` option on this socket.
|
/// Sets the value of the `TCP_NODELAY` option on this socket.
|
||||||
///
|
///
|
||||||
/// If set, this option disables the Nagle algorithm. This means that
|
/// If set, this option disables the Nagle algorithm. This means that
|
||||||
|
|
|
@ -767,6 +767,21 @@ fn test_timeout_zero_duration() {
|
||||||
drop(listener);
|
drop(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(target_env = "sgx", ignore)]
|
||||||
|
fn linger() {
|
||||||
|
let addr = next_test_ip4();
|
||||||
|
let _listener = t!(TcpListener::bind(&addr));
|
||||||
|
|
||||||
|
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
|
||||||
|
|
||||||
|
assert_eq!(None, t!(stream.linger()));
|
||||||
|
t!(stream.set_linger(Some(Duration::from_secs(1))));
|
||||||
|
assert_eq!(Some(Duration::from_secs(1)), t!(stream.linger()));
|
||||||
|
t!(stream.set_linger(None));
|
||||||
|
assert_eq!(None, t!(stream.linger()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(target_env = "sgx", ignore)]
|
#[cfg_attr(target_env = "sgx", ignore)]
|
||||||
fn nodelay() {
|
fn nodelay() {
|
||||||
|
|
|
@ -182,6 +182,14 @@ impl TcpStream {
|
||||||
Ok(self.clone())
|
Ok(self.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
|
||||||
abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
|
abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
|
||||||
.map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed"))
|
.map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed"))
|
||||||
|
|
|
@ -183,6 +183,14 @@ impl TcpStream {
|
||||||
Ok(self.clone())
|
Ok(self.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
|
||||||
|
sgx_ineffective(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
sgx_ineffective(None)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
||||||
sgx_ineffective(())
|
sgx_ineffective(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,14 @@ pub mod net {
|
||||||
unimpl!();
|
unimpl!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
|
||||||
|
unimpl!();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
unimpl!();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
||||||
unimpl!();
|
unimpl!();
|
||||||
}
|
}
|
||||||
|
@ -214,6 +222,14 @@ pub mod net {
|
||||||
unimpl!();
|
unimpl!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
|
||||||
|
unimpl!();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
unimpl!();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
||||||
unimpl!();
|
unimpl!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,14 @@ use crate::time::{Duration, Instant};
|
||||||
|
|
||||||
use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
|
use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_vendor = "apple")] {
|
||||||
|
use libc::SO_LINGER_SEC as SO_LINGER;
|
||||||
|
} else {
|
||||||
|
use libc::SO_LINGER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub use crate::sys::{cvt, cvt_r};
|
pub use crate::sys::{cvt, cvt_r};
|
||||||
|
|
||||||
#[allow(unused_extern_crates)]
|
#[allow(unused_extern_crates)]
|
||||||
|
@ -376,6 +384,21 @@ impl Socket {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
|
||||||
|
let linger = libc::linger {
|
||||||
|
l_onoff: linger.is_some() as libc::c_int,
|
||||||
|
l_linger: linger.map(|dur| dur.as_secs() as libc::c_int).unwrap_or_default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
let val: libc::linger = getsockopt(self, libc::SOL_SOCKET, SO_LINGER)?;
|
||||||
|
|
||||||
|
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||||
setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int)
|
setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int)
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,14 @@ impl TcpStream {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,14 @@ impl TcpStream {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,6 +197,7 @@ pub const SOCK_DGRAM: c_int = 2;
|
||||||
pub const SOCK_STREAM: c_int = 1;
|
pub const SOCK_STREAM: c_int = 1;
|
||||||
pub const SOCKET_ERROR: c_int = -1;
|
pub const SOCKET_ERROR: c_int = -1;
|
||||||
pub const SOL_SOCKET: c_int = 0xffff;
|
pub const SOL_SOCKET: c_int = 0xffff;
|
||||||
|
pub const SO_LINGER: c_int = 0x0080;
|
||||||
pub const SO_RCVTIMEO: c_int = 0x1006;
|
pub const SO_RCVTIMEO: c_int = 0x1006;
|
||||||
pub const SO_SNDTIMEO: c_int = 0x1005;
|
pub const SO_SNDTIMEO: c_int = 0x1005;
|
||||||
pub const IPPROTO_IP: c_int = 0;
|
pub const IPPROTO_IP: c_int = 0;
|
||||||
|
@ -216,6 +217,13 @@ pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
|
||||||
pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
|
pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
|
||||||
pub const MSG_PEEK: c_int = 0x2;
|
pub const MSG_PEEK: c_int = 0x2;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct linger {
|
||||||
|
pub l_onoff: c_ushort,
|
||||||
|
pub l_linger: c_ushort,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct ip_mreq {
|
pub struct ip_mreq {
|
||||||
pub imr_multiaddr: in_addr,
|
pub imr_multiaddr: in_addr,
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::sys_common::net;
|
||||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
use libc::{c_int, c_long, c_ulong};
|
use libc::{c_int, c_long, c_ulong, c_ushort};
|
||||||
|
|
||||||
pub type wrlen_t = i32;
|
pub type wrlen_t = i32;
|
||||||
|
|
||||||
|
@ -446,6 +446,21 @@ impl Socket {
|
||||||
cvt(result).map(drop)
|
cvt(result).map(drop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
|
||||||
|
let linger = c::linger {
|
||||||
|
l_onoff: linger.is_some() as c_ushort,
|
||||||
|
l_linger: linger.map(|dur| dur.as_secs() as c_ushort).unwrap_or_default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
net::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
let val: c::linger = net::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
|
||||||
|
|
||||||
|
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||||
net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE)
|
net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE)
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,14 @@ impl TcpStream {
|
||||||
self.inner.duplicate().map(|s| TcpStream { inner: s })
|
self.inner.duplicate().map(|s| TcpStream { inner: s })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
|
||||||
|
self.inner.set_linger(linger)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
self.inner.linger()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||||
self.inner.set_nodelay(nodelay)
|
self.inner.set_nodelay(nodelay)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue