diff --git a/vnt/src/channel/context.rs b/vnt/src/channel/context.rs index 72bb564..0cbc107 100644 --- a/vnt/src/channel/context.rs +++ b/vnt/src/channel/context.rs @@ -453,14 +453,19 @@ impl RouteTable { } None } - pub fn need_punch(&self, id: &Ipv4Addr) -> bool { + pub fn no_need_punch(&self, id: &Ipv4Addr) -> bool { if let Some((_, v)) = self.route_table.read().get(id) { - //存在p2p的通道则不再打洞 - if v.iter().filter(|(k, _)| k.is_p2p()).count() >= 1 { - return false; - } + //p2p的通道数符合要求 + return v.iter().filter(|(k, _)| k.is_p2p()).count() >= self.channel_num; + } + false + } + pub fn p2p_num(&self, id: &Ipv4Addr) -> usize { + if let Some((_, v)) = self.route_table.read().get(id) { + v.iter().filter(|(k, _)| k.is_p2p()).count() + } else { + 0 } - true } /// 返回所有路由 pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec)> { diff --git a/vnt/src/channel/punch.rs b/vnt/src/channel/punch.rs index 56d3101..6342265 100644 --- a/vnt/src/channel/punch.rs +++ b/vnt/src/channel/punch.rs @@ -235,7 +235,7 @@ impl Punch { nat_info: NatInfo, punch_tcp: bool, ) -> io::Result<()> { - if !self.context.route_table.need_punch(&id) { + if self.context.route_table.no_need_punch(&id) { log::info!("已打洞成功,无需打洞:{:?}", id); return Ok(()); } diff --git a/vnt/src/handle/maintain/punch.rs b/vnt/src/handle/maintain/punch.rs index c01235a..95a7ff5 100644 --- a/vnt/src/handle/maintain/punch.rs +++ b/vnt/src/handle/maintain/punch.rs @@ -227,7 +227,9 @@ fn punch0( if total_count < 10 && (nat_info.public_ips.is_empty() || nat_info.public_ports.is_empty() - || nat_info.public_ports[0] == 0) + || nat_info.public_ports[0] == 0 + || nat_info.public_ports.iter().filter(|&&v| v == 0).count() + > nat_info.public_ports.len() / 2) { log::info!("公网地址为空,暂时放弃打洞,第{}轮", total_count); return Ok(()); @@ -242,22 +244,33 @@ fn punch0( .collect(); list.shuffle(&mut rand::thread_rng()); for info in list { - if !context.route_table.need_punch(&info.virtual_ip) { - punch_record.lock().remove(&info.virtual_ip); - continue; - } - // 能发起打洞的前提是自己空闲,这里会间隔5秒以上发起一次打洞,所以假定上一轮打洞已结束 let punch_count = punch_record .lock() .get(&info.virtual_ip) .cloned() .unwrap_or(0); + let p2p_num = context.route_table.p2p_num(&info.virtual_ip); + let mut max_punch_interval = 70; + if p2p_num > 0 { + if punch_count == 0 { + continue; + } + if p2p_num >= context.channel_num() { + //通道数满足要求,不再打洞 + punch_record.lock().remove(&info.virtual_ip); + continue; + } + //有p2p通道,但是通道数量不够,则继续打洞 + // 提高等待上限 + max_punch_interval = 300; + } + // 能发起打洞的前提是自己空闲,这里会间隔5秒以上发起一次打洞,所以假定上一轮打洞已结束 let last_punch = last_punch_record .get(&info.virtual_ip) .cloned() .unwrap_or(0); - // 梯度减少打洞频率 - if total_count > last_punch + punch_count.min(35) { + // 梯度增加打洞时间间隔 + if total_count > last_punch + punch_count.min(max_punch_interval) { last_punch_record.insert(info.virtual_ip, total_count); let packet = punch_packet( client_cipher,