1#![deny(
10 rust_2018_idioms,
11 trivial_numeric_casts,
12 unreachable_pub,
13 unused_import_braces,
14 unused_must_use,
15 unused_qualifications
16)]
17
18#[cfg(windows)]
19pub use socket::wsa_poll;
20
21#[cfg(windows)]
22mod socket {
23 use std::convert::TryInto;
24 use std::io;
25
26 use winapi::shared::minwindef::INT;
27 use winapi::um::winsock2::{WSAGetLastError, WSAPoll, SOCKET_ERROR, WSAPOLLFD};
28
29 pub fn wsa_poll(fd_array: &mut [WSAPOLLFD], timeout: INT) -> io::Result<usize> {
36 unsafe {
37 let length = fd_array.len().try_into().unwrap();
38 let rc = WSAPoll(fd_array.as_mut_ptr(), length, timeout);
39 if rc == SOCKET_ERROR {
40 return Err(io::Error::from_raw_os_error(WSAGetLastError()));
41 };
42 Ok(rc.try_into().unwrap())
43 }
44 }
45
46 #[cfg(test)]
47 mod test {
48 use std::io::{Result, Write};
49 use std::net::{TcpListener, TcpStream};
50 use std::os::windows::io::{AsRawSocket, RawSocket};
51
52 use winapi::um::winnt::SHORT;
53 use winapi::um::winsock2::{POLLIN, POLLOUT, POLLRDNORM, WSAPOLLFD};
54
55 use super::wsa_poll;
56
57 fn get_connection_pair() -> Result<(TcpStream, TcpStream)> {
59 let listener = TcpListener::bind("127.0.0.1:0")?;
60 let stream1 = TcpStream::connect(listener.local_addr()?)?;
61 let stream2 = listener.accept()?.0;
62
63 Ok((stream1, stream2))
64 }
65
66 fn poll(socket: RawSocket, events: SHORT, revents: SHORT) -> Result<()> {
67 let mut sockets = [WSAPOLLFD {
68 fd: socket as _,
69 events,
70 revents: 0,
71 }];
72 let count = wsa_poll(&mut sockets, -1)?;
73 assert_eq!(count, 1);
74 assert_eq!(sockets[0].revents, revents);
75
76 Ok(())
77 }
78
79 #[test]
80 fn test_poll() -> Result<()> {
81 let (mut stream1, stream2) = get_connection_pair()?;
82
83 poll(stream1.as_raw_socket(), POLLOUT, POLLOUT)?;
85
86 stream1.write_all(b"1")?;
88
89 poll(
91 stream2.as_raw_socket(),
92 POLLIN | POLLOUT,
93 POLLOUT | POLLRDNORM,
94 )?;
95
96 Ok(())
97 }
98 }
99}