use crate::context::config::Config; use crate::context::nat::{MyNatInfo, PunchBackoff}; use crate::nat::SubnetExternalRoute; use crate::protocol::client_message::PunchInfo; use crate::protocol::control_message::{ClientSimpleInfo, ClientSimpleInfoList}; use crate::tunnel_core::p2p::route_table::RouteTable; use crate::tunnel_core::server::transport::config::ProtocolAddress; use ipnet::Ipv4Net; use parking_lot::{Mutex, RwLock}; use rust_p2p_core::nat::NatInfo; use rust_p2p_core::route::RouteKey; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::net::Ipv4Addr; use std::sync::Arc; #[derive(Default)] struct PingStats { sent: u64, received: u64, } #[derive(Default)] struct TrafficCounter { tx_bytes: u64, rx_bytes: u64, } #[derive(Clone, Default)] pub struct TrafficStats { inner: Arc>>>>, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct TrafficInfo { pub ip: Ipv4Addr, pub tx_bytes: u64, pub rx_bytes: u64, } impl TrafficStats { fn get_or_create(&self, ip: Ipv4Addr) -> Arc> { { let read = self.inner.read(); if let Some(counter) = read.get(&ip) { return counter.clone(); } } let mut write = self.inner.write(); write .entry(ip) .or_insert_with(|| Arc::new(Mutex::new(TrafficCounter::default()))) .clone() } pub fn record_tx(&self, ip: Ipv4Addr, bytes: u64) { let counter = self.get_or_create(ip); counter.lock().tx_bytes += bytes; } pub fn record_rx(&self, ip: Ipv4Addr, bytes: u64) { let counter = self.get_or_create(ip); counter.lock().rx_bytes += bytes; } pub fn get_traffic_info(&self, ip: &Ipv4Addr) -> Option { let read = self.inner.read(); read.get(ip).map(|counter| { let guard = counter.lock(); TrafficInfo { ip: *ip, tx_bytes: guard.tx_bytes, rx_bytes: guard.rx_bytes, } }) } pub fn get_all_traffic_info(&self) -> Vec { let read = self.inner.read(); read.iter() .map(|(ip, counter)| { let guard = counter.lock(); TrafficInfo { ip: *ip, tx_bytes: guard.tx_bytes, rx_bytes: guard.rx_bytes, } }) .collect() } pub fn reset(&self, ip: &Ipv4Addr) { let read = self.inner.read(); if let Some(counter) = read.get(ip) { *counter.lock() = TrafficCounter::default(); } } pub fn reset_all(&self) { let read = self.inner.read(); for counter in read.values() { *counter.lock() = TrafficCounter::default(); } } pub fn clear(&self) { self.inner.write().clear(); } } #[derive(Clone, Default)] pub struct PacketLossStats { inner: Arc>>>>, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PacketLossInfo { pub ip: Ipv4Addr, #[serde(skip)] pub route_key: Option, pub sent: u64, pub received: u64, pub loss_rate: f64, } impl PacketLossStats { fn get_or_create(&self, ip: Ipv4Addr, route_key: RouteKey) -> Arc> { { let read = self.inner.read(); if let Some(stats) = read.get(&(ip, route_key)) { return stats.clone(); } } let mut write = self.inner.write(); write .entry((ip, route_key)) .or_insert_with(|| Arc::new(Mutex::new(PingStats::default()))) .clone() } pub fn record_sent(&self, ip: Ipv4Addr, route_key: RouteKey) { let stats = self.get_or_create(ip, route_key); stats.lock().sent += 1; } pub fn record_received(&self, ip: Ipv4Addr, route_key: RouteKey) -> f64 { let stats = self.get_or_create(ip, route_key); let mut guard = stats.lock(); guard.received += 1; // 计算并返回丢包率 if guard.sent > 0 { 1.0 - (guard.received as f64 / guard.sent as f64) } else { 0.0 } } pub fn get_loss_info(&self, ip: &Ipv4Addr, route_key: &RouteKey) -> Option { let read = self.inner.read(); read.get(&(*ip, *route_key)).map(|stats| { let guard = stats.lock(); let loss_rate = if guard.sent > 0 { 1.0 - (guard.received as f64 / guard.sent as f64) } else { 0.0 }; PacketLossInfo { ip: *ip, route_key: Some(*route_key), sent: guard.sent, received: guard.received, loss_rate, } }) } /// 获取指定 IP 的所有路由的丢包信息 pub fn get_loss_info_by_ip(&self, ip: &Ipv4Addr) -> Vec { let read = self.inner.read(); read.iter() .filter(|((addr, _), _)| addr == ip) .map(|((addr, route_key), stats)| { let guard = stats.lock(); let loss_rate = if guard.sent > 0 { 1.0 - (guard.received as f64 / guard.sent as f64) } else { 0.0 }; PacketLossInfo { ip: *addr, route_key: Some(*route_key), sent: guard.sent, received: guard.received, loss_rate, } }) .collect() } /// 获取指定 IP 的聚合丢包信息(所有路由合并) pub fn get_aggregated_loss_info(&self, ip: &Ipv4Addr) -> Option { let read = self.inner.read(); let mut total_sent = 0u64; let mut total_received = 0u64; let mut found = false; for ((addr, _), stats) in read.iter() { if addr == ip { found = true; let guard = stats.lock(); total_sent += guard.sent; total_received += guard.received; } } if found { let loss_rate = if total_sent > 0 { 1.0 - (total_received as f64 / total_sent as f64) } else { 0.0 }; Some(PacketLossInfo { ip: *ip, route_key: None, sent: total_sent, received: total_received, loss_rate, }) } else { None } } pub fn get_all_loss_info(&self) -> Vec { let read = self.inner.read(); read.iter() .map(|((ip, route_key), stats)| { let guard = stats.lock(); let loss_rate = if guard.sent > 0 { 1.0 - (guard.received as f64 / guard.sent as f64) } else { 0.0 }; PacketLossInfo { ip: *ip, route_key: Some(*route_key), sent: guard.sent, received: guard.received, loss_rate, } }) .collect() } pub fn reset(&self, ip: &Ipv4Addr, route_key: &RouteKey) { let read = self.inner.read(); if let Some(stats) = read.get(&(*ip, *route_key)) { *stats.lock() = PingStats::default(); } } pub fn remove(&self, ip: &Ipv4Addr, route_key: &RouteKey) { let mut write = self.inner.write(); write.remove(&(*ip, *route_key)); } pub fn remove_batch(&self, keys: &[(Ipv4Addr, RouteKey)]) { let mut write = self.inner.write(); for key in keys { write.remove(key); } } pub fn reset_all(&self) { let read = self.inner.read(); for stats in read.values() { *stats.lock() = PingStats::default(); } } pub fn clear(&self) { self.inner.write().clear(); } } pub mod config; pub(crate) mod nat; #[derive(Clone, Default)] pub(crate) struct AppState { config: Arc>>>, pub(crate) network: SharedNetworkAddr, pub(crate) server_info_collection: ServerInfoCollection, pub(crate) peer_map: PeerInfoMap, pub(crate) route_table: RouteTable, pub(crate) subnet_route: SubnetExternalRoute, pub(crate) nat_info: MyNatInfo, pub(crate) punch_backoff: PunchBackoff, pub(crate) packet_loss_stats: PacketLossStats, pub(crate) traffic_stats: TrafficStats, } #[derive(Clone, Default)] pub(crate) struct SharedNetworkAddr { inner: Arc>>, } impl SharedNetworkAddr { pub fn network(&self) -> Option { self.inner.lock().as_ref().map(|v| v.network()) } pub fn ip(&self) -> Option { self.inner.lock().map(|v| v.ip) } pub fn get(&self) -> Option { *self.inner.lock() } pub fn set(&self, addr: NetworkAddr) { *self.inner.lock() = Some(addr); } pub fn clear(&self) { *self.inner.lock() = None; } } /// 网络路由封装,包含本地网络信息和子网路由 #[derive(Clone)] pub(crate) struct NetworkRoute { pub network: SharedNetworkAddr, pub subnet_route: SubnetExternalRoute, } impl NetworkRoute { pub fn new(network: SharedNetworkAddr, subnet_route: SubnetExternalRoute) -> Self { Self { network, subnet_route, } } /// 检查 IP 是否在本地网络或子网路由中 pub fn network_contains(&self, ip: &Ipv4Addr) -> bool { if let Some(network) = self.network.network() && network.contains(ip) { return true; } self.subnet_route.route(ip).is_some() } } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PeerClientInfo { pub nat_info: Option, } #[derive(Clone, Default)] pub(crate) struct PeerInfoMap { inner: Arc>>, } impl PeerInfoMap { pub fn get(&self, ip: &Ipv4Addr) -> Option { self.inner.lock().get(ip).cloned() } pub fn update_nat_info(&self, ip: Ipv4Addr, nat_info: NatInfo) { let mut guard = self.inner.lock(); if let Some(v) = guard.get_mut(&ip) { v.nat_info = Some(nat_info); return; } guard.insert( ip, PeerClientInfo { nat_info: Some(nat_info), }, ); } pub fn clear(&self) { self.inner.lock().clear(); } } #[derive(Clone, Default)] pub(crate) struct ServerInfoCollection { client_simple_list: Arc>>, server_node_map: Arc>>, } #[derive(Clone, Default)] pub struct ServerNodeInfo { pub server_id: u32, pub server_addr: ProtocolAddress, pub connected: bool, pub rtt: Option, pub data_version: u64, pub client_map: HashMap, pub last_connected_time: Option, pub disconnected_time: Option, pub server_version: Option, } impl ServerInfoCollection { pub fn server_client_ip_map(&self) -> HashMap, u32)> { self.server_node_map .read() .iter() .map(|(k, v)| { ( *k, ( v.client_map .iter() .filter(|(_, v)| v.online) .map(|(k, _)| *k) .collect(), v.rtt.unwrap_or(500), ), ) }) .collect() } pub fn server_node_list(&self) -> Vec { self.server_node_map.read().values().cloned().collect() } pub fn update_server(&self, addr: Vec<(u32, ProtocolAddress)>) { let mut server_node_map_guard = self.server_node_map.write(); let mut client_simple_list_guard = self.client_simple_list.write(); server_node_map_guard.clear(); client_simple_list_guard.clear(); for (server_id, server_addr) in addr { let server_node = ServerNodeInfo { server_id, server_addr, ..Default::default() }; server_node_map_guard.insert(server_id, server_node); } } pub fn find_connected_server(&self, server_ids: &[u32]) -> Option { let map = self.server_node_map.read(); server_ids .iter() .filter_map(|id| { let server = map.get(id)?; if !server.connected { return None; } let rtt = server.rtt.unwrap_or(u32::MAX); Some((*id, rtt)) }) .min_by_key(|(_, rtt)| *rtt) .map(|(id, _)| id) } pub fn find_ip_to_server(&self, server_ids: &[u32], ip: &Ipv4Addr) -> Option { let map = self.server_node_map.read(); server_ids .iter() .filter_map(|id| { let server = map.get(id)?; if !server.connected { return None; } let client = server.client_map.get(ip)?; if !client.online { return None; } let rtt = server.rtt.unwrap_or(u32::MAX); Some((*id, rtt)) }) .min_by_key(|(_, rtt)| *rtt) .map(|(id, _)| id) } pub fn client_online_ips(&self) -> Vec { self.client_simple_list .read() .iter() .filter(|v| v.online) .map(|c| c.ip) .collect() } pub fn client_ips(&self) -> Vec { self.client_simple_list.read().clone() } pub fn data_version(&self, server_id: u32) -> u64 { self.server_node_map .read() .get(&server_id) .map(|v| v.data_version) .unwrap_or(0) } pub fn update_client_simple_list( &self, server_id: u32, self_ip: Ipv4Addr, client_simple_list: ClientSimpleInfoList, now: i64, ) { let mut guard = self.server_node_map.write(); let server_node = guard.entry(server_id).or_default(); if now > client_simple_list.time { server_node.rtt = Some((now - client_simple_list.time) as u32); } server_node.data_version = client_simple_list.data_version; let map: HashMap = client_simple_list .list .into_iter() .filter(|v| v.ip != self_ip) .map(|info| (info.ip, info)) .collect(); if client_simple_list.is_all { server_node.client_map = map; } else { server_node.client_map.extend(map); } let mut client_simple_map = HashMap::::new(); for (_, server_node) in guard.iter() { for (_, x) in server_node.client_map.iter() { if let Some(v) = client_simple_map.get_mut(&x.ip) { if x.online { v.online = true; } } else { client_simple_map.insert(x.ip, x.clone()); } } } let mut guard = self.client_simple_list.write(); *guard = client_simple_map.into_values().collect() } pub fn set_server_connected(&self, server_id: u32, val: bool) -> bool { let mut mutex_guard = self.server_node_map.write(); let server_node = mutex_guard.entry(server_id).or_default(); let old = server_node.connected; server_node.connected = val; old } pub fn is_any_server_connected(&self, server_ids: Option<&[u32]>) -> bool { let guard = self.server_node_map.read(); if let Some(server_ids) = server_ids { for id in server_ids { if guard.get(id).map(|v| v.connected).unwrap_or(false) { return true; } } } else { for (_, server_node) in guard.iter() { if server_node.connected { return true; } } } false } pub fn is_server_connected(&self, server_id: u32) -> bool { self.server_node_map .read() .get(&server_id) .map(|v| v.connected) .unwrap_or(false) } pub fn set_last_connected_time(&self, server_id: u32, last_connected_time: Option) { self.server_node_map .write() .entry(server_id) .or_default() .last_connected_time = last_connected_time; } pub fn set_disconnected_time(&self, server_id: u32, last_connected_time: Option) { self.server_node_map .write() .entry(server_id) .or_default() .disconnected_time = last_connected_time; } pub fn set_server_rtt(&self, server_id: u32, rtt: u32) { if let Some(v) = self.server_node_map.write().get_mut(&server_id) { v.rtt = Some(rtt); } } pub fn set_server_version(&self, server_id: u32, version: String) { if let Some(v) = self.server_node_map.write().get_mut(&server_id) { v.server_version = Some(version); } } pub fn get_server_rtt(&self, ip: &Ipv4Addr) -> Option { let server_node_map_guard = self.server_node_map.read(); for (_, server_node) in server_node_map_guard.iter() { if !server_node.connected { continue; } if let Some(v) = server_node.client_map.get(ip) && v.online { return server_node.rtt; } } None } pub fn exists_online_client_ip(&self, ip: &Ipv4Addr) -> bool { self.client_simple_list .read() .iter() .any(|v| v.ip == *ip && v.online) } pub fn clear(&self) { self.client_simple_list.write().clear(); let mut guard = self.server_node_map.write(); for server_node in guard.values_mut() { server_node.connected = false; server_node.rtt = None; server_node.data_version = 0; server_node.client_map.clear(); server_node.last_connected_time = None; server_node.disconnected_time = None; } } } #[derive(Copy, Clone, Debug)] pub struct NetworkAddr { pub gateway: Ipv4Addr, pub broadcast: Ipv4Addr, pub ip: Ipv4Addr, pub prefix_len: u8, } impl NetworkAddr { pub fn network(&self) -> Ipv4Net { Ipv4Net::new_assert(self.ip, self.prefix_len) } } impl AppState { pub fn stop_network(&self) { self.network.clear(); self.server_info_collection.clear(); self.peer_map.clear(); // route_table 来自外部 crate,会在任务停止后自动失效 self.nat_info.clear(); self.punch_backoff.clear(); self.packet_loss_stats.clear(); self.traffic_stats.clear(); } fn network(&self) -> Option { self.network.network() } pub fn get_network(&self) -> Option { self.network.get() } fn network_contains(&self, ip: &Ipv4Addr) -> bool { let Some(network) = self.network() else { return false; }; if network.contains(ip) { return true; } self.subnet_route.route(ip).is_some() } pub fn client_ips(&self) -> Vec { self.server_info_collection.client_ips() } pub fn get_peer_info(&self, ip: &Ipv4Addr) -> Option { self.peer_map.get(ip) } pub fn set_config(&self, config: Box) { *self.config.lock() = Some(config); } pub fn get_config(&self) -> Option> { self.config.lock().clone() } pub(crate) fn udp_stun(&self) -> Vec { self.config .lock() .as_ref() .map(|v| v.udp_stun.clone()) .unwrap_or_default() } pub(crate) fn tcp_stun(&self) -> Vec { self.config .lock() .as_ref() .map(|v| v.tcp_stun.clone()) .unwrap_or_default() } } impl AppState { pub fn get_punch_info(&self) -> Option { self.nat_info.get().map(|info| PunchInfo { nat_info: self.filter_ip(info), }) } pub fn get_nat_info(&self) -> Option { self.nat_info.get().map(|info| self.filter_ip(info)) } pub fn filter_ip(&self, mut info: NatInfo) -> NatInfo { if self.network_contains(&info.local_ipv4) { info.local_ipv4 = Ipv4Addr::UNSPECIFIED; } info.local_ipv4s.retain(|ip| !self.network_contains(ip)); info } }