use std::{ net::{SocketAddr, SocketAddrV4, SocketAddrV6}, sync::Arc, }; #[cfg(feature = "quic")] use crate::tunnel::quic::QUICTunnelConnector; #[cfg(feature = "wireguard")] use crate::tunnel::wireguard::{WgConfig, WgTunnelConnector}; use crate::{ common::{error::Error, global_ctx::ArcGlobalCtx, network::IPCollector}, tunnel::{ check_scheme_and_get_socket_addr, ring::RingTunnelConnector, tcp::TcpTunnelConnector, udp::UdpTunnelConnector, TunnelConnector, }, }; pub mod direct; pub mod manual; pub mod udp_hole_punch; async fn set_bind_addr_for_peer_connector( connector: &mut (impl TunnelConnector + ?Sized), is_ipv4: bool, ip_collector: &Arc, ) { if cfg!(target_os = "android") { return; } let ips = ip_collector.collect_ip_addrs().await; if is_ipv4 { let mut bind_addrs = vec![]; for ipv4 in ips.interface_ipv4s { let socket_addr = SocketAddrV4::new(ipv4.into(), 0).into(); bind_addrs.push(socket_addr); } connector.set_bind_addrs(bind_addrs); } else { let mut bind_addrs = vec![]; for ipv6 in ips.interface_ipv6s { let socket_addr = SocketAddrV6::new(ipv6.into(), 0, 0, 0).into(); bind_addrs.push(socket_addr); } connector.set_bind_addrs(bind_addrs); } let _ = connector; } pub async fn create_connector_by_url( url: &str, global_ctx: &ArcGlobalCtx, ) -> Result, Error> { let url = url::Url::parse(url).map_err(|_| Error::InvalidUrl(url.to_owned()))?; match url.scheme() { "tcp" => { let dst_addr = check_scheme_and_get_socket_addr::(&url, "tcp")?; let mut connector = TcpTunnelConnector::new(url); set_bind_addr_for_peer_connector( &mut connector, dst_addr.is_ipv4(), &global_ctx.get_ip_collector(), ) .await; return Ok(Box::new(connector)); } "udp" => { let dst_addr = check_scheme_and_get_socket_addr::(&url, "udp")?; let mut connector = UdpTunnelConnector::new(url); set_bind_addr_for_peer_connector( &mut connector, dst_addr.is_ipv4(), &global_ctx.get_ip_collector(), ) .await; return Ok(Box::new(connector)); } "ring" => { check_scheme_and_get_socket_addr::(&url, "ring")?; let connector = RingTunnelConnector::new(url); return Ok(Box::new(connector)); } #[cfg(feature = "quic")] "quic" => { let dst_addr = check_scheme_and_get_socket_addr::(&url, "quic")?; let mut connector = QUICTunnelConnector::new(url); set_bind_addr_for_peer_connector( &mut connector, dst_addr.is_ipv4(), &global_ctx.get_ip_collector(), ) .await; return Ok(Box::new(connector)); } #[cfg(feature = "wireguard")] "wg" => { let dst_addr = check_scheme_and_get_socket_addr::(&url, "wg")?; let nid = global_ctx.get_network_identity(); let wg_config = WgConfig::new_from_network_identity( &nid.network_name, &nid.network_secret.unwrap_or_default(), ); let mut connector = WgTunnelConnector::new(url, wg_config); set_bind_addr_for_peer_connector( &mut connector, dst_addr.is_ipv4(), &global_ctx.get_ip_collector(), ) .await; return Ok(Box::new(connector)); } #[cfg(feature = "websocket")] "ws" | "wss" => { use crate::tunnel::{FromUrl, IpVersion}; let dst_addr = SocketAddr::from_url(url.clone(), IpVersion::Both)?; let mut connector = crate::tunnel::websocket::WSTunnelConnector::new(url); set_bind_addr_for_peer_connector( &mut connector, dst_addr.is_ipv4(), &global_ctx.get_ip_collector(), ) .await; return Ok(Box::new(connector)); } _ => { return Err(Error::InvalidUrl(url.into())); } } }