diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/net/tcp/socket.rs | 6 | ||||
-rw-r--r-- | src/sys/shell/tcp.rs | 5 | ||||
-rw-r--r-- | src/sys/unix/tcp.rs | 18 | ||||
-rw-r--r-- | src/sys/unix/uds/socketaddr.rs | 2 | ||||
-rw-r--r-- | src/sys/windows/selector.rs | 43 | ||||
-rw-r--r-- | src/sys/windows/tcp.rs | 34 |
7 files changed, 75 insertions, 35 deletions
@@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/mio/0.7.3")] +#![doc(html_root_url = "https://docs.rs/mio/0.7.4")] #![deny( missing_docs, missing_debug_implementations, diff --git a/src/net/tcp/socket.rs b/src/net/tcp/socket.rs index 0094de9..a91f665 100644 --- a/src/net/tcp/socket.rs +++ b/src/net/tcp/socket.rs @@ -4,6 +4,7 @@ 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}; #[cfg(windows)] @@ -80,6 +81,11 @@ impl TcpSocket { pub fn set_reuseaddr(&self, reuseaddr: bool) -> io::Result<()> { sys::tcp::set_reuseaddr(self.sys, reuseaddr) } + + /// Sets the value of `SO_LINGER` on this socket. + pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> { + sys::tcp::set_linger(self.sys, dur) + } } impl Drop for TcpSocket { diff --git a/src/sys/shell/tcp.rs b/src/sys/shell/tcp.rs index 963fccb..de1520b 100644 --- a/src/sys/shell/tcp.rs +++ b/src/sys/shell/tcp.rs @@ -1,5 +1,6 @@ use std::io; use std::net::{self, SocketAddr}; +use std::time::Duration; pub(crate) type TcpSocket = i32; @@ -31,6 +32,10 @@ pub(crate) fn set_reuseaddr(_: TcpSocket, _: bool) -> io::Result<()> { os_required!(); } +pub(crate) fn set_linger(_: TcpSocket, _: Option<Duration>) -> io::Result<()> { + os_required!(); +} + pub fn accept(_: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> { os_required!(); } diff --git a/src/sys/unix/tcp.rs b/src/sys/unix/tcp.rs index 9d59632..81b371b 100644 --- a/src/sys/unix/tcp.rs +++ b/src/sys/unix/tcp.rs @@ -1,6 +1,7 @@ use std::io; use std::mem::{size_of, MaybeUninit}; use std::net::{self, SocketAddr}; +use std::time::Duration; use std::os::unix::io::{AsRawFd, FromRawFd}; use crate::sys::unix::net::{new_socket, socket_addr, to_socket_addr}; @@ -54,8 +55,21 @@ pub(crate) fn set_reuseaddr(socket: TcpSocket, reuseaddr: bool) -> io::Result<() libc::SO_REUSEADDR, &val as *const libc::c_int as *const libc::c_void, size_of::<libc::c_int>() as libc::socklen_t, - ))?; - Ok(()) + )).map(|_| ()) +} + +pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result<()> { + let val: libc::linger = libc::linger { + l_onoff: if dur.is_some() { 1 } else { 0 }, + l_linger: dur.map(|dur| dur.as_secs() as libc::c_int).unwrap_or_default(), + }; + syscall!(setsockopt( + socket, + libc::SOL_SOCKET, + libc::SO_LINGER, + &val as *const libc::linger as *const libc::c_void, + size_of::<libc::linger>() as libc::socklen_t, + )).map(|_| ()) } pub fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> { diff --git a/src/sys/unix/uds/socketaddr.rs b/src/sys/unix/uds/socketaddr.rs index 69f311a..ddfa2f0 100644 --- a/src/sys/unix/uds/socketaddr.rs +++ b/src/sys/unix/uds/socketaddr.rs @@ -74,6 +74,8 @@ cfg_os_poll! { /// Documentation reflected in [`SocketAddr`] /// /// [`SocketAddr`]: std::os::unix::net::SocketAddr + // FIXME: The matches macro requires rust 1.42.0 and we still support 1.39.0 + #[allow(clippy::match_like_matches_macro)] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { true diff --git a/src/sys/windows/selector.rs b/src/sys/windows/selector.rs index 792a5c5..4a38300 100644 --- a/src/sys/windows/selector.rs +++ b/src/sys/windows/selector.rs @@ -1,11 +1,14 @@ use super::afd::{self, Afd, AfdPollInfo}; use super::io_status_block::IoStatusBlock; use super::Event; -use crate::sys::event::{ - ERROR_FLAGS, READABLE_FLAGS, READ_CLOSED_FLAGS, WRITABLE_FLAGS, WRITE_CLOSED_FLAGS, -}; use crate::sys::Events; -use crate::Interest; + +cfg_net! { + use crate::sys::event::{ + ERROR_FLAGS, READABLE_FLAGS, READ_CLOSED_FLAGS, WRITABLE_FLAGS, WRITE_CLOSED_FLAGS, + }; + use crate::Interest; +} use miow::iocp::{CompletionPort, CompletionStatus}; use std::collections::VecDeque; @@ -226,15 +229,7 @@ impl SockState { // In mio, we have to simulate Edge-triggered behavior to match API usage. // The strategy here is to intercept all read/write from user that could cause WouldBlock usage, // then reregister the socket to reset the interests. - - // Reset readable event - if (afd_events & interests_to_afd_flags(Interest::READABLE)) != 0 { - self.user_evts &= !(interests_to_afd_flags(Interest::READABLE)); - } - // Reset writable event - if (afd_events & interests_to_afd_flags(Interest::WRITABLE)) != 0 { - self.user_evts &= !interests_to_afd_flags(Interest::WRITABLE); - } + self.user_evts &= !afd_events; Some(Event { data: self.user_data, @@ -730,16 +725,18 @@ impl Drop for SelectorInner { } } -fn interests_to_afd_flags(interests: Interest) -> u32 { - let mut flags = 0; +cfg_net! { + fn interests_to_afd_flags(interests: Interest) -> u32 { + let mut flags = 0; - if interests.is_readable() { - flags |= READABLE_FLAGS | READ_CLOSED_FLAGS | ERROR_FLAGS; - } + if interests.is_readable() { + flags |= READABLE_FLAGS | READ_CLOSED_FLAGS | ERROR_FLAGS; + } - if interests.is_writable() { - flags |= WRITABLE_FLAGS | WRITE_CLOSED_FLAGS | ERROR_FLAGS; - } + if interests.is_writable() { + flags |= WRITABLE_FLAGS | WRITE_CLOSED_FLAGS | ERROR_FLAGS; + } - flags -} + flags + } +}
\ No newline at end of file diff --git a/src/sys/windows/tcp.rs b/src/sys/windows/tcp.rs index c5b0410..46ac1ac 100644 --- a/src/sys/windows/tcp.rs +++ b/src/sys/windows/tcp.rs @@ -1,11 +1,15 @@ use std::io; +use std::mem::size_of; use std::net::{self, SocketAddr}; +use std::time::Duration; use std::os::windows::io::FromRawSocket; use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64. +use winapi::ctypes::{c_char, c_int, c_ushort}; +use winapi::shared::minwindef::{BOOL, TRUE, FALSE}; use winapi::um::winsock2::{ - self, - closesocket, PF_INET, PF_INET6, SOCKET, SOCKET_ERROR, SOCK_STREAM, + self, closesocket, linger, setsockopt, PF_INET, PF_INET6, SOCKET, SOCKET_ERROR, + SOCK_STREAM, SOL_SOCKET, SO_LINGER, SO_REUSEADDR, }; use crate::sys::windows::net::{init, new_socket, socket_addr}; @@ -69,11 +73,6 @@ pub(crate) fn close(socket: TcpSocket) { } pub(crate) fn set_reuseaddr(socket: TcpSocket, reuseaddr: bool) -> io::Result<()> { - use winapi::ctypes::{c_char, c_int}; - use winapi::shared::minwindef::{BOOL, TRUE, FALSE}; - use winapi::um::winsock2::{setsockopt, SOCKET_ERROR, SO_REUSEADDR, SOL_SOCKET}; - use std::mem::size_of; - let val: BOOL = if reuseaddr { TRUE } else { FALSE }; match unsafe { setsockopt( @@ -83,9 +82,26 @@ pub(crate) fn set_reuseaddr(socket: TcpSocket, reuseaddr: bool) -> io::Result<() &val as *const _ as *const c_char, size_of::<BOOL>() as c_int, ) } { - 0 => Ok(()), SOCKET_ERROR => Err(io::Error::last_os_error()), - _ => panic!("unexpected return value"), + _ => Ok(()), + } +} + +pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result<()> { + let val: linger = linger { + l_onoff: if dur.is_some() { 1 } else { 0 }, + l_linger: dur.map(|dur| dur.as_secs() as c_ushort).unwrap_or_default(), + }; + + match unsafe { setsockopt( + socket, + SOL_SOCKET, + SO_LINGER, + &val as *const _ as *const c_char, + size_of::<linger>() as c_int, + ) } { + SOCKET_ERROR => Err(io::Error::last_os_error()), + _ => Ok(()), } } |