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 16:16:58 +02:00
committed by GitHub
parent 869e1b89f5
commit 6f3e708679
10 changed files with 370 additions and 5846 deletions
+40 -58
View File
@@ -6,6 +6,23 @@ use std::{
time::Duration,
};
use super::{
FromUrl, IpVersion, Tunnel, TunnelError, TunnelInfo, TunnelListener, TunnelUrl, ZCPacketSink,
ZCPacketStream,
common::wait_for_connect_futures,
generate_digest_from_str,
packet_def::{PEER_MANAGER_HEADER_SIZE, ZCPacketType},
ring::create_ring_tunnel_pair,
};
use crate::tunnel::common::{BindDev, bind};
use crate::{
common::shrink_dashmap,
tunnel::{
build_url_from_socket_addr,
common::TunnelWrapper,
packet_def::{WG_TUNNEL_HEADER_SIZE, ZCPacket},
},
};
use anyhow::Context;
use async_recursion::async_recursion;
use async_trait::async_trait;
@@ -20,23 +37,6 @@ use futures::{SinkExt, StreamExt, stream::FuturesUnordered};
use rand::RngCore;
use tokio::{net::UdpSocket, sync::Mutex, task::JoinSet};
use super::{
FromUrl, IpVersion, Tunnel, TunnelError, TunnelInfo, TunnelListener, TunnelUrl, ZCPacketSink,
ZCPacketStream,
common::{setup_socket2, setup_socket2_ext, wait_for_connect_futures},
generate_digest_from_str,
packet_def::{PEER_MANAGER_HEADER_SIZE, ZCPacketType},
ring::create_ring_tunnel_pair,
};
use crate::{
common::shrink_dashmap,
tunnel::{
build_url_from_socket_addr,
common::TunnelWrapper,
packet_def::{WG_TUNNEL_HEADER_SIZE, ZCPacket},
},
};
const MAX_PACKET: usize = 2048;
#[derive(Debug, Clone)]
@@ -555,20 +555,14 @@ impl WgTunnelListener {
impl TunnelListener for WgTunnelListener {
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.udp = Some(Arc::new(UdpSocket::from_std(socket2_socket.into())?));
self.udp = Some(Arc::new(
bind()
.addr(addr)
.only_v6(true)
.maybe_dev(tunnel_url.bind_dev())
.call()?,
));
self.addr
.set_port(Some(self.udp.as_ref().unwrap().local_addr()?.port()))
.unwrap();
@@ -695,13 +689,11 @@ impl WgTunnelConnector {
}
async fn connect_with_ipv6(&self, addr: SocketAddr) -> Result<Box<dyn Tunnel>, TunnelError> {
let socket2_socket = socket2::Socket::new(
socket2::Domain::for_address(addr),
socket2::Type::DGRAM,
Some(socket2::Protocol::UDP),
)?;
setup_socket2_ext(&socket2_socket, &"[::]:0".parse().unwrap(), None, true)?;
let socket = UdpSocket::from_std(socket2_socket.into())?;
let socket = bind()
.addr("[::]:0".parse().unwrap())
.dev(BindDev::Disabled)
.only_v6(true)
.call()?;
Self::connect_with_socket(self.addr.clone(), self.config.clone(), socket, addr).await
}
}
@@ -723,29 +715,19 @@ impl super::TunnelConnector for WgTunnelConnector {
};
let futures = FuturesUnordered::new();
for bind_addr in bind_addrs.into_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;
}
let socket = match UdpSocket::from_std(socket2_socket.into()) {
Ok(s) => s,
Err(e) => {
tracing::error!(bind_addr = ?bind_addr, ?addr, "create udp socket fail: {:?}", e);
tracing::info!(?bind_addr, ?addr, "bind addr");
match bind().addr(bind_addr).only_v6(true).call() {
Ok(socket) => futures.push(Self::connect_with_socket(
self.addr.clone(),
self.config.clone(),
socket,
addr,
)),
Err(error) => {
tracing::error!(?error, ?bind_addr, ?addr, "bind addr fail");
continue;
}
};
tracing::info!(?bind_addr, ?self.addr, "prepare wg connect task");
futures.push(Self::connect_with_socket(
self.addr.clone(),
self.config.clone(),
socket,
addr,
));
}
}
wait_for_connect_futures(futures).await