Files
vnt/vnt-core/src/context/mod.rs
T
2026-03-02 15:52:24 +08:00

715 lines
21 KiB
Rust

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<RwLock<HashMap<Ipv4Addr, Arc<Mutex<TrafficCounter>>>>>,
}
#[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<Mutex<TrafficCounter>> {
{
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<TrafficInfo> {
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<TrafficInfo> {
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<RwLock<HashMap<(Ipv4Addr, RouteKey), Arc<Mutex<PingStats>>>>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PacketLossInfo {
pub ip: Ipv4Addr,
#[serde(skip)]
pub route_key: Option<RouteKey>,
pub sent: u64,
pub received: u64,
pub loss_rate: f64,
}
impl PacketLossStats {
fn get_or_create(&self, ip: Ipv4Addr, route_key: RouteKey) -> Arc<Mutex<PingStats>> {
{
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<PacketLossInfo> {
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<PacketLossInfo> {
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<PacketLossInfo> {
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<PacketLossInfo> {
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<Mutex<Option<Box<Config>>>>,
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<Mutex<Option<NetworkAddr>>>,
}
impl SharedNetworkAddr {
pub fn network(&self) -> Option<Ipv4Net> {
self.inner.lock().as_ref().map(|v| v.network())
}
pub fn ip(&self) -> Option<Ipv4Addr> {
self.inner.lock().map(|v| v.ip)
}
pub fn get(&self) -> Option<NetworkAddr> {
*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<NatInfo>,
}
#[derive(Clone, Default)]
pub(crate) struct PeerInfoMap {
inner: Arc<Mutex<HashMap<Ipv4Addr, PeerClientInfo>>>,
}
impl PeerInfoMap {
pub fn get(&self, ip: &Ipv4Addr) -> Option<PeerClientInfo> {
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<RwLock<Vec<ClientSimpleInfo>>>,
server_node_map: Arc<RwLock<HashMap<u32, ServerNodeInfo>>>,
}
#[derive(Clone, Default)]
pub struct ServerNodeInfo {
pub server_id: u32,
pub server_addr: ProtocolAddress,
pub connected: bool,
pub rtt: Option<u32>,
pub data_version: u64,
pub client_map: HashMap<Ipv4Addr, ClientSimpleInfo>,
pub last_connected_time: Option<i64>,
pub disconnected_time: Option<i64>,
pub server_version: Option<String>,
}
impl ServerInfoCollection {
pub fn server_client_ip_map(&self) -> HashMap<u32, (Vec<Ipv4Addr>, 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<ServerNodeInfo> {
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<u32> {
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<u32> {
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<Ipv4Addr> {
self.client_simple_list
.read()
.iter()
.filter(|v| v.online)
.map(|c| c.ip)
.collect()
}
pub fn client_ips(&self) -> Vec<ClientSimpleInfo> {
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<Ipv4Addr, ClientSimpleInfo> = 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::<Ipv4Addr, ClientSimpleInfo>::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<i64>) {
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<i64>) {
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<u32> {
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<Ipv4Net> {
self.network.network()
}
pub fn get_network(&self) -> Option<NetworkAddr> {
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<ClientSimpleInfo> {
self.server_info_collection.client_ips()
}
pub fn get_peer_info(&self, ip: &Ipv4Addr) -> Option<PeerClientInfo> {
self.peer_map.get(ip)
}
pub fn set_config(&self, config: Box<Config>) {
*self.config.lock() = Some(config);
}
pub fn get_config(&self) -> Option<Box<Config>> {
self.config.lock().clone()
}
pub(crate) fn udp_stun(&self) -> Vec<String> {
self.config
.lock()
.as_ref()
.map(|v| v.udp_stun.clone())
.unwrap_or_default()
}
pub(crate) fn tcp_stun(&self) -> Vec<String> {
self.config
.lock()
.as_ref()
.map(|v| v.tcp_stun.clone())
.unwrap_or_default()
}
}
impl AppState {
pub fn get_punch_info(&self) -> Option<PunchInfo> {
self.nat_info.get().map(|info| PunchInfo {
nat_info: self.filter_ip(info),
})
}
pub fn get_nat_info(&self) -> Option<NatInfo> {
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
}
}