use std::path::PathBuf;
use std::net::{SocketAddrV4, SocketAddrV6};
pub enum SocketAddr
{
InProc(String),
Ipc(PathBuf),
Inet(SocketAddrV4),
Inet6(SocketAddrV6),
#[doc(hidden)]
ZeroTier(SocketAddrZt),
#[doc(hidden)]
Unspecified,
}
impl From<nng_sys::nng_sockaddr> for SocketAddr
{
fn from(addr: nng_sys::nng_sockaddr) -> SocketAddr
{
unsafe { match addr.s_family {
nng_sys::NNG_AF_INPROC => SocketAddr::InProc(buf_to_string(&addr.s_inproc.sa_name[..])),
nng_sys::NNG_AF_IPC => SocketAddr::Ipc(buf_to_string(&addr.s_ipc.sa_path[..]).into()),
nng_sys::NNG_AF_INET => SocketAddr::Inet(SocketAddrV4::new(addr.s_in.sa_addr.into(), addr.s_in.sa_port)),
nng_sys::NNG_AF_INET6 => SocketAddr::Inet6(SocketAddrV6::new(addr.s_in6.sa_addr.into(), addr.s_in6.sa_port, 0, 0)),
nng_sys::NNG_AF_ZT => SocketAddr::ZeroTier(SocketAddrZt::new(&addr.s_zt)),
_ => SocketAddr::Unspecified,
}}
}
}
#[doc(hidden)]
pub struct SocketAddrZt
{
pub family: u16,
pub nwid: u64,
pub nodeid: u64,
pub port: u32,
}
impl SocketAddrZt
{
fn new(addr: &nng_sys::nng_sockaddr_zt) -> SocketAddrZt
{
SocketAddrZt {
family: addr.sa_family,
nwid: addr.sa_nwid,
nodeid: addr.sa_nodeid,
port: addr.sa_port,
}
}
}
unsafe fn buf_to_string(buf: &[i8]) -> String
{
use std::slice;
let len = buf.len();
let buf = slice::from_raw_parts(&buf[0] as *const i8 as _, len);
let null_byte = buf.iter().position(|&b| b == 0).unwrap_or(len);
String::from_utf8_lossy(&buf[..null_byte]).into_owned()
}