diff --git a/bin/ssurl.rs b/bin/ssurl.rs index fc19c467..d1662536 100644 --- a/bin/ssurl.rs +++ b/bin/ssurl.rs @@ -7,7 +7,7 @@ use clap::{Arg, ArgAction, Command, ValueHint}; use qrcode::{types::Color, QrCode}; use shadowsocks_service::{ - config::{Config, ConfigType}, + config::{Config, ConfigType, ServerInstanceConfig}, shadowsocks::config::ServerConfig, }; @@ -48,12 +48,12 @@ fn encode(filename: &str, need_qrcode: bool) { let config = Config::load_from_file(filename, ConfigType::Server).unwrap(); for svr in config.server { - let encoded = svr.to_url(); + let encoded = svr.config.to_url(); println!("{}", encoded); if need_qrcode { - let encoded = svr.to_qrcode_url(); + let encoded = svr.config.to_qrcode_url(); print_qrcode(&encoded); } } @@ -63,7 +63,7 @@ fn decode(encoded: &str, need_qrcode: bool) { let svrconfig = ServerConfig::from_url(encoded).unwrap(); let mut config = Config::new(ConfigType::Server); - config.server.push(svrconfig); + config.server.push(ServerInstanceConfig::with_server_config(svrconfig)); println!("{}", config); diff --git a/crates/shadowsocks-service/src/config.rs b/crates/shadowsocks-service/src/config.rs index c5aa49b6..83c95d8c 100644 --- a/crates/shadowsocks-service/src/config.rs +++ b/crates/shadowsocks-service/src/config.rs @@ -66,14 +66,7 @@ use serde::{Deserialize, Serialize}; use shadowsocks::relay::socks5::Address; use shadowsocks::{ config::{ - ManagerAddr, - Mode, - ReplayAttackPolicy, - ServerAddr, - ServerConfig, - ServerUser, - ServerUserManager, - ServerWeight, + ManagerAddr, Mode, ReplayAttackPolicy, ServerAddr, ServerConfig, ServerUser, ServerUserManager, ServerWeight, }, crypto::CipherKind, plugin::PluginConfig, @@ -272,6 +265,9 @@ struct SSLocalExtConfig { #[cfg(feature = "local")] #[serde(skip_serializing_if = "Option::is_none")] socks5_auth_config_path: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + acl: Option, } #[derive(Serialize, Deserialize, Debug)] @@ -322,6 +318,9 @@ struct SSServerExtConfig { tcp_weight: Option, #[serde(skip_serializing_if = "Option::is_none")] udp_weight: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + acl: Option, } /// Server config type @@ -1032,13 +1031,45 @@ pub enum LocalFlowStatAddress { TcpStreamAddr(SocketAddr), } +/// Server instance config +#[derive(Debug, Clone)] +pub struct ServerInstanceConfig { + /// Server's config + pub config: ServerConfig, + /// Server's private ACL, set to `None` will use the global `AccessControl` + pub acl: Option, +} + +impl ServerInstanceConfig { + /// Create with `ServerConfig` + pub fn with_server_config(config: ServerConfig) -> ServerInstanceConfig { + ServerInstanceConfig { config, acl: None } + } +} + +/// Local instance config +#[derive(Debug, Clone)] +pub struct LocalInstanceConfig { + /// Local server's config + pub config: LocalConfig, + /// Server's private ACL, set to `None` will use the global `AccessControl` + pub acl: Option, +} + +impl LocalInstanceConfig { + /// Create with `LocalConfig` + pub fn with_local_config(config: LocalConfig) -> LocalInstanceConfig { + LocalInstanceConfig { config, acl: None } + } +} + /// Configuration #[derive(Clone, Debug)] pub struct Config { /// Remote ShadowSocks server configurations - pub server: Vec, + pub server: Vec, /// Local server configuration - pub local: Vec, + pub local: Vec, /// DNS configuration, uses system-wide DNS configuration by default /// @@ -1106,7 +1137,9 @@ pub struct Config { /// Maximum number of UDP Associations, default is unconfigured pub udp_max_associations: Option, - /// ACL configuration + /// ACL configuration (Global) + /// + /// Could be overwritten by servers/locals' private `acl` pub acl: Option, /// Flow statistic report Unix socket path (only for Android) @@ -1325,7 +1358,13 @@ impl Config { } }, }; - nconfig.local.push(local_config); + + let local_instance = LocalInstanceConfig { + config: local_config, + acl: None, + }; + + nconfig.local.push(local_instance); } // Ext locals @@ -1491,7 +1530,27 @@ impl Config { local_config.socks5_auth = Socks5AuthConfig::load_from_file(&socks5_auth_config_path)?; } - nconfig.local.push(local_config); + let mut local_instance = LocalInstanceConfig { + config: local_config, + acl: None, + }; + + if let Some(acl_path) = local.acl { + let acl = match AccessControl::load_from_file(&acl_path) { + Ok(acl) => acl, + Err(err) => { + let err = Error::new( + ErrorKind::Invalid, + "acl loading failed", + Some(format!("file {}, error: {}", acl_path, err)), + ); + return Err(err); + } + }; + local_instance.acl = Some(acl); + } + + nconfig.local.push(local_instance); } } } @@ -1564,7 +1623,12 @@ impl Config { nsvr.set_timeout(timeout); } - nconfig.server.push(nsvr); + let server_instance = ServerInstanceConfig { + config: nsvr, + acl: None, + }; + + nconfig.server.push(server_instance); } (None, None, None, Some(_)) if config_type.is_manager() => { // Set the default method for manager @@ -1711,7 +1775,27 @@ impl Config { nsvr.set_weight(weight); } - nconfig.server.push(nsvr); + let mut server_instance = ServerInstanceConfig { + config: nsvr, + acl: None, + }; + + if let Some(acl_path) = svr.acl { + let acl = match AccessControl::load_from_file(&acl_path) { + Ok(acl) => acl, + Err(err) => { + let err = Error::new( + ErrorKind::Invalid, + "acl loading failed", + Some(format!("file {}, error: {}", acl_path, err)), + ); + return Err(err); + } + }; + server_instance.acl = Some(acl); + } + + nconfig.server.push(server_instance); } } @@ -1719,7 +1803,8 @@ impl Config { if let Some(timeout) = config.timeout { let timeout = Duration::from_secs(timeout); // Set as a default timeout - for svr in &mut nconfig.server { + for inst in &mut nconfig.server { + let svr = &mut inst.config; if svr.timeout().is_none() { svr.set_timeout(timeout); } @@ -2029,7 +2114,9 @@ impl Config { /// Check if there are any plugin are enabled with servers pub fn has_server_plugins(&self) -> bool { - for server in &self.server { + for inst in &self.server { + let server = &inst.config; + if server.plugin().is_some() { return true; } @@ -2050,7 +2137,7 @@ impl Config { } for local_config in &self.local { - local_config.check_integrity()?; + local_config.config.check_integrity()?; } // Balancer related checks @@ -2087,7 +2174,9 @@ impl Config { return Err(err); } - for server in &self.server { + for inst in &self.server { + let server = &inst.config; + // Plugin shouldn't be an empty string if let Some(plugin) = server.plugin() { if plugin.plugin.trim().is_empty() { @@ -2157,8 +2246,9 @@ impl fmt::Display for Config { // Locals if !self.local.is_empty() { - if self.local.len() == 1 && self.local[0].is_basic() { - let local = &self.local[0]; + if self.local.len() == 1 && self.local[0].config.is_basic() { + let local_instance = &self.local[0]; + let local = &local_instance.config; if let Some(ref a) = local.addr { jconf.local_address = Some(match a { ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(), @@ -2169,12 +2259,20 @@ impl fmt::Display for Config { ServerAddr::DomainName(.., port) => *port, }); } + if local.protocol != ProtocolType::Socks { jconf.protocol = Some(local.protocol.as_str().to_owned()); } + + // ACL + if let Some(ref acl) = local_instance.acl { + jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned()); + } } else { let mut jlocals = Vec::with_capacity(self.local.len()); - for local in &self.local { + for local_instance in &self.local { + let local = &local_instance.config; + let jlocal = SSLocalExtConfig { local_address: local.addr.as_ref().map(|a| match a { ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(), @@ -2275,6 +2373,11 @@ impl fmt::Display for Config { #[cfg(feature = "local")] socks5_auth_config_path: None, + + acl: local_instance + .acl + .as_ref() + .and_then(|a| a.file_path().to_str().map(ToOwned::to_owned)), }; jlocals.push(jlocal); } @@ -2286,8 +2389,9 @@ impl fmt::Display for Config { match self.server.len() { 0 => {} // For 1 server, uses standard configure format - 1 if self.server[0].is_basic() => { - let svr = &self.server[0]; + 1 if self.server[0].config.is_basic() => { + let inst = &self.server[0]; + let svr = &inst.config; jconf.server = Some(match *svr.addr() { ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(), @@ -2314,12 +2418,18 @@ impl fmt::Display for Config { }); jconf.timeout = svr.timeout().map(|t| t.as_secs()); jconf.mode = Some(svr.mode().to_string()); + + if let Some(ref acl) = inst.acl { + jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned()); + } } // For >1 servers, uses extended multiple server format _ => { let mut vsvr = Vec::new(); - for svr in &self.server { + for inst in &self.server { + let svr = &inst.config; + vsvr.push(SSServerExtConfig { server: match *svr.addr() { ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(), @@ -2369,6 +2479,10 @@ impl fmt::Display for Config { } else { None }, + acl: inst + .acl + .as_ref() + .and_then(|a| a.file_path().to_str().map(ToOwned::to_owned)), }); } diff --git a/crates/shadowsocks-service/src/local/context.rs b/crates/shadowsocks-service/src/local/context.rs index 5a7a7bd7..5eb542ab 100644 --- a/crates/shadowsocks-service/src/local/context.rs +++ b/crates/shadowsocks-service/src/local/context.rs @@ -19,20 +19,21 @@ use tokio::sync::Mutex; use crate::{acl::AccessControl, config::SecurityConfig, net::FlowStat}; /// Local Service Context +#[derive(Clone)] pub struct ServiceContext { context: SharedContext, connect_opts: ConnectOpts, accept_opts: AcceptOpts, // Access Control - acl: Option, + acl: Option>, // Flow statistic report flow_stat: Arc, // For DNS relay's ACL domain name reverse lookup -- whether the IP shall be forwarded #[cfg(feature = "local-dns")] - reverse_lookup_cache: Mutex>, + reverse_lookup_cache: Arc>>, } impl Default for ServiceContext { @@ -51,10 +52,10 @@ impl ServiceContext { acl: None, flow_stat: Arc::new(FlowStat::new()), #[cfg(feature = "local-dns")] - reverse_lookup_cache: Mutex::new(LruCache::with_expiry_duration_and_capacity( + reverse_lookup_cache: Arc::new(Mutex::new(LruCache::with_expiry_duration_and_capacity( Duration::from_secs(3 * 24 * 60 * 60), 10240, // XXX: It should be enough for a normal user. - )), + ))), } } @@ -89,13 +90,13 @@ impl ServiceContext { } /// Set Access Control List - pub fn set_acl(&mut self, acl: AccessControl) { + pub fn set_acl(&mut self, acl: Arc) { self.acl = Some(acl); } /// Get Access Control List reference pub fn acl(&self) -> Option<&AccessControl> { - self.acl.as_ref() + self.acl.as_deref() } /// Get cloned flow statistic diff --git a/crates/shadowsocks-service/src/local/mod.rs b/crates/shadowsocks-service/src/local/mod.rs index db8d99b8..703c714f 100644 --- a/crates/shadowsocks-service/src/local/mod.rs +++ b/crates/shadowsocks-service/src/local/mod.rs @@ -109,7 +109,9 @@ pub async fn create(config: Config) -> io::Result { // Warning for Stream Ciphers #[cfg(feature = "stream-cipher")] - for server in config.server.iter() { + for inst in config.server.iter() { + let server = &inst.config; + if server.method().is_stream() { log::warn!("stream cipher {} for server {} have inherent weaknesses (see discussion in https://github.com/shadowsocks/shadowsocks-org/issues/36). \ DO NOT USE. It will be removed in the future.", server.method(), server.addr()); @@ -124,6 +126,8 @@ pub async fn create(config: Config) -> io::Result { } } + // Global ServiceContext template + // Each Local instance will hold a copy of its fields let mut context = ServiceContext::new(); let mut connect_opts = ConnectOpts { @@ -165,15 +169,13 @@ pub async fn create(config: Config) -> io::Result { } if let Some(acl) = config.acl { - context.set_acl(acl); + context.set_acl(Arc::new(acl)); } context.set_security_config(&config.security); assert!(!config.local.is_empty(), "no valid local server configuration"); - let context = Arc::new(context); - let mut vfut = Vec::new(); // Create a service balancer for choosing between multiple servers @@ -181,10 +183,11 @@ pub async fn create(config: Config) -> io::Result { let mut mode = Mode::TcpOnly; for local in &config.local { - mode = mode.merge(local.mode); + mode = mode.merge(local.config.mode); } - let mut balancer_builder = PingBalancerBuilder::new(context.clone(), mode); + // Load balancer will hold an individual ServiceContext + let mut balancer_builder = PingBalancerBuilder::new(Arc::new(context.clone()), mode); // max_server_rtt have to be set before add_server if let Some(rtt) = config.balancer.max_server_rtt { @@ -200,7 +203,7 @@ pub async fn create(config: Config) -> io::Result { } for server in config.server { - balancer_builder.add_server(server); + balancer_builder.add_server(server.config); } balancer_builder.build().await? @@ -214,7 +217,19 @@ pub async fn create(config: Config) -> io::Result { vfut.push(ServerHandle(tokio::spawn(report_fut))); } - for local_config in config.local { + for local_instance in config.local { + let local_config = local_instance.config; + + // Clone from global ServiceContext instance + // It will shares Shadowsocks' global context, and FlowStat, DNS reverse cache + let mut context = context.clone(); + + // Private ACL + if let Some(acl) = local_instance.acl { + context.set_acl(Arc::new(acl)) + } + + let context = Arc::new(context); let balancer = balancer.clone(); match local_config.protocol { diff --git a/crates/shadowsocks-service/src/manager/mod.rs b/crates/shadowsocks-service/src/manager/mod.rs index 4d417787..8bc66ada 100644 --- a/crates/shadowsocks-service/src/manager/mod.rs +++ b/crates/shadowsocks-service/src/manager/mod.rs @@ -81,8 +81,8 @@ pub async fn run(config: Config) -> io::Result<()> { manager.set_acl(Arc::new(acl)); } - for svr_cfg in config.server { - manager.add_server(svr_cfg).await; + for svr_inst in config.server { + manager.add_server(svr_inst.config).await; } manager.run().await diff --git a/crates/shadowsocks-service/src/manager/server.rs b/crates/shadowsocks-service/src/manager/server.rs index fc13f569..af5ef3a6 100644 --- a/crates/shadowsocks-service/src/manager/server.rs +++ b/crates/shadowsocks-service/src/manager/server.rs @@ -11,22 +11,12 @@ use shadowsocks::{ crypto::CipherKind, dns_resolver::DnsResolver, manager::protocol::{ - self, - AddRequest, - AddResponse, - ErrorResponse, - ListResponse, - ManagerRequest, - PingResponse, - RemoveRequest, - RemoveResponse, - ServerUserConfig, - StatRequest, + self, AddRequest, AddResponse, ErrorResponse, ListResponse, ManagerRequest, PingResponse, RemoveRequest, + RemoveResponse, ServerUserConfig, StatRequest, }, net::{AcceptOpts, ConnectOpts}, plugin::PluginConfig, - ManagerListener, - ServerAddr, + ManagerListener, ServerAddr, }; use tokio::{sync::Mutex, task::JoinHandle}; @@ -332,7 +322,7 @@ impl Manager { use tokio::process::Command; - use crate::config::{Config, ConfigType}; + use crate::config::{Config, ConfigType, ServerInstanceConfig}; // Lock the map first incase there are multiple requests to create one server instance let mut servers = self.servers.lock().await; @@ -351,8 +341,13 @@ impl Manager { let config_file_path = self.server_config_path(port); let pid_path = self.server_pid_path(port); + let server_instance = ServerInstanceConfig { + config: svr_cfg.clone(), + acl: None, // Set with --acl command line argument + }; + let mut config = Config::new(ConfigType::Server); - config.server.push(svr_cfg.clone()); + config.server.push(server_instance); trace!("created standalone server with config {:?}", config); @@ -618,7 +613,7 @@ impl Manager { continue; } - let svr_cfg = config.server[0].clone(); + let svr_cfg = config.server[0].config.clone(); vac.insert(ServerInstance { mode: ServerInstanceMode::Standalone { flow_stat: *flow }, diff --git a/crates/shadowsocks-service/src/server/context.rs b/crates/shadowsocks-service/src/server/context.rs index f4ce9d23..0a89fde1 100644 --- a/crates/shadowsocks-service/src/server/context.rs +++ b/crates/shadowsocks-service/src/server/context.rs @@ -13,6 +13,7 @@ use shadowsocks::{ use crate::{acl::AccessControl, config::SecurityConfig, net::FlowStat}; /// Server Service Context +#[derive(Clone)] pub struct ServiceContext { context: SharedContext, connect_opts: ConnectOpts, diff --git a/crates/shadowsocks-service/src/server/mod.rs b/crates/shadowsocks-service/src/server/mod.rs index e5dd8bcd..e0a6b136 100644 --- a/crates/shadowsocks-service/src/server/mod.rs +++ b/crates/shadowsocks-service/src/server/mod.rs @@ -41,7 +41,9 @@ pub async fn run(config: Config) -> io::Result<()> { // Warning for Stream Ciphers #[cfg(feature = "stream-cipher")] - for server in config.server.iter() { + for inst in config.server.iter() { + let server = &inst.config; + if server.method().is_stream() { log::warn!("stream cipher {} for server {} have inherent weaknesses (see discussion in https://github.com/shadowsocks/shadowsocks-org/issues/36). \ DO NOT USE. It will be removed in the future.", server.method(), server.addr()); @@ -93,7 +95,8 @@ pub async fn run(config: Config) -> io::Result<()> { let acl = config.acl.map(Arc::new); - for svr_cfg in config.server { + for inst in config.server { + let svr_cfg = inst.config; let mut server = Server::new(svr_cfg); if let Some(ref r) = resolver { @@ -113,8 +116,13 @@ pub async fn run(config: Config) -> io::Result<()> { server.set_manager_addr(m.addr.clone()); } - if let Some(ref acl) = acl { - server.set_acl(acl.clone()); + match inst.acl { + Some(acl) => server.set_acl(Arc::new(acl)), + None => { + if let Some(ref acl) = acl { + server.set_acl(acl.clone()); + } + } } if config.ipv6_first { diff --git a/src/service/local.rs b/src/service/local.rs index 77928326..19497dca 100644 --- a/src/service/local.rs +++ b/src/service/local.rs @@ -13,7 +13,10 @@ use shadowsocks_service::config::RedirType; use shadowsocks_service::shadowsocks::relay::socks5::Address; use shadowsocks_service::{ acl::AccessControl, - config::{read_variable_field_value, Config, ConfigType, LocalConfig, ProtocolType}, + config::{ + read_variable_field_value, Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, + ServerInstanceConfig, + }, create_local, local::loadbalancing::PingBalancer, shadowsocks::{ @@ -27,8 +30,7 @@ use shadowsocks_service::{ use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, - monitor, - vparser, + monitor, vparser, }; #[cfg(feature = "local-dns")] @@ -571,11 +573,11 @@ pub fn main(matches: &ArgMatches) -> ExitCode { sc.set_plugin(plugin); } - config.server.push(sc); + config.server.push(ServerInstanceConfig::with_server_config(sc)); } if let Some(svr_addr) = matches.get_one::("URL").cloned() { - config.server.push(svr_addr); + config.server.push(ServerInstanceConfig::with_server_config(svr_addr)); } #[cfg(feature = "local-flow-stat")] @@ -710,7 +712,7 @@ pub fn main(matches: &ArgMatches) -> ExitCode { local_config.mode = Mode::TcpAndUdp; } - config.local.push(local_config); + config.local.push(LocalInstanceConfig::with_local_config(local_config)); } if matches.get_flag("TCP_NO_DELAY") { @@ -888,7 +890,7 @@ fn launch_reload_server_task(config_path: PathBuf, balancer: PingBalancer) { } }; - let servers = config.server; + let servers: Vec = config.server.into_iter().map(|s| s.config).collect(); info!("auto-reload {} with {} servers", config_path.display(), servers.len()); if let Err(err) = balancer.reset_servers(servers).await { diff --git a/src/service/server.rs b/src/service/server.rs index 45b6eb79..c06b5973 100644 --- a/src/service/server.rs +++ b/src/service/server.rs @@ -9,7 +9,7 @@ use tokio::{self, runtime::Builder}; use shadowsocks_service::{ acl::AccessControl, - config::{read_variable_field_value, Config, ConfigType, ManagerConfig}, + config::{read_variable_field_value, Config, ConfigType, ManagerConfig, ServerInstanceConfig}, run_server, shadowsocks::{ config::{ManagerAddr, Mode, ServerAddr, ServerConfig}, @@ -22,8 +22,7 @@ use shadowsocks_service::{ use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, - monitor, - vparser, + monitor, vparser, }; /// Defines command line options @@ -369,7 +368,7 @@ pub fn main(matches: &ArgMatches) -> ExitCode { sc.set_mode(Mode::TcpAndUdp); } - config.server.push(sc); + config.server.push(ServerInstanceConfig::with_server_config(sc)); } if matches.get_flag("TCP_NO_DELAY") { diff --git a/tests/socks4.rs b/tests/socks4.rs index 326a08ff..dcd60f95 100644 --- a/tests/socks4.rs +++ b/tests/socks4.rs @@ -11,10 +11,9 @@ use tokio::{ }; use shadowsocks_service::{ - config::{Config, ConfigType, LocalConfig, ProtocolType}, + config::{Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig}, local::socks::client::Socks4TcpClient, - run_local, - run_server, + run_local, run_server, shadowsocks::{ config::{ServerAddr, ServerConfig}, crypto::CipherKind, @@ -40,16 +39,24 @@ impl Socks4TestServer { local_addr, svr_config: { let mut cfg = Config::new(ConfigType::Server); - cfg.server = vec![ServerConfig::new(svr_addr, pwd.to_owned(), method)]; + cfg.server = vec![ServerInstanceConfig::with_server_config(ServerConfig::new( + svr_addr, + pwd.to_owned(), + method, + ))]; cfg }, cli_config: { let mut cfg = Config::new(ConfigType::Local); - cfg.local = vec![LocalConfig::new_with_addr( + cfg.local = vec![LocalInstanceConfig::with_local_config(LocalConfig::new_with_addr( ServerAddr::from(local_addr), ProtocolType::Socks, - )]; - cfg.server = vec![ServerConfig::new(svr_addr, pwd.to_owned(), method)]; + ))]; + cfg.server = vec![ServerInstanceConfig::with_server_config(ServerConfig::new( + svr_addr, + pwd.to_owned(), + method, + ))]; cfg }, } diff --git a/tests/socks5.rs b/tests/socks5.rs index f6357b73..61abc17f 100644 --- a/tests/socks5.rs +++ b/tests/socks5.rs @@ -11,10 +11,9 @@ use tokio::{ }; use shadowsocks_service::{ - config::{Config, ConfigType, LocalConfig, ProtocolType}, + config::{Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig}, local::socks::client::socks5::Socks5TcpClient, - run_local, - run_server, + run_local, run_server, shadowsocks::{ config::{Mode, ServerAddr, ServerConfig}, crypto::CipherKind, @@ -41,18 +40,28 @@ impl Socks5TestServer { local_addr, svr_config: { let mut cfg = Config::new(ConfigType::Server); - cfg.server = vec![ServerConfig::new(svr_addr, pwd.to_owned(), method)]; - cfg.server[0].set_mode(if enable_udp { Mode::TcpAndUdp } else { Mode::TcpOnly }); + cfg.server = vec![ServerInstanceConfig::with_server_config(ServerConfig::new( + svr_addr, + pwd.to_owned(), + method, + ))]; + cfg.server[0] + .config + .set_mode(if enable_udp { Mode::TcpAndUdp } else { Mode::TcpOnly }); cfg }, cli_config: { let mut cfg = Config::new(ConfigType::Local); - cfg.local = vec![LocalConfig::new_with_addr( + cfg.local = vec![LocalInstanceConfig::with_local_config(LocalConfig::new_with_addr( ServerAddr::from(local_addr), ProtocolType::Socks, - )]; - cfg.local[0].mode = if enable_udp { Mode::TcpAndUdp } else { Mode::TcpOnly }; - cfg.server = vec![ServerConfig::new(svr_addr, pwd.to_owned(), method)]; + ))]; + cfg.local[0].config.mode = if enable_udp { Mode::TcpAndUdp } else { Mode::TcpOnly }; + cfg.server = vec![ServerInstanceConfig::with_server_config(ServerConfig::new( + svr_addr, + pwd.to_owned(), + method, + ))]; cfg }, } diff --git a/tests/udp.rs b/tests/udp.rs index a12515d9..dba2bcab 100644 --- a/tests/udp.rs +++ b/tests/udp.rs @@ -7,10 +7,9 @@ use log::debug; use tokio::time::{self, Duration}; use shadowsocks_service::{ - config::{Config, ConfigType, LocalConfig, ProtocolType}, + config::{Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig}, local::socks::client::socks5::Socks5UdpClient, - run_local, - run_server, + run_local, run_server, shadowsocks::{config::Mode, crypto::CipherKind, relay::socks5::Address, ServerConfig}, }; @@ -24,27 +23,27 @@ const METHOD: CipherKind = CipherKind::AES_128_GCM; fn get_svr_config() -> Config { let mut cfg = Config::new(ConfigType::Server); - cfg.server = vec![ServerConfig::new( + cfg.server = vec![ServerInstanceConfig::with_server_config(ServerConfig::new( SERVER_ADDR.parse::().unwrap(), PASSWORD.to_owned(), METHOD, - )]; - cfg.server[0].set_mode(Mode::TcpAndUdp); + ))]; + cfg.server[0].config.set_mode(Mode::TcpAndUdp); cfg } fn get_cli_config() -> Config { let mut cfg = Config::new(ConfigType::Local); - cfg.local = vec![LocalConfig::new_with_addr( + cfg.local = vec![LocalInstanceConfig::with_local_config(LocalConfig::new_with_addr( LOCAL_ADDR.parse().unwrap(), ProtocolType::Socks, - )]; - cfg.local[0].mode = Mode::TcpAndUdp; - cfg.server = vec![ServerConfig::new( + ))]; + cfg.local[0].config.mode = Mode::TcpAndUdp; + cfg.server = vec![ServerInstanceConfig::with_server_config(ServerConfig::new( SERVER_ADDR.parse::().unwrap(), PASSWORD.to_owned(), METHOD, - )]; + ))]; cfg }