use std::{
collections::HashSet,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
time::{SystemTime, UNIX_EPOCH},
};
use crate::connection::{protocol::Protocol, scope::NetworkScope};
use bincode::{Decode, Encode};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Encode, Decode)]
pub struct Node {
pub id: Vec<u8>, pub version: u8, pub started_at: u64, pub port: u16, pub protocols: HashSet<Protocol>,
pub ips: Vec<(NetworkScope, IpAddr)>,
}
impl Node {
pub fn new(port: u16, id: Vec<u8>, version: u8, ips: Vec<(NetworkScope, IpAddr)>) -> Self {
Self {
id,
version,
port,
started_at: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
ips,
protocols: Self::default_protocols(),
}
}
pub fn from_addr(addr: SocketAddr, version: Option<u8>, id: Option<Vec<u8>>) -> Self {
let ip = addr.ip();
let port = addr.port();
let scope = crate::connection::node::NetworkScope::from_ip(&ip);
let ips = match scope {
NetworkScope::Intranet => Self::system_ips(),
NetworkScope::Extranet => vec![(scope, ip)],
};
let id = id.unwrap_or(vec![0u8; 32]);
Self::new(port, id, version.unwrap_or(1), ips)
}
pub fn default_protocols() -> HashSet<Protocol> {
let mut set = HashSet::new();
set.insert(Protocol::Tcp);
set.insert(Protocol::Udp);
set.insert(Protocol::Http);
set.insert(Protocol::Ws);
set
}
pub fn with_protocols(mut self, protocols: HashSet<Protocol>) -> Self {
self.protocols = protocols;
self
}
pub fn from_system(port: u16, id: Vec<u8>, version: u8) -> Self {
Self {
id,
version,
port,
started_at: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
ips: Self::system_ips(),
protocols: Self::default_protocols(),
}
}
pub fn system_ips() -> Vec<(NetworkScope, IpAddr)> {
let mut ips = vec![];
if let Ok(interfaces) = get_if_addrs::get_if_addrs() {
for interface in interfaces {
let ip = interface.ip();
if ip.is_loopback() {
continue;
}
let scope = NetworkScope::from_ip(&ip);
ips.push((scope, ip));
}
}
ips
}
pub fn get_all(&self) -> Vec<IpAddr> {
self.ips.iter().map(|(_, addr)| *addr).collect()
}
pub fn get_ips(&self, scope: NetworkScope, version: Option<IpAddr>) -> Vec<IpAddr> {
self.ips
.iter()
.filter(|(s, addr)| {
if *s != scope {
return false;
}
match version {
Some(v) => {
(v.is_ipv4() && addr.is_ipv4()) || (v.is_ipv6() && addr.is_ipv6())
}
None => true, }
})
.map(|(_, addr)| *addr)
.collect()
}
pub fn get_extranet_ips(&self) -> Vec<IpAddr> {
self.get_ips(NetworkScope::Extranet, None)
}
pub fn get_extranet_ips_v4(&self) -> Vec<IpAddr> {
self.get_ips(
NetworkScope::Extranet,
Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))),
)
}
pub fn get_extranet_ips_v6(&self) -> Vec<IpAddr> {
self.get_ips(
NetworkScope::Extranet,
Some(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0))),
)
}
pub fn get_intranet_ips(&self) -> Vec<IpAddr> {
self.get_ips(NetworkScope::Intranet, None)
}
pub fn get_intranet_v4(&self) -> Vec<IpAddr> {
self.get_ips(
NetworkScope::Intranet,
Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))),
)
}
pub fn get_intranet_v6(&self) -> Vec<IpAddr> {
self.get_ips(
NetworkScope::Intranet,
Some(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0))),
)
}
pub fn add_observed_ip(&mut self, scope: NetworkScope, addr: IpAddr) {
if !self.ips.contains(&(scope, addr)) {
self.ips.push((scope, addr));
}
}
}