1 use std::io;
2 use std::mem::size_of_val;
3 use std::net::SocketAddr;
4 #[cfg(all(feature = "os-poll", feature = "tcp"))]
5 use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
6 use std::sync::Once;
7 
8 use winapi::ctypes::c_int;
9 use winapi::shared::ws2def::SOCKADDR;
10 use winapi::um::winsock2::{
11     ioctlsocket, socket, FIONBIO, INVALID_SOCKET, PF_INET, PF_INET6, SOCKET,
12 };
13 
14 /// Initialise the network stack for Windows.
init()15 pub(crate) fn init() {
16     static INIT: Once = Once::new();
17     INIT.call_once(|| {
18         // Let standard library call `WSAStartup` for us, we can't do it
19         // ourselves because otherwise using any type in `std::net` would panic
20         // when it tries to call `WSAStartup` a second time.
21         drop(std::net::UdpSocket::bind("127.0.0.1:0"));
22     });
23 }
24 
25 /// Create a new non-blocking socket.
new_socket(addr: SocketAddr, socket_type: c_int) -> io::Result<SOCKET>26 pub(crate) fn new_socket(addr: SocketAddr, socket_type: c_int) -> io::Result<SOCKET> {
27     let domain = match addr {
28         SocketAddr::V4(..) => PF_INET,
29         SocketAddr::V6(..) => PF_INET6,
30     };
31 
32     syscall!(
33         socket(domain, socket_type, 0),
34         PartialEq::eq,
35         INVALID_SOCKET
36     )
37     .and_then(|socket| {
38         syscall!(ioctlsocket(socket, FIONBIO, &mut 1), PartialEq::ne, 0).map(|_| socket as SOCKET)
39     })
40 }
41 
socket_addr(addr: &SocketAddr) -> (*const SOCKADDR, c_int)42 pub(crate) fn socket_addr(addr: &SocketAddr) -> (*const SOCKADDR, c_int) {
43     match addr {
44         SocketAddr::V4(ref addr) => (
45             addr as *const _ as *const SOCKADDR,
46             size_of_val(addr) as c_int,
47         ),
48         SocketAddr::V6(ref addr) => (
49             addr as *const _ as *const SOCKADDR,
50             size_of_val(addr) as c_int,
51         ),
52     }
53 }
54 
55 #[cfg(all(feature = "os-poll", feature = "tcp"))]
inaddr_any(other: SocketAddr) -> SocketAddr56 pub(crate) fn inaddr_any(other: SocketAddr) -> SocketAddr {
57     match other {
58         SocketAddr::V4(..) => {
59             let any = Ipv4Addr::new(0, 0, 0, 0);
60             let addr = SocketAddrV4::new(any, 0);
61             SocketAddr::V4(addr)
62         }
63         SocketAddr::V6(..) => {
64             let any = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
65             let addr = SocketAddrV6::new(any, 0, 0, 0);
66             SocketAddr::V6(addr)
67         }
68     }
69 }
70