mirror of
https://github.com/EasyTier/EasyTier.git
synced 2024-11-16 03:32:43 +08:00
fix wg client hang after some time (#297)
wg portal doesn't know client disconnect causing msg overstocked in queue, make entire peer packet process pipeline hang.
This commit is contained in:
parent
6964fb71fc
commit
2058dbc470
|
@ -187,10 +187,6 @@ pub enum SocksError {
|
||||||
#[error("Error with reply: {0}.")]
|
#[error("Error with reply: {0}.")]
|
||||||
ReplyError(#[from] ReplyError),
|
ReplyError(#[from] ReplyError),
|
||||||
|
|
||||||
#[cfg(feature = "socks4")]
|
|
||||||
#[error("Error with reply: {0}.")]
|
|
||||||
ReplySocks4Error(#[from] socks4::ReplyError),
|
|
||||||
|
|
||||||
#[error("Argument input error: `{0}`.")]
|
#[error("Argument input error: `{0}`.")]
|
||||||
ArgumentInputError(&'static str),
|
ArgumentInputError(&'static str),
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,13 @@ impl MpscTunnelSender {
|
||||||
self.0.send(item).await.with_context(|| "send error")?;
|
self.0.send(item).await.with_context(|| "send error")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_send(&self, item: ZCPacket) -> Result<(), TunnelError> {
|
||||||
|
self.0.try_send(item).map_err(|e| match e {
|
||||||
|
tachyonix::TrySendError::Full(_) => TunnelError::BufferFull,
|
||||||
|
tachyonix::TrySendError::Closed(_) => TunnelError::Shutdown,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MpscTunnel<T> {
|
pub struct MpscTunnel<T> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
net::{Ipv4Addr, SocketAddr},
|
net::{Ipv4Addr, SocketAddr},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
@ -9,7 +10,7 @@ use cidr::Ipv4Inet;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use pnet::packet::ipv4::Ipv4Packet;
|
use pnet::packet::ipv4::Ipv4Packet;
|
||||||
use tokio::task::JoinSet;
|
use tokio::{task::JoinSet, time::timeout};
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -23,7 +24,7 @@ use crate::{
|
||||||
mpsc::{MpscTunnel, MpscTunnelSender},
|
mpsc::{MpscTunnel, MpscTunnelSender},
|
||||||
packet_def::{PacketType, ZCPacket, ZCPacketType},
|
packet_def::{PacketType, ZCPacket, ZCPacketType},
|
||||||
wireguard::{WgConfig, WgTunnelListener},
|
wireguard::{WgConfig, WgTunnelListener},
|
||||||
Tunnel, TunnelListener,
|
Tunnel, TunnelError, TunnelListener,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,7 +93,25 @@ impl WireGuardImpl {
|
||||||
info.remote_addr.clone(),
|
info.remote_addr.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
while let Some(Ok(msg)) = stream.next().await {
|
let mut map_key = None;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let msg = match timeout(Duration::from_secs(120), stream.next()).await {
|
||||||
|
Ok(Some(Ok(msg))) => msg,
|
||||||
|
Ok(Some(Err(err))) => {
|
||||||
|
tracing::error!(?err, "Failed to receive from wg client");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
tracing::info!("Wireguard client disconnected");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!(?err, "Timeout while receiving from wg client");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
assert_eq!(msg.packet_type(), ZCPacketType::WG);
|
assert_eq!(msg.packet_type(), ZCPacketType::WG);
|
||||||
let inner = msg.inner();
|
let inner = msg.inner();
|
||||||
let Some(i) = Ipv4Packet::new(&inner) else {
|
let Some(i) = Ipv4Packet::new(&inner) else {
|
||||||
|
@ -104,6 +123,7 @@ impl WireGuardImpl {
|
||||||
endpoint_addr: remote_addr.parse().ok(),
|
endpoint_addr: remote_addr.parse().ok(),
|
||||||
sink: mpsc_tunnel.get_sink(),
|
sink: mpsc_tunnel.get_sink(),
|
||||||
});
|
});
|
||||||
|
map_key = Some(i.get_source());
|
||||||
wg_peer_ip_table.insert(i.get_source(), client_entry.clone());
|
wg_peer_ip_table.insert(i.get_source(), client_entry.clone());
|
||||||
ip_registered = true;
|
ip_registered = true;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +134,11 @@ impl WireGuardImpl {
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if map_key.is_some() {
|
||||||
|
tracing::info!(?map_key, "Removing wg client from table");
|
||||||
|
wg_peer_ip_table.remove(&map_key.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
peer_mgr
|
peer_mgr
|
||||||
.get_global_ctx()
|
.get_global_ctx()
|
||||||
.issue_event(GlobalCtxEvent::VpnPortalClientDisconnected(
|
.issue_event(GlobalCtxEvent::VpnPortalClientDisconnected(
|
||||||
|
@ -157,9 +182,15 @@ impl WireGuardImpl {
|
||||||
ZCPacketType::WG,
|
ZCPacketType::WG,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Err(ret) = entry.sink.send(packet).await {
|
match entry.sink.try_send(packet) {
|
||||||
tracing::debug!(?ret, "Failed to send packet to wg client");
|
Ok(_) => {
|
||||||
|
tracing::trace!("Sent packet to wg client");
|
||||||
}
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::debug!(?e, "Failed to send packet to wg client");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user