const SOCKADDR_IN_LEN: libc::socklen_t = mem::size_of::<libc::sockaddr_in>() as libc::socklen_t;
const SOCKADDR_IN6_LEN: libc::socklen_t = mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t;
fn from_socket_addr(addr: SocketAddr) -> (libc::sockaddr_storage, libc::socklen_t) {
let mut out = MaybeUninit::<libc::sockaddr_storage>::uninit();
let len = match addr {
SocketAddr::V4(addr) => {
let out = out.as_mut_ptr().cast::<libc::sockaddr_in>();
unsafe {
out.write(libc::sockaddr_in {
sin_family: libc::AF_INET as u16,
sin_port: addr.port().to_be(),
sin_addr: libc::in_addr {
s_addr: u32::from_ne_bytes(addr.ip().octets()),
},
sin_zero: [0; 8],
});
}
SOCKADDR_IN_LEN
}
SocketAddr::V6(addr) => {
let out = out.as_mut_ptr().cast::<libc::sockaddr_in6>();
unsafe {
out.write(libc::sockaddr_in6 {
sin6_family: libc::AF_INET6 as u16,
sin6_port: addr.port().to_be(),
sin6_flowinfo: addr.flowinfo(),
sin6_addr: libc::in6_addr {
s6_addr: addr.ip().octets(),
},
sin6_scope_id: addr.scope_id(),
});
}
SOCKADDR_IN6_LEN
}
};
let addr = unsafe { out.assume_init() };
(addr, len)
}
fn to_socket_addr(
mut addr: MaybeUninit<libc::sockaddr_storage>,
len: libc::socklen_t,
) -> Option<SocketAddr> {
match len {
SOCKADDR_IN_LEN => {
let addr = unsafe { *addr.as_mut_ptr().cast::<libc::sockaddr_in>() };
if addr.sin_family as i32 == libc::AF_INET {
let ip = Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr));
let port = u16::from_be(addr.sin_port);
let addr = SocketAddrV4::new(ip, port);
Some(SocketAddr::V4(addr))
} else {
None
}
}
SOCKADDR_IN6_LEN => {
let addr = unsafe { *addr.as_mut_ptr().cast::<libc::sockaddr_in6>() };
if addr.sin6_family as i32 == libc::AF_INET6 {
let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
let port = u16::from_be(addr.sin6_port);
let flowinfo = addr.sin6_flowinfo;
let scope_id = addr.sin6_scope_id;
let addr = SocketAddrV6::new(ip, port, flowinfo, scope_id);
Some(SocketAddr::V6(addr))
} else {
None
}
}
_ => None,
}
}