diff options
author | Haibo Huang <hhb@google.com> | 2020-11-16 17:42:39 -0800 |
---|---|---|
committer | Haibo Huang <hhb@google.com> | 2020-11-16 17:42:39 -0800 |
commit | b871bf78acdb643f7b39ac9d1110ab94d886d7d1 (patch) | |
tree | 9953974f4f90698632f6dcdcb001e8f962af4dbd /src/sys/windows/net.rs | |
parent | 8414138e74aa469015108049230e70b0a325c6e9 (diff) | |
download | mio-b871bf78acdb643f7b39ac9d1110ab94d886d7d1.tar.gz |
Upgrade rust/crates/mio to 0.7.6
Test: make
Change-Id: I26de17b65a22ec1ba472a61c51b55681afdb8ffa
Diffstat (limited to 'src/sys/windows/net.rs')
-rw-r--r-- | src/sys/windows/net.rs | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/src/sys/windows/net.rs b/src/sys/windows/net.rs index f825ee3..2de98fa 100644 --- a/src/sys/windows/net.rs +++ b/src/sys/windows/net.rs @@ -1,13 +1,14 @@ use std::io; -use std::mem::size_of_val; +use std::mem; use std::net::SocketAddr; use std::sync::Once; use winapi::ctypes::c_int; -use winapi::shared::ws2def::SOCKADDR; -use winapi::um::winsock2::{ - ioctlsocket, socket, FIONBIO, INVALID_SOCKET, SOCKET, -}; +use winapi::shared::inaddr::{in_addr_S_un, IN_ADDR}; +use winapi::shared::in6addr::{in6_addr_u, IN6_ADDR}; +use winapi::shared::ws2def::{AF_INET, AF_INET6, ADDRESS_FAMILY, SOCKADDR, SOCKADDR_IN}; +use winapi::shared::ws2ipdef::{SOCKADDR_IN6_LH, SOCKADDR_IN6_LH_u}; +use winapi::um::winsock2::{ioctlsocket, socket, FIONBIO, INVALID_SOCKET, SOCKET}; /// Initialise the network stack for Windows. pub(crate) fn init() { @@ -21,7 +22,6 @@ pub(crate) fn init() { } /// Create a new non-blocking socket. -#[cfg(feature = "udp")] pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: c_int) -> io::Result<SOCKET> { use winapi::um::winsock2::{PF_INET, PF_INET6}; @@ -44,15 +44,65 @@ pub(crate) fn new_socket(domain: c_int, socket_type: c_int) -> io::Result<SOCKET }) } -pub(crate) fn socket_addr(addr: &SocketAddr) -> (*const SOCKADDR, c_int) { +/// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level +/// SocketAddr* types into their system representation. The benefit of this specific +/// type over using `SOCKADDR_STORAGE` is that this type is exactly as large as it +/// needs to be and not a lot larger. And it can be initialized cleaner from Rust. +#[repr(C)] +pub(crate) union SocketAddrCRepr { + v4: SOCKADDR_IN, + v6: SOCKADDR_IN6_LH, +} + +impl SocketAddrCRepr { + pub(crate) fn as_ptr(&self) -> *const SOCKADDR { + self as *const _ as *const SOCKADDR + } +} + +pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, c_int) { match addr { - SocketAddr::V4(ref addr) => ( - addr as *const _ as *const SOCKADDR, - size_of_val(addr) as c_int, - ), - SocketAddr::V6(ref addr) => ( - addr as *const _ as *const SOCKADDR, - size_of_val(addr) as c_int, - ), + SocketAddr::V4(ref addr) => { + // `s_addr` is stored as BE on all machine and the array is in BE order. + // So the native endian conversion method is used so that it's never swapped. + let sin_addr = unsafe { + let mut s_un = mem::zeroed::<in_addr_S_un>(); + *s_un.S_addr_mut() = u32::from_ne_bytes(addr.ip().octets()); + IN_ADDR { S_un: s_un } + }; + + let sockaddr_in = SOCKADDR_IN { + sin_family: AF_INET as ADDRESS_FAMILY, + sin_port: addr.port().to_be(), + sin_addr, + sin_zero: [0; 8], + }; + + let sockaddr = SocketAddrCRepr { v4: sockaddr_in }; + (sockaddr, mem::size_of::<SOCKADDR_IN>() as c_int) + }, + SocketAddr::V6(ref addr) => { + let sin6_addr = unsafe { + let mut u = mem::zeroed::<in6_addr_u>(); + *u.Byte_mut() = addr.ip().octets(); + IN6_ADDR { u } + }; + let u = unsafe { + let mut u = mem::zeroed::<SOCKADDR_IN6_LH_u>(); + *u.sin6_scope_id_mut() = addr.scope_id(); + u + }; + + let sockaddr_in6 = SOCKADDR_IN6_LH { + sin6_family: AF_INET6 as ADDRESS_FAMILY, + sin6_port: addr.port().to_be(), + sin6_addr, + sin6_flowinfo: addr.flowinfo(), + u, + }; + + let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 }; + (sockaddr, mem::size_of::<SOCKADDR_IN6_LH>() as c_int) + } } } |