crate::ix!();
#[derive(Builder,Setters,Getters,MutGetters,Debug,Serialize,Deserialize,Clone,Hash)]
#[getset(get="pub",set="pub",get_mut="pub")]
#[builder(setter(into))]
pub struct NetAddr {
addr: PreVector<u8,ADDR_IPV6_SIZE>,
net: Network,
scope_id: u32,
}
impl Default for NetAddr {
fn default() -> Self {
Self {
addr: PreVector::with_capacity(ADDR_IPV6_SIZE),
net: Network::NET_IPV6,
scope_id: 0,
}
}
}
impl PartialEq<NetAddr> for NetAddr {
#[inline]
fn eq(&self, other: &NetAddr) -> bool {
trace!(
target: "netaddr",
ours = ?self.net(),
theirs = ?other.net(),
"Comparing NetAddr equality"
);
*self.net() == *other.net() && self.addr() == other.addr()
}
}
impl Eq for NetAddr {}
impl Ord for NetAddr {
#[inline]
fn cmp(&self, other: &NetAddr) -> std::cmp::Ordering {
use std::cmp::Ordering;
let by_net = (*self.net() as u8).cmp(&(*other.net() as u8));
if by_net == Ordering::Equal {
self.addr().cmp(other.addr())
} else {
by_net
}
}
}
impl PartialOrd<NetAddr> for NetAddr {
#[inline] fn partial_cmp(&self, other: &NetAddr) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl From<&InAddr> for NetAddr {
fn from(ipv4_addr: &InAddr) -> Self {
trace!(target: "netaddr", "Constructing NetAddr from InAddr (IPv4)");
let bytes = unsafe {
std::slice::from_raw_parts(ipv4_addr as *const _ as *const u8, ADDR_IPV4_SIZE)
};
NetAddrBuilder::default()
.addr(PreVector::from(bytes))
.net(Network::NET_IPV4)
.scope_id(0_u32)
.build()
.expect("building IPv4 NetAddr never fails")
}
}
impl NetAddr {
pub fn new(ipv_6addr: &In6Addr, scope: Option<u32>) -> Self {
trace!(target: "netaddr", scope = scope.unwrap_or(0), "Constructing NetAddr from legacy IPv6");
let bytes = unsafe {
std::slice::from_raw_parts(ipv_6addr as *const _ as *const u8, ADDR_IPV6_SIZE)
};
let mut out = NetAddr::default();
out.set_legacy_ipv6(bytes);
*out.scope_id_mut() = scope.unwrap_or(0);
debug!(target: "netaddr", net = ?out.get_net_class(), "Constructed NetAddr from IPv6 input");
out
}
pub fn get_addr_bytes(&self) -> Vec<u8> {
trace!(target: "netaddr", net = ?self.get_net_class(), "Computing NetAddr::get_addr_bytes");
if self.is_addr_v1compatible() {
let mut serialized = [0u8; NET_ADDR_V1_SERIALIZATION_SIZE];
self.serialize_v1array(&mut serialized);
debug!(target: "netaddr", "Serialized in legacy (v1) ADDR format");
serialized.to_vec()
} else {
debug!(target: "netaddr", len = self.addr().len(), "Returning raw address bytes");
self.addr().as_slice().to_vec()
}
}
pub fn get_hash(&self) -> u64 {
trace!(target: "netaddr", "Computing NetAddr::get_hash (Core-compatible double-SHA256)");
let hash: u256 = bitcoin_hash::hash1(self.addr().as_slice());
let bytes: &[u8; 32] = hash.as_ref();
let mut tmp = [0u8; 8];
tmp.copy_from_slice(&bytes[..8]);
let nret = u64::from_le_bytes(tmp);
debug!(target: "netaddr", hash = ?hash, hash64 = nret, "Derived 64-bit NetAddr hash");
nret
}
}