#![allow(dead_code)]
use std::net::SocketAddr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NatType {
None,
FullCone,
RestrictedCone,
PortRestrictedCone,
Symmetric,
Unknown,
}
#[derive(Debug, Clone)]
pub struct PeerEndpoint {
pub public_addr: SocketAddr,
pub private_addr: Option<SocketAddr>,
pub nat_type: NatType,
}
impl PeerEndpoint {
pub fn new(public_addr: SocketAddr) -> Self {
Self {
public_addr,
private_addr: None,
nat_type: NatType::Unknown,
}
}
pub fn same_lan(&self, other: &PeerEndpoint) -> bool {
if let (Some(a), Some(b)) = (&self.private_addr, &other.private_addr) {
match (a.ip(), b.ip()) {
(std::net::IpAddr::V4(ip_a), std::net::IpAddr::V4(ip_b)) => {
let oct_a = ip_a.octets();
let oct_b = ip_b.octets();
oct_a[0] == oct_b[0] && oct_a[1] == oct_b[1] && oct_a[2] == oct_b[2]
}
_ => false,
}
} else {
false
}
}
pub fn best_addr(&self, local: &PeerEndpoint) -> SocketAddr {
if self.same_lan(local) {
self.private_addr.unwrap_or(self.public_addr)
} else {
self.public_addr
}
}
}
pub fn can_punch(a: NatType, b: NatType) -> bool {
match (a, b) {
(NatType::None, _) | (_, NatType::None) => true,
(NatType::FullCone, _) | (_, NatType::FullCone) => true,
(NatType::RestrictedCone, NatType::RestrictedCone) => true,
(NatType::RestrictedCone, NatType::PortRestrictedCone) => true,
(NatType::PortRestrictedCone, NatType::RestrictedCone) => true,
(NatType::PortRestrictedCone, NatType::PortRestrictedCone) => true,
(NatType::Symmetric, NatType::Symmetric) => false,
(NatType::Unknown, _) | (_, NatType::Unknown) => true,
_ => true,
}
}