diff options
Diffstat (limited to 'src/sys/windows/tcp.rs')
-rw-r--r-- | src/sys/windows/tcp.rs | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/src/sys/windows/tcp.rs b/src/sys/windows/tcp.rs index 46ac1ac..b78d864 100644 --- a/src/sys/windows/tcp.rs +++ b/src/sys/windows/tcp.rs @@ -1,14 +1,17 @@ use std::io; use std::mem::size_of; -use std::net::{self, SocketAddr}; +use std::net::{self, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::time::Duration; use std::os::windows::io::FromRawSocket; use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64. use winapi::ctypes::{c_char, c_int, c_ushort}; +use winapi::shared::ws2def::{SOCKADDR_STORAGE, AF_INET, SOCKADDR_IN}; +use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH; + use winapi::shared::minwindef::{BOOL, TRUE, FALSE}; use winapi::um::winsock2::{ - self, closesocket, linger, setsockopt, PF_INET, PF_INET6, SOCKET, SOCKET_ERROR, + self, closesocket, linger, setsockopt, getsockopt, getsockname, PF_INET, PF_INET6, SOCKET, SOCKET_ERROR, SOCK_STREAM, SOL_SOCKET, SO_LINGER, SO_REUSEADDR, }; @@ -87,6 +90,47 @@ pub(crate) fn set_reuseaddr(socket: TcpSocket, reuseaddr: bool) -> io::Result<() } } +pub(crate) fn get_reuseaddr(socket: TcpSocket) -> io::Result<bool> { + let mut optval: c_char = 0; + let mut optlen = size_of::<BOOL>() as c_int; + + match unsafe { getsockopt( + socket, + SOL_SOCKET, + SO_REUSEADDR, + &mut optval as *mut _ as *mut _, + &mut optlen, + ) } { + SOCKET_ERROR => Err(io::Error::last_os_error()), + _ => Ok(optval != 0), + } +} + +pub(crate) fn get_localaddr(socket: TcpSocket) -> io::Result<SocketAddr> { + let mut addr: SOCKADDR_STORAGE = unsafe { std::mem::zeroed() }; + let mut length = std::mem::size_of_val(&addr) as c_int; + + match unsafe { getsockname( + socket, + &mut addr as *mut _ as *mut _, + &mut length + ) } { + SOCKET_ERROR => Err(io::Error::last_os_error()), + _ => { + let storage: *const SOCKADDR_STORAGE = (&addr) as *const _; + if addr.ss_family as c_int == AF_INET { + let sock_addr : SocketAddrV4 = unsafe { *(storage as *const SOCKADDR_IN as *const _) }; + Ok(sock_addr.into()) + } else { + let sock_addr : SocketAddrV6 = unsafe { *(storage as *const SOCKADDR_IN6_LH as *const _) }; + Ok(sock_addr.into()) + } + }, + } + + +} + pub(crate) fn set_linger(socket: TcpSocket, dur: Option<Duration>) -> io::Result<()> { let val: linger = linger { l_onoff: if dur.is_some() { 1 } else { 0 }, |