Replace winapi/ntapi with windows-sys

This updates miow to 0.4, which now uses the windows-sys crate instead
of winapi, as the former is maintained and updated frequently as opposed
to winapi. The windows-sys crate also covers more of the Windows API
surface, which also allowed me to remove the dependency on ntapi (as it
still depends on winapi). There was only a single function,
`NtCancelIoFileEx` that was present in ntapi but not windows-sys, so I
merely added the extern declaration in the one place it was used as it
is not worth bringing in a dependency just for that.
This commit is contained in:
Jake Shadle
2022-03-18 11:00:30 +01:00
committed by Thomas de Zeeuw
parent 5d8cc365f3
commit 527db2e976
11 changed files with 135 additions and 107 deletions
+12 -4
View File
@@ -34,7 +34,7 @@ default = []
# Enables the `Poll` and `Registry` types.
os-poll = []
# Enables additional OS specific extensions, e.g. Unix `pipe(2)`.
os-ext = ["os-poll"]
os-ext = ["os-poll", "windows-sys/Win32_System_Pipes"]
# Enables `mio::net` module containing networking primitives.
net = []
@@ -45,9 +45,17 @@ log = "0.4.8"
libc = "0.2.121"
[target.'cfg(windows)'.dependencies]
miow = "0.3.6"
winapi = { version = "0.3", features = ["winsock2", "mswsock"] }
ntapi = "0.3"
miow = "0.4"
[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.28" # This matches the version in miow, but it's fairly outdated
features = [
"Win32_Storage_FileSystem", # Enables NtCreateFile
"Win32_Foundation", # Basic types eg HANDLE
"Win32_Networking_WinSock", # winsock2 types/functions
"Win32_System_IO", # IO types like OVERLAPPED etc
"Win32_System_WindowsProgramming", # General future used for various types/funcs
]
[target.'cfg(target_os = "wasi")'.dependencies]
wasi = "0.11.0"
+39 -26
View File
@@ -1,17 +1,28 @@
use ntapi::ntioapi::{IO_STATUS_BLOCK_u, IO_STATUS_BLOCK};
use ntapi::ntioapi::{NtCancelIoFileEx, NtDeviceIoControlFile};
use ntapi::ntrtl::RtlNtStatusToDosError;
use std::ffi::c_void;
use std::fmt;
use std::fs::File;
use std::io;
use std::mem::size_of;
use std::os::windows::io::AsRawHandle;
use std::ptr::null_mut;
use winapi::shared::ntdef::{HANDLE, LARGE_INTEGER, NTSTATUS, PVOID, ULONG};
use winapi::shared::ntstatus::{STATUS_NOT_FOUND, STATUS_PENDING, STATUS_SUCCESS};
use windows_sys::Win32::{
Foundation::{
RtlNtStatusToDosError, HANDLE, NTSTATUS, STATUS_NOT_FOUND, STATUS_PENDING, STATUS_SUCCESS,
},
System::WindowsProgramming::{NtDeviceIoControlFile, IO_STATUS_BLOCK, IO_STATUS_BLOCK_0},
};
const IOCTL_AFD_POLL: ULONG = 0x00012024;
const IOCTL_AFD_POLL: u32 = 0x00012024;
/// <https://processhacker.sourceforge.io/doc/ntioapi_8h.html#a0d4d550cad4d62d75b76961e25f6550c>
#[link(name = "ntdll")]
extern "system" {
fn NtCancelIoFileEx(
FileHandle: HANDLE,
IoRequestToCancel: *mut IO_STATUS_BLOCK,
IoStatusBlock: *mut IO_STATUS_BLOCK,
) -> NTSTATUS;
}
/// Winsock2 AFD driver instance.
///
/// All operations are unsafe due to IO_STATUS_BLOCK parameter are being used by Afd driver during STATUS_PENDING before I/O Completion Port returns its result.
@@ -24,7 +35,7 @@ pub struct Afd {
#[derive(Debug)]
pub struct AfdPollHandleInfo {
pub handle: HANDLE,
pub events: ULONG,
pub events: u32,
pub status: NTSTATUS,
}
@@ -32,10 +43,10 @@ unsafe impl Send for AfdPollHandleInfo {}
#[repr(C)]
pub struct AfdPollInfo {
pub timeout: LARGE_INTEGER,
pub timeout: i64,
// Can have only value 1.
pub number_of_handles: ULONG,
pub exclusive: ULONG,
pub number_of_handles: u32,
pub exclusive: u32,
pub handles: [AfdPollHandleInfo; 1],
}
@@ -58,10 +69,10 @@ impl Afd {
&self,
info: &mut AfdPollInfo,
iosb: *mut IO_STATUS_BLOCK,
overlapped: PVOID,
overlapped: *mut c_void,
) -> io::Result<bool> {
let info_ptr: PVOID = info as *mut _ as PVOID;
(*iosb).u.Status = STATUS_PENDING;
let info_ptr = info as *mut _ as *mut c_void;
(*iosb).Anonymous.Status = STATUS_PENDING;
let status = NtDeviceIoControlFile(
self.fd.as_raw_handle(),
null_mut(),
@@ -93,12 +104,12 @@ impl Afd {
/// Use it only with request is still being polled so that you have valid `IO_STATUS_BLOCK` to use.
/// User should NOT deallocate there overlapped value after the `cancel` to prevent double free.
pub unsafe fn cancel(&self, iosb: *mut IO_STATUS_BLOCK) -> io::Result<()> {
if (*iosb).u.Status != STATUS_PENDING {
if (*iosb).Anonymous.Status != STATUS_PENDING {
return Ok(());
}
let mut cancel_iosb = IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_u { Status: 0 },
Anonymous: IO_STATUS_BLOCK_0 { Status: 0 },
Information: 0,
};
let status = NtCancelIoFileEx(self.fd.as_raw_handle(), iosb, &mut cancel_iosb);
@@ -117,14 +128,16 @@ cfg_io_source! {
use std::sync::atomic::{AtomicUsize, Ordering};
use miow::iocp::CompletionPort;
use ntapi::ntioapi::{NtCreateFile, FILE_OPEN};
use winapi::shared::ntdef::{OBJECT_ATTRIBUTES, UNICODE_STRING, USHORT, WCHAR};
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::winbase::{SetFileCompletionNotificationModes, FILE_SKIP_SET_EVENT_ON_HANDLE};
use winapi::um::winnt::{SYNCHRONIZE, FILE_SHARE_READ, FILE_SHARE_WRITE};
use windows_sys::Win32::{
Foundation::{UNICODE_STRING, INVALID_HANDLE_VALUE},
System::WindowsProgramming::{
OBJECT_ATTRIBUTES, FILE_SKIP_SET_EVENT_ON_HANDLE,
},
Storage::FileSystem::{FILE_OPEN, NtCreateFile, SetFileCompletionNotificationModes, SYNCHRONIZE, FILE_SHARE_READ, FILE_SHARE_WRITE},
};
const AFD_HELPER_ATTRIBUTES: OBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES {
Length: size_of::<OBJECT_ATTRIBUTES>() as ULONG,
Length: size_of::<OBJECT_ATTRIBUTES>() as u32,
RootDirectory: null_mut(),
ObjectName: &AFD_OBJ_NAME as *const _ as *mut _,
Attributes: 0,
@@ -133,12 +146,12 @@ cfg_io_source! {
};
const AFD_OBJ_NAME: UNICODE_STRING = UNICODE_STRING {
Length: (AFD_HELPER_NAME.len() * size_of::<WCHAR>()) as USHORT,
MaximumLength: (AFD_HELPER_NAME.len() * size_of::<WCHAR>()) as USHORT,
Length: (AFD_HELPER_NAME.len() * size_of::<u16>()) as u16,
MaximumLength: (AFD_HELPER_NAME.len() * size_of::<u16>()) as u16,
Buffer: AFD_HELPER_NAME.as_ptr() as *mut _,
};
const AFD_HELPER_NAME: &[WCHAR] = &[
const AFD_HELPER_NAME: &[u16] = &[
'\\' as _,
'D' as _,
'e' as _,
@@ -169,7 +182,7 @@ cfg_io_source! {
pub fn new(cp: &CompletionPort) -> io::Result<Afd> {
let mut afd_helper_handle: HANDLE = INVALID_HANDLE_VALUE;
let mut iosb = IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_u { Status: 0 },
Anonymous: IO_STATUS_BLOCK_0 { Status: 0 },
Information: 0,
};
@@ -204,7 +217,7 @@ cfg_io_source! {
cp.add_handle(token, &afd.fd)?;
match SetFileCompletionNotificationModes(
afd_helper_handle,
FILE_SKIP_SET_EVENT_ON_HANDLE,
FILE_SKIP_SET_EVENT_ON_HANDLE as u8 // This is just 2, so fits in u8
) {
0 => Err(io::Error::last_os_error()),
_ => Ok(afd),
+3 -3
View File
@@ -1,17 +1,17 @@
use std::fmt;
use std::ops::{Deref, DerefMut};
use ntapi::ntioapi::IO_STATUS_BLOCK;
use windows_sys::Win32::System::WindowsProgramming::IO_STATUS_BLOCK;
pub struct IoStatusBlock(IO_STATUS_BLOCK);
cfg_io_source! {
use ntapi::ntioapi::IO_STATUS_BLOCK_u;
use windows_sys::Win32::System::WindowsProgramming::{IO_STATUS_BLOCK_0};
impl IoStatusBlock {
pub fn zeroed() -> Self {
Self(IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_u { Status: 0 },
Anonymous: IO_STATUS_BLOCK_0 { Status: 0 },
Information: 0,
})
}
+4 -3
View File
@@ -8,9 +8,10 @@ use std::{fmt, mem, slice};
use miow::iocp::{CompletionPort, CompletionStatus};
use miow::pipe;
use winapi::shared::winerror::{ERROR_BROKEN_PIPE, ERROR_PIPE_LISTENING};
use winapi::um::ioapiset::CancelIoEx;
use winapi::um::minwinbase::{OVERLAPPED, OVERLAPPED_ENTRY};
use windows_sys::Win32::{
Foundation::{ERROR_BROKEN_PIPE, ERROR_PIPE_LISTENING},
System::IO::{CancelIoEx, OVERLAPPED, OVERLAPPED_ENTRY},
};
use crate::event::Source;
use crate::sys::windows::{Event, Overlapped};
+29 -27
View File
@@ -3,12 +3,16 @@ use std::mem;
use std::net::SocketAddr;
use std::sync::Once;
use winapi::ctypes::c_int;
use winapi::shared::in6addr::{in6_addr_u, IN6_ADDR};
use winapi::shared::inaddr::{in_addr_S_un, IN_ADDR};
use winapi::shared::ws2def::{ADDRESS_FAMILY, AF_INET, AF_INET6, SOCKADDR, SOCKADDR_IN};
use winapi::shared::ws2ipdef::{SOCKADDR_IN6_LH_u, SOCKADDR_IN6_LH};
use winapi::um::winsock2::{ioctlsocket, socket, FIONBIO, INVALID_SOCKET, SOCKET};
use windows_sys::Win32::Networking::WinSock::{
ioctlsocket, socket, FIONBIO, IN6_ADDR, IN6_ADDR_0, INVALID_SOCKET, IN_ADDR, IN_ADDR_0,
SOCKADDR, SOCKADDR_IN, SOCKADDR_IN6, SOCKADDR_IN6_0, SOCKET,
};
// AF_INET/6 are in the Win32_NetworkManagement_IpHelper feature for some reason,
// so just directly define them here rather than import that whole feature set
// these constants won't ever change
pub(crate) const AF_INET: u16 = 2;
pub(crate) const AF_INET6: u16 = 23;
/// Initialise the network stack for Windows.
pub(crate) fn init() {
@@ -22,20 +26,18 @@ pub(crate) fn init() {
}
/// Create a new non-blocking socket.
pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: c_int) -> io::Result<SOCKET> {
use winapi::um::winsock2::{PF_INET, PF_INET6};
pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: u16) -> io::Result<SOCKET> {
let domain = match addr {
SocketAddr::V4(..) => PF_INET,
SocketAddr::V6(..) => PF_INET6,
SocketAddr::V4(..) => AF_INET,
SocketAddr::V6(..) => AF_INET6,
};
new_socket(domain, socket_type)
}
pub(crate) fn new_socket(domain: c_int, socket_type: c_int) -> io::Result<SOCKET> {
pub(crate) fn new_socket(domain: u16, socket_type: u16) -> io::Result<SOCKET> {
syscall!(
socket(domain, socket_type, 0),
socket(domain as i32, socket_type as i32, 0),
PartialEq::eq,
INVALID_SOCKET
)
@@ -51,7 +53,7 @@ pub(crate) fn new_socket(domain: c_int, socket_type: c_int) -> io::Result<SOCKET
#[repr(C)]
pub(crate) union SocketAddrCRepr {
v4: SOCKADDR_IN,
v6: SOCKADDR_IN6_LH,
v6: SOCKADDR_IN6,
}
impl SocketAddrCRepr {
@@ -60,49 +62,49 @@ impl SocketAddrCRepr {
}
}
pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, c_int) {
pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, i32) {
match addr {
SocketAddr::V4(ref addr) => {
// `s_addr` is stored as BE on all machine and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
let sin_addr = unsafe {
let mut s_un = mem::zeroed::<in_addr_S_un>();
*s_un.S_addr_mut() = u32::from_ne_bytes(addr.ip().octets());
let mut s_un = mem::zeroed::<IN_ADDR_0>();
s_un.S_addr = u32::from_ne_bytes(addr.ip().octets());
IN_ADDR { S_un: s_un }
};
let sockaddr_in = SOCKADDR_IN {
sin_family: AF_INET as ADDRESS_FAMILY,
sin_family: AF_INET,
sin_port: addr.port().to_be(),
sin_addr,
sin_zero: [0; 8],
};
let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
(sockaddr, mem::size_of::<SOCKADDR_IN>() as c_int)
(sockaddr, mem::size_of::<SOCKADDR_IN>() as i32)
}
SocketAddr::V6(ref addr) => {
let sin6_addr = unsafe {
let mut u = mem::zeroed::<in6_addr_u>();
*u.Byte_mut() = addr.ip().octets();
let mut u = mem::zeroed::<IN6_ADDR_0>();
u.Byte = addr.ip().octets();
IN6_ADDR { u }
};
let u = unsafe {
let mut u = mem::zeroed::<SOCKADDR_IN6_LH_u>();
*u.sin6_scope_id_mut() = addr.scope_id();
let mut u = mem::zeroed::<SOCKADDR_IN6_0>();
u.sin6_scope_id = addr.scope_id();
u
};
let sockaddr_in6 = SOCKADDR_IN6_LH {
sin6_family: AF_INET6 as ADDRESS_FAMILY,
let sockaddr_in6 = SOCKADDR_IN6 {
sin6_family: AF_INET6,
sin6_port: addr.port().to_be(),
sin6_addr,
sin6_flowinfo: addr.flowinfo(),
u,
Anonymous: u,
};
let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
(sockaddr, mem::size_of::<SOCKADDR_IN6_LH>() as c_int)
(sockaddr, mem::size_of::<SOCKADDR_IN6>() as i32)
}
}
}
+2 -2
View File
@@ -4,8 +4,8 @@ use std::cell::UnsafeCell;
use std::fmt;
#[cfg(feature = "os-ext")]
use winapi::um::minwinbase::OVERLAPPED;
use winapi::um::minwinbase::OVERLAPPED_ENTRY;
use windows_sys::Win32::System::IO::OVERLAPPED;
use windows_sys::Win32::System::IO::OVERLAPPED_ENTRY;
#[repr(C)]
pub(crate) struct Overlapped {
+22 -17
View File
@@ -12,6 +12,7 @@ cfg_net! {
use miow::iocp::{CompletionPort, CompletionStatus};
use std::collections::VecDeque;
use std::ffi::c_void;
use std::io;
use std::marker::PhantomPinned;
use std::os::windows::io::RawSocket;
@@ -21,11 +22,11 @@ use std::sync::atomic::AtomicUsize;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use winapi::shared::ntdef::NT_SUCCESS;
use winapi::shared::ntdef::{HANDLE, PVOID};
use winapi::shared::ntstatus::STATUS_CANCELLED;
use winapi::shared::winerror::{ERROR_INVALID_HANDLE, ERROR_IO_PENDING, WAIT_TIMEOUT};
use winapi::um::minwinbase::OVERLAPPED;
use windows_sys::Win32::{
Foundation::{ERROR_INVALID_HANDLE, ERROR_IO_PENDING, HANDLE, STATUS_CANCELLED, WAIT_TIMEOUT},
System::IO::OVERLAPPED,
};
#[derive(Debug)]
struct AfdGroup {
@@ -141,7 +142,7 @@ impl SockState {
/* No poll operation is pending; start one. */
self.poll_info.exclusive = 0;
self.poll_info.number_of_handles = 1;
*unsafe { self.poll_info.timeout.QuadPart_mut() } = std::i64::MAX;
self.poll_info.timeout = i64::MAX;
self.poll_info.handles[0].handle = self.base_socket as HANDLE;
self.poll_info.handles[0].status = 0;
self.poll_info.handles[0].events = self.user_evts | afd::POLL_LOCAL_CLOSE;
@@ -204,9 +205,9 @@ impl SockState {
unsafe {
if self.delete_pending {
return None;
} else if self.iosb.u.Status == STATUS_CANCELLED {
} else if self.iosb.Anonymous.Status == STATUS_CANCELLED {
/* The poll request was cancelled by CancelIoEx. */
} else if !NT_SUCCESS(self.iosb.u.Status) {
} else if self.iosb.Anonymous.Status < 0 {
/* The overlapped request itself failed in an unexpected way. */
afd_events = afd::POLL_CONNECT_FAIL;
} else if self.poll_info.number_of_handles < 1 {
@@ -295,7 +296,7 @@ impl Drop for SockState {
/// Converts the pointer to a `SockState` into a raw pointer.
/// To revert see `from_overlapped`.
fn into_overlapped(sock_state: Pin<Arc<Mutex<SockState>>>) -> PVOID {
fn into_overlapped(sock_state: Pin<Arc<Mutex<SockState>>>) -> *mut c_void {
let overlapped_ptr: *const Mutex<SockState> =
unsafe { Arc::into_raw(Pin::into_inner_unchecked(sock_state)) };
overlapped_ptr as *mut _
@@ -534,9 +535,13 @@ impl SelectorInner {
cfg_io_source! {
use std::mem::size_of;
use std::ptr::null_mut;
use winapi::um::mswsock;
use winapi::um::winsock2::WSAGetLastError;
use winapi::um::winsock2::{WSAIoctl, SOCKET_ERROR};
use windows_sys::Win32::Networking::WinSock::{WSAGetLastError, SOCKET_ERROR, WSAIoctl, IOC_OUT, IOC_WS2};
const SIO_BSP_HANDLE: u32 = IOC_OUT | IOC_WS2 | 27; // 1_207_959_579u32
const SIO_BSP_HANDLE_SELECT: u32 = IOC_OUT | IOC_WS2 | 28; // 1_207_959_580u32
const SIO_BSP_HANDLE_POLL: u32 = IOC_OUT | IOC_WS2 | 29; // 1_207_959_581u32
const SIO_BASE_HANDLE: u32 = IOC_OUT | IOC_WS2 | 34; // 1_207_959_586u32
impl SelectorInner {
fn register(
@@ -640,7 +645,7 @@ cfg_io_source! {
ioctl,
null_mut(),
0,
&mut base_socket as *mut _ as PVOID,
&mut base_socket as *mut _ as *mut c_void,
size_of::<RawSocket>() as u32,
&mut bytes,
null_mut(),
@@ -655,7 +660,7 @@ cfg_io_source! {
}
fn get_base_socket(raw_socket: RawSocket) -> io::Result<RawSocket> {
let res = try_get_base_socket(raw_socket, mswsock::SIO_BASE_HANDLE);
let res = try_get_base_socket(raw_socket, SIO_BASE_HANDLE);
if let Ok(base_socket) = res {
return Ok(base_socket);
}
@@ -666,9 +671,9 @@ cfg_io_source! {
// However, at least one known LSP deliberately breaks it, so we try
// some alternative IOCTLs, starting with the most appropriate one.
for &ioctl in &[
mswsock::SIO_BSP_HANDLE_SELECT,
mswsock::SIO_BSP_HANDLE_POLL,
mswsock::SIO_BSP_HANDLE,
SIO_BSP_HANDLE_SELECT,
SIO_BSP_HANDLE_POLL,
SIO_BSP_HANDLE,
] {
if let Ok(base_socket) = try_get_base_socket(raw_socket, ioctl) {
// Since we know now that we're dealing with an LSP (otherwise
+7 -7
View File
@@ -2,21 +2,21 @@ use std::io;
use std::net::{self, SocketAddr};
use std::os::windows::io::AsRawSocket;
use winapi::um::winsock2::{self, PF_INET, PF_INET6, SOCKET, SOCKET_ERROR, SOCK_STREAM};
use windows_sys::Win32::Networking::WinSock::{self, SOCKET, SOCKET_ERROR, SOCK_STREAM};
use crate::sys::windows::net::{init, new_socket, socket_addr};
use crate::sys::windows::net::{init, new_socket, socket_addr, AF_INET, AF_INET6};
pub(crate) fn new_for_addr(address: SocketAddr) -> io::Result<SOCKET> {
init();
let domain = match address {
SocketAddr::V4(_) => PF_INET,
SocketAddr::V6(_) => PF_INET6,
SocketAddr::V4(_) => AF_INET,
SocketAddr::V6(_) => AF_INET6,
};
new_socket(domain, SOCK_STREAM)
}
pub(crate) fn bind(socket: &net::TcpListener, addr: SocketAddr) -> io::Result<()> {
use winsock2::bind;
use WinSock::bind;
let (raw_addr, raw_addr_length) = socket_addr(&addr);
syscall!(
@@ -32,7 +32,7 @@ pub(crate) fn bind(socket: &net::TcpListener, addr: SocketAddr) -> io::Result<()
}
pub(crate) fn connect(socket: &net::TcpStream, addr: SocketAddr) -> io::Result<()> {
use winsock2::connect;
use WinSock::connect;
let (raw_addr, raw_addr_length) = socket_addr(&addr);
let res = syscall!(
@@ -53,7 +53,7 @@ pub(crate) fn connect(socket: &net::TcpStream, addr: SocketAddr) -> io::Result<(
pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()> {
use std::convert::TryInto;
use winsock2::listen;
use WinSock::listen;
let backlog = backlog.try_into().unwrap_or(i32::max_value());
syscall!(
+9 -11
View File
@@ -2,14 +2,12 @@ use std::io;
use std::mem::{self, MaybeUninit};
use std::net::{self, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
use winapi::ctypes::c_int;
use winapi::shared::ws2def::IPPROTO_IPV6;
use winapi::shared::ws2ipdef::IPV6_V6ONLY;
use winapi::um::winsock2::{bind as win_bind, closesocket, getsockopt, SOCKET_ERROR, SOCK_DGRAM};
use std::os::windows::raw::SOCKET as StdSocket; // windows-sys uses usize, stdlib uses u32/u64.
use crate::sys::windows::net::{init, new_ip_socket, socket_addr};
use windows_sys::Win32::Networking::WinSock::{
bind as win_bind, closesocket, getsockopt, IPPROTO_IPV6, IPV6_V6ONLY, SOCKET_ERROR, SOCK_DGRAM,
};
pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
init();
@@ -31,14 +29,14 @@ pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
}
pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> {
let mut optval: MaybeUninit<c_int> = MaybeUninit::uninit();
let mut optlen = mem::size_of::<c_int>() as c_int;
let mut optval: MaybeUninit<i32> = MaybeUninit::uninit();
let mut optlen = mem::size_of::<i32>() as i32;
syscall!(
getsockopt(
socket.as_raw_socket() as usize,
IPPROTO_IPV6 as c_int,
IPV6_V6ONLY as c_int,
IPPROTO_IPV6 as i32,
IPV6_V6ONLY as i32,
optval.as_mut_ptr().cast(),
&mut optlen,
),
@@ -46,7 +44,7 @@ pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> {
SOCKET_ERROR
)?;
debug_assert_eq!(optlen as usize, mem::size_of::<c_int>());
debug_assert_eq!(optlen as usize, mem::size_of::<i32>());
// Safety: `getsockopt` initialised `optval` for us.
let optval = unsafe { optval.assume_init() };
Ok(optval != 0)
+7 -5
View File
@@ -263,9 +263,11 @@ pub fn set_linger_zero(socket: &TcpStream) {
#[cfg(windows)]
pub fn set_linger_zero(socket: &TcpStream) {
use std::os::windows::io::AsRawSocket;
use winapi::um::winsock2::{linger, setsockopt, SOCKET_ERROR, SOL_SOCKET, SO_LINGER};
use windows_sys::Win32::Networking::WinSock::{
linger, setsockopt, SOCKET_ERROR, SOL_SOCKET, SO_LINGER,
};
let val = linger {
let mut val = linger {
l_onoff: 1,
l_linger: 0,
};
@@ -273,9 +275,9 @@ pub fn set_linger_zero(socket: &TcpStream) {
let res = unsafe {
setsockopt(
socket.as_raw_socket() as _,
SOL_SOCKET,
SO_LINGER,
&val as *const _ as *const _,
SOL_SOCKET as i32,
SO_LINGER as i32,
&mut val as *mut _ as *mut _,
size_of::<linger>() as _,
)
};
+1 -2
View File
@@ -9,8 +9,7 @@ use std::time::Duration;
use mio::windows::NamedPipe;
use mio::{Events, Interest, Poll, Token};
use rand::Rng;
use winapi::shared::winerror::*;
use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
use windows_sys::Win32::{Foundation::ERROR_NO_DATA, Storage::FileSystem::FILE_FLAG_OVERLAPPED};
fn _assert_kinds() {
fn _assert_send<T: Send>() {}