diff --git a/vnt/src/handle/maintain/punch.rs b/vnt/src/handle/maintain/punch.rs index 8bbbe84..d4ef933 100644 --- a/vnt/src/handle/maintain/punch.rs +++ b/vnt/src/handle/maintain/punch.rs @@ -175,7 +175,7 @@ fn punch_request( client_cipher: Cipher, count: usize, punch_record: Arc>>, - mut last_punch_record: HashMap, + mut last_punch_record: HashMap, ) { let curr = current_device.load(); let secs = if curr.status.online() { @@ -213,6 +213,11 @@ fn punch_request( log::info!("定时任务停止"); } } +#[derive(Copy, Clone, Default)] +struct PunchRecordItem { + pub punch_record: usize, + pub last_p2p_num: usize, +} /// 随机对需要打洞的客户端发起打洞请求 fn punch0( @@ -222,7 +227,7 @@ fn punch0( current_device: CurrentDeviceInfo, client_cipher: &Cipher, punch_record: &Mutex>, - last_punch_record: &mut HashMap, + last_punch_record: &mut HashMap, total_count: usize, ) -> anyhow::Result<()> { let nat_info = nat_test.nat_info(); @@ -241,12 +246,17 @@ fn punch0( .lock() .1 .values() - .filter(|info| !info.wireguard && info.status.is_online() && info.virtual_ip > current_ip) + .filter(|info| !info.wireguard && info.virtual_ip > current_ip) .cloned() .collect(); list.shuffle(&mut rand::thread_rng()); for info in list { - let punch_count = punch_record + if info.status.is_online() { + // 客户端掉线了要重置打洞记录 + punch_record.lock().remove(&info.virtual_ip); + continue; + } + let mut punch_count = punch_record .lock() .get(&info.virtual_ip) .cloned() @@ -269,13 +279,18 @@ fn punch0( max_punch_interval = 300; } // 能发起打洞的前提是自己空闲,这里会间隔5秒以上发起一次打洞,所以假定上一轮打洞已结束 - let last_punch = last_punch_record - .get(&info.virtual_ip) - .cloned() - .unwrap_or(0); + let last_punch = last_punch_record.entry(info.virtual_ip).or_default(); + if last_punch.last_p2p_num > p2p_num { + // 打的洞掉线了,需要重置重新打 + punch_record.lock().remove(&info.virtual_ip); + punch_count = 0; + } + // 梯度增加打洞时间间隔 - if total_count > last_punch + punch_count.min(max_punch_interval) { - last_punch_record.insert(info.virtual_ip, total_count); + if total_count > last_punch.punch_record + punch_count.min(max_punch_interval) { + // 记录打洞周期,抑制下一次打洞,从而递减打洞频率 + last_punch.punch_record = total_count; + last_punch.last_p2p_num = p2p_num; let packet = punch_packet( client_cipher, current_device.virtual_ip(),