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