diff --git a/crates/shadowsocks-service/src/local/dns/server.rs b/crates/shadowsocks-service/src/local/dns/server.rs index 1ed89efd0c25..fdcf36968a41 100644 --- a/crates/shadowsocks-service/src/local/dns/server.rs +++ b/crates/shadowsocks-service/src/local/dns/server.rs @@ -32,8 +32,7 @@ use tokio::{ use shadowsocks::{ config::Mode, - lookup_then, - net::{TcpListener, UdpSocket as ShadowUdpSocket}, + net::TcpListener, relay::{udprelay::MAXIMUM_UDP_PAYLOAD_SIZE, Address}, ServerAddr, }; @@ -41,6 +40,7 @@ use shadowsocks::{ use crate::{ acl::AccessControl, local::{context::ServiceContext, loadbalancing::PingBalancer}, + net::listener::{create_standard_tcp_listener, create_standard_udp_listener}, }; use super::{client_cache::DnsClientCache, config::NameServerAddr}; @@ -213,34 +213,18 @@ impl DnsTcpServerBuilder { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; - let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name)?; - let tokio_listener = TokioTcpListener::from_std(std_listener)?; - TcpListener::from_listener(tokio_listener, self.context.accept_opts())? - } else { - match self.bind_addr { - ServerAddr::SocketAddr(ref saddr) => { - TcpListener::bind_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - TcpListener::bind_with_opts(&addr, self.context.accept_opts()).await - })? - .1 + match get_launch_activate_tcp_listener(&launchd_socket_name)? { + Some(std_listener) => { + let tokio_listener = TokioTcpListener::from_std(std_listener)?; + TcpListener::from_listener(tokio_listener, self.context.accept_opts())? } + None => create_standard_tcp_listener(&self.context, &self.bind_addr).await? } + } else { + create_standard_tcp_listener(&self.context, &self.bind_addr).await? }; } else { - let listener = match self.bind_addr { - ServerAddr::SocketAddr(ref saddr) => { - TcpListener::bind_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - TcpListener::bind_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; + let listener = create_standard_tcp_listener(&self.context, &self.bind_addr).await?; } } @@ -406,35 +390,15 @@ impl DnsUdpServerBuilder { use tokio::net::UdpSocket as TokioUdpSocket; use crate::net::launch_activate_socket::get_launch_activate_udp_socket; - let std_socket = get_launch_activate_udp_socket(&launchd_socket_name)?; - TokioUdpSocket::from_std(std_socket)? + match get_launch_activate_udp_socket(&launchd_socket_name)? { + Some(std_socket) => TokioUdpSocket::from_std(std_socket)?, + None => create_standard_udp_listener(&self.context, &self.bind_addr).await?.into() + } } else { - let shadow_socket = match self.bind_addr { - ServerAddr::SocketAddr(ref saddr) => { - ShadowUdpSocket::listen_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowUdpSocket::listen_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; - shadow_socket.into() + create_standard_udp_listener(&self.context, &self.bind_addr).await?.into() }; } else { - let shadow_socket = match self.bind_addr { - ServerAddr::SocketAddr(ref saddr) => { - ShadowUdpSocket::listen_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowUdpSocket::listen_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; - let socket = shadow_socket.into(); + let socket = create_standard_udp_listener(&self.context, &self.bind_addr).await?.into(); } } diff --git a/crates/shadowsocks-service/src/local/http/server.rs b/crates/shadowsocks-service/src/local/http/server.rs index 83aaec21d2ab..cd6c7fb60825 100644 --- a/crates/shadowsocks-service/src/local/http/server.rs +++ b/crates/shadowsocks-service/src/local/http/server.rs @@ -16,13 +16,16 @@ use hyper::{ Server, }; use log::{error, info}; -use shadowsocks::{config::ServerAddr, lookup_then, net::TcpListener}; - -use crate::local::{ - context::ServiceContext, - http::connector::Connector, - loadbalancing::PingBalancer, - LOCAL_DEFAULT_KEEPALIVE_TIMEOUT, +use shadowsocks::{config::ServerAddr, net::TcpListener}; + +use crate::{ + local::{ + context::ServiceContext, + http::connector::Connector, + loadbalancing::PingBalancer, + LOCAL_DEFAULT_KEEPALIVE_TIMEOUT, + }, + net::listener::create_standard_tcp_listener, }; use super::{client_cache::ProxyClientCache, dispatcher::HttpDispatcher}; @@ -71,26 +74,18 @@ impl HttpBuilder { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; - let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name)?; - let tokio_listener = TokioTcpListener::from_std(std_listener)?; - TcpListener::from_listener(tokio_listener, self.context.accept_opts())? + match get_launch_activate_tcp_listener(&launchd_socket_name)? { + Some(std_listener) => { + let tokio_listener = TokioTcpListener::from_std(std_listener)?; + TcpListener::from_listener(tokio_listener, self.context.accept_opts())? + } + None => create_standard_tcp_listener(&self.context, &self.client_config).await? + } } else { - match self.client_config { - ServerAddr::SocketAddr(sa) => TcpListener::bind_with_opts(&sa, self.context.accept_opts().clone()).await, - ServerAddr::DomainName(ref dname, port) => lookup_then!(self.context.context_ref(), dname, port, |addr| { - TcpListener::bind_with_opts(&addr, self.context.accept_opts().clone()).await - }) - .map(|(_, b)| b), - }? + create_standard_tcp_listener(&self.context, &self.client_config).await? }; } else { - let listener = match self.client_config { - ServerAddr::SocketAddr(sa) => TcpListener::bind_with_opts(&sa, self.context.accept_opts().clone()).await, - ServerAddr::DomainName(ref dname, port) => lookup_then!(self.context.context_ref(), dname, port, |addr| { - TcpListener::bind_with_opts(&addr, self.context.accept_opts().clone()).await - }) - .map(|(_, b)| b), - }?; + let listener = create_standard_tcp_listener(&self.context, &self.client_config).await?; } } diff --git a/crates/shadowsocks-service/src/local/socks/server/server.rs b/crates/shadowsocks-service/src/local/socks/server/server.rs index b7b43f1ceeb0..2ee21e115315 100644 --- a/crates/shadowsocks-service/src/local/socks/server/server.rs +++ b/crates/shadowsocks-service/src/local/socks/server/server.rs @@ -1,17 +1,18 @@ use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use log::{error, info}; -use shadowsocks::{config::Mode, lookup_then, net::TcpListener as ShadowTcpListener, ServerAddr}; +use shadowsocks::{config::Mode, net::TcpListener as ShadowTcpListener, ServerAddr}; use tokio::{net::TcpStream, time}; -use crate::local::{context::ServiceContext, loadbalancing::PingBalancer}; +use crate::{ + local::{context::ServiceContext, loadbalancing::PingBalancer, socks::config::Socks5AuthConfig}, + net::listener::create_standard_tcp_listener, +}; #[cfg(feature = "local-socks4")] use super::socks4::Socks4TcpHandler; use super::socks5::{Socks5TcpHandler, Socks5UdpServer}; -use crate::local::socks::config::Socks5AuthConfig; - pub struct SocksTcpServerBuilder { context: Arc, client_config: ServerAddr, @@ -57,34 +58,18 @@ impl SocksTcpServerBuilder { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; - let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name)?; - let tokio_listener = TokioTcpListener::from_std(std_listener)?; - ShadowTcpListener::from_listener(tokio_listener, self.context.accept_opts())? - } else { - match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowTcpListener::bind_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowTcpListener::bind_with_opts(&addr, self.context.accept_opts()).await - })? - .1 + match get_launch_activate_tcp_listener(&launchd_socket_name)? { + Some(std_listener) => { + let tokio_listener = TokioTcpListener::from_std(std_listener)?; + ShadowTcpListener::from_listener(tokio_listener, self.context.accept_opts())? } + None => create_standard_tcp_listener(&self.context, &self.client_config).await? } + } else { + create_standard_tcp_listener(&self.context, &self.client_config).await? }; } else { - let listener = match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowTcpListener::bind_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowTcpListener::bind_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; + let listener = create_standard_tcp_listener(&self.context, &self.client_config).await?; } } diff --git a/crates/shadowsocks-service/src/local/socks/server/socks5/udprelay.rs b/crates/shadowsocks-service/src/local/socks/server/socks5/udprelay.rs index 65917be9e610..14ce16fa5958 100644 --- a/crates/shadowsocks-service/src/local/socks/server/socks5/udprelay.rs +++ b/crates/shadowsocks-service/src/local/socks/server/socks5/udprelay.rs @@ -12,8 +12,6 @@ use byte_string::ByteStr; use bytes::{BufMut, BytesMut}; use log::{debug, error, info, trace}; use shadowsocks::{ - lookup_then, - net::UdpSocket as ShadowUdpSocket, relay::{ socks5::{Address, UdpAssociateHeader}, udprelay::MAXIMUM_UDP_PAYLOAD_SIZE, @@ -28,7 +26,7 @@ use crate::{ loadbalancing::PingBalancer, net::{UdpAssociationManager, UdpInboundWrite}, }, - net::utils::to_ipv4_mapped, + net::{listener::create_standard_udp_listener, utils::to_ipv4_mapped}, }; pub struct Socks5UdpServerBuilder { @@ -73,35 +71,15 @@ impl Socks5UdpServerBuilder { use tokio::net::UdpSocket as TokioUdpSocket; use crate::net::launch_activate_socket::get_launch_activate_udp_socket; - let std_socket = get_launch_activate_udp_socket(&launchd_socket_name)?; - TokioUdpSocket::from_std(std_socket)? + match get_launch_activate_udp_socket(&launchd_socket_name)? { + Some(std_socket) => TokioUdpSocket::from_std(std_socket)?, + None => create_standard_udp_listener(&self.context, &self.client_config).await?.into() + } } else { - let shadow_socket = match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowUdpSocket::listen_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowUdpSocket::listen_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; - shadow_socket.into() + create_standard_udp_listener(&self.context, &self.client_config).await?.into() }; } else { - let shadow_socket = match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowUdpSocket::listen_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowUdpSocket::listen_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; - let socket = shadow_socket.into(); + let socket = create_standard_udp_listener(&self.context, &self.client_config).await?.into(); } } diff --git a/crates/shadowsocks-service/src/local/tunnel/tcprelay.rs b/crates/shadowsocks-service/src/local/tunnel/tcprelay.rs index 44ef476b0fca..4bc49cd63391 100644 --- a/crates/shadowsocks-service/src/local/tunnel/tcprelay.rs +++ b/crates/shadowsocks-service/src/local/tunnel/tcprelay.rs @@ -3,14 +3,17 @@ use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use log::{error, info, trace}; -use shadowsocks::{lookup_then, net::TcpListener as ShadowTcpListener, relay::socks5::Address, ServerAddr}; +use shadowsocks::{net::TcpListener as ShadowTcpListener, relay::socks5::Address, ServerAddr}; use tokio::{net::TcpStream, time}; -use crate::local::{ - context::ServiceContext, - loadbalancing::PingBalancer, - net::AutoProxyClientStream, - utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, +use crate::{ + local::{ + context::ServiceContext, + loadbalancing::PingBalancer, + net::AutoProxyClientStream, + utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, + }, + net::listener::create_standard_tcp_listener, }; pub struct TunnelTcpServerBuilder { @@ -52,34 +55,18 @@ impl TunnelTcpServerBuilder { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; - let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name)?; - let tokio_listener = TokioTcpListener::from_std(std_listener)?; - ShadowTcpListener::from_listener(tokio_listener, self.context.accept_opts())? - } else { - match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowTcpListener::bind_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowTcpListener::bind_with_opts(&addr, self.context.accept_opts()).await - })? - .1 + match get_launch_activate_tcp_listener(&launchd_socket_name)? { + Some(std_listener) => { + let tokio_listener = TokioTcpListener::from_std(std_listener)?; + ShadowTcpListener::from_listener(tokio_listener, self.context.accept_opts())? } + None => create_standard_tcp_listener(&self.context, &self.client_config).await? } + } else { + create_standard_tcp_listener(&self.context, &self.client_config).await? }; } else { - let listener = match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowTcpListener::bind_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowTcpListener::bind_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; + let listener = create_standard_tcp_listener(&self.context, &self.client_config).await?; } } diff --git a/crates/shadowsocks-service/src/local/tunnel/udprelay.rs b/crates/shadowsocks-service/src/local/tunnel/udprelay.rs index aae9dd8c5783..a7f75b8c0e9a 100644 --- a/crates/shadowsocks-service/src/local/tunnel/udprelay.rs +++ b/crates/shadowsocks-service/src/local/tunnel/udprelay.rs @@ -5,17 +5,18 @@ use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use async_trait::async_trait; use log::{debug, error, info}; use shadowsocks::{ - lookup_then, - net::UdpSocket as ShadowUdpSocket, relay::{socks5::Address, udprelay::MAXIMUM_UDP_PAYLOAD_SIZE}, ServerAddr, }; use tokio::{net::UdpSocket, time}; -use crate::local::{ - context::ServiceContext, - loadbalancing::PingBalancer, - net::{UdpAssociationManager, UdpInboundWrite}, +use crate::{ + local::{ + context::ServiceContext, + loadbalancing::PingBalancer, + net::{UdpAssociationManager, UdpInboundWrite}, + }, + net::listener::create_standard_udp_listener, }; pub struct TunnelUdpServerBuilder { @@ -63,35 +64,15 @@ impl TunnelUdpServerBuilder { use tokio::net::UdpSocket as TokioUdpSocket; use crate::net::launch_activate_socket::get_launch_activate_udp_socket; - let std_socket = get_launch_activate_udp_socket(&launchd_socket_name)?; - TokioUdpSocket::from_std(std_socket)? + match get_launch_activate_udp_socket(&launchd_socket_name)? { + Some(std_socket) => TokioUdpSocket::from_std(std_socket)?, + None => create_standard_udp_listener(&self.context, &self.client_config).await?.into() + } } else { - let shadow_socket = match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowUdpSocket::listen_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowUdpSocket::listen_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; - shadow_socket.into() + create_standard_udp_listener(&self.context, &self.client_config).await?.into() }; } else { - let shadow_socket = match self.client_config { - ServerAddr::SocketAddr(ref saddr) => { - ShadowUdpSocket::listen_with_opts(saddr, self.context.accept_opts()).await? - } - ServerAddr::DomainName(ref dname, port) => { - lookup_then!(self.context.context_ref(), dname, port, |addr| { - ShadowUdpSocket::listen_with_opts(&addr, self.context.accept_opts()).await - })? - .1 - } - }; - let socket = shadow_socket.into(); + let socket = create_standard_udp_listener(&self.context, &self.client_config).await?.into(); } } diff --git a/crates/shadowsocks-service/src/net/launch_activate_socket.rs b/crates/shadowsocks-service/src/net/launch_activate_socket.rs index f39cbea23f88..9189025ce52b 100644 --- a/crates/shadowsocks-service/src/net/launch_activate_socket.rs +++ b/crates/shadowsocks-service/src/net/launch_activate_socket.rs @@ -13,14 +13,22 @@ use log::debug; use crate::sys::get_launch_activate_socket; -pub fn get_launch_activate_tcp_listener(name: &str) -> io::Result { - let fd = get_launch_activate_socket(name)?; - debug!("created TCP listener from launch activate socket {}", fd); - Ok(unsafe { TcpListener::from_raw_fd(fd) }) +pub fn get_launch_activate_tcp_listener(name: &str) -> io::Result> { + match get_launch_activate_socket(name)? { + Some(fd) => { + debug!("created TCP listener from launch activate socket {}", fd); + Ok(Some(unsafe { TcpListener::from_raw_fd(fd) })) + } + None => Ok(None), + } } -pub fn get_launch_activate_udp_socket(name: &str) -> io::Result { - let fd = get_launch_activate_socket(name)?; - debug!("created UDP socket from launch activate socket {}", fd); - Ok(unsafe { UdpSocket::from_raw_fd(fd) }) +pub fn get_launch_activate_udp_socket(name: &str) -> io::Result> { + match get_launch_activate_socket(name)? { + Some(fd) => { + debug!("created UDP socket from launch activate socket {}", fd); + Ok(Some(unsafe { UdpSocket::from_raw_fd(fd) })) + } + None => Ok(None), + } } diff --git a/crates/shadowsocks-service/src/net/listener.rs b/crates/shadowsocks-service/src/net/listener.rs new file mode 100644 index 000000000000..b86187d3b929 --- /dev/null +++ b/crates/shadowsocks-service/src/net/listener.rs @@ -0,0 +1,37 @@ +use std::io; + +use shadowsocks::{ + config::ServerAddr, + lookup_then, + net::{TcpListener, UdpSocket}, +}; + +use crate::local::context::ServiceContext; + +/// Create a standard TCP listener listening on `client_config` +pub async fn create_standard_tcp_listener( + context: &ServiceContext, + client_config: &ServerAddr, +) -> io::Result { + match client_config { + ServerAddr::SocketAddr(saddr) => TcpListener::bind_with_opts(saddr, context.accept_opts()).await, + ServerAddr::DomainName(dname, port) => lookup_then!(context.context_ref(), dname, *port, |addr| { + TcpListener::bind_with_opts(&addr, context.accept_opts()).await + }) + .map(|(_, l)| l), + } +} + +/// Create a standard UDP listener listening on `client_config` +pub async fn create_standard_udp_listener( + context: &ServiceContext, + client_config: &ServerAddr, +) -> io::Result { + match client_config { + ServerAddr::SocketAddr(saddr) => UdpSocket::listen_with_opts(saddr, context.accept_opts()).await, + ServerAddr::DomainName(dname, port) => lookup_then!(context.context_ref(), dname, *port, |addr| { + UdpSocket::listen_with_opts(&addr, context.accept_opts()).await + }) + .map(|(_, s)| s), + } +} diff --git a/crates/shadowsocks-service/src/net/mod.rs b/crates/shadowsocks-service/src/net/mod.rs index 44ea46cc9ef1..7b3c62d947e6 100644 --- a/crates/shadowsocks-service/src/net/mod.rs +++ b/crates/shadowsocks-service/src/net/mod.rs @@ -5,6 +5,7 @@ pub use self::{flow::FlowStat, mon_socket::MonProxySocket, mon_stream::MonProxyS pub mod flow; #[cfg(target_os = "macos")] pub mod launch_activate_socket; +pub mod listener; pub mod mon_socket; pub mod mon_stream; pub mod packet_window; diff --git a/crates/shadowsocks-service/src/sys/unix/macos.rs b/crates/shadowsocks-service/src/sys/unix/macos.rs index 4f8fc2f0e8a5..dc50e3ba80e0 100644 --- a/crates/shadowsocks-service/src/sys/unix/macos.rs +++ b/crates/shadowsocks-service/src/sys/unix/macos.rs @@ -2,7 +2,7 @@ use std::{ffi::CString, io, os::fd::RawFd, ptr}; -use log::error; +use log::{error, warn}; extern "C" { /// https://developer.apple.com/documentation/xpc/1505523-launch_activate_socket @@ -13,7 +13,7 @@ extern "C" { ) -> libc::c_int; } -pub fn get_launch_activate_socket(name: &str) -> io::Result { +pub fn get_launch_activate_socket(name: &str) -> io::Result> { let mut fds: *mut libc::c_int = ptr::null_mut(); let mut cnt: libc::size_t = 0; @@ -33,13 +33,18 @@ pub fn get_launch_activate_socket(name: &str) -> io::Result { let err = io::Error::last_os_error(); match err.raw_os_error() { Some(libc::ENOENT) => { - error!("activate socket name \"{}\" doesn't exist", name); + warn!("activate socket name \"{}\" doesn't exist, error: {}", name, err); + return Ok(None); } Some(libc::ESRCH) => { - error!("current process is not managed by launchd"); + warn!("current process is not managed by launchd, error: {}", err); + return Ok(None); } Some(libc::EALREADY) => { - error!("activate socket name \"{}\" has already been activated", name); + error!( + "activate socket name \"{}\" has already been activated, error: {}", + name, err + ); } _ => {} } @@ -49,10 +54,7 @@ pub fn get_launch_activate_socket(name: &str) -> io::Result { } let result = if cnt == 0 { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("could not find launch socket with name \"{}\"", name), - )) + Ok(None) } else if cnt > 1 { for idx in 0..cnt { unsafe { @@ -71,7 +73,7 @@ pub fn get_launch_activate_socket(name: &str) -> io::Result { } else { // Take fds[0] as the result let fd = unsafe { *fds }; - Ok(fd as RawFd) + Ok(Some(fd as RawFd)) }; if !fds.is_null() {