use std::{collections::HashMap, fmt, net::IpAddr};
pub(crate) use ipnet::{Ipv4Net, Ipv6Net};
use n0_future::time::Instant;
use crate::ip::LocalAddresses;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Interface;
impl fmt::Display for Interface {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "unknown")
}
}
impl Interface {
pub fn addrs(&self) -> impl Iterator<Item = IpNet> + '_ {
std::iter::empty()
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct Ipv6AddrFlags {
pub deprecated: bool,
pub temporary: bool,
pub tentative: bool,
pub duplicated: bool,
pub permanent: bool,
}
#[derive(Clone, Debug)]
pub enum IpNet {
V4(Ipv4Net),
V6 {
net: Ipv6Net,
scope_id: u32,
flags: Ipv6AddrFlags,
},
}
impl PartialEq for IpNet {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(IpNet::V4(a), IpNet::V4(b)) => {
a.addr() == b.addr()
&& a.prefix_len() == b.prefix_len()
&& a.netmask() == b.netmask()
}
(
IpNet::V6 {
net: net_a,
scope_id: scope_id_a,
flags: flags_a,
},
IpNet::V6 {
net: net_b,
scope_id: scope_id_b,
flags: flags_b,
},
) => {
net_a.addr() == net_b.addr()
&& net_a.prefix_len() == net_b.prefix_len()
&& net_a.netmask() == net_b.netmask()
&& scope_id_a == scope_id_b
&& flags_a == flags_b
}
_ => false,
}
}
}
impl Eq for IpNet {}
impl IpNet {
pub fn addr(&self) -> IpAddr {
match self {
IpNet::V4(a) => IpAddr::V4(a.addr()),
IpNet::V6 { net, .. } => IpAddr::V6(net.addr()),
}
}
}
#[derive(Debug, Clone)]
pub struct HomeRouter {
pub gateway: IpAddr,
pub my_ip: Option<IpAddr>,
}
impl HomeRouter {
pub fn new() -> Option<Self> {
None
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct State {
pub interfaces: HashMap<String, Interface>,
pub local_addresses: LocalAddresses,
pub have_v6: bool,
pub have_v4: bool,
pub(crate) is_expensive: bool,
pub default_route_interface: Option<String>,
pub last_unsuspend: Option<Instant>,
}
impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "fallback(no interfaces)")
}
}
impl State {
pub async fn new() -> Self {
State {
interfaces: HashMap::new(),
local_addresses: LocalAddresses::default(),
have_v6: false,
have_v4: true,
is_expensive: false,
default_route_interface: None,
last_unsuspend: None,
}
}
pub fn is_major_change(&self, old: &State) -> bool {
self != old
}
}