use std::io;
use std::mem;
use std::net::SocketAddr;
use windows_sys::Win32::Networking::WinSock as WS;
use crate::sys::Fd;
pub(crate) fn encode_sockaddr(addr: SocketAddr, storage: &mut WS::SOCKADDR_STORAGE) -> i32 {
match addr {
SocketAddr::V4(v4) => {
let sin = WS::SOCKADDR_IN {
sin_family: WS::AF_INET,
sin_port: v4.port().to_be(),
sin_addr: WS::IN_ADDR {
S_un: WS::IN_ADDR_0 {
S_addr: u32::from_ne_bytes(v4.ip().octets()),
},
},
sin_zero: [0i8; 8],
};
unsafe {
*(storage as *mut _ as *mut WS::SOCKADDR_IN) = sin;
}
mem::size_of::<WS::SOCKADDR_IN>() as i32
}
SocketAddr::V6(v6) => {
let sin6 = WS::SOCKADDR_IN6 {
sin6_family: WS::AF_INET6,
sin6_port: v6.port().to_be(),
sin6_flowinfo: v6.flowinfo(),
sin6_addr: WS::IN6_ADDR {
u: WS::IN6_ADDR_0 {
Byte: v6.ip().octets(),
},
},
Anonymous: WS::SOCKADDR_IN6_0 {
sin6_scope_id: v6.scope_id(),
},
};
unsafe {
*(storage as *mut _ as *mut WS::SOCKADDR_IN6) = sin6;
}
mem::size_of::<WS::SOCKADDR_IN6>() as i32
}
}
}
pub(crate) fn decode_sockaddr(storage: &WS::SOCKADDR_STORAGE, len: i32) -> SocketAddr {
if len == 0 {
return SocketAddr::V4(std::net::SocketAddrV4::new(
std::net::Ipv4Addr::UNSPECIFIED,
0,
));
}
match storage.ss_family as i32 {
x if x == WS::AF_INET as i32 => {
let sin: &WS::SOCKADDR_IN =
unsafe { &*(storage as *const _ as *const WS::SOCKADDR_IN) };
let ip = std::net::Ipv4Addr::from(u32::from_be(unsafe { sin.sin_addr.S_un.S_addr }));
let port = u16::from_be(sin.sin_port);
SocketAddr::V4(std::net::SocketAddrV4::new(ip, port))
}
x if x == WS::AF_INET6 as i32 => {
let sin6: &WS::SOCKADDR_IN6 =
unsafe { &*(storage as *const _ as *const WS::SOCKADDR_IN6) };
let ip = std::net::Ipv6Addr::from(unsafe { sin6.sin6_addr.u.Byte });
let port = u16::from_be(sin6.sin6_port);
SocketAddr::V6(std::net::SocketAddrV6::new(
ip,
port,
sin6.sin6_flowinfo,
unsafe { sin6.Anonymous.sin6_scope_id },
))
}
_ => SocketAddr::V4(std::net::SocketAddrV4::new(
std::net::Ipv4Addr::UNSPECIFIED,
0,
)),
}
}
pub(crate) fn is_connected(fd: Fd) -> bool {
let mut storage: WS::SOCKADDR_STORAGE = unsafe { mem::zeroed() };
let mut len = mem::size_of::<WS::SOCKADDR_STORAGE>() as i32;
unsafe { WS::getpeername(fd, &mut storage as *mut _ as *mut WS::SOCKADDR, &mut len) == 0 }
}
pub(crate) fn raw_getsockname(fd: Fd) -> io::Result<SocketAddr> {
let mut storage: WS::SOCKADDR_STORAGE = unsafe { mem::zeroed() };
let mut len = mem::size_of::<WS::SOCKADDR_STORAGE>() as i32;
let ret = unsafe { WS::getsockname(fd, &mut storage as *mut _ as *mut WS::SOCKADDR, &mut len) };
if ret == 0 {
Ok(decode_sockaddr(&storage, len))
} else {
Err(io::Error::last_os_error())
}
}
pub(crate) fn raw_connect(fd: Fd, addr: SocketAddr) -> io::Result<()> {
let mut storage: WS::SOCKADDR_STORAGE = unsafe { mem::zeroed() };
let addr_len = encode_sockaddr(addr, &mut storage);
let ret = unsafe { WS::connect(fd, &storage as *const _ as *const WS::SOCKADDR, addr_len) };
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
}
}
pub(crate) fn raw_setsockopt(fd: Fd, level: i32, optname: i32, val: i32) -> io::Result<()> {
let ret = unsafe {
WS::setsockopt(
fd,
level,
optname,
&val as *const _ as *const u8,
mem::size_of_val(&val) as i32,
)
};
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
}
}
#[allow(dead_code)]
pub(crate) fn raw_sendto(fd: Fd, data: &[u8], addr: SocketAddr) -> io::Result<usize> {
let mut storage: WS::SOCKADDR_STORAGE = unsafe { mem::zeroed() };
let addr_len = encode_sockaddr(addr, &mut storage);
let ret = unsafe {
WS::sendto(
fd,
data.as_ptr().cast(),
data.len() as i32,
0,
&storage as *const _ as *const WS::SOCKADDR,
addr_len,
)
};
if ret >= 0 {
Ok(ret as usize)
} else {
Err(io::Error::last_os_error())
}
}
#[allow(dead_code)]
pub(crate) fn raw_send(fd: Fd, data: &[u8]) -> io::Result<usize> {
let ret = unsafe { WS::send(fd, data.as_ptr().cast(), data.len() as i32, 0) };
if ret >= 0 {
Ok(ret as usize)
} else {
Err(io::Error::last_os_error())
}
}
#[allow(dead_code)]
pub(crate) fn raw_recvfrom(fd: Fd, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
let mut storage: WS::SOCKADDR_STORAGE = unsafe { mem::zeroed() };
let mut addr_len = mem::size_of::<WS::SOCKADDR_STORAGE>() as i32;
let ret = unsafe {
WS::recvfrom(
fd,
buf.as_mut_ptr().cast(),
buf.len() as i32,
0,
&mut storage as *mut _ as *mut WS::SOCKADDR,
&mut addr_len,
)
};
if ret >= 0 {
Ok((ret as usize, decode_sockaddr(&storage, addr_len)))
} else {
Err(io::Error::last_os_error())
}
}
pub(crate) fn raw_getsockopt(fd: Fd, level: i32, optname: i32) -> io::Result<i32> {
let mut val: i32 = 0;
let mut len = mem::size_of_val(&val) as i32;
let ret =
unsafe { WS::getsockopt(fd, level, optname, &mut val as *mut _ as *mut u8, &mut len) };
if ret == 0 {
Ok(val)
} else {
Err(io::Error::last_os_error())
}
}