Skip to content

Commit da97fa3

Browse files
committed
Add support for Windows Registered I/O
1 parent 15ade51 commit da97fa3

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

src/sys/windows.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use windows_sys::Win32::Networking::WinSock::{
2525
self, tcp_keepalive, FIONBIO, IN6_ADDR, IN6_ADDR_0, INVALID_SOCKET, IN_ADDR, IN_ADDR_0,
2626
POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, SD_BOTH, SD_RECEIVE, SD_SEND, SIO_KEEPALIVE_VALS,
2727
SOCKET_ERROR, WSABUF, WSAEMSGSIZE, WSAESHUTDOWN, WSAPOLLFD, WSAPROTOCOL_INFOW,
28-
WSA_FLAG_NO_HANDLE_INHERIT, WSA_FLAG_OVERLAPPED,
28+
WSA_FLAG_NO_HANDLE_INHERIT, WSA_FLAG_OVERLAPPED, WSA_FLAG_REGISTERED_IO,
2929
};
3030
#[cfg(feature = "all")]
3131
use windows_sys::Win32::Networking::WinSock::{
@@ -125,13 +125,21 @@ impl Type {
125125
/// Our custom flag to set `WSA_FLAG_NO_HANDLE_INHERIT` on socket creation.
126126
/// Trying to mimic `Type::cloexec` on windows.
127127
const NO_INHERIT: c_int = 1 << ((size_of::<c_int>() * 8) - 1); // Last bit.
128+
/// Our custom flag to set `WSA_FLAG_REGISTERED_IO` on socket creation.
129+
const REGISTERED_IO: c_int = 1 << ((size_of::<c_int>() * 8) - 2); // Second last bit.
128130

129131
/// Set `WSA_FLAG_NO_HANDLE_INHERIT` on the socket.
130132
#[cfg(feature = "all")]
131133
pub const fn no_inherit(self) -> Type {
132134
self._no_inherit()
133135
}
134136

137+
/// Set `WSA_FLAG_REGISTERED_IO` on the socket.
138+
#[cfg(feature = "all")]
139+
pub const fn registered_io(self) -> Type {
140+
Type(self.0 | Type::REGISTERED_IO)
141+
}
142+
135143
pub(crate) const fn _no_inherit(self) -> Type {
136144
Type(self.0 | Type::NO_INHERIT)
137145
}
@@ -252,13 +260,19 @@ pub(crate) fn socket_into_raw(socket: Socket) -> RawSocket {
252260
pub(crate) fn socket(family: c_int, mut ty: c_int, protocol: c_int) -> io::Result<RawSocket> {
253261
init();
254262

255-
// Check if we set our custom flag.
263+
// Check if we set our custom flags.
256264
let flags = if ty & Type::NO_INHERIT != 0 {
257265
ty = ty & !Type::NO_INHERIT;
258266
WSA_FLAG_NO_HANDLE_INHERIT
259267
} else {
260268
0
261269
};
270+
let flags = if ty & Type::REGISTERED_IO != 0 {
271+
ty = ty & !Type::REGISTERED_IO;
272+
flags | WSA_FLAG_REGISTERED_IO
273+
} else {
274+
flags
275+
};
262276

263277
syscall!(
264278
WSASocketW(

tests/socket.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,48 @@ where
418418
);
419419
}
420420

421+
#[cfg(all(feature = "all", windows))]
422+
#[test]
423+
fn type_registered_io() {
424+
let ty = Type::DGRAM.registered_io();
425+
let socket = Socket::new(Domain::IPV4, ty, None).unwrap();
426+
assert_registered_io(&socket);
427+
}
428+
429+
/// Assert that registered I/O is enabled on `socket`.
430+
#[cfg(windows)]
431+
#[track_caller]
432+
pub fn assert_registered_io<S>(socket: &S)
433+
where
434+
S: AsRawSocket,
435+
{
436+
use std::ptr;
437+
use windows_sys::core::GUID;
438+
use windows_sys::Win32::Networking::WinSock;
439+
440+
let mut table = MaybeUninit::<WinSock::RIO_EXTENSION_FUNCTION_TABLE>::uninit();
441+
let guid = WinSock::WSAID_MULTIPLE_RIO;
442+
let mut bytes = 0;
443+
444+
let r = unsafe {
445+
WinSock::WSAIoctl(
446+
socket.as_raw_socket() as _,
447+
WinSock::SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER,
448+
(&guid as *const GUID) as *const _,
449+
size_of_val(&guid) as u32,
450+
table.as_mut_ptr() as *mut _,
451+
size_of_val(&table) as u32,
452+
(&mut bytes as *mut i32) as *mut _,
453+
ptr::null_mut(),
454+
None,
455+
)
456+
};
457+
if r != 0 {
458+
let err = io::Error::last_os_error();
459+
panic!("unexpected error: {err}");
460+
}
461+
}
462+
421463
#[cfg(all(
422464
feature = "all",
423465
any(

0 commit comments

Comments
 (0)