tunnel(bind): gather all bind logic to a single function (#2070)

* extract a Bindable trait for binding TcpSocket, TcpListener, and UdpSocket
This commit is contained in:
Luna Yao
2026-04-12 22:16:58 +08:00
committed by GitHub
parent 869e1b89f5
commit 6f3e708679
10 changed files with 370 additions and 5846 deletions
+22 -33
View File
@@ -18,16 +18,16 @@ use tokio::{
sync::mpsc::{Receiver, Sender, UnboundedReceiver, UnboundedSender},
task::JoinSet,
};
use tracing::{Instrument, instrument};
use super::{
FromUrl, IpVersion, Tunnel, TunnelConnCounter, TunnelError, TunnelInfo, TunnelListener,
TunnelUrl,
common::{setup_socket2, setup_socket2_ext, wait_for_connect_futures},
common::wait_for_connect_futures,
packet_def::{UDP_TUNNEL_HEADER_SIZE, UDPTunnelHeader, V6HolePunchPacket},
ring::{RingSink, RingStream},
};
use crate::tunnel::common::bind;
use crate::{
common::{join_joinset_background, scoped_task::ScopedTask, shrink_dashmap},
tunnel::{
@@ -536,21 +536,14 @@ impl UdpTunnelListener {
impl TunnelListener for UdpTunnelListener {
async fn listen(&mut self) -> Result<(), TunnelError> {
let addr = SocketAddr::from_url(self.addr.clone(), IpVersion::Both).await?;
let socket2_socket = socket2::Socket::new(
socket2::Domain::for_address(addr),
socket2::Type::DGRAM,
Some(socket2::Protocol::UDP),
)?;
let tunnel_url: TunnelUrl = self.addr.clone().into();
if let Some(bind_dev) = tunnel_url.bind_dev() {
setup_socket2_ext(&socket2_socket, &addr, Some(bind_dev), true)?;
} else {
setup_socket2(&socket2_socket, &addr, true)?;
}
self.socket = Some(Arc::new(UdpSocket::from_std(socket2_socket.into())?));
self.socket = Some(Arc::new(
bind()
.addr(addr)
.only_v6(true)
.maybe_dev(tunnel_url.bind_dev())
.call()?,
));
self.data.socket = self.socket.clone();
self.addr
@@ -833,17 +826,14 @@ impl UdpTunnelConnector {
let futures = FuturesUnordered::new();
for bind_addr in self.bind_addrs.iter() {
let socket2_socket = socket2::Socket::new(
socket2::Domain::for_address(*bind_addr),
socket2::Type::DGRAM,
Some(socket2::Protocol::UDP),
)?;
if let Err(e) = setup_socket2(&socket2_socket, bind_addr, true) {
tracing::error!(bind_addr = ?bind_addr, ?addr, "bind addr fail: {:?}", e);
continue;
tracing::info!(?bind_addr, ?addr, "bind addr");
match bind().addr(*bind_addr).only_v6(true).call() {
Ok(socket) => futures.push(self.try_connect_with_socket(Arc::new(socket), addr)),
Err(error) => {
tracing::error!(?error, ?bind_addr, ?addr, "bind addr fail");
continue;
}
}
let socket = UdpSocket::from_std(socket2_socket.into())?;
futures.push(self.try_connect_with_socket(Arc::new(socket), addr));
}
wait_for_connect_futures(futures).await
}
@@ -1034,13 +1024,12 @@ mod tests {
)
.await
.unwrap();
let socket2_socket = socket2::Socket::new(
socket2::Domain::for_address(addr),
socket2::Type::DGRAM,
Some(socket2::Protocol::UDP),
)
.unwrap();
setup_socket2_ext(&socket2_socket, &addr, bind_dev.clone(), true).unwrap();
let _ = bind::<UdpSocket>()
.addr(addr)
.maybe_dev(bind_dev.clone())
.only_v6(true)
.call()
.unwrap();
}
}