urma-runtime 0.3.5

URMA publication planning, network transports and recovery
Documentation
use crate::error::Error;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::time::{SystemTime, UNIX_EPOCH};

pub(super) fn unix_now() -> Result<u64, Error> {
    let elapsed = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map_err(|error| {
            Error::Invalid(format!("system clock precedes the unix epoch: {error}"))
        })?;
    Ok(elapsed.as_secs())
}

fn routable_v4(ip: Ipv4Addr) -> bool {
    let [first, second, ..] = ip.octets();
    !(ip.is_unspecified()
        || ip.is_loopback()
        || ip.is_private()
        || ip.is_link_local()
        || ip.is_broadcast()
        || ip.is_documentation()
        || ip.is_multicast()
        || first == 0
        || first >= 240
        || (first == 100 && (64..128).contains(&second))
        || (first == 198 && (second & 0xfe) == 18))
}

fn routable_v6(ip: Ipv6Addr) -> bool {
    match ip.to_ipv4_mapped() {
        Some(mapped) => routable_v4(mapped),
        None => routable_native_v6(ip),
    }
}

fn routable_native_v6(ip: Ipv6Addr) -> bool {
    let [first, second, ..] = ip.segments();
    !(ip.is_unspecified()
        || ip.is_loopback()
        || ip.is_multicast()
        || (first & 0xfe00) == 0xfc00
        || (first & 0xffc0) == 0xfe80
        || (first == 0x2001 && second == 0x0db8))
}

pub(super) fn routable(address: &SocketAddr) -> bool {
    address.port() != 0
        && match address.ip() {
            IpAddr::V4(ip) => routable_v4(ip),
            IpAddr::V6(ip) => routable_v6(ip),
        }
}