kcp connect retry (#952)

This commit is contained in:
Sijie.Sun
2025-06-07 12:24:11 +08:00
committed by GitHub
parent 47f3efe71b
commit f890812577
+47 -14
View File
@@ -20,7 +20,7 @@ use pnet::packet::{
Packet as _, Packet as _,
}; };
use prost::Message; use prost::Message;
use tokio::{io::copy_bidirectional, task::JoinSet}; use tokio::{io::copy_bidirectional, select, task::JoinSet};
use super::{ use super::{
tcp_proxy::{NatDstConnector, NatDstTcpConnector, TcpProxy}, tcp_proxy::{NatDstConnector, NatDstTcpConnector, TcpProxy},
@@ -134,21 +134,54 @@ impl NatDstConnector for NatDstKcpConnector {
return Err(anyhow::anyhow!("no dst peer found for nat dst: {}", nat_dst).into()); return Err(anyhow::anyhow!("no dst peer found for nat dst: {}", nat_dst).into());
} }
let ret = self let mut connect_tasks: JoinSet<std::result::Result<ConnId, anyhow::Error>> = JoinSet::new();
.kcp_endpoint let mut retry_remain = 5;
.connect( loop {
Duration::from_secs(10), select! {
self.peer_mgr.my_peer_id(), Some(Ok(Ok(ret))) = connect_tasks.join_next() => {
dst_peers[0], // just wait for the previous connection to finish
Bytes::from(conn_data.encode_to_vec()), let stream = KcpStream::new(&self.kcp_endpoint, ret)
) .ok_or(anyhow::anyhow!("failed to create kcp stream"))?;
.await return Ok(stream);
.with_context(|| format!("failed to connect to nat dst: {}", nat_dst.to_string()))?; }
_ = tokio::time::sleep(Duration::from_millis(200)), if !connect_tasks.is_empty() && retry_remain > 0 => {
// no successful connection yet, trigger another connection attempt
}
else => {
// got error in connect_tasks, continue to retry
if retry_remain == 0 && connect_tasks.is_empty() {
break;
}
}
}
let stream = KcpStream::new(&self.kcp_endpoint, ret) // create a new connection task
.ok_or(anyhow::anyhow!("failed to create kcp stream"))?; if retry_remain == 0 {
continue;
}
retry_remain -= 1;
Ok(stream) let kcp_endpoint = self.kcp_endpoint.clone();
let peer_mgr = self.peer_mgr.clone();
let dst_peer = dst_peers[0];
let conn_data_clone = conn_data.clone();
connect_tasks.spawn(async move {
kcp_endpoint
.connect(
Duration::from_secs(10),
peer_mgr.my_peer_id(),
dst_peer,
Bytes::from(conn_data_clone.encode_to_vec()),
)
.await
.with_context(|| {
format!("failed to connect to nat dst: {}", nat_dst.to_string())
})
});
}
Err(anyhow::anyhow!("failed to connect to nat dst: {}", nat_dst).into())
} }
fn check_packet_from_peer_fast(&self, _cidr_set: &CidrSet, _global_ctx: &GlobalCtx) -> bool { fn check_packet_from_peer_fast(&self, _cidr_set: &CidrSet, _global_ctx: &GlobalCtx) -> bool {