1 use std::io;
2 use std::mem;
3 use std::net::SocketAddr;
4 use std::sync::Once;
5
6 use winapi::ctypes::c_int;
7 use winapi::shared::inaddr::{in_addr_S_un, IN_ADDR};
8 use winapi::shared::in6addr::{in6_addr_u, IN6_ADDR};
9 use winapi::shared::ws2def::{AF_INET, AF_INET6, ADDRESS_FAMILY, SOCKADDR, SOCKADDR_IN};
10 use winapi::shared::ws2ipdef::{SOCKADDR_IN6_LH, SOCKADDR_IN6_LH_u};
11 use winapi::um::winsock2::{ioctlsocket, socket, FIONBIO, INVALID_SOCKET, SOCKET};
12
13 /// Initialise the network stack for Windows.
init()14 pub(crate) fn init() {
15 static INIT: Once = Once::new();
16 INIT.call_once(|| {
17 // Let standard library call `WSAStartup` for us, we can't do it
18 // ourselves because otherwise using any type in `std::net` would panic
19 // when it tries to call `WSAStartup` a second time.
20 drop(std::net::UdpSocket::bind("127.0.0.1:0"));
21 });
22 }
23
24 /// Create a new non-blocking socket.
new_ip_socket(addr: SocketAddr, socket_type: c_int) -> io::Result<SOCKET>25 pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: c_int) -> io::Result<SOCKET> {
26 use winapi::um::winsock2::{PF_INET, PF_INET6};
27
28 let domain = match addr {
29 SocketAddr::V4(..) => PF_INET,
30 SocketAddr::V6(..) => PF_INET6,
31 };
32
33 new_socket(domain, socket_type)
34 }
35
new_socket(domain: c_int, socket_type: c_int) -> io::Result<SOCKET>36 pub(crate) fn new_socket(domain: c_int, socket_type: c_int) -> io::Result<SOCKET> {
37 syscall!(
38 socket(domain, socket_type, 0),
39 PartialEq::eq,
40 INVALID_SOCKET
41 )
42 .and_then(|socket| {
43 syscall!(ioctlsocket(socket, FIONBIO, &mut 1), PartialEq::ne, 0).map(|_| socket as SOCKET)
44 })
45 }
46
47 /// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level
48 /// SocketAddr* types into their system representation. The benefit of this specific
49 /// type over using `SOCKADDR_STORAGE` is that this type is exactly as large as it
50 /// needs to be and not a lot larger. And it can be initialized cleaner from Rust.
51 #[repr(C)]
52 pub(crate) union SocketAddrCRepr {
53 v4: SOCKADDR_IN,
54 v6: SOCKADDR_IN6_LH,
55 }
56
57 impl SocketAddrCRepr {
as_ptr(&self) -> *const SOCKADDR58 pub(crate) fn as_ptr(&self) -> *const SOCKADDR {
59 self as *const _ as *const SOCKADDR
60 }
61 }
62
socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, c_int)63 pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, c_int) {
64 match addr {
65 SocketAddr::V4(ref addr) => {
66 // `s_addr` is stored as BE on all machine and the array is in BE order.
67 // So the native endian conversion method is used so that it's never swapped.
68 let sin_addr = unsafe {
69 let mut s_un = mem::zeroed::<in_addr_S_un>();
70 *s_un.S_addr_mut() = u32::from_ne_bytes(addr.ip().octets());
71 IN_ADDR { S_un: s_un }
72 };
73
74 let sockaddr_in = SOCKADDR_IN {
75 sin_family: AF_INET as ADDRESS_FAMILY,
76 sin_port: addr.port().to_be(),
77 sin_addr,
78 sin_zero: [0; 8],
79 };
80
81 let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
82 (sockaddr, mem::size_of::<SOCKADDR_IN>() as c_int)
83 },
84 SocketAddr::V6(ref addr) => {
85 let sin6_addr = unsafe {
86 let mut u = mem::zeroed::<in6_addr_u>();
87 *u.Byte_mut() = addr.ip().octets();
88 IN6_ADDR { u }
89 };
90 let u = unsafe {
91 let mut u = mem::zeroed::<SOCKADDR_IN6_LH_u>();
92 *u.sin6_scope_id_mut() = addr.scope_id();
93 u
94 };
95
96 let sockaddr_in6 = SOCKADDR_IN6_LH {
97 sin6_family: AF_INET6 as ADDRESS_FAMILY,
98 sin6_port: addr.port().to_be(),
99 sin6_addr,
100 sin6_flowinfo: addr.flowinfo(),
101 u,
102 };
103
104 let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
105 (sockaddr, mem::size_of::<SOCKADDR_IN6_LH>() as c_int)
106 }
107 }
108 }
109