diff --git a/vnt/src/channel/context.rs b/vnt/src/channel/context.rs index d7f2cad..2ac454a 100644 --- a/vnt/src/channel/context.rs +++ b/vnt/src/channel/context.rs @@ -12,7 +12,7 @@ use rand::Rng; use crate::channel::punch::NatType; use crate::channel::sender::{AcceptSocketSender, ChannelSender, PacketSender}; -use crate::channel::{Route, RouteKey, UseChannelType}; +use crate::channel::{Route, RouteKey, UseChannelType, DEFAULT_RT}; use crate::handle::{ConnectStatus, CurrentDeviceInfo}; /// 传输通道上下文,持有udp socket、tcp socket和路由信息 @@ -331,31 +331,47 @@ impl RouteTable { impl RouteTable { fn get_route_by_id(&self, id: &Ipv4Addr) -> io::Result { if let Some((count, v)) = self.route_table.read().get(id) { - if v.is_empty() { + let len = v.len(); + if len == 0 { return Err(io::Error::new(io::ErrorKind::NotFound, "route not found")); } - if self.channel_num > 1 { - //多通道的,则轮流使用,不需要精确轮询 不使用cas性能估计好点 + let index = if self.channel_num > 1 { let index = count.load(Ordering::Relaxed); count.store(index + 1, Ordering::Relaxed); - if let Some((route, _time)) = v.get(index) { - if route.is_p2p() && route.rt != 199 { + index + } else { + 0 + }; + // 基准延迟,选中的路由不能和这个延迟大太多 + let mut rt0 = v[0].0.rt; + let (route, time) = &v[index % len]; + + // 刚加入的或者长时间没通信的不使用 + if route.rt - rt0 < 5 + && route.rt != DEFAULT_RT + && time.load().elapsed() < Duration::from_secs(5) + { + return Ok(*route); + } + // 如果指定路由不符合,则遍历路由表找到符合条件的 + if len > 1 { + let mut re_rt = false; + for (i, (route, time)) in v.iter().enumerate() { + let recent = time.load().elapsed() < Duration::from_secs(5); + if i == 0 && !recent { + // 如果第一条路由不符合条件,则要重新选择基准延迟 + re_rt = true; + continue; + } + if re_rt && recent { + re_rt = false; + rt0 = route.rt; + } + if recent && route.rt - rt0 < 5 && route.rt != DEFAULT_RT { return Ok(*route); } } } - let (route, time) = &v[0]; - if route.rt == 199 { - //这通常是刚加入路由,直接放弃使用,避免抖动 - return Err(io::Error::new(io::ErrorKind::NotFound, "route not found")); - } - if !route.is_p2p() { - //借道传输时,长时间不通信的通道不使用 - if time.load().elapsed() > Duration::from_secs(5) { - return Err(io::Error::new(io::ErrorKind::NotFound, "route time out")); - } - } - return Ok(*route); } Err(io::Error::new(io::ErrorKind::NotFound, "route not found")) } @@ -400,18 +416,18 @@ impl RouteTable { if exist { list.sort_by_key(|(k, _)| k.rt); } else { - let max_len = if self.first_latency { - self.channel_num + 1 + let limit_len = if self.first_latency { + self.channel_num } else { if route.metric == 1 { //非优先延迟的情况下 添加了直连的则排除非直连的 list.retain(|(k, _)| k.metric == 1); } - self.channel_num + self.channel_num - 1 }; list.sort_by_key(|(k, _)| k.rt); - if list.len() > max_len { - list.truncate(max_len); + if list.len() > limit_len { + list.truncate(limit_len); } list.push((route, AtomicCell::new(Instant::now()))); } diff --git a/vnt/src/channel/mod.rs b/vnt/src/channel/mod.rs index 3d44ae4..80fce49 100644 --- a/vnt/src/channel/mod.rs +++ b/vnt/src/channel/mod.rs @@ -75,7 +75,7 @@ pub struct RouteSortKey { pub metric: u8, pub rt: i64, } - +const DEFAULT_RT: i64 = 999; impl Route { pub fn new(is_tcp: bool, index: usize, addr: SocketAddr, metric: u8, rt: i64) -> Self { Self { @@ -95,6 +95,15 @@ impl Route { rt, } } + pub fn from_default_rt(route_key: RouteKey, metric: u8) -> Self { + Self { + is_tcp: route_key.is_tcp, + index: route_key.index, + addr: route_key.addr, + metric, + rt: DEFAULT_RT, + } + } pub fn route_key(&self) -> RouteKey { RouteKey { is_tcp: self.is_tcp, diff --git a/vnt/src/handle/recv_data/client.rs b/vnt/src/handle/recv_data/client.rs index 332780b..01c9063 100644 --- a/vnt/src/handle/recv_data/client.rs +++ b/vnt/src/handle/recv_data/client.rs @@ -174,7 +174,7 @@ impl ClientPacketHandler { net_packet.first_set_ttl(MAX_TTL); self.client_cipher.encrypt_ipv4(&mut net_packet)?; context.send_by_key(net_packet.buffer(), route_key)?; - let route = Route::from(route_key, metric, 199); + let route = Route::from_default_rt(route_key, metric); context.route_table.add_route_if_absent(source, route); } ControlPacket::PongPacket(pong_packet) => { @@ -197,14 +197,14 @@ impl ClientPacketHandler { net_packet.first_set_ttl(1); self.client_cipher.encrypt_ipv4(&mut net_packet)?; context.send_by_key(net_packet.buffer(), route_key)?; - let route = Route::from(route_key, 1, 199); + let route = Route::from_default_rt(route_key, 1); context.route_table.add_route_if_absent(source, route); } ControlPacket::PunchResponse => { if context.use_channel_type().is_only_relay() { return Ok(()); } - let route = Route::from(route_key, 1, 199); + let route = Route::from_default_rt(route_key, 1); context.route_table.add_route_if_absent(source, route); } ControlPacket::AddrRequest => match route_key.addr.ip() { diff --git a/vnt/src/handle/recv_data/server.rs b/vnt/src/handle/recv_data/server.rs index bbe2cc7..29d98b6 100644 --- a/vnt/src/handle/recv_data/server.rs +++ b/vnt/src/handle/recv_data/server.rs @@ -226,7 +226,7 @@ impl ServerPacketHandler { Ipv4Addr::from(response.virtual_ip & response.virtual_netmask); let register_info = RegisterInfo::new(virtual_ip, virtual_netmask, virtual_gateway); if self.callback.register(register_info) { - let route = Route::from(route_key, 1, 199); + let route = Route::from_default_rt(route_key, 1); context .route_table .add_route_if_absent(virtual_gateway, route);