84 lines
2.7 KiB
Rust
Executable File

use std::{collections::HashMap, net::Ipv4Addr, sync::atomic::{AtomicBool, Ordering}, time::Duration};
use ahash::RandomState;
use dashmap::{DashMap};
use ipnet::Ipv4Net;
use sdlan_sn_rs::utils::{Result, SDLanError};
use tokio::sync::oneshot::{Receiver, Sender, channel};
use tracing::{debug, error};
use crate::{RouteTableTrie, network::tun::add_route, pb::{SdlArpResponse, SdlStunReply}};
pub struct RouteTable2 {
pub cache_table: DashMap<(Ipv4Net, Ipv4Addr), AtomicBool, RandomState>,
pub route_table: RouteTableTrie,
}
impl RouteTable2 {
pub fn new() -> Self {
Self {
cache_table: DashMap::with_hasher(RandomState::new()),
route_table: RouteTableTrie::new(),
}
}
pub fn parse_and_add_route(&self, route_str: &str) -> Result<()> {
let routes = parse_route(route_str);
for route in routes.keys() {
if self.cache_table.get(route).is_some() {
error!("route {} {} has been added", route.0.to_string(), route.1);
return Err(SDLanError::IOError(format!("route {} already added", route.0.to_string())));
}
}
for route in routes.keys() {
self.cache_table.insert(*route, AtomicBool::new(false));
self.route_table.insert(route.0.addr().into(), route.0.prefix_len(), route.1);
}
Ok(())
}
pub fn apply_system(&self) {
for route in &self.cache_table {
let origin = route.fetch_or(true, Ordering::Relaxed);
if !origin {
// should add to system
add_route(route.key().0, route.key().1);
}
}
}
}
// ip, mask, gateway, cidr gateway,cidr2 gateway2
pub fn parse_route(route: &str) -> HashMap<(Ipv4Net, Ipv4Addr), bool> {
let mut result = HashMap::new();
// let routes: Vec<_> = route.split(",").collect();
for route in route.trim().split(",") {
let route_info: Vec<_> = route.trim().split_whitespace().collect();
if route_info.len() != 2 {
error!("route info format error: {}", route);
continue;
}
debug!("got route info: {:?}", route_info);
let Ok(gateway) = route_info[1].parse::<Ipv4Addr>() else {
error!("failed to parse gw: {}", route_info[1]);
continue;
};
let cidr = route_info[0];
let Ok(net )= cidr.parse::<Ipv4Net>() else {
error!("failed to parse cidr: {}, skipping", cidr);
continue;
};
let origin = result.insert((net, gateway), true);
if origin.is_some() {
error!("{} {} already added", net.to_string(), gateway.to_string());
}
}
result
}