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::() else { error!("failed to parse gw: {}", route_info[1]); continue; }; let cidr = route_info[0]; let Ok(net )= cidr.parse::() 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 }