use super::rfc_nat_traversal::{RfcAddAddress, RfcPunchMeNow, RfcRemoveAddress};
use crate::{
VarInt,
frame::{AddAddress, PunchMeNow, RemoveAddress},
};
use std::net::SocketAddr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[allow(dead_code)]
pub enum NatCompatMode {
Legacy,
RfcCompliant,
#[default]
Mixed,
}
#[allow(dead_code)]
pub fn add_address_to_rfc(old: &AddAddress) -> RfcAddAddress {
RfcAddAddress {
sequence_number: old.sequence,
address: old.address,
}
}
#[allow(dead_code)]
pub fn rfc_to_add_address(rfc: &RfcAddAddress, default_priority: VarInt) -> AddAddress {
AddAddress {
sequence: rfc.sequence_number,
address: rfc.address,
priority: default_priority,
}
}
#[allow(dead_code)]
pub fn punch_me_now_to_rfc(old: &PunchMeNow) -> RfcPunchMeNow {
RfcPunchMeNow {
round: old.round,
paired_with_sequence_number: old.paired_with_sequence_number,
address: old.address,
}
}
#[allow(dead_code)]
pub fn rfc_to_punch_me_now(rfc: &RfcPunchMeNow) -> PunchMeNow {
PunchMeNow {
round: rfc.round,
paired_with_sequence_number: rfc.paired_with_sequence_number,
address: rfc.address,
target_peer_id: None,
}
}
#[allow(dead_code)]
pub fn remove_address_to_rfc(old: &RemoveAddress) -> RfcRemoveAddress {
RfcRemoveAddress {
sequence_number: old.sequence,
}
}
#[allow(dead_code)]
pub fn rfc_to_remove_address(rfc: &RfcRemoveAddress) -> RemoveAddress {
RemoveAddress {
sequence: rfc.sequence_number,
}
}
#[allow(dead_code)]
pub trait NatFrameCompat {
fn needs_compat(&self) -> bool;
fn compat_mode(&self) -> NatCompatMode;
}
#[allow(dead_code)]
pub fn detect_frame_format(frame_type: u64) -> FrameFormat {
match frame_type {
0x3d7e90..=0x3d7e94 => FrameFormat::Rfc,
_ => FrameFormat::Legacy,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub enum FrameFormat {
Legacy,
Rfc,
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub struct PriorityStrategy {
pub default_priority: VarInt,
pub use_ice_priority: bool,
}
#[allow(dead_code)]
impl Default for PriorityStrategy {
fn default() -> Self {
Self {
default_priority: VarInt::from_u32(65535), use_ice_priority: false,
}
}
}
#[allow(dead_code)]
impl PriorityStrategy {
pub fn calculate_priority(&self, address: &SocketAddr) -> VarInt {
if !self.use_ice_priority {
return self.default_priority;
}
let priority = match address {
SocketAddr::V4(addr) => {
if addr.ip().is_loopback() {
65535 } else if addr.ip().is_private() {
98304 } else {
131071 }
}
SocketAddr::V6(addr) => {
if addr.ip().is_loopback() {
32768 } else if addr.ip().is_unicast_link_local() {
49152 } else {
114688 }
}
};
VarInt::from_u32(priority)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_address_conversion() {
let old = AddAddress {
sequence: VarInt::from_u32(42),
address: "192.168.1.1:8080".parse().unwrap(),
priority: VarInt::from_u32(12345),
};
let rfc = add_address_to_rfc(&old);
assert_eq!(rfc.sequence_number, old.sequence);
assert_eq!(rfc.address, old.address);
let converted_back = rfc_to_add_address(&rfc, VarInt::from_u32(99999));
assert_eq!(converted_back.sequence, old.sequence);
assert_eq!(converted_back.address, old.address);
assert_eq!(converted_back.priority, VarInt::from_u32(99999)); }
#[test]
fn test_priority_strategy() {
let strategy = PriorityStrategy {
use_ice_priority: true,
..Default::default()
};
let public_v4 = "8.8.8.8:53".parse().unwrap();
let private_v4 = "192.168.1.1:80".parse().unwrap();
let loopback_v4 = "127.0.0.1:8080".parse().unwrap();
let pub_priority = strategy.calculate_priority(&public_v4);
let priv_priority = strategy.calculate_priority(&private_v4);
let loop_priority = strategy.calculate_priority(&loopback_v4);
assert!(pub_priority.into_inner() > priv_priority.into_inner());
assert!(priv_priority.into_inner() > loop_priority.into_inner());
}
}