mirror of https://github.com/rapiz1/rathole.git
fix: log error when failed to listen on udp port
This commit is contained in:
parent
f1f4044f7b
commit
a071b0786b
|
@ -17,7 +17,7 @@ use tokio::io::{self, copy_bidirectional, AsyncWriteExt};
|
||||||
use tokio::net::{TcpStream, UdpSocket};
|
use tokio::net::{TcpStream, UdpSocket};
|
||||||
use tokio::sync::{broadcast, mpsc, oneshot, RwLock};
|
use tokio::sync::{broadcast, mpsc, oneshot, RwLock};
|
||||||
use tokio::time::{self, Duration};
|
use tokio::time::{self, Duration};
|
||||||
use tracing::{debug, error, info, instrument, warn, Instrument, Span};
|
use tracing::{debug, error, info, instrument, trace, warn, Instrument, Span};
|
||||||
|
|
||||||
#[cfg(feature = "noise")]
|
#[cfg(feature = "noise")]
|
||||||
use crate::transport::NoiseTransport;
|
use crate::transport::NoiseTransport;
|
||||||
|
@ -236,8 +236,13 @@ async fn run_data_channel_for_udp<T: Transport>(conn: T::Stream, local_addr: &st
|
||||||
// Keep sending items from the outbound channel to the server
|
// Keep sending items from the outbound channel to the server
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
while let Some(t) = outbound_rx.recv().await {
|
while let Some(t) = outbound_rx.recv().await {
|
||||||
debug!("outbound {:?}", t);
|
trace!("outbound {:?}", t);
|
||||||
if t.write(&mut wr).await.is_err() {
|
if let Err(e) = t
|
||||||
|
.write(&mut wr)
|
||||||
|
.await
|
||||||
|
.with_context(|| "Failed to forward UDP traffic to the server")
|
||||||
|
{
|
||||||
|
debug!("{:?}", e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,7 +250,10 @@ async fn run_data_channel_for_udp<T: Transport>(conn: T::Stream, local_addr: &st
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Read a packet from the server
|
// Read a packet from the server
|
||||||
let packet = UdpTraffic::read(&mut rd).await?;
|
let hdr_len = rd.read_u16().await?;
|
||||||
|
let packet = UdpTraffic::read(&mut rd, hdr_len)
|
||||||
|
.await
|
||||||
|
.with_context(|| "Failed to read UDPTraffic from the server")?;
|
||||||
let m = port_map.read().await;
|
let m = port_map.read().await;
|
||||||
|
|
||||||
if m.get(&packet.from).is_none() {
|
if m.get(&packet.from).is_none() {
|
||||||
|
@ -290,6 +298,7 @@ async fn run_data_channel_for_udp<T: Transport>(conn: T::Stream, local_addr: &st
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run a UdpSocket for the visitor `from`
|
// Run a UdpSocket for the visitor `from`
|
||||||
|
#[instrument(skip_all, fields(from))]
|
||||||
async fn run_udp_forwarder(
|
async fn run_udp_forwarder(
|
||||||
s: UdpSocket,
|
s: UdpSocket,
|
||||||
mut inbound_rx: mpsc::Receiver<Bytes>,
|
mut inbound_rx: mpsc::Receiver<Bytes>,
|
||||||
|
@ -297,6 +306,7 @@ async fn run_udp_forwarder(
|
||||||
from: SocketAddr,
|
from: SocketAddr,
|
||||||
port_map: UdpPortMap,
|
port_map: UdpPortMap,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
debug!("Forwarder created");
|
||||||
let mut buf = BytesMut::new();
|
let mut buf = BytesMut::new();
|
||||||
buf.resize(UDP_BUFFER_SIZE, 0);
|
buf.resize(UDP_BUFFER_SIZE, 0);
|
||||||
|
|
||||||
|
@ -336,6 +346,7 @@ async fn run_udp_forwarder(
|
||||||
let mut port_map = port_map.write().await;
|
let mut port_map = port_map.write().await;
|
||||||
port_map.remove(&from);
|
port_map.remove(&from);
|
||||||
|
|
||||||
|
debug!("Forwarder dropped");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,12 +162,12 @@ impl<'a, T: 'static + Transport> Server<'a, T> {
|
||||||
}
|
}
|
||||||
Ok((conn, addr)) => {
|
Ok((conn, addr)) => {
|
||||||
backoff.reset();
|
backoff.reset();
|
||||||
debug!("Incomming connection from {}", addr);
|
debug!("Incoming connection from {}", addr);
|
||||||
|
|
||||||
let services = self.services.clone();
|
let services = self.services.clone();
|
||||||
let control_channels = self.control_channels.clone();
|
let control_channels = self.control_channels.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(err) = handle_connection(conn, addr, services, control_channels).await.with_context(||"Failed to handle a connection to `server.bind_addr`") {
|
if let Err(err) = handle_connection(conn, services, control_channels).await {
|
||||||
error!("{:?}", err);
|
error!("{:?}", err);
|
||||||
}
|
}
|
||||||
}.instrument(info_span!("handle_connection", %addr)));
|
}.instrument(info_span!("handle_connection", %addr)));
|
||||||
|
@ -215,7 +215,6 @@ impl<'a, T: 'static + Transport> Server<'a, T> {
|
||||||
// Handle connections to `server.bind_addr`
|
// Handle connections to `server.bind_addr`
|
||||||
async fn handle_connection<T: 'static + Transport>(
|
async fn handle_connection<T: 'static + Transport>(
|
||||||
mut conn: T::Stream,
|
mut conn: T::Stream,
|
||||||
addr: SocketAddr,
|
|
||||||
services: Arc<RwLock<HashMap<ServiceDigest, ServerServiceConfig>>>,
|
services: Arc<RwLock<HashMap<ServiceDigest, ServerServiceConfig>>>,
|
||||||
control_channels: Arc<RwLock<ControlChannelMap<T>>>,
|
control_channels: Arc<RwLock<ControlChannelMap<T>>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -223,8 +222,7 @@ async fn handle_connection<T: 'static + Transport>(
|
||||||
let hello = read_hello(&mut conn).await?;
|
let hello = read_hello(&mut conn).await?;
|
||||||
match hello {
|
match hello {
|
||||||
ControlChannelHello(_, service_digest) => {
|
ControlChannelHello(_, service_digest) => {
|
||||||
do_control_channel_handshake(conn, addr, services, control_channels, service_digest)
|
do_control_channel_handshake(conn, services, control_channels, service_digest).await?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
DataChannelHello(_, nonce) => {
|
DataChannelHello(_, nonce) => {
|
||||||
do_data_channel_handshake(conn, control_channels, nonce).await?;
|
do_data_channel_handshake(conn, control_channels, nonce).await?;
|
||||||
|
@ -235,12 +233,11 @@ async fn handle_connection<T: 'static + Transport>(
|
||||||
|
|
||||||
async fn do_control_channel_handshake<T: 'static + Transport>(
|
async fn do_control_channel_handshake<T: 'static + Transport>(
|
||||||
mut conn: T::Stream,
|
mut conn: T::Stream,
|
||||||
addr: SocketAddr,
|
|
||||||
services: Arc<RwLock<HashMap<ServiceDigest, ServerServiceConfig>>>,
|
services: Arc<RwLock<HashMap<ServiceDigest, ServerServiceConfig>>>,
|
||||||
control_channels: Arc<RwLock<ControlChannelMap<T>>>,
|
control_channels: Arc<RwLock<ControlChannelMap<T>>>,
|
||||||
service_digest: ServiceDigest,
|
service_digest: ServiceDigest,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
info!("New control channel incomming from {}", addr);
|
info!("New control channel incoming");
|
||||||
|
|
||||||
// Generate a nonce
|
// Generate a nonce
|
||||||
let mut nonce = vec![0u8; HASH_WIDTH_IN_BYTES];
|
let mut nonce = vec![0u8; HASH_WIDTH_IN_BYTES];
|
||||||
|
@ -321,6 +318,8 @@ async fn do_data_channel_handshake<T: 'static + Transport>(
|
||||||
control_channels: Arc<RwLock<ControlChannelMap<T>>>,
|
control_channels: Arc<RwLock<ControlChannelMap<T>>>,
|
||||||
nonce: Nonce,
|
nonce: Nonce,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
info!("New control channel incoming");
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
let control_channels_guard = control_channels.read().await;
|
let control_channels_guard = control_channels.read().await;
|
||||||
match control_channels_guard.get2(&nonce) {
|
match control_channels_guard.get2(&nonce) {
|
||||||
|
@ -358,27 +357,6 @@ where
|
||||||
// Store data channel creation requests
|
// Store data channel creation requests
|
||||||
let (data_ch_req_tx, data_ch_req_rx) = mpsc::unbounded_channel();
|
let (data_ch_req_tx, data_ch_req_rx) = mpsc::unbounded_channel();
|
||||||
|
|
||||||
match service.service_type {
|
|
||||||
ServiceType::Tcp => tokio::spawn(
|
|
||||||
run_tcp_connection_pool::<T>(
|
|
||||||
service.bind_addr.clone(),
|
|
||||||
data_ch_rx,
|
|
||||||
data_ch_req_tx.clone(),
|
|
||||||
shutdown_tx.subscribe(),
|
|
||||||
)
|
|
||||||
.instrument(Span::current()),
|
|
||||||
),
|
|
||||||
ServiceType::Udp => tokio::spawn(
|
|
||||||
run_udp_connection_pool::<T>(
|
|
||||||
service.bind_addr.clone(),
|
|
||||||
data_ch_rx,
|
|
||||||
data_ch_req_tx.clone(),
|
|
||||||
shutdown_tx.subscribe(),
|
|
||||||
)
|
|
||||||
.instrument(Span::current()),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cache some data channels for later use
|
// Cache some data channels for later use
|
||||||
let pool_size = match service.service_type {
|
let pool_size = match service.service_type {
|
||||||
ServiceType::Tcp => TCP_POOL_SIZE,
|
ServiceType::Tcp => TCP_POOL_SIZE,
|
||||||
|
@ -391,6 +369,43 @@ where
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let shutdown_rx_clone = shutdown_tx.subscribe();
|
||||||
|
let bind_addr = service.bind_addr.clone();
|
||||||
|
match service.service_type {
|
||||||
|
ServiceType::Tcp => tokio::spawn(
|
||||||
|
async move {
|
||||||
|
if let Err(e) = run_tcp_connection_pool::<T>(
|
||||||
|
bind_addr,
|
||||||
|
data_ch_rx,
|
||||||
|
data_ch_req_tx,
|
||||||
|
shutdown_rx_clone,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.with_context(|| "Failed to run TCP connection pool")
|
||||||
|
{
|
||||||
|
error!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.instrument(Span::current()),
|
||||||
|
),
|
||||||
|
ServiceType::Udp => tokio::spawn(
|
||||||
|
async move {
|
||||||
|
if let Err(e) = run_udp_connection_pool::<T>(
|
||||||
|
bind_addr,
|
||||||
|
data_ch_rx,
|
||||||
|
data_ch_req_tx,
|
||||||
|
shutdown_rx_clone,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.with_context(|| "Failed to run TCP connection pool")
|
||||||
|
{
|
||||||
|
error!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.instrument(Span::current()),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
// Create the control channel
|
// Create the control channel
|
||||||
let ch = ControlChannel::<T> {
|
let ch = ControlChannel::<T> {
|
||||||
conn,
|
conn,
|
||||||
|
@ -568,7 +583,16 @@ async fn run_udp_connection_pool<T: Transport>(
|
||||||
// TODO: Load balance
|
// TODO: Load balance
|
||||||
|
|
||||||
let l: UdpSocket = backoff::future::retry(listen_backoff(), || async {
|
let l: UdpSocket = backoff::future::retry(listen_backoff(), || async {
|
||||||
Ok(UdpSocket::bind(&bind_addr).await?)
|
Ok(match UdpSocket::bind(&bind_addr)
|
||||||
|
.await
|
||||||
|
.with_context(|| "Failed to listen for the service")
|
||||||
|
{
|
||||||
|
Err(e) => {
|
||||||
|
error!("{:?}", e);
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
v => v,
|
||||||
|
}?)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.with_context(|| "Failed to listen for the service")?;
|
.with_context(|| "Failed to listen for the service")?;
|
||||||
|
@ -605,5 +629,7 @@ async fn run_udp_connection_pool<T: Transport>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("UDP pool dropped");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue