mirror of
https://github.com/EasyTier/EasyTier.git
synced 2025-10-29 19:21:47 +08:00
fix direct connector only select one listener (#875)
Some checks failed
EasyTier Core / pre_job (push) Has been cancelled
EasyTier Core / build_web (push) Has been cancelled
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-22.04, x86_64-unknown-freebsd) (push) Has been cancelled
EasyTier Core / build (linux-aarch64, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-arm, ubuntu-22.04, arm-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armhf, ubuntu-22.04, arm-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-armv7, ubuntu-22.04, armv7-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armv7hf, ubuntu-22.04, armv7-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-mips, ubuntu-22.04, mips-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mipsel, ubuntu-22.04, mipsel-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-x86_64, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (windows-arm64, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-i686, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / core-result (push) Has been cancelled
EasyTier Core / magisk_build (push) Has been cancelled
EasyTier GUI / pre_job (push) Has been cancelled
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-i686, i686-pc-windows-msvc, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / gui-result (push) Has been cancelled
EasyTier Mobile / pre_job (push) Has been cancelled
EasyTier Mobile / build-mobile (android, ubuntu-22.04, android) (push) Has been cancelled
EasyTier Mobile / mobile-result (push) Has been cancelled
EasyTier Test / pre_job (push) Has been cancelled
EasyTier Test / test (push) Has been cancelled
Some checks failed
EasyTier Core / pre_job (push) Has been cancelled
EasyTier Core / build_web (push) Has been cancelled
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-22.04, x86_64-unknown-freebsd) (push) Has been cancelled
EasyTier Core / build (linux-aarch64, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-arm, ubuntu-22.04, arm-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armhf, ubuntu-22.04, arm-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-armv7, ubuntu-22.04, armv7-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armv7hf, ubuntu-22.04, armv7-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-mips, ubuntu-22.04, mips-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mipsel, ubuntu-22.04, mipsel-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-x86_64, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (windows-arm64, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-i686, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / core-result (push) Has been cancelled
EasyTier Core / magisk_build (push) Has been cancelled
EasyTier GUI / pre_job (push) Has been cancelled
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-i686, i686-pc-windows-msvc, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / gui-result (push) Has been cancelled
EasyTier Mobile / pre_job (push) Has been cancelled
EasyTier Mobile / build-mobile (android, ubuntu-22.04, android) (push) Has been cancelled
EasyTier Mobile / mobile-result (push) Has been cancelled
EasyTier Test / pre_job (push) Has been cancelled
EasyTier Test / test (push) Has been cancelled
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -820,15 +820,6 @@ dependencies = [
|
|||||||
"syn 2.0.87",
|
"syn 2.0.87",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bounded_join_set"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ae18fd8f4a623bcf416b5bc8f1e0905534d9911597ed17cc57ab9b6eed65454d"
|
|
||||||
dependencies = [
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli"
|
name = "brotli"
|
||||||
version = "7.0.0"
|
version = "7.0.0"
|
||||||
@@ -1941,7 +1932,6 @@ dependencies = [
|
|||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bitflags 2.8.0",
|
"bitflags 2.8.0",
|
||||||
"boringtun-easytier",
|
"boringtun-easytier",
|
||||||
"bounded_join_set",
|
|
||||||
"bytecodec",
|
"bytecodec",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|||||||
@@ -213,8 +213,6 @@ humantime-serde = "1.1.1"
|
|||||||
multimap = "0.10.0"
|
multimap = "0.10.0"
|
||||||
version-compare = "0.2.0"
|
version-compare = "0.2.0"
|
||||||
|
|
||||||
bounded_join_set = "0.3.0"
|
|
||||||
|
|
||||||
jemallocator = { version = "0.5.4", optional = true }
|
jemallocator = { version = "0.5.4", optional = true }
|
||||||
jemalloc-ctl = { version = "0.5.4", optional = true }
|
jemalloc-ctl = { version = "0.5.4", optional = true }
|
||||||
jemalloc-sys = { version = "0.5.4", features = [
|
jemalloc-sys = { version = "0.5.4", features = [
|
||||||
|
|||||||
@@ -221,16 +221,18 @@ impl DirectConnectorManagerData {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument(skip(self))]
|
||||||
async fn try_connect_to_ip(
|
async fn try_connect_to_ip(
|
||||||
self: Arc<DirectConnectorManagerData>,
|
self: Arc<DirectConnectorManagerData>,
|
||||||
dst_peer_id: PeerId,
|
dst_peer_id: PeerId,
|
||||||
addr: String,
|
addr: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut rand_gen = rand::rngs::OsRng::default();
|
let mut rand_gen = rand::rngs::OsRng::default();
|
||||||
let backoff_ms = vec![1000, 2000];
|
let backoff_ms = vec![1000, 2000, 4000];
|
||||||
let mut backoff_idx = 0;
|
let mut backoff_idx = 0;
|
||||||
|
|
||||||
|
tracing::debug!(?dst_peer_id, ?addr, "try_connect_to_ip start");
|
||||||
|
|
||||||
self.dst_listener_blacklist.cleanup();
|
self.dst_listener_blacklist.cleanup();
|
||||||
|
|
||||||
if self
|
if self
|
||||||
@@ -244,12 +246,21 @@ impl DirectConnectorManagerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
if self.peer_manager.has_directly_connected_conn(dst_peer_id) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::debug!(?dst_peer_id, ?addr, "try_connect_to_ip start one round");
|
||||||
let ret = self.do_try_connect_to_ip(dst_peer_id, addr.clone()).await;
|
let ret = self.do_try_connect_to_ip(dst_peer_id, addr.clone()).await;
|
||||||
tracing::debug!(?ret, ?dst_peer_id, ?addr, "try_connect_to_ip return");
|
tracing::debug!(?ret, ?dst_peer_id, ?addr, "try_connect_to_ip return");
|
||||||
if ret.is_ok() {
|
if ret.is_ok() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.peer_manager.has_directly_connected_conn(dst_peer_id) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
if backoff_idx < backoff_ms.len() {
|
if backoff_idx < backoff_ms.len() {
|
||||||
let delta = backoff_ms[backoff_idx] >> 1;
|
let delta = backoff_ms[backoff_idx] >> 1;
|
||||||
assert!(delta > 0);
|
assert!(delta > 0);
|
||||||
@@ -273,37 +284,19 @@ impl DirectConnectorManagerData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
fn spawn_direct_connect_task(
|
||||||
async fn do_try_direct_connect_internal(
|
|
||||||
self: &Arc<DirectConnectorManagerData>,
|
self: &Arc<DirectConnectorManagerData>,
|
||||||
dst_peer_id: PeerId,
|
dst_peer_id: PeerId,
|
||||||
ip_list: GetIpListResponse,
|
ip_list: &GetIpListResponse,
|
||||||
) -> Result<(), Error> {
|
listener: &url::Url,
|
||||||
let enable_ipv6 = self.global_ctx.get_flags().enable_ipv6;
|
tasks: &mut JoinSet<Result<(), Error>>,
|
||||||
let available_listeners = ip_list
|
) {
|
||||||
.listeners
|
let Ok(mut addrs) = listener.socket_addrs(|| None) else {
|
||||||
.into_iter()
|
tracing::error!(?listener, "failed to parse socket address from listener");
|
||||||
.map(Into::<url::Url>::into)
|
return;
|
||||||
.filter_map(|l| if l.scheme() != "ring" { Some(l) } else { None })
|
};
|
||||||
.filter(|l| l.port().is_some() && l.host().is_some())
|
let listener_host = addrs.pop();
|
||||||
.filter(|l| enable_ipv6 || !matches!(l.host().unwrap().to_owned(), Host::Ipv6(_)))
|
tracing::info!(?listener_host, ?listener, "try direct connect to peer");
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
tracing::debug!(?available_listeners, "got available listeners");
|
|
||||||
|
|
||||||
if available_listeners.is_empty() {
|
|
||||||
return Err(anyhow::anyhow!("peer {} have no valid listener", dst_peer_id).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// if have default listener, use it first
|
|
||||||
let listener = available_listeners
|
|
||||||
.iter()
|
|
||||||
.find(|l| l.scheme() == self.global_ctx.get_flags().default_protocol)
|
|
||||||
.unwrap_or(available_listeners.get(0).unwrap());
|
|
||||||
|
|
||||||
let mut tasks = bounded_join_set::JoinSet::new(2);
|
|
||||||
|
|
||||||
let listener_host = listener.socket_addrs(|| None)?.pop();
|
|
||||||
match listener_host {
|
match listener_host {
|
||||||
Some(SocketAddr::V4(s_addr)) => {
|
Some(SocketAddr::V4(s_addr)) => {
|
||||||
if s_addr.ip().is_unspecified() {
|
if s_addr.ip().is_unspecified() {
|
||||||
@@ -386,30 +379,90 @@ impl DirectConnectorManagerData {
|
|||||||
tracing::error!(?p, ?listener, "failed to parse ip version from listener");
|
tracing::error!(?p, ?listener, "failed to parse ip version from listener");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while let Some(ret) = tasks.join_next().await {
|
#[tracing::instrument(skip(self))]
|
||||||
match ret {
|
async fn do_try_direct_connect_internal(
|
||||||
Ok(Ok(_)) => {
|
self: &Arc<DirectConnectorManagerData>,
|
||||||
tracing::info!(
|
dst_peer_id: PeerId,
|
||||||
?dst_peer_id,
|
ip_list: GetIpListResponse,
|
||||||
?listener,
|
) -> Result<(), Error> {
|
||||||
"try direct connect to peer success"
|
let enable_ipv6 = self.global_ctx.get_flags().enable_ipv6;
|
||||||
);
|
let available_listeners = ip_list
|
||||||
|
.listeners
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::<url::Url>::into)
|
||||||
|
.filter_map(|l| if l.scheme() != "ring" { Some(l) } else { None })
|
||||||
|
.filter(|l| l.port().is_some() && l.host().is_some())
|
||||||
|
.filter(|l| enable_ipv6 || !matches!(l.host().unwrap().to_owned(), Host::Ipv6(_)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
tracing::debug!(?available_listeners, "got available listeners");
|
||||||
|
|
||||||
|
if available_listeners.is_empty() {
|
||||||
|
return Err(anyhow::anyhow!("peer {} have no valid listener", dst_peer_id).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let default_protocol = self.global_ctx.get_flags().default_protocol;
|
||||||
|
// sort available listeners, default protocol has the highest priority, udp is second, others just random
|
||||||
|
// highest priority is in the last
|
||||||
|
let mut available_listeners = available_listeners;
|
||||||
|
available_listeners.sort_by_key(|l| {
|
||||||
|
let scheme = l.scheme();
|
||||||
|
if scheme == default_protocol {
|
||||||
|
3
|
||||||
|
} else if scheme == "udp" {
|
||||||
|
2
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while !available_listeners.is_empty() {
|
||||||
|
let mut tasks = JoinSet::new();
|
||||||
|
let mut listener_list = vec![];
|
||||||
|
|
||||||
|
let cur_scheme = available_listeners.last().unwrap().scheme().to_owned();
|
||||||
|
while let Some(listener) = available_listeners.last() {
|
||||||
|
if listener.scheme() != cur_scheme {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Ok(Err(e)) => {
|
|
||||||
tracing::info!(?e, "try direct connect to peer failed");
|
tracing::debug!("try direct connect to peer with listener: {}", listener);
|
||||||
}
|
self.spawn_direct_connect_task(
|
||||||
Err(e) => {
|
dst_peer_id.clone(),
|
||||||
tracing::error!(?e, "try direct connect to peer task join failed");
|
&ip_list,
|
||||||
}
|
&listener,
|
||||||
|
&mut tasks,
|
||||||
|
);
|
||||||
|
|
||||||
|
listener_list.push(listener.clone().to_string());
|
||||||
|
available_listeners.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = tasks.join_all().await;
|
||||||
|
tracing::debug!(
|
||||||
|
?ret,
|
||||||
|
?dst_peer_id,
|
||||||
|
?cur_scheme,
|
||||||
|
?listener_list,
|
||||||
|
"all tasks finished for current scheme"
|
||||||
|
);
|
||||||
|
|
||||||
|
if self.peer_manager.has_directly_connected_conn(dst_peer_id) {
|
||||||
|
tracing::info!(
|
||||||
|
"direct connect to peer {} success, has direct conn",
|
||||||
|
dst_peer_id
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument(skip(self))]
|
||||||
async fn do_try_direct_connect(
|
async fn do_try_direct_connect(
|
||||||
self: Arc<DirectConnectorManagerData>,
|
self: Arc<DirectConnectorManagerData>,
|
||||||
dst_peer_id: PeerId,
|
dst_peer_id: PeerId,
|
||||||
|
|||||||
Reference in New Issue
Block a user