refactored command line options getter with clap::value_t!

This commit is contained in:
zonyitoo
2021-11-25 20:21:50 +08:00
parent 0b5933b4b6
commit 11262f5f99
6 changed files with 315 additions and 205 deletions
Generated
+1 -1
View File
@@ -1694,7 +1694,7 @@ dependencies = [
[[package]]
name = "shadowsocks-service"
version = "1.12.1"
version = "1.12.2"
dependencies = [
"arc-swap 1.5.0",
"async-trait",
+146 -106
View File
@@ -6,7 +6,7 @@
use std::{net::IpAddr, path::PathBuf, process, time::Duration};
use clap::{clap_app, Arg, Error as ClapError, ErrorKind as ClapErrorKind};
use clap::{clap_app, Arg, ErrorKind as ClapErrorKind};
use futures::future::{self, Either};
use log::info;
use tokio::{self, runtime::Builder};
@@ -50,7 +50,7 @@ fn main() {
(@arg PROTOCOL: --protocol +takes_value possible_values(ProtocolType::available_protocols()) "Protocol for communicating with clients (SOCKS5 by default)")
(@arg UDP_BIND_ADDR: --("udp-bind-addr") +takes_value requires[LOCAL_ADDR] {validator::validate_server_addr} "UDP relay's bind address, default is the same as local-addr")
(@arg SERVER_ADDR: -s --("server-addr") +takes_value {validator::validate_server_addr} requires[PASSWORD ENCRYPT_METHOD] "Server address")
(@arg SERVER_ADDR: -s --("server-addr") +takes_value {validator::validate_server_addr} requires[ENCRYPT_METHOD] "Server address")
(@arg PASSWORD: -k --password +takes_value requires[SERVER_ADDR] "Server's password")
(@arg ENCRYPT_METHOD: -m --("encrypt-method") +takes_value requires[SERVER_ADDR] possible_values(available_ciphers()) "Server's encryption method")
(@arg TIMEOUT: --timeout +takes_value {validator::validate_u64} requires[SERVER_ADDR] "Server's timeout seconds for TCP relay")
@@ -227,30 +227,25 @@ fn main() {
};
if let Some(svr_addr) = matches.value_of("SERVER_ADDR") {
let password = match matches.value_of("PASSWORD") {
Some(pwd) => pwd.to_owned(),
None => {
let password = match clap::value_t!(matches.value_of("PASSWORD"), String) {
Ok(pwd) => pwd.to_owned(),
Err(err) => {
// NOTE: svr_addr should have been checked by common::validator
match common::password::read_server_password(svr_addr) {
Ok(pwd) => pwd,
Err(..) => {
panic!("missing server's password");
}
Err(..) => err.exit(),
}
}
};
let method = matches
.value_of("ENCRYPT_METHOD")
.expect("encrypt-method")
.parse::<CipherKind>()
.expect("encryption method");
let method = clap::value_t_or_exit!(matches.value_of("ENCRYPT_METHOD"), CipherKind);
let svr_addr = svr_addr.parse::<ServerAddr>().expect("server-addr");
let timeout = matches
.value_of("TIMEOUT")
.map(|t| t.parse::<u64>().expect("timeout"))
.map(Duration::from_secs);
let timeout = match clap::value_t!(matches.value_of("TIMEOUT"), u64) {
Ok(t) => Some(Duration::from_secs(t)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => None,
Err(err) => err.exit(),
};
let mut sc = ServerConfig::new(svr_addr, password, method);
if let Some(timeout) = timeout {
@@ -270,9 +265,10 @@ fn main() {
config.server.push(sc);
}
if let Some(url) = matches.value_of("URL") {
let svr_addr = url.parse::<ServerConfig>().expect("server SIP002 url");
config.server.push(svr_addr);
match clap::value_t!(matches.value_of("URL"), ServerConfig) {
Ok(svr_addr) => config.server.push(svr_addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(feature = "local-flow-stat")]
@@ -307,76 +303,89 @@ fn main() {
};
let mut local_config = LocalConfig::new(protocol);
match (protocol, matches.value_of("LOCAL_ADDR")) {
#[cfg(feature = "local-tun")]
(ProtocolType::Tun, local_addr_opt) => {
if let Some(local_addr) = local_addr_opt {
local_config.addr = Some(local_addr.parse::<ServerAddr>().expect("local bind addr"));
match clap::value_t!(matches.value_of("LOCAL_ADDR"), ServerAddr) {
Ok(local_addr) => local_config.addr = Some(local_addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound =>
{
#[cfg(feature = "local-tun")]
if protocol == ProtocolType::Tun {
err.exit();
}
}
(_, None) => {
ClapError::with_description(
format!("Protocol \"{}\" requires local-addr", protocol.as_str()).as_str(),
ClapErrorKind::ArgumentNotFound,
)
.exit();
}
(_, Some(local_addr)) => {
local_config.addr = Some(local_addr.parse::<ServerAddr>().expect("local bind addr"));
}
Err(err) => err.exit(),
}
if let Some(udp_bind_addr) = matches.value_of("UDP_BIND_ADDR") {
local_config.udp_addr = Some(udp_bind_addr.parse::<ServerAddr>().expect("udp-bind-addr"));
match clap::value_t!(matches.value_of("UDP_BIND_ADDR"), ServerAddr) {
Ok(udp_bind_addr) => local_config.udp_addr = Some(udp_bind_addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(feature = "local-tunnel")]
if let Some(faddr) = matches.value_of("FORWARD_ADDR") {
let addr = faddr.parse::<Address>().expect("forward-addr");
local_config.forward_addr = Some(addr);
match clap::value_t!(matches.value_of("FORWARD_ADDR"), Address) {
Ok(addr) => local_config.forward_addr = Some(addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(feature = "local-redir")]
{
if let Some(tcp_redir) = matches.value_of("TCP_REDIR") {
local_config.tcp_redir = tcp_redir.parse::<RedirType>().expect("TCP redir type");
match clap::value_t!(matches.value_of("TCP_REDIR"), RedirType) {
Ok(tcp_redir) => local_config.tcp_redir = tcp_redir,
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(udp_redir) = matches.value_of("UDP_REDIR") {
local_config.udp_redir = udp_redir.parse::<RedirType>().expect("UDP redir type");
match clap::value_t!(matches.value_of("UDP_REDIR"), RedirType) {
Ok(udp_redir) => local_config.udp_redir = udp_redir,
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
}
#[cfg(feature = "local-dns")]
{
use shadowsocks_service::{local::dns::NameServerAddr, shadowsocks::relay::socks5::AddressError};
use std::net::SocketAddr;
use std::{net::SocketAddr, str::FromStr};
#[inline]
fn parse_remote_dns_addr(a: &str) -> Result<Address, AddressError> {
if let Ok(ip) = a.parse::<IpAddr>() {
return Ok(Address::SocketAddress(SocketAddr::new(ip, 53)));
}
struct RemoteDnsAddress(Address);
if let Ok(saddr) = a.parse::<SocketAddr>() {
return Ok(Address::SocketAddress(saddr));
}
impl FromStr for RemoteDnsAddress {
type Err = AddressError;
if a.find(':').is_some() {
a.parse::<Address>()
} else {
Ok(Address::DomainNameAddress(a.to_owned(), 53))
fn from_str(a: &str) -> Result<RemoteDnsAddress, Self::Err> {
if let Ok(ip) = a.parse::<IpAddr>() {
return Ok(Address::SocketAddress(SocketAddr::new(ip, 53)).into());
}
if let Ok(saddr) = a.parse::<SocketAddr>() {
return Ok(Address::SocketAddress(saddr).into());
}
if a.find(':').is_some() {
a.parse::<Address>().map(Into::into)
} else {
Ok(Address::DomainNameAddress(a.to_owned(), 53).into())
}
}
}
if let Some(local_dns_addr) = matches.value_of("LOCAL_DNS_ADDR") {
let addr = local_dns_addr.parse::<NameServerAddr>().expect("local dns address");
local_config.local_dns_addr = Some(addr);
impl Into<RemoteDnsAddress> for Address {
fn into(self) -> RemoteDnsAddress {
RemoteDnsAddress(self)
}
}
if let Some(remote_dns_addr) = matches.value_of("REMOTE_DNS_ADDR") {
let addr = parse_remote_dns_addr(remote_dns_addr).expect("remote dns address");
local_config.remote_dns_addr = Some(addr);
match clap::value_t!(matches.value_of("LOCAL_DNS_ADDR"), NameServerAddr) {
Ok(addr) => local_config.local_dns_addr = Some(addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
match clap::value_t!(matches.value_of("REMOTE_DNS_ADDR"), RemoteDnsAddress) {
Ok(addr) => local_config.remote_dns_addr = Some(addr.0),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
}
@@ -385,31 +394,41 @@ fn main() {
// Start a DNS local server binding to DNS_LOCAL_ADDR
//
// This is a special route only for shadowsocks-android
if let Some(dns_relay_addr) = matches.value_of("DNS_LOCAL_ADDR") {
let addr = dns_relay_addr.parse::<ServerAddr>().expect("dns relay address");
match clap::value_t!(matches.value_of("DNS_LOCAL_ADDR"), ServerAddr) {
Ok(addr) => {
let mut local_dns_config = LocalConfig::new_with_addr(addr, ProtocolType::Dns);
let mut local_dns_config = LocalConfig::new_with_addr(addr, ProtocolType::Dns);
// The `local_dns_addr` and `remote_dns_addr` are for this DNS server (for compatibility)
local_dns_config.local_dns_addr = local_config.local_dns_addr.take();
local_dns_config.remote_dns_addr = local_config.remote_dns_addr.take();
// The `local_dns_addr` and `remote_dns_addr` are for this DNS server (for compatibility)
local_dns_config.local_dns_addr = local_config.local_dns_addr.take();
local_dns_config.remote_dns_addr = local_config.remote_dns_addr.take();
config.local.push(local_dns_config);
config.local.push(local_dns_config);
}
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
}
#[cfg(feature = "local-tun")]
{
if let Some(tun_address) = matches.value_of("TUN_INTERFACE_ADDRESS") {
local_config.tun_interface_address = Some(tun_address.parse().expect("tun-interface-address"));
use ipnet::IpNet;
match clap::value_t!(matches.value_of("TUN_INTERFACE_ADDRESS"), IpNet) {
Ok(tun_address) => local_config.tun_interface_address = Some(tun_address),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(tun_name) = matches.value_of("TUN_INTERFACE_NAME") {
local_config.tun_interface_name = Some(tun_name.to_owned());
match clap::value_t!(matches.value_of("TUN_INTERFACE_NAME"), String) {
Ok(tun_name) => local_config.tun_interface_name = Some(tun_name),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(unix)]
if let Some(fd_path) = matches.value_of("TUN_DEVICE_FD_FROM_PATH") {
local_config.tun_device_fd_from_path = Some(fd_path.into());
match clap::value_t!(matches.value_of("TUN_DEVICE_FD_FROM_PATH"), PathBuf) {
Ok(fd_path) => local_config.tun_device_fd_from_path = Some(fd_path),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
}
@@ -432,26 +451,30 @@ fn main() {
config.fast_open = true;
}
if let Some(keep_alive) = matches.value_of("TCP_KEEP_ALIVE") {
config.keep_alive = Some(Duration::from_secs(
keep_alive
.parse::<u64>()
.expect("`tcp-keep-alive` is expecting an integer"),
));
match clap::value_t!(matches.value_of("TCP_KEEP_ALIVE"), u64) {
Ok(keep_alive) => config.keep_alive = Some(Duration::from_secs(keep_alive)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(any(target_os = "linux", target_os = "android"))]
if let Some(mark) = matches.value_of("OUTBOUND_FWMARK") {
config.outbound_fwmark = Some(mark.parse::<u32>().expect("an unsigned integer for `outbound-fwmark`"));
match clap::value_t!(matches.value_of("OUTBOUND_FWMARK"), u32) {
Ok(mark) => config.outbound_fwmark = Some(mark),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(iface) = matches.value_of("OUTBOUND_BIND_INTERFACE") {
config.outbound_bind_interface = Some(iface.to_owned());
match clap::value_t!(matches.value_of("OUTBOUND_BIND_INTERFACE"), String) {
Ok(iface) => config.outbound_bind_interface = Some(iface),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(all(unix, not(target_os = "android")))]
if let Some(nofile) = matches.value_of("NOFILE") {
config.nofile = Some(nofile.parse::<u64>().expect("an unsigned integer for `nofile`"));
match clap::value_t!(matches.value_of("NOFILE"), u64) {
Ok(nofile) => config.nofile = Some(nofile),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(acl_file) = matches.value_of("ACL") {
@@ -473,30 +496,43 @@ fn main() {
config.ipv6_first = true;
}
if let Some(udp_timeout) = matches.value_of("UDP_TIMEOUT") {
config.udp_timeout = Some(Duration::from_secs(udp_timeout.parse::<u64>().expect("udp-timeout")));
match clap::value_t!(matches.value_of("UDP_TIMEOUT"), u64) {
Ok(udp_timeout) => config.udp_timeout = Some(Duration::from_secs(udp_timeout)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(udp_max_assoc) = matches.value_of("UDP_MAX_ASSOCIATIONS") {
config.udp_max_associations = Some(udp_max_assoc.parse::<usize>().expect("udp-max-associations"));
match clap::value_t!(matches.value_of("UDP_MAX_ASSOCIATIONS"), usize) {
Ok(udp_max_assoc) => config.udp_max_associations = Some(udp_max_assoc),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("INBOUND_SEND_BUFFER_SIZE") {
config.inbound_send_buffer_size = Some(bs.parse::<u32>().expect("inbound-send-buffer-size"));
match clap::value_t!(matches.value_of("INBOUND_SEND_BUFFER_SIZE"), u32) {
Ok(bs) => config.inbound_send_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("INBOUND_RECV_BUFFER_SIZE") {
config.inbound_recv_buffer_size = Some(bs.parse::<u32>().expect("inbound-recv-buffer-size"));
match clap::value_t!(matches.value_of("INBOUND_RECV_BUFFER_SIZE"), u32) {
Ok(bs) => config.inbound_recv_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("OUTBOUND_SEND_BUFFER_SIZE") {
config.outbound_send_buffer_size = Some(bs.parse::<u32>().expect("outbound-send-buffer-size"));
match clap::value_t!(matches.value_of("OUTBOUND_SEND_BUFFER_SIZE"), u32) {
Ok(bs) => config.outbound_send_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("OUTBOUND_RECV_BUFFER_SIZE") {
config.outbound_recv_buffer_size = Some(bs.parse::<u32>().expect("outbound-recv-buffer-size"));
match clap::value_t!(matches.value_of("OUTBOUND_RECV_BUFFER_SIZE"), u32) {
Ok(bs) => config.outbound_recv_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bind_addr) = matches.value_of("OUTBOUND_BIND_ADDR") {
let bind_addr = bind_addr.parse::<IpAddr>().expect("outbound-bind-addr");
config.outbound_bind_addr = Some(bind_addr);
match clap::value_t!(matches.value_of("OUTBOUND_BIND_ADDR"), IpAddr) {
Ok(bind_addr) => config.outbound_bind_addr = Some(bind_addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
// DONE READING options
@@ -540,8 +576,12 @@ fn main() {
Builder::new_current_thread()
} else {
let mut builder = Builder::new_multi_thread();
if let Some(worker_threads) = matches.value_of("WORKER_THREADS") {
builder.worker_threads(worker_threads.parse::<usize>().expect("worker-threads"));
match clap::value_t!(matches.value_of("WORKER_THREADS"), usize) {
Ok(worker_threads) => {
builder.worker_threads(worker_threads);
}
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
builder
};
+78 -47
View File
@@ -9,11 +9,13 @@
use std::{net::IpAddr, path::PathBuf, process, time::Duration};
use clap::{clap_app, Arg};
use clap::{clap_app, Arg, ErrorKind as ClapErrorKind};
use futures::future::{self, Either};
use log::info;
use tokio::{self, runtime::Builder};
#[cfg(unix)]
use shadowsocks_service::config::ManagerServerMode;
use shadowsocks_service::{
acl::AccessControl,
config::{Config, ConfigType, ManagerConfig, ManagerServerHost},
@@ -156,11 +158,6 @@ fn main() {
None => Config::new(ConfigType::Manager),
};
if let Some(bind_addr) = matches.value_of("OUTBOUND_BIND_ADDR") {
let bind_addr = bind_addr.parse::<IpAddr>().expect("outbound-bind-addr");
config.outbound_bind_addr = Some(bind_addr);
}
if matches.is_present("TCP_NO_DELAY") {
config.no_delay = true;
}
@@ -169,42 +166,54 @@ fn main() {
config.fast_open = true;
}
if let Some(keep_alive) = matches.value_of("TCP_KEEP_ALIVE") {
config.keep_alive = Some(Duration::from_secs(
keep_alive
.parse::<u64>()
.expect("`tcp-keep-alive` is expecting an integer"),
));
match clap::value_t!(matches.value_of("TCP_KEEP_ALIVE"), u64) {
Ok(keep_alive) => config.keep_alive = Some(Duration::from_secs(keep_alive)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(any(target_os = "linux", target_os = "android"))]
if let Some(mark) = matches.value_of("OUTBOUND_FWMARK") {
config.outbound_fwmark = Some(mark.parse::<u32>().expect("an unsigned integer for `outbound-fwmark`"));
match clap::value_t!(matches.value_of("OUTBOUND_FWMARK"), u32) {
Ok(mark) => config.outbound_fwmark = Some(mark),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(iface) = matches.value_of("OUTBOUND_BIND_INTERFACE") {
config.outbound_bind_interface = Some(iface.to_owned());
match clap::value_t!(matches.value_of("OUTBOUND_BIND_INTERFACE"), String) {
Ok(iface) => config.outbound_bind_interface = Some(iface),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(m) = matches.value_of("MANAGER_ADDR") {
if let Some(ref mut manager_config) = config.manager {
manager_config.addr = m.parse::<ManagerAddr>().expect("manager-address");
} else {
config.manager = Some(ManagerConfig::new(m.parse::<ManagerAddr>().expect("manager-address")));
match clap::value_t!(matches.value_of("MANAGER_ADDR"), ManagerAddr) {
Ok(addr) => {
if let Some(ref mut manager_config) = config.manager {
manager_config.addr = addr;
} else {
config.manager = Some(ManagerConfig::new(addr));
}
}
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(ref mut manager_config) = config.manager {
if let Some(m) = matches.value_of("ENCRYPT_METHOD") {
manager_config.method = Some(m.parse::<CipherKind>().expect("encrypt-method"));
match clap::value_t!(matches.value_of("ENCRYPT_METHOD"), CipherKind) {
Ok(m) => manager_config.method = Some(m),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(t) = matches.value_of("TIMEOUT") {
manager_config.timeout = Some(Duration::from_secs(t.parse::<u64>().expect("timeout")));
match clap::value_t!(matches.value_of("TIMEOUT"), u64) {
Ok(t) => manager_config.timeout = Some(Duration::from_secs(t)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(sh) = matches.value_of("SERVER_HOST") {
manager_config.server_host = sh.parse::<ManagerServerHost>().unwrap();
match clap::value_t!(matches.value_of("SERVER_HOST"), ManagerServerHost) {
Ok(sh) => manager_config.server_host = sh,
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(p) = matches.value_of("PLUGIN") {
@@ -216,15 +225,17 @@ fn main() {
}
#[cfg(unix)]
if let Some(server_mode) = matches.value_of("MANAGER_SERVER_MODE") {
manager_config.server_mode = server_mode.parse().expect("manager-server-mode");
match clap::value_t!(matches.value_of("MANAGER_SERVER_MODE"), ManagerServerMode) {
Ok(server_mode) => manager_config.server_mode = server_mode,
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(unix)]
if let Some(server_working_directory) = matches.value_of("MANAGER_SERVER_WORKING_DIRECTORY") {
manager_config.server_working_directory = server_working_directory
.parse()
.expect("manager-server-working-directory");
match clap::value_t!(matches.value_of("MANAGER_SERVER_WORKING_DIRECTORY"), PathBuf) {
Ok(server_working_directory) => manager_config.server_working_directory = server_working_directory,
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
}
@@ -242,8 +253,10 @@ fn main() {
}
#[cfg(all(unix, not(target_os = "android")))]
if let Some(nofile) = matches.value_of("NOFILE") {
config.nofile = Some(nofile.parse::<u64>().expect("an unsigned integer for `nofile`"));
match clap::value_t!(matches.value_of("NOFILE"), u64) {
Ok(nofile) => config.nofile = Some(nofile),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(acl_file) = matches.value_of("ACL") {
@@ -265,25 +278,43 @@ fn main() {
config.ipv6_first = true;
}
if let Some(udp_timeout) = matches.value_of("UDP_TIMEOUT") {
config.udp_timeout = Some(Duration::from_secs(udp_timeout.parse::<u64>().expect("udp-timeout")));
match clap::value_t!(matches.value_of("UDP_TIMEOUT"), u64) {
Ok(udp_timeout) => config.udp_timeout = Some(Duration::from_secs(udp_timeout)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(udp_max_assoc) = matches.value_of("UDP_MAX_ASSOCIATIONS") {
config.udp_max_associations = Some(udp_max_assoc.parse::<usize>().expect("udp-max-associations"));
match clap::value_t!(matches.value_of("UDP_MAX_ASSOCIATIONS"), usize) {
Ok(udp_max_assoc) => config.udp_max_associations = Some(udp_max_assoc),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("INBOUND_SEND_BUFFER_SIZE") {
config.inbound_send_buffer_size = Some(bs.parse::<u32>().expect("inbound-send-buffer-size"));
match clap::value_t!(matches.value_of("INBOUND_SEND_BUFFER_SIZE"), u32) {
Ok(bs) => config.inbound_send_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("INBOUND_RECV_BUFFER_SIZE") {
config.inbound_recv_buffer_size = Some(bs.parse::<u32>().expect("inbound-recv-buffer-size"));
match clap::value_t!(matches.value_of("INBOUND_RECV_BUFFER_SIZE"), u32) {
Ok(bs) => config.inbound_recv_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("OUTBOUND_SEND_BUFFER_SIZE") {
config.outbound_send_buffer_size = Some(bs.parse::<u32>().expect("outbound-send-buffer-size"));
match clap::value_t!(matches.value_of("OUTBOUND_SEND_BUFFER_SIZE"), u32) {
Ok(bs) => config.outbound_send_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("OUTBOUND_RECV_BUFFER_SIZE") {
config.outbound_recv_buffer_size = Some(bs.parse::<u32>().expect("outbound-recv-buffer-size"));
match clap::value_t!(matches.value_of("OUTBOUND_RECV_BUFFER_SIZE"), u32) {
Ok(bs) => config.outbound_recv_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
match clap::value_t!(matches.value_of("OUTBOUND_BIND_ADDR"), IpAddr) {
Ok(bind_addr) => config.outbound_bind_addr = Some(bind_addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
// DONE reading options
+76 -50
View File
@@ -9,7 +9,7 @@
use std::{net::IpAddr, path::PathBuf, process, time::Duration};
use clap::{clap_app, Arg};
use clap::{clap_app, Arg, ErrorKind as ClapErrorKind};
use futures::future::{self, Either};
use log::info;
use tokio::{self, runtime::Builder};
@@ -46,7 +46,7 @@ fn main() {
(@arg OUTBOUND_BIND_ADDR: -b --("outbound-bind-addr") +takes_value alias("bind-addr") {validator::validate_ip_addr} "Bind address, outbound socket will bind this address")
(@arg OUTBOUND_BIND_INTERFACE: --("outbound-bind-interface") +takes_value "Set SO_BINDTODEVICE / IP_BOUND_IF / IP_UNICAST_IF option for outbound socket")
(@arg SERVER_ADDR: -s --("server-addr") +takes_value {validator::validate_server_addr} requires[PASSWORD ENCRYPT_METHOD] "Server address")
(@arg SERVER_ADDR: -s --("server-addr") +takes_value {validator::validate_server_addr} requires[ENCRYPT_METHOD] "Server address")
(@arg PASSWORD: -k --password +takes_value requires[SERVER_ADDR] "Server's password")
(@arg ENCRYPT_METHOD: -m --("encrypt-method") +takes_value requires[SERVER_ADDR] possible_values(available_ciphers()) "Server's encryption method")
(@arg TIMEOUT: --timeout +takes_value {validator::validate_u64} requires[SERVER_ADDR] "Server's timeout seconds for TCP relay")
@@ -151,29 +151,24 @@ fn main() {
};
if let Some(svr_addr) = matches.value_of("SERVER_ADDR") {
let password = match matches.value_of("PASSWORD") {
Some(pwd) => pwd.to_owned(),
None => {
let password = match clap::value_t!(matches.value_of("PASSWORD"), String) {
Ok(pwd) => pwd.to_owned(),
Err(err) => {
// NOTE: svr_addr should have been checked by common::validator
match common::password::read_server_password(svr_addr) {
Ok(pwd) => pwd,
Err(..) => {
panic!("missing server's password");
}
Err(..) => err.exit(),
}
}
};
let method = matches
.value_of("ENCRYPT_METHOD")
.expect("encrypt-method")
.parse::<CipherKind>()
.expect("encryption method");
let method = clap::value_t_or_exit!(matches.value_of("ENCRYPT_METHOD"), CipherKind);
let svr_addr = svr_addr.parse::<ServerAddr>().expect("server-addr");
let timeout = matches
.value_of("TIMEOUT")
.map(|t| t.parse::<u64>().expect("timeout"))
.map(Duration::from_secs);
let timeout = match clap::value_t!(matches.value_of("TIMEOUT"), u64) {
Ok(t) => Some(Duration::from_secs(t)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => None,
Err(err) => err.exit(),
};
let mut sc = ServerConfig::new(svr_addr, password.to_owned(), method);
if let Some(timeout) = timeout {
@@ -204,11 +199,6 @@ fn main() {
config.server.push(sc);
}
if let Some(bind_addr) = matches.value_of("OUTBOUND_BIND_ADDR") {
let bind_addr = bind_addr.parse::<IpAddr>().expect("outbound-bind-addr");
config.outbound_bind_addr = Some(bind_addr);
}
if matches.is_present("TCP_NO_DELAY") {
config.no_delay = true;
}
@@ -217,30 +207,42 @@ fn main() {
config.fast_open = true;
}
if let Some(keep_alive) = matches.value_of("TCP_KEEP_ALIVE") {
config.keep_alive = Some(Duration::from_secs(
keep_alive
.parse::<u64>()
.expect("`tcp-keep-alive` is expecting an integer"),
));
match clap::value_t!(matches.value_of("TCP_KEEP_ALIVE"), u64) {
Ok(keep_alive) => config.keep_alive = Some(Duration::from_secs(keep_alive)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(any(target_os = "linux", target_os = "android"))]
if let Some(mark) = matches.value_of("OUTBOUND_FWMARK") {
config.outbound_fwmark = Some(mark.parse::<u32>().expect("an unsigned integer for `outbound-fwmark`"));
match clap::value_t!(matches.value_of("OUTBOUND_FWMARK"), u32) {
Ok(mark) => config.outbound_fwmark = Some(mark),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(iface) = matches.value_of("OUTBOUND_BIND_INTERFACE") {
config.outbound_bind_interface = Some(iface.to_owned());
match clap::value_t!(matches.value_of("OUTBOUND_BIND_INTERFACE"), String) {
Ok(iface) => config.outbound_bind_interface = Some(iface),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(m) = matches.value_of("MANAGER_ADDR") {
config.manager = Some(ManagerConfig::new(m.parse::<ManagerAddr>().expect("manager address")));
match clap::value_t!(matches.value_of("MANAGER_ADDR"), ManagerAddr) {
Ok(addr) => {
if let Some(ref mut manager_config) = config.manager {
manager_config.addr = addr;
} else {
config.manager = Some(ManagerConfig::new(addr));
}
}
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
#[cfg(all(unix, not(target_os = "android")))]
if let Some(nofile) = matches.value_of("NOFILE") {
config.nofile = Some(nofile.parse::<u64>().expect("an unsigned integer for `nofile`"));
match clap::value_t!(matches.value_of("NOFILE"), u64) {
Ok(nofile) => config.nofile = Some(nofile),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(acl_file) = matches.value_of("ACL") {
@@ -262,25 +264,43 @@ fn main() {
config.ipv6_first = true;
}
if let Some(udp_timeout) = matches.value_of("UDP_TIMEOUT") {
config.udp_timeout = Some(Duration::from_secs(udp_timeout.parse::<u64>().expect("udp-timeout")));
match clap::value_t!(matches.value_of("UDP_TIMEOUT"), u64) {
Ok(udp_timeout) => config.udp_timeout = Some(Duration::from_secs(udp_timeout)),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(udp_max_assoc) = matches.value_of("UDP_MAX_ASSOCIATIONS") {
config.udp_max_associations = Some(udp_max_assoc.parse::<usize>().expect("udp-max-associations"));
match clap::value_t!(matches.value_of("UDP_MAX_ASSOCIATIONS"), usize) {
Ok(udp_max_assoc) => config.udp_max_associations = Some(udp_max_assoc),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("INBOUND_SEND_BUFFER_SIZE") {
config.inbound_send_buffer_size = Some(bs.parse::<u32>().expect("inbound-send-buffer-size"));
match clap::value_t!(matches.value_of("INBOUND_SEND_BUFFER_SIZE"), u32) {
Ok(bs) => config.inbound_send_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("INBOUND_RECV_BUFFER_SIZE") {
config.inbound_recv_buffer_size = Some(bs.parse::<u32>().expect("inbound-recv-buffer-size"));
match clap::value_t!(matches.value_of("INBOUND_RECV_BUFFER_SIZE"), u32) {
Ok(bs) => config.inbound_recv_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("OUTBOUND_SEND_BUFFER_SIZE") {
config.outbound_send_buffer_size = Some(bs.parse::<u32>().expect("outbound-send-buffer-size"));
match clap::value_t!(matches.value_of("OUTBOUND_SEND_BUFFER_SIZE"), u32) {
Ok(bs) => config.outbound_send_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
if let Some(bs) = matches.value_of("OUTBOUND_RECV_BUFFER_SIZE") {
config.outbound_recv_buffer_size = Some(bs.parse::<u32>().expect("outbound-recv-buffer-size"));
match clap::value_t!(matches.value_of("OUTBOUND_RECV_BUFFER_SIZE"), u32) {
Ok(bs) => config.outbound_recv_buffer_size = Some(bs),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
match clap::value_t!(matches.value_of("OUTBOUND_BIND_ADDR"), IpAddr) {
Ok(bind_addr) => config.outbound_bind_addr = Some(bind_addr),
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
// DONE READING options
@@ -314,9 +334,15 @@ fn main() {
Builder::new_current_thread()
} else {
let mut builder = Builder::new_multi_thread();
if let Some(worker_threads) = matches.value_of("WORKER_THREADS") {
builder.worker_threads(worker_threads.parse::<usize>().expect("worker-threads"));
match clap::value_t!(matches.value_of("WORKER_THREADS"), usize) {
Ok(worker_threads) => {
builder.worker_threads(worker_threads);
}
Err(ref err) if err.kind == ClapErrorKind::ArgumentNotFound => {}
Err(err) => err.exit(),
}
builder
};
#[cfg(not(feature = "multi-threaded"))]
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-service"
version = "1.12.1"
version = "1.12.2"
authors = ["Shadowsocks Contributors"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/shadowsocks/shadowsocks-rust"
+13
View File
@@ -1,3 +1,16 @@
shadowsocks-rust (1.12.3) unstable; urgency=medium
## Features
- #688 Support default configuration file path for `sslocal`, `ssserver` and `ssmanager`
- Linux: `$XDG_CONFIG_PATH/shadowsocks-rust/config.json` or `$HOME/.config/shadowsocks-rust/config.json`
- Windows: `{FOLDERID_RoamingAppData}\shadowsocks\shadowsocks-rust\config\config.json`
- macOS: `$HOME/Library/Application Support/org.shadowsocks.shadowsocks-rust/config.json`
- #691 Manipulating default logging options (command line options `-vvv` and `--log-without-time`) with environment variable `SS_LOG_VERBOSE_LEVEL` and `SS_LOG_WITHOUT_TIME`
- #419 Read servers' password from environment variables
- Server created from command line argument without `--password`, reading password from `SS_SERVER_${SERVER_ADDR}_PASSWORD`, `SS_SERVER_PASSWORD` or TTY
- Server defined in configuration file, `"password"` field support `${VAR_NAME}` format to read password from environment variable `VAR_NAME`
shadowsocks-rust (1.12.2) unstable; urgency=medium
## BUG Fixes