Skip to content

Commit e905aa2

Browse files
committed
[#184] Basic supports for TCP Fast Open on Windows, macOS, Linux
Removed `trust-dns` feature gate, uses trust-dns-resolver as default
1 parent af958e8 commit e905aa2

24 files changed

+830
-315
lines changed

Cargo.toml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "shadowsocks-rust"
3-
version = "1.8.0"
3+
version = "1.9.0"
44
authors = ["Y. T. CHUNG <[email protected]>"]
55
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
66
repository = "https://github.com/zonyitoo/shadowsocks-rust"
@@ -32,14 +32,14 @@ path = "src/bin/ssurl.rs"
3232
lto = true
3333

3434
[features]
35-
default = ["sodium", "rc4", "aes-cfb", "aes-ctr", "trust-dns"]
35+
default = ["sodium", "rc4", "aes-cfb", "aes-ctr", "tfo"]
3636
sodium = ["libsodium-sys"]
3737
rc4 = ["openssl"]
3838
aes-cfb = ["openssl"]
3939
aes-ctr = ["openssl"]
4040
camellia-cfb = ["openssl"]
4141
single-threaded = []
42-
trust-dns = ["trust-dns-resolver"]
42+
tfo = []
4343

4444
[dependencies]
4545
log = "0.4"
@@ -66,14 +66,22 @@ url = "2.1"
6666
byte_string = "1.0"
6767
libsodium-sys = { version = "0.2", optional = true }
6868
miscreant = { version = "0.5", optional = true }
69-
trust-dns-resolver = { version = "0.18", features = ["dns-over-rustls", "dns-over-https-rustls"], optional = true }
69+
trust-dns-resolver = { version = "0.18", features = ["dns-over-rustls", "dns-over-https-rustls"] }
7070
hkdf = "0.8"
7171
hmac = "0.7"
7272
sha-1 = "0.8"
7373
lru_time_cache = "0.9"
7474
hyper = "0.13"
7575
tower = "0.3"
7676
pin-project = "0.4"
77+
net2 = "0.2"
78+
cfg-if = "0.1"
7779

7880
[target.'cfg(windows)'.dependencies]
79-
winapi = { version = "0.3", features = ["mswsock", "winsock2"] }
81+
winapi = { version = "0.3", features = ["mswsock", "winsock2"] }
82+
83+
# [patch.crates-io]
84+
# libc = { git = "https://github.com/zonyitoo/libc.git", branch = "feature-linux-fastopen-connect", optional = true }
85+
86+
[patch.crates-io]
87+
libc = { git = "https://github.com/zonyitoo/libc.git", branch = "feature-macos-fastopen", optional = true }

build/build-release

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,5 @@ function build() {
5757
echo "* Done build package ${PKG_NAME}"
5858
}
5959

60-
build "x86_64-unknown-linux-musl"
61-
build "x86_64-pc-windows-gnu"
60+
#build "x86_64-unknown-linux-musl"
61+
build "x86_64-pc-windows-gnu"

src/config.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ use json5;
6363
use log::error;
6464
use serde::{Deserialize, Serialize};
6565
use serde_urlencoded;
66-
#[cfg(feature = "trust-dns")]
6766
use trust_dns_resolver::config::{NameServerConfigGroup, ResolverConfig};
6867
use url::{self, Url};
6968

@@ -101,6 +100,8 @@ struct SSConfig {
101100
mode: Option<String>,
102101
#[serde(skip_serializing_if = "Option::is_none")]
103102
no_delay: Option<bool>,
103+
#[serde(skip_serializing_if = "Option::is_none")]
104+
fast_open: Option<bool>,
104105
}
105106

106107
#[derive(Serialize, Deserialize, Debug)]
@@ -535,6 +536,7 @@ pub struct Config {
535536
pub manager_address: Option<ServerAddr>,
536537
pub config_type: ConfigType,
537538
pub udp_timeout: Option<Duration>,
539+
pub fast_open: bool,
538540
}
539541

540542
/// Configuration parsing error kind
@@ -596,6 +598,7 @@ impl Config {
596598
manager_address: None,
597599
config_type,
598600
udp_timeout: None,
601+
fast_open: false,
599602
}
600603
}
601604

@@ -765,6 +768,9 @@ impl Config {
765768
// UDP
766769
nconfig.udp_timeout = config.udp_timeout.map(Duration::from_secs);
767770

771+
// TCP Fast Open
772+
nconfig.fast_open = config.fast_open.unwrap_or(false);
773+
768774
Ok(nconfig)
769775
}
770776

@@ -780,7 +786,6 @@ impl Config {
780786
Config::load_from_str(&content[..], config_type)
781787
}
782788

783-
#[cfg(feature = "trust-dns")]
784789
pub fn get_dns_config(&self) -> Option<ResolverConfig> {
785790
self.dns.as_ref().and_then(|ds| {
786791
match &ds[..] {
@@ -900,6 +905,8 @@ impl fmt::Display for Config {
900905

901906
jconf.udp_timeout = self.udp_timeout.map(|t| t.as_secs());
902907

908+
jconf.fast_open = Some(self.fast_open);
909+
903910
write!(f, "{}", json5::to_string(&jconf).unwrap())
904911
}
905912
}

src/context.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,19 @@ use std::{
99
};
1010

1111
use tokio::runtime::Handle;
12-
#[cfg(feature = "trust-dns")]
1312
use trust_dns_resolver::TokioAsyncResolver;
1413

15-
use crate::config::Config;
16-
#[cfg(feature = "trust-dns")]
17-
use crate::relay::dns_resolver::create_resolver;
14+
use crate::{config::Config, relay::dns_resolver::create_resolver};
1815

1916
#[derive(Clone)]
2017
pub struct SharedServerState {
21-
#[cfg(feature = "trust-dns")]
2218
dns_resolver: Arc<TokioAsyncResolver>,
2319
server_running: Arc<AtomicBool>,
2420
}
2521

2622
impl SharedServerState {
27-
#[allow(unused_variables)]
2823
pub async fn new(config: &Config, rt: Handle) -> io::Result<SharedServerState> {
2924
let state = SharedServerState {
30-
#[cfg(feature = "trust-dns")]
3125
dns_resolver: Arc::new(create_resolver(config.get_dns_config(), rt).await?),
3226
server_running: Arc::new(AtomicBool::new(true)),
3327
};
@@ -46,7 +40,6 @@ impl SharedServerState {
4640
}
4741

4842
/// Get the global shared resolver
49-
#[cfg(feature = "trust-dns")]
5043
pub fn dns_resolver(&self) -> &TokioAsyncResolver {
5144
&*self.dns_resolver
5245
}
@@ -83,7 +76,6 @@ impl Context {
8376
}
8477

8578
/// Get the global shared resolver
86-
#[cfg(feature = "trust-dns")]
8779
pub fn dns_resolver(&self) -> &TokioAsyncResolver {
8880
self.server_state.dns_resolver()
8981
}

src/relay/dns_resolver/tokio_dns_resolver.rs

Lines changed: 0 additions & 77 deletions
This file was deleted.

src/relay/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Relay server in local and server side implementations.
22
3-
#[cfg(feature = "trust-dns")]
43
pub(crate) mod dns_resolver;
54
pub(crate) mod loadbalancing;
65
pub mod local;

src/relay/tcprelay/context.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,12 @@ impl TcpServerContext {
9898
ServerAddr::SocketAddr(ref addr) => {
9999
socket.send_to(payload.as_ref(), addr).await?;
100100
}
101-
#[cfg(feature = "trust-dns")]
102101
ServerAddr::DomainName(ref domain, ref port) => {
103102
use crate::relay::dns_resolver::resolve;
104103

105104
let addrs = resolve(&*self.context, &domain[..], *port, false).await?;
106105
socket.send_to(payload.as_ref(), addrs[0]).await?;
107106
}
108-
#[cfg(not(feature = "trust-dns"))]
109-
ServerAddr::DomainName(ref domain, ref port) => {
110-
socket.send_to(payload.as_ref(), (domain.as_str(), *port)).await?;
111-
}
112107
}
113108

114109
Ok(())

src/relay/tcprelay/mod.rs

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,23 @@ use std::{
1414
time::Duration,
1515
};
1616

17-
use crate::{
18-
config::{ConfigType, ServerAddr, ServerConfig},
19-
context::Context,
20-
relay::{socks5::Address, utils::try_timeout},
21-
};
22-
2317
use bytes::BytesMut;
2418
use futures::{future::FusedFuture, ready, select, Future};
2519
use log::{debug, error, trace};
2620
use tokio::{
2721
self,
2822
io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, BufReader, ReadHalf, WriteHalf},
29-
net::TcpStream,
3023
time::{self, Delay},
3124
};
3225

26+
use crate::{
27+
config::{ConfigType, ServerAddr, ServerConfig},
28+
context::Context,
29+
relay::socks5::Address,
30+
};
31+
32+
use self::utils::TcpStream;
33+
3334
mod aead;
3435
pub mod client;
3536
mod context;
@@ -191,47 +192,11 @@ async fn connect_proxy_server_internal(
191192
context: &Context,
192193
svr_addr: &ServerAddr,
193194
timeout: Option<Duration>,
195+
fast_open: bool,
194196
) -> io::Result<STcpStream> {
195-
match svr_addr {
196-
ServerAddr::SocketAddr(ref addr) => {
197-
let stream = try_timeout(TcpStream::connect(addr), timeout).await?;
198-
Ok(STcpStream::new(stream, timeout))
199-
}
200-
#[cfg(feature = "trust-dns")]
201-
ServerAddr::DomainName(ref domain, port) => {
202-
use crate::relay::dns_resolver::resolve;
203-
204-
let vec_ipaddr = try_timeout(resolve(context, &domain[..], *port, false), timeout).await?;
205-
206-
assert!(!vec_ipaddr.is_empty());
207-
208-
let mut last_err: Option<io::Error> = None;
209-
for addr in &vec_ipaddr {
210-
match try_timeout(TcpStream::connect(addr), timeout).await {
211-
Ok(s) => return Ok(STcpStream::new(s, timeout)),
212-
Err(e) => {
213-
error!(
214-
"Failed to connect {}:{}, resolved address {}, try another (err: {})",
215-
domain, port, addr, e
216-
);
217-
last_err = Some(e);
218-
}
219-
}
220-
}
221-
222-
let err = last_err.unwrap();
223-
error!(
224-
"Failed to connect {}:{}, tried all addresses but still failed (last err: {})",
225-
domain, port, err
226-
);
227-
Err(err)
228-
}
229-
#[cfg(not(feature = "trust-dns"))]
230-
ServerAddr::DomainName(ref domain, port) => {
231-
let stream = try_timeout(TcpStream::connect((domain.as_str(), *port)), timeout).await?;
232-
Ok(STcpStream::new(stream, timeout))
233-
}
234-
}
197+
TcpStream::connect_server(context, svr_addr, timeout, fast_open)
198+
.await
199+
.map(|s| STcpStream::new(s, timeout))
235200
}
236201

237202
/// Connect to proxy server with `ServerConfig`
@@ -256,7 +221,7 @@ async fn connect_proxy_server(context: &Context, svr_cfg: &ServerConfig) -> io::
256221
trace!("Connecting to proxy {}, timeout: {:?}", svr_addr, timeout);
257222
let mut last_err = None;
258223
for retry_time in 0..RETRY_TIMES {
259-
match connect_proxy_server_internal(context, svr_addr, timeout).await {
224+
match connect_proxy_server_internal(context, svr_addr, timeout, context.config().fast_open).await {
260225
Ok(s) => return Ok(s),
261226
Err(err) => {
262227
// Connection failure, retry

0 commit comments

Comments
 (0)