mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 10:14:35 +00:00
v6 hole punch (#873)
Some devices have ipv6 but don't allow input connection, this patch add hole punching for these devices. - **add v6 hole punch msg to udp tunnel** - **send hole punch packet when do ipv6 direct connect**
This commit is contained in:
@@ -61,11 +61,11 @@ pub struct GlobalCtx {
|
||||
cached_ipv4: AtomicCell<Option<cidr::Ipv4Inet>>,
|
||||
cached_proxy_cidrs: AtomicCell<Option<Vec<cidr::IpCidr>>>,
|
||||
|
||||
ip_collector: Arc<IPCollector>,
|
||||
ip_collector: Mutex<Option<Arc<IPCollector>>>,
|
||||
|
||||
hostname: Mutex<String>,
|
||||
|
||||
stun_info_collection: Box<dyn StunInfoCollectorTrait>,
|
||||
stun_info_collection: Mutex<Arc<dyn StunInfoCollectorTrait>>,
|
||||
|
||||
running_listeners: Mutex<Vec<url::Url>>,
|
||||
|
||||
@@ -120,11 +120,14 @@ impl GlobalCtx {
|
||||
cached_ipv4: AtomicCell::new(None),
|
||||
cached_proxy_cidrs: AtomicCell::new(None),
|
||||
|
||||
ip_collector: Arc::new(IPCollector::new(net_ns, stun_info_collection.clone())),
|
||||
ip_collector: Mutex::new(Some(Arc::new(IPCollector::new(
|
||||
net_ns,
|
||||
stun_info_collection.clone(),
|
||||
)))),
|
||||
|
||||
hostname: Mutex::new(hostname),
|
||||
|
||||
stun_info_collection: Box::new(stun_info_collection),
|
||||
stun_info_collection: Mutex::new(stun_info_collection),
|
||||
|
||||
running_listeners: Mutex::new(Vec::new()),
|
||||
|
||||
@@ -215,7 +218,7 @@ impl GlobalCtx {
|
||||
}
|
||||
|
||||
pub fn get_ip_collector(&self) -> Arc<IPCollector> {
|
||||
self.ip_collector.clone()
|
||||
self.ip_collector.lock().unwrap().as_ref().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn get_hostname(&self) -> String {
|
||||
@@ -226,19 +229,19 @@ impl GlobalCtx {
|
||||
*self.hostname.lock().unwrap() = hostname;
|
||||
}
|
||||
|
||||
pub fn get_stun_info_collector(&self) -> impl StunInfoCollectorTrait + '_ {
|
||||
self.stun_info_collection.as_ref()
|
||||
pub fn get_stun_info_collector(&self) -> Arc<dyn StunInfoCollectorTrait> {
|
||||
self.stun_info_collection.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn replace_stun_info_collector(&self, collector: Box<dyn StunInfoCollectorTrait>) {
|
||||
// force replace the stun_info_collection without mut and drop the old one
|
||||
let ptr = &self.stun_info_collection as *const Box<dyn StunInfoCollectorTrait>;
|
||||
let ptr = ptr as *mut Box<dyn StunInfoCollectorTrait>;
|
||||
unsafe {
|
||||
std::ptr::drop_in_place(ptr);
|
||||
#[allow(invalid_reference_casting)]
|
||||
std::ptr::write(ptr, collector);
|
||||
}
|
||||
let arc_collector: Arc<dyn StunInfoCollectorTrait> = Arc::new(collector);
|
||||
*self.stun_info_collection.lock().unwrap() = arc_collector.clone();
|
||||
|
||||
// rebuild the ip collector
|
||||
*self.ip_collector.lock().unwrap() = Some(Arc::new(IPCollector::new(
|
||||
self.net_ns.clone(),
|
||||
arc_collector,
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn get_running_listeners(&self) -> Vec<url::Url> {
|
||||
|
||||
@@ -179,18 +179,16 @@ impl IPCollector {
|
||||
Self::do_collect_local_ip_addrs(self.net_ns.clone()).await;
|
||||
let net_ns = self.net_ns.clone();
|
||||
let stun_info_collector = self.stun_info_collector.clone();
|
||||
task.spawn(async move {
|
||||
loop {
|
||||
let ip_addrs = Self::do_collect_local_ip_addrs(net_ns.clone()).await;
|
||||
*cached_ip_list.write().await = ip_addrs;
|
||||
tokio::time::sleep(std::time::Duration::from_secs(CACHED_IP_LIST_TIMEOUT_SEC))
|
||||
.await;
|
||||
}
|
||||
});
|
||||
|
||||
let cached_ip_list = self.cached_ip_list.clone();
|
||||
task.spawn(async move {
|
||||
let mut last_fetch_iface_time = std::time::Instant::now();
|
||||
loop {
|
||||
if last_fetch_iface_time.elapsed().as_secs() > CACHED_IP_LIST_TIMEOUT_SEC {
|
||||
let ifaces = Self::do_collect_local_ip_addrs(net_ns.clone()).await;
|
||||
*cached_ip_list.write().await = ifaces;
|
||||
last_fetch_iface_time = std::time::Instant::now();
|
||||
}
|
||||
|
||||
let stun_info = stun_info_collector.get_stun_info();
|
||||
for ip in stun_info.public_ip.iter() {
|
||||
let Ok(ip_addr) = ip.parse::<IpAddr>() else {
|
||||
@@ -199,14 +197,20 @@ impl IPCollector {
|
||||
|
||||
match ip_addr {
|
||||
IpAddr::V4(v) => {
|
||||
cached_ip_list.write().await.public_ipv4 = Some(v.into())
|
||||
cached_ip_list.write().await.public_ipv4.replace(v.into());
|
||||
}
|
||||
IpAddr::V6(v) => {
|
||||
cached_ip_list.write().await.public_ipv6 = Some(v.into())
|
||||
cached_ip_list.write().await.public_ipv6.replace(v.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tracing::debug!(
|
||||
"got public ip: {:?}, {:?}",
|
||||
cached_ip_list.read().await.public_ipv4,
|
||||
cached_ip_list.read().await.public_ipv6
|
||||
);
|
||||
|
||||
let sleep_sec = if !cached_ip_list.read().await.public_ipv4.is_none() {
|
||||
CACHED_IP_LIST_TIMEOUT_SEC
|
||||
} else {
|
||||
@@ -217,7 +221,7 @@ impl IPCollector {
|
||||
});
|
||||
}
|
||||
|
||||
return self.cached_ip_list.read().await.deref().clone();
|
||||
self.cached_ip_list.read().await.deref().clone()
|
||||
}
|
||||
|
||||
pub async fn collect_interfaces(net_ns: NetNS, filter: bool) -> Vec<NetworkInterface> {
|
||||
|
||||
@@ -890,7 +890,7 @@ impl StunInfoCollectorTrait for MockStunInfoCollector {
|
||||
last_update_time: std::time::Instant::now().elapsed().as_secs() as i64,
|
||||
min_port: 100,
|
||||
max_port: 200,
|
||||
public_ip: vec!["127.0.0.1".to_string()],
|
||||
public_ip: vec!["127.0.0.1".to_string(), "::1".to_string()],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user