From c60869aa50b3ad02ba0b307058e237beecf64dc4 Mon Sep 17 00:00:00 2001 From: "Y. T. Chung" Date: Mon, 1 Oct 2018 10:32:04 +0800 Subject: [PATCH] Refactor some boxed futures with impl Trait - Replaced EncryptedWriterFut and DecryptedReaderFut with impl Trait - Replaced boxed future in try_timeout and io_timeout with a static type - Modified rustfmt configuration, fully reformatted --- Cargo.lock | 259 ++++++++----- Cargo.toml | 3 +- rustfmt.toml | 11 +- src/bin/local.rs | 265 +++++++------ src/bin/server.rs | 216 ++++++----- src/bin/ssdns.rs | 216 ++++++----- src/bin/ssurl.rs | 10 +- src/config.rs | 383 ++++++++++--------- src/crypto/aead.rs | 5 +- src/crypto/cipher.rs | 58 ++- src/crypto/mod.rs | 8 +- src/crypto/openssl.rs | 16 +- src/crypto/rc4_md5.rs | 29 +- src/crypto/ring.rs | 39 +- src/crypto/siv.rs | 45 ++- src/crypto/sodium.rs | 184 +++++---- src/crypto/stream.rs | 20 +- src/crypto/table.rs | 43 ++- src/lib.rs | 9 +- src/monitor.rs | 152 ++++---- src/plugin/mod.rs | 26 +- src/plugin/obfs_proxy.rs | 35 +- src/plugin/ss_plugin.rs | 25 +- src/relay/dns.rs | 3 +- src/relay/dns_resolver.rs | 90 ++--- src/relay/loadbalancing/server/roundrobin.rs | 6 +- src/relay/local.rs | 36 +- src/relay/mod.rs | 3 +- src/relay/server.rs | 36 +- src/relay/socks5.rs | 248 ++++++------ src/relay/tcprelay/aead.rs | 86 +++-- src/relay/tcprelay/client.rs | 107 +++--- src/relay/tcprelay/crypto_io.rs | 181 +++++---- src/relay/tcprelay/local.rs | 3 +- src/relay/tcprelay/mod.rs | 275 +++++++------ src/relay/tcprelay/server.rs | 285 ++++++++------ src/relay/tcprelay/socks5_local.rs | 132 ++++--- src/relay/tcprelay/stream.rs | 54 ++- src/relay/tcprelay/utils.rs | 72 ++-- src/relay/udprelay/crypto_io.rs | 3 +- src/relay/udprelay/dns.rs | 344 +++++++++-------- src/relay/udprelay/local.rs | 135 ++++--- src/relay/udprelay/mod.rs | 40 +- src/relay/udprelay/server.rs | 184 ++++----- src/relay/utils.rs | 27 +- tests/dns.rs | 29 +- tests/socks5.rs | 116 +++--- tests/udp.rs | 85 ++-- 48 files changed, 2611 insertions(+), 2026 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bd98ffc..4ee6f783 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,6 +199,16 @@ name = "checked_int_cast" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chrono" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "clap" version = "2.32.0" @@ -450,7 +460,7 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -535,7 +545,7 @@ name = "lazy_static" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -570,7 +580,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -615,7 +625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -623,6 +633,14 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "mime" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miniz-sys" version = "0.1.10" @@ -731,6 +749,19 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "1.8.0" @@ -781,7 +812,7 @@ name = "parking_lot" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -991,7 +1022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_json" -version = "1.0.28" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1034,15 +1065,15 @@ dependencies = [ "qrcode 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "subprocess 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "subprocess 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-signal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.10.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.10.0-alpha.2 (git+https://github.com/bluejekyll/trust-dns)", "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1093,7 +1124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "subprocess" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1184,46 +1215,47 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.1.0" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-codec" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1235,13 +1267,13 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1251,7 +1283,7 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1262,8 +1294,8 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1272,7 +1304,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1285,28 +1317,28 @@ dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-tcp" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1315,18 +1347,18 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1338,14 +1370,14 @@ dependencies = [ "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1355,28 +1387,30 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-https" version = "0.1.0-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/bluejekyll/trust-dns#3ebe2d6edce8ff696d87035498dd3800d9f4b33b" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.5.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-rustls 0.4.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.5.0-alpha.1 (git+https://github.com/bluejekyll/trust-dns)", + "trust-dns-rustls 0.4.0-alpha.2 (git+https://github.com/bluejekyll/trust-dns)", + "typed-headers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1384,7 +1418,7 @@ dependencies = [ [[package]] name = "trust-dns-proto" version = "0.5.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/bluejekyll/trust-dns#3ebe2d6edce8ff696d87035498dd3800d9f4b33b" dependencies = [ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1395,11 +1429,11 @@ dependencies = [ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1407,7 +1441,7 @@ dependencies = [ [[package]] name = "trust-dns-resolver" version = "0.10.0-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/bluejekyll/trust-dns#3ebe2d6edce8ff696d87035498dd3800d9f4b33b" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1419,26 +1453,39 @@ dependencies = [ "resolv-conf 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-https 0.1.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.5.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-rustls 0.4.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-https 0.1.0-alpha.2 (git+https://github.com/bluejekyll/trust-dns)", + "trust-dns-proto 0.5.0-alpha.1 (git+https://github.com/bluejekyll/trust-dns)", + "trust-dns-rustls 0.4.0-alpha.2 (git+https://github.com/bluejekyll/trust-dns)", "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-rustls" version = "0.4.0-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/bluejekyll/trust-dns#3ebe2d6edce8ff696d87035498dd3800d9f4b33b" dependencies = [ "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.5.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.5.0-alpha.1 (git+https://github.com/bluejekyll/trust-dns)", "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typed-headers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typenum" version = "1.10.0" @@ -1449,6 +1496,14 @@ name = "ucd-util" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicase" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -1517,7 +1572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "version_check" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1667,6 +1722,7 @@ dependencies = [ "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum checked_int_cast 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" +"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1711,13 +1767,14 @@ dependencies = [ "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum libsodium-ffi 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "68b36690c5fa7d3cf212f498f24e712b87a276979d622d9e121e22171ecafc4e" "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" -"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" +"checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" "checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum md-5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9402eaae33a9e144ce18ef488a0e4ca19869673c7bcdbbfe2030fdc3f84211cd" "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum mime 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4b082692d3f6cf41b453af73839ce3dfc212c4411cbb2441dff80a716e38bd79" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miniz_oxide 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba430291c9d6cedae28bcd2d49d1c32fc57d60cd49086646c5dd5673a870eb5" "checksum miniz_oxide_c_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5a5b8234d6103ebfba71e29786da4608540f862de5ce980a1c94f86a40ca0d51" @@ -1728,6 +1785,8 @@ dependencies = [ "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" "checksum openssl 0.10.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2e79eede055813a3ac52fb3915caf8e1c9da2dec1587871aec9f6f7b48508d" @@ -1761,7 +1820,7 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" -"checksum serde_json 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "d30ec34ac923489285d24688c7a9c0898d16edff27fc1f1bd854edeff6ca3b7f" +"checksum serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "bb47a3d5c84320222f66d7db21157c4a7407755de41798f9b4c1c40593397b1a" "checksum serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aaed41d9fb1e2f587201b863356590c90c1157495d811430a0c0325fe8169650" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" @@ -1770,7 +1829,7 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum subprocess 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "782b7c981ee2a9a30a96e9b125d64156a68712dac069428684b31d100a6d21d7" +"checksum subprocess 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "a085ed5b2586bb28a5793845331dac6c58afe7a343f52522cc016dbc943a6343" "checksum subtle 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7a6bab57c3efd01ebd3d750f4244ae0af4cdd1fc505a7904a41603192b803c5" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" @@ -1780,26 +1839,28 @@ dependencies = [ "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fbb6a6e9db2702097bfdfddcb09841211ad423b86c75b5ddaca1d62842ac492c" -"checksum tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "881e9645b81c2ce95fcb799ded2c29ffb9f25ef5bef909089a420e5961dd8ccb" -"checksum tokio-current-thread 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdfb899688ac16f618076bd09215edbfda0fd5dfecb375b6942636cb31fa8a7" -"checksum tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "84823b932d566bc3c6aa644df4ca36cb38593c50b7db06011fd4e12e31e4047e" +"checksum tokio 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "b67db11af0b714dc0c6cd134e4189491623cd60fdcdf534e8d4d26fa3c46407d" +"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f90fcd90952f0a496d438a976afba8e5c205fb12123f813d8ab3aa1c8436638c" +"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" "checksum tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5cbe4ca6e71cb0b62a66e4e6f53a8c06a6eefe46cc5f665ad6f274c9906f135" -"checksum tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6cc2de7725863c86ac71b0b9068476fec50834f055a243558ef1655bbd34cb" -"checksum tokio-reactor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4bfbaf9f260635649ec26b6fb4aded03887295ffcd999f6e43fd2c4758f758ea" +"checksum tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "8b8a85fffbec3c5ab1ab62324570230dcd37ee5996a7859da5caf7b9d45e3e8c" +"checksum tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4b26fd37f1125738b2170c80b551f69ff6fecb277e6e5ca885e53eec2b005018" "checksum tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "208d62fa3e015426e3c64039d9d20adf054a3c9b4d9445560f1c41c75bef3eab" "checksum tokio-signal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b6893092932264944edee8486d54b578c7098bea794aedaf9bd7947b49e6b7bf" -"checksum tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4c329b47f071eb8a746040465fa751bd95e4716e98daef6a9b4e434c17d565" -"checksum tokio-threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a5758cecb6e0633cea5d563ac07c975e04961690b946b04fd84e7d6445a8f6af" -"checksum tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d03fa701f9578a01b7014f106b47f0a363b4727a7f3f75d666e312ab7acbbf1c" +"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" +"checksum tokio-threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bbd8a8b911301c60cbfaa2a6588fb210e5c1038375b8bdecc47aa09a94c3c05f" +"checksum tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3a52f00c97fedb6d535d27f65cccb7181c8dd4c6edc3eda9ea93f6d45d05168e" "checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c" -"checksum tokio-uds 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "424c1ed15a0132251813ccea50640b224c809d6ceafb88154c1a8775873a0e89" -"checksum trust-dns-https 0.1.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a9e0478d560377fbf7ad0392ffaf8352cd9b7e5e763afee01be2edfd61eaf590" -"checksum trust-dns-proto 0.5.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "117d25ce0cfc13c1b55f97d1a665c2aae1c218ccd91f64117e1903b841412c13" -"checksum trust-dns-resolver 0.10.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a3cb4eec55b1494f438430ed74005d15cc9c134fa2b395a2d82630425fa58cc" -"checksum trust-dns-rustls 0.4.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7694ad20bb17527508580111b89bb511548f9d550cf94a86b34b4b5f803524b4" +"checksum tokio-uds 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22e3aa6d1fcc19e635418dc0a30ab5bd65d347973d6f43f1a37bf8d9d1335fc9" +"checksum trust-dns-https 0.1.0-alpha.2 (git+https://github.com/bluejekyll/trust-dns)" = "" +"checksum trust-dns-proto 0.5.0-alpha.1 (git+https://github.com/bluejekyll/trust-dns)" = "" +"checksum trust-dns-resolver 0.10.0-alpha.2 (git+https://github.com/bluejekyll/trust-dns)" = "" +"checksum trust-dns-rustls 0.4.0-alpha.2 (git+https://github.com/bluejekyll/trust-dns)" = "" +"checksum typed-headers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fb9c89066fda8824c7c9570d0f5c0dddd2a0b272b189855f89450e830f196eb" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" @@ -1811,7 +1872,7 @@ dependencies = [ "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f" "checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf" diff --git a/Cargo.toml b/Cargo.toml index bb1561ea..7c86659b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,8 @@ libsodium-ffi = { version = "0.1", optional = true } miscreant = { version = "0.4.0-beta", optional = true } lru-cache = "0.1" dns-parser = "0.7" -trust-dns-resolver = { version = "0.10.0-alpha", features = ["dns-over-rustls", "dns-over-https"] } +#trust-dns-resolver = { version = "0.10.0-alpha", features = ["dns-over-rustls", "dns-over-https"] } +trust-dns-resolver = { git = "https://github.com/bluejekyll/trust-dns", features = ["dns-over-rustls", "dns-over-https-rustls"] } spin = "0.4" [target.'cfg(unix)'.dependencies] diff --git a/rustfmt.toml b/rustfmt.toml index 762f11c0..a2241e92 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,12 +1,17 @@ max_width = 120 -indent_style = "Visual" +#indent_style = "Visual" #fn_call_width = 120 reorder_imports = true -reorder_imports_in_group = true -reorder_imported_names = true +reorder_modules = true +#reorder_imports_in_group = true +#reorder_imported_names = true condense_wildcard_suffixes = true #fn_args_layout = "Visual" #fn_call_style = "Visual" #chain_indent = "Visual" normalize_comments = true use_try_shorthand = true +reorder_impl_items = true +#use_small_heuristics = "Max" +imports_layout = "HorizontalVertical" +merge_imports = true diff --git a/src/bin/local.rs b/src/bin/local.rs index 1bb71203..8d95d5ae 100644 --- a/src/bin/local.rs +++ b/src/bin/local.rs @@ -3,7 +3,6 @@ //! You have to provide all needed configuration attributes via command line parameters, //! or you could specify a configuration file. The format of configuration file is defined //! in mod `config`. -//! extern crate clap; extern crate env_logger; @@ -14,47 +13,52 @@ extern crate shadowsocks; extern crate time; extern crate tokio; +use std::{ + env, + io::{self, Write}, + net::SocketAddr, +}; + use clap::{App, Arg}; - -use std::env; -use std::io::{self, Write}; -use std::net::SocketAddr; - -use env_logger::fmt::Formatter; -use env_logger::Builder; +use env_logger::{fmt::Formatter, Builder}; use futures::Future; use log::{LevelFilter, Record}; use tokio::runtime::Runtime; -use shadowsocks::plugin::PluginConfig; -use shadowsocks::{run_local, Config, ConfigType, ServerAddr, ServerConfig}; +use shadowsocks::{plugin::PluginConfig, run_local, Config, ConfigType, ServerAddr, ServerConfig}; fn log_time(fmt: &mut Formatter, without_time: bool, record: &Record) -> io::Result<()> { if without_time { writeln!(fmt, "[{}] {}", record.level(), record.args()) } else { - writeln!(fmt, - "[{}][{}] {}", - time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), - record.level(), - record.args()) + writeln!( + fmt, + "[{}][{}] {}", + time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), + record.level(), + record.args() + ) } } fn log_time_module(fmt: &mut Formatter, without_time: bool, record: &Record) -> io::Result<()> { if without_time { - writeln!(fmt, - "[{}] [{}] {}", - record.level(), - record.module_path().unwrap_or("*"), - record.args()) + writeln!( + fmt, + "[{}] [{}] {}", + record.level(), + record.module_path().unwrap_or("*"), + record.args() + ) } else { - writeln!(fmt, - "[{}][{}] [{}] {}", - time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), - record.level(), - record.module_path().unwrap_or("*"), - record.args()) + writeln!( + fmt, + "[{}][{}] [{}] {}", + time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), + record.level(), + record.module_path().unwrap_or("*"), + record.args() + ) } } @@ -62,54 +66,76 @@ fn main() { let matches = App::new("shadowsocks") .version(shadowsocks::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls.") - .arg(Arg::with_name("VERBOSE") - .short("v") - .multiple(true) - .help("Set the level of debug")) - .arg(Arg::with_name("ENABLE_UDP") - .short("u") - .long("enable-udp") - .help("Enable UDP relay")) - .arg(Arg::with_name("CONFIG") - .short("c") - .long("config") - .takes_value(true) - .help("Specify config file")) - .arg(Arg::with_name("SERVER_ADDR") - .short("s") - .long("server-addr") - .takes_value(true) - .help("Server address")) - .arg(Arg::with_name("LOCAL_ADDR") - .short("b") - .long("local-addr") - .takes_value(true) - .help("Local address, listen only to this address if specified")) - .arg(Arg::with_name("PASSWORD") - .short("k") - .long("password") - .takes_value(true) - .help("Password")) - .arg(Arg::with_name("ENCRYPT_METHOD") - .short("m") - .long("encrypt-method") - .takes_value(true) - .help("Encryption method")) - .arg(Arg::with_name("PLUGIN") - .long("plugin") - .takes_value(true) - .help("Enable SIP003 plugin")) - .arg(Arg::with_name("PLUGIN_OPT") - .long("plugin-opts") - .takes_value(true) - .help("Set SIP003 plugin options")) - .arg(Arg::with_name("LOG_WITHOUT_TIME") - .long("log-without-time") - .help("Disable time in log")) - .arg(Arg::with_name("URL") - .long("server-url") - .takes_value(true) - .help("Server address in SIP002 URL")) + .arg( + Arg::with_name("VERBOSE") + .short("v") + .multiple(true) + .help("Set the level of debug"), + ) + .arg( + Arg::with_name("ENABLE_UDP") + .short("u") + .long("enable-udp") + .help("Enable UDP relay"), + ) + .arg( + Arg::with_name("CONFIG") + .short("c") + .long("config") + .takes_value(true) + .help("Specify config file"), + ) + .arg( + Arg::with_name("SERVER_ADDR") + .short("s") + .long("server-addr") + .takes_value(true) + .help("Server address"), + ) + .arg( + Arg::with_name("LOCAL_ADDR") + .short("b") + .long("local-addr") + .takes_value(true) + .help("Local address, listen only to this address if specified"), + ) + .arg( + Arg::with_name("PASSWORD") + .short("k") + .long("password") + .takes_value(true) + .help("Password"), + ) + .arg( + Arg::with_name("ENCRYPT_METHOD") + .short("m") + .long("encrypt-method") + .takes_value(true) + .help("Encryption method"), + ) + .arg( + Arg::with_name("PLUGIN") + .long("plugin") + .takes_value(true) + .help("Enable SIP003 plugin"), + ) + .arg( + Arg::with_name("PLUGIN_OPT") + .long("plugin-opts") + .takes_value(true) + .help("Set SIP003 plugin options"), + ) + .arg( + Arg::with_name("LOG_WITHOUT_TIME") + .long("log-without-time") + .help("Disable time in log"), + ) + .arg( + Arg::with_name("URL") + .long("server-url") + .takes_value(true) + .help("Server address in SIP002 URL"), + ) .get_matches(); let mut log_builder = Builder::new(); @@ -129,13 +155,15 @@ fn main() { } 2 => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); - log_builder.filter(Some("sslocal"), LevelFilter::Debug) - .filter(Some("shadowsocks"), LevelFilter::Debug); + log_builder + .filter(Some("sslocal"), LevelFilter::Debug) + .filter(Some("shadowsocks"), LevelFilter::Debug); } 3 => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); - log_builder.filter(Some("sslocal"), LevelFilter::Trace) - .filter(Some("shadowsocks"), LevelFilter::Trace); + log_builder + .filter(Some("sslocal"), LevelFilter::Trace) + .filter(Some("shadowsocks"), LevelFilter::Trace); } _ => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); @@ -152,48 +180,51 @@ fn main() { let mut has_provided_config = false; let mut config = match matches.value_of("CONFIG") { - Some(cpath) => { - match Config::load_from_file(cpath, ConfigType::Local) { - Ok(cfg) => { - has_provided_config = true; - cfg - } - Err(err) => { - error!("{:?}", err); - return; - } + Some(cpath) => match Config::load_from_file(cpath, ConfigType::Local) { + Ok(cfg) => { + has_provided_config = true; + cfg } - } + Err(err) => { + error!("{:?}", err); + return; + } + }, None => Config::new(), }; - let mut has_provided_server_config = - match (matches.value_of("SERVER_ADDR"), matches.value_of("PASSWORD"), matches.value_of("ENCRYPT_METHOD")) { - (Some(svr_addr), Some(password), Some(method)) => { - let method = match method.parse() { - Ok(m) => m, - Err(err) => { - panic!("Does not support {:?} method: {:?}", method, err); - } - }; + let mut has_provided_server_config = match ( + matches.value_of("SERVER_ADDR"), + matches.value_of("PASSWORD"), + matches.value_of("ENCRYPT_METHOD"), + ) { + (Some(svr_addr), Some(password), Some(method)) => { + let method = match method.parse() { + Ok(m) => m, + Err(err) => { + panic!("Does not support {:?} method: {:?}", method, err); + } + }; - let sc = ServerConfig::new(svr_addr.parse::().expect("Invalid server addr"), - password.to_owned(), - method, - None, - None); + let sc = ServerConfig::new( + svr_addr.parse::().expect("Invalid server addr"), + password.to_owned(), + method, + None, + None, + ); - config.server.push(sc); - true - } - (None, None, None) => { - // Does not provide server config - false - } - _ => { - panic!("`server-addr`, `method` and `password` should be provided together"); - } - }; + config.server.push(sc); + true + } + (None, None, None) => { + // Does not provide server config + false + } + _ => { + panic!("`server-addr`, `method` and `password` should be provided together"); + } + }; if let Some(url) = matches.value_of("URL") { let svr_addr = url.parse::().expect("Failed to parse `url`"); @@ -222,8 +253,10 @@ fn main() { config.enable_udp |= matches.is_present("ENABLE_UDP"); if let Some(p) = matches.value_of("PLUGIN") { - let plugin = PluginConfig { plugin: p.to_owned(), - plugin_opt: matches.value_of("PLUGIN_OPT").map(ToOwned::to_owned), }; + let plugin = PluginConfig { + plugin: p.to_owned(), + plugin_opt: matches.value_of("PLUGIN_OPT").map(ToOwned::to_owned), + }; // Overrides config in file for svr in config.server.iter_mut() { diff --git a/src/bin/server.rs b/src/bin/server.rs index 7c7494a7..17151ddc 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -16,83 +16,116 @@ extern crate shadowsocks; extern crate time; extern crate tokio; -use std::env; -use std::io::{self, Write}; +use std::{ + env, + io::{self, Write}, +}; use clap::{App, Arg}; - -use env_logger::fmt::Formatter; -use env_logger::Builder; +use env_logger::{fmt::Formatter, Builder}; use futures::Future; use log::{LevelFilter, Record}; use tokio::runtime::Runtime; -use shadowsocks::plugin::PluginConfig; -use shadowsocks::{run_server, Config, ConfigType, ServerAddr, ServerConfig}; +use shadowsocks::{plugin::PluginConfig, run_server, Config, ConfigType, ServerAddr, ServerConfig}; fn log_time(fmt: &mut Formatter, without_time: bool, record: &Record) -> io::Result<()> { if without_time { writeln!(fmt, "[{}] {}", record.level(), record.args()) } else { - writeln!(fmt, - "[{}][{}] {}", - time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), - record.level(), - record.args()) + writeln!( + fmt, + "[{}][{}] {}", + time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), + record.level(), + record.args() + ) } } fn log_time_module(fmt: &mut Formatter, without_time: bool, record: &Record) -> io::Result<()> { if without_time { - writeln!(fmt, - "[{}] [{}] {}", - record.level(), - record.module_path().unwrap_or("*"), - record.args()) + writeln!( + fmt, + "[{}] [{}] {}", + record.level(), + record.module_path().unwrap_or("*"), + record.args() + ) } else { - writeln!(fmt, - "[{}][{}] [{}] {}", - time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), - record.level(), - record.module_path().unwrap_or("*"), - record.args()) + writeln!( + fmt, + "[{}][{}] [{}] {}", + time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), + record.level(), + record.module_path().unwrap_or("*"), + record.args() + ) } } fn main() { - let matches = App::new("shadowsocks").version(shadowsocks::VERSION) - .about("A fast tunnel proxy that helps you bypass firewalls.") - .arg(Arg::with_name("VERBOSE").short("v") - .multiple(true) - .help("Set the level of debug")) - .arg(Arg::with_name("ENABLE_UDP").short("u") - .long("enable-udp") - .help("Enable UDP relay")) - .arg(Arg::with_name("CONFIG").short("c") - .long("config") - .takes_value(true) - .help("Specify config file")) - .arg(Arg::with_name("SERVER_ADDR").short("s") - .long("server-addr") - .takes_value(true) - .help("Server address")) - .arg(Arg::with_name("PASSWORD").short("k") - .long("password") - .takes_value(true) - .help("Password")) - .arg(Arg::with_name("ENCRYPT_METHOD").short("m") - .long("encrypt-method") - .takes_value(true) - .help("Encryption method")) - .arg(Arg::with_name("PLUGIN").long("plugin") - .takes_value(true) - .help("Enable SIP003 plugin")) - .arg(Arg::with_name("PLUGIN_OPT").long("plugin-opts") - .takes_value(true) - .help("Set SIP003 plugin options")) - .arg(Arg::with_name("LOG_WITHOUT_TIME").long("log-without-time") - .help("Disable time in log")) - .get_matches(); + let matches = App::new("shadowsocks") + .version(shadowsocks::VERSION) + .about("A fast tunnel proxy that helps you bypass firewalls.") + .arg( + Arg::with_name("VERBOSE") + .short("v") + .multiple(true) + .help("Set the level of debug"), + ) + .arg( + Arg::with_name("ENABLE_UDP") + .short("u") + .long("enable-udp") + .help("Enable UDP relay"), + ) + .arg( + Arg::with_name("CONFIG") + .short("c") + .long("config") + .takes_value(true) + .help("Specify config file"), + ) + .arg( + Arg::with_name("SERVER_ADDR") + .short("s") + .long("server-addr") + .takes_value(true) + .help("Server address"), + ) + .arg( + Arg::with_name("PASSWORD") + .short("k") + .long("password") + .takes_value(true) + .help("Password"), + ) + .arg( + Arg::with_name("ENCRYPT_METHOD") + .short("m") + .long("encrypt-method") + .takes_value(true) + .help("Encryption method"), + ) + .arg( + Arg::with_name("PLUGIN") + .long("plugin") + .takes_value(true) + .help("Enable SIP003 plugin"), + ) + .arg( + Arg::with_name("PLUGIN_OPT") + .long("plugin-opts") + .takes_value(true) + .help("Set SIP003 plugin options"), + ) + .arg( + Arg::with_name("LOG_WITHOUT_TIME") + .long("log-without-time") + .help("Disable time in log"), + ) + .get_matches(); let mut log_builder = Builder::new(); log_builder.filter(None, LevelFilter::Info); @@ -111,13 +144,15 @@ fn main() { } 2 => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); - log_builder.filter(Some("ssserver"), LevelFilter::Debug) - .filter(Some("shadowsocks"), LevelFilter::Debug); + log_builder + .filter(Some("ssserver"), LevelFilter::Debug) + .filter(Some("shadowsocks"), LevelFilter::Debug); } 3 => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); - log_builder.filter(Some("ssserver"), LevelFilter::Trace) - .filter(Some("shadowsocks"), LevelFilter::Trace); + log_builder + .filter(Some("ssserver"), LevelFilter::Trace) + .filter(Some("shadowsocks"), LevelFilter::Trace); } _ => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); @@ -146,33 +181,38 @@ fn main() { None => Config::new(), }; - let has_provided_server_config = - match (matches.value_of("SERVER_ADDR"), matches.value_of("PASSWORD"), matches.value_of("ENCRYPT_METHOD")) { - (Some(svr_addr), Some(password), Some(method)) => { - let method = match method.parse() { - Ok(m) => m, - Err(err) => { - panic!("Does not support {:?} method: {:?}", method, err); - } - }; + let has_provided_server_config = match ( + matches.value_of("SERVER_ADDR"), + matches.value_of("PASSWORD"), + matches.value_of("ENCRYPT_METHOD"), + ) { + (Some(svr_addr), Some(password), Some(method)) => { + let method = match method.parse() { + Ok(m) => m, + Err(err) => { + panic!("Does not support {:?} method: {:?}", method, err); + } + }; - let sc = ServerConfig::new(svr_addr.parse::().expect("Invalid server addr"), - password.to_owned(), - method, - None, - None); + let sc = ServerConfig::new( + svr_addr.parse::().expect("Invalid server addr"), + password.to_owned(), + method, + None, + None, + ); - config.server.push(sc); - true - } - (None, None, None) => { - // Does not provide server config - false - } - _ => { - panic!("`server-addr`, `method` and `password` should be provided together"); - } - }; + config.server.push(sc); + true + } + (None, None, None) => { + // Does not provide server config + false + } + _ => { + panic!("`server-addr`, `method` and `password` should be provided together"); + } + }; if !has_provided_config && !has_provided_server_config { println!("You have to specify a configuration file or pass arguments from argument list"); @@ -183,8 +223,10 @@ fn main() { config.enable_udp |= matches.is_present("ENABLE_UDP"); if let Some(p) = matches.value_of("PLUGIN") { - let plugin = PluginConfig { plugin: p.to_owned(), - plugin_opt: matches.value_of("PLUGIN_OPT").map(ToOwned::to_owned), }; + let plugin = PluginConfig { + plugin: p.to_owned(), + plugin_opt: matches.value_of("PLUGIN_OPT").map(ToOwned::to_owned), + }; // Overrides config in file for svr in config.server.iter_mut() { diff --git a/src/bin/ssdns.rs b/src/bin/ssdns.rs index 48526cb5..b750c096 100644 --- a/src/bin/ssdns.rs +++ b/src/bin/ssdns.rs @@ -9,14 +9,14 @@ extern crate env_logger; extern crate futures; extern crate time; +use std::{ + env, + io::{self, Write}, + net::SocketAddr, +}; + use clap::{App, Arg}; - -use std::env; -use std::io::{self, Write}; -use std::net::SocketAddr; - -use env_logger::fmt::Formatter; -use env_logger::Builder; +use env_logger::{fmt::Formatter, Builder}; use futures::Future; use log::{LevelFilter, Record}; use tokio::runtime::Runtime; @@ -27,28 +27,34 @@ fn log_time(fmt: &mut Formatter, without_time: bool, record: &Record) -> io::Res if without_time { writeln!(fmt, "[{}] {}", record.level(), record.args()) } else { - writeln!(fmt, - "[{}][{}] {}", - time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), - record.level(), - record.args()) + writeln!( + fmt, + "[{}][{}] {}", + time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), + record.level(), + record.args() + ) } } fn log_time_module(fmt: &mut Formatter, without_time: bool, record: &Record) -> io::Result<()> { if without_time { - writeln!(fmt, - "[{}] [{}] {}", - record.level(), - record.module_path().unwrap_or("*"), - record.args()) + writeln!( + fmt, + "[{}] [{}] {}", + record.level(), + record.module_path().unwrap_or("*"), + record.args() + ) } else { - writeln!(fmt, - "[{}][{}] [{}] {}", - time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), - record.level(), - record.module_path().unwrap_or("*"), - record.args()) + writeln!( + fmt, + "[{}][{}] [{}] {}", + time::now().strftime("%Y-%m-%d][%H:%M:%S.%f").unwrap(), + record.level(), + record.module_path().unwrap_or("*"), + record.args() + ) } } @@ -56,46 +62,64 @@ fn main() { let matches = App::new("ssdns") .version(shadowsocks::VERSION) .about("A DNS proxy that helps you bypass firewalls.") - .arg(Arg::with_name("VERBOSE") - .short("v") - .multiple(true) - .help("Set the level of debug")) - .arg(Arg::with_name("CONFIG") - .short("c") - .long("config") - .takes_value(true) - .help("Specify config file")) - .arg(Arg::with_name("SERVER_ADDR") - .short("s") - .long("server-addr") - .takes_value(true) - .help("Server address")) - .arg(Arg::with_name("LOCAL_ADDR") - .short("b") - .long("local-addr") - .takes_value(true) - .help("Local address, listen only to this address if specified")) - .arg(Arg::with_name("PASSWORD") - .short("k") - .long("password") - .takes_value(true) - .help("Password")) - .arg(Arg::with_name("ENCRYPT_METHOD") - .short("m") - .long("encrypt-method") - .takes_value(true) - .help("Encryption method")) - .arg(Arg::with_name("LOG_WITHOUT_TIME") - .long("log-without-time") - .help("Disable time in log")) - .arg(Arg::with_name("URL") - .long("server-url") - .takes_value(true) - .help("Server address in SIP002 URL")) - .arg(Arg::with_name("REMOTE_DNS") + .arg( + Arg::with_name("VERBOSE") + .short("v") + .multiple(true) + .help("Set the level of debug"), + ) + .arg( + Arg::with_name("CONFIG") + .short("c") + .long("config") + .takes_value(true) + .help("Specify config file"), + ) + .arg( + Arg::with_name("SERVER_ADDR") + .short("s") + .long("server-addr") + .takes_value(true) + .help("Server address"), + ) + .arg( + Arg::with_name("LOCAL_ADDR") + .short("b") + .long("local-addr") + .takes_value(true) + .help("Local address, listen only to this address if specified"), + ) + .arg( + Arg::with_name("PASSWORD") + .short("k") + .long("password") + .takes_value(true) + .help("Password"), + ) + .arg( + Arg::with_name("ENCRYPT_METHOD") + .short("m") + .long("encrypt-method") + .takes_value(true) + .help("Encryption method"), + ) + .arg( + Arg::with_name("LOG_WITHOUT_TIME") + .long("log-without-time") + .help("Disable time in log"), + ) + .arg( + Arg::with_name("URL") + .long("server-url") + .takes_value(true) + .help("Server address in SIP002 URL"), + ) + .arg( + Arg::with_name("REMOTE_DNS") .long("remote-dns") .takes_value(true) - .help("Remote DNS server, default is 8.8.8.8:53")) + .help("Remote DNS server, default is 8.8.8.8:53"), + ) .get_matches(); let mut log_builder = Builder::new(); @@ -115,13 +139,15 @@ fn main() { } 2 => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); - log_builder.filter(Some("ssdns"), LevelFilter::Debug) - .filter(Some("shadowsocks"), LevelFilter::Debug); + log_builder + .filter(Some("ssdns"), LevelFilter::Debug) + .filter(Some("shadowsocks"), LevelFilter::Debug); } 3 => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); - log_builder.filter(Some("ssdns"), LevelFilter::Trace) - .filter(Some("shadowsocks"), LevelFilter::Trace); + log_builder + .filter(Some("ssdns"), LevelFilter::Trace) + .filter(Some("shadowsocks"), LevelFilter::Trace); } _ => { let log_builder = log_builder.format(move |fmt, r| log_time_module(fmt, without_time, r)); @@ -151,33 +177,38 @@ fn main() { None => Config::new(), }; - let mut has_provided_server_config = - match (matches.value_of("SERVER_ADDR"), matches.value_of("PASSWORD"), matches.value_of("ENCRYPT_METHOD")) { - (Some(svr_addr), Some(password), Some(method)) => { - let method = match method.parse() { - Ok(m) => m, - Err(err) => { - panic!("Does not support {:?} method: {:?}", method, err); - } - }; + let mut has_provided_server_config = match ( + matches.value_of("SERVER_ADDR"), + matches.value_of("PASSWORD"), + matches.value_of("ENCRYPT_METHOD"), + ) { + (Some(svr_addr), Some(password), Some(method)) => { + let method = match method.parse() { + Ok(m) => m, + Err(err) => { + panic!("Does not support {:?} method: {:?}", method, err); + } + }; - let sc = ServerConfig::new(svr_addr.parse::().expect("Invalid server addr"), - password.to_owned(), - method, - None, - None); + let sc = ServerConfig::new( + svr_addr.parse::().expect("Invalid server addr"), + password.to_owned(), + method, + None, + None, + ); - config.server.push(sc); - true - } - (None, None, None) => { - // Does not provide server config - false - } - _ => { - panic!("`server-addr`, `method` and `password` should be provided together"); - } - }; + config.server.push(sc); + true + } + (None, None, None) => { + // Does not provide server config + false + } + _ => { + panic!("`server-addr`, `method` and `password` should be provided together"); + } + }; if let Some(url) = matches.value_of("URL") { let svr_addr = url.parse::().expect("Failed to parse `url`"); @@ -204,8 +235,9 @@ fn main() { } if let Some(dns) = matches.value_of("REMOTE_DNS") { - let dns_addr = dns.parse::() - .expect("`remote-dns` is not a valid SocketAddr, must be IP:Port"); + let dns_addr = dns + .parse::() + .expect("`remote-dns` is not a valid SocketAddr, must be IP:Port"); config.remote_dns = Some(dns_addr); } diff --git a/src/bin/ssurl.rs b/src/bin/ssurl.rs index 4b3b1f0e..fb18fa0d 100644 --- a/src/bin/ssurl.rs +++ b/src/bin/ssurl.rs @@ -9,12 +9,12 @@ extern crate serde_json; extern crate shadowsocks; use clap::{App, Arg}; +use qrcode::{types::Color, QrCode}; -use qrcode::types::Color; -use qrcode::QrCode; - -use shadowsocks::config::{Config, ConfigType, ServerConfig}; -use shadowsocks::VERSION; +use shadowsocks::{ + config::{Config, ConfigType, ServerConfig}, + VERSION, +}; const BLACK: &'static str = "\x1b[40m \x1b[0m"; const WHITE: &'static str = "\x1b[47m \x1b[0m"; diff --git a/src/config.rs b/src/config.rs index 873c1ac9..ce7939db 100644 --- a/src/config.rs +++ b/src/config.rs @@ -41,19 +41,20 @@ //! //! These defined server will be used with a load balancing algorithm. -use std::collections::HashSet; -use std::convert::From; -use std::default::Default; -use std::error; -use std::fmt::{self, Debug, Display, Formatter}; -use std::fs::OpenOptions; -use std::net::IpAddr; -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; -use std::option::Option; -use std::path::Path; -use std::str::FromStr; -use std::string::ToString; -use std::time::Duration; +use std::{ + collections::HashSet, + convert::From, + default::Default, + error, + fmt::{self, Debug, Display, Formatter}, + fs::OpenOptions, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, + option::Option, + path::Path, + str::FromStr, + string::ToString, + time::Duration, +}; use base64::{decode_config, encode_config, URL_SAFE_NO_PAD}; use bytes::Bytes; @@ -132,6 +133,7 @@ pub struct ServerAddrError; impl FromStr for ServerAddr { type Err = ServerAddrError; + fn from_str(s: &str) -> Result { match s.parse::() { Ok(addr) => Ok(ServerAddr::SocketAddr(addr)), @@ -179,21 +181,24 @@ pub struct ServerConfig { impl ServerConfig { /// Creates a new ServerConfig - pub fn new(addr: ServerAddr, - pwd: String, - method: CipherType, - timeout: Option, - plugin: Option) - -> ServerConfig { + pub fn new( + addr: ServerAddr, + pwd: String, + method: CipherType, + timeout: Option, + plugin: Option, + ) -> ServerConfig { let enc_key = method.bytes_to_key(pwd.as_bytes()); trace!("Initialize config with pwd: {:?}, key: {:?}", pwd, enc_key); - ServerConfig { addr: addr, - password: pwd, - method: method, - timeout: timeout, - enc_key: enc_key, - plugin: plugin, - udp_timeout: None, } + ServerConfig { + addr: addr, + password: pwd, + method: method, + timeout: timeout, + enc_key: enc_key, + plugin: plugin, + udp_timeout: None, + } } /// Create a basic config @@ -346,8 +351,10 @@ impl ServerConfig { match vsp.next() { None => {} Some(p) => { - plugin = Some(PluginConfig { plugin: p.to_owned(), - plugin_opt: vsp.next().map(ToOwned::to_owned), }) + plugin = Some(PluginConfig { + plugin: p.to_owned(), + plugin_opt: vsp.next().map(ToOwned::to_owned), + }) } } } @@ -361,6 +368,7 @@ impl ServerConfig { impl FromStr for ServerConfig { type Err = UrlParseError; + fn from_str(s: &str) -> Result { ServerConfig::from_url(s) } @@ -501,9 +509,11 @@ pub struct Error { impl Error { pub fn new(kind: ErrorKind, desc: &'static str, detail: Option) -> Error { - Error { kind: kind, - desc: desc, - detail: detail, } + Error { + kind: kind, + desc: desc, + detail: detail, + } } } @@ -545,80 +555,82 @@ impl Debug for Error { impl Config { /// Creates an empty configuration pub fn new() -> Config { - Config { server: Vec::new(), - local: None, - enable_udp: false, - forbidden_ip: HashSet::new(), - dns: None, - remote_dns: None, } + Config { + server: Vec::new(), + local: None, + enable_udp: false, + forbidden_ip: HashSet::new(), + dns: None, + remote_dns: None, + } } fn parse_server(server: &Map, default_timeout: Option) -> Result { - let method = server.get("method") - .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a method", None)) - .and_then(|method_o| { - method_o.as_str().ok_or_else(|| { - Error::new(ErrorKind::Malformed, - "`method` should be a string", - None) - }) - }) - .and_then(|method_str| { - method_str.parse::().map_err(|_| { - Error::new(ErrorKind::Invalid, - "not supported method", - Some(format!("`{}` is not a supported method", method_str))) - }) - })?; + let method = server + .get("method") + .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a method", None)) + .and_then(|method_o| { + method_o + .as_str() + .ok_or_else(|| Error::new(ErrorKind::Malformed, "`method` should be a string", None)) + }) + .and_then(|method_str| { + method_str.parse::().map_err(|_| { + Error::new( + ErrorKind::Invalid, + "not supported method", + Some(format!("`{}` is not a supported method", method_str)), + ) + }) + })?; - let port = server.get("port") - .or_else(|| server.get("server_port")) - .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a server port", None)) - .and_then(|port_o| { - port_o.as_u64().map(|u| u as u16).ok_or_else(|| { - Error::new(ErrorKind::Malformed, - "`port` should be an integer", - None) - }) - })?; + let port = server + .get("port") + .or_else(|| server.get("server_port")) + .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a server port", None)) + .and_then(|port_o| { + port_o + .as_u64() + .map(|u| u as u16) + .ok_or_else(|| Error::new(ErrorKind::Malformed, "`port` should be an integer", None)) + })?; - let addr = server.get("address") - .or_else(|| server.get("server")) - .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a server address", None)) - .and_then(|addr_o| { - addr_o.as_str().ok_or_else(|| { - Error::new(ErrorKind::Malformed, - "`address` should be a string", - None) - }) - }) - .and_then(|addr_str| { - addr_str.parse::() - .map(|v4| ServerAddr::SocketAddr(SocketAddr::V4(SocketAddrV4::new(v4, port)))) - .or_else(|_| { - addr_str + let addr = server + .get("address") + .or_else(|| server.get("server")) + .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a server address", None)) + .and_then(|addr_o| { + addr_o + .as_str() + .ok_or_else(|| Error::new(ErrorKind::Malformed, "`address` should be a string", None)) + }) + .and_then(|addr_str| { + addr_str + .parse::() + .map(|v4| ServerAddr::SocketAddr(SocketAddr::V4(SocketAddrV4::new(v4, port)))) + .or_else(|_| { + addr_str .parse::() .map(|v6| ServerAddr::SocketAddr(SocketAddr::V6(SocketAddrV6::new(v6, port, 0, 0)))) - }) - .or_else(|_| Ok(ServerAddr::DomainName(addr_str.to_string(), port))) - })?; + }) + .or_else(|_| Ok(ServerAddr::DomainName(addr_str.to_string(), port))) + })?; - let password = server.get("password") - .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a password", None)) - .and_then(|pwd_o| { - pwd_o.as_str() - .ok_or_else(|| { - Error::new(ErrorKind::Malformed, - "`password` should be a string", - None) - }) - .map(|s| s.to_string()) - })?; + let password = server + .get("password") + .ok_or_else(|| Error::new(ErrorKind::MissingField, "need to specify a password", None)) + .and_then(|pwd_o| { + pwd_o + .as_str() + .ok_or_else(|| Error::new(ErrorKind::Malformed, "`password` should be a string", None)) + .map(|s| s.to_string()) + })?; let timeout = match server.get("timeout") { Some(t) => { - let val = t.as_u64() - .ok_or(Error::new(ErrorKind::Malformed, "`timeout` should be an integer", None))?; + let val = t + .as_u64() + .ok_or(Error::new(ErrorKind::Malformed, "`timeout` should be an integer", None))?; Some(Duration::from_secs(val)) } None => default_timeout, @@ -626,8 +638,11 @@ impl Config { let udp_timeout = match server.get("udp_timeout") { Some(t) => { - let val = t.as_u64() - .ok_or(Error::new(ErrorKind::Malformed, "`udp_timeout` should be an integer", None))?; + let val = t.as_u64().ok_or(Error::new( + ErrorKind::Malformed, + "`udp_timeout` should be an integer", + None, + ))?; Some(Duration::from_secs(val)) } None => None, @@ -635,24 +650,24 @@ impl Config { let plugin = match server.get("plugin") { Some(p) => { - let plugin = - p.as_str() - .ok_or_else(|| Error::new(ErrorKind::Malformed, "`plugin` should be a string", None))?; + let plugin = p + .as_str() + .ok_or_else(|| Error::new(ErrorKind::Malformed, "`plugin` should be a string", None))?; let opt = match server.get("plugin_opts") { None => None, Some(o) => { let o = o.as_str().ok_or_else(|| { - Error::new(ErrorKind::Malformed, - "`plugin_opts` should be a string", - None) - })?; + Error::new(ErrorKind::Malformed, "`plugin_opts` should be a string", None) + })?; Some(o.to_owned()) } }; - Some(PluginConfig { plugin: plugin.to_owned(), - plugin_opt: opt, }) + Some(PluginConfig { + plugin: plugin.to_owned(), + plugin_opt: opt, + }) } None => None, }; @@ -666,16 +681,18 @@ impl Config { let mut config = Config::new(); if o.contains_key("servers") { - let server_list = o.get("servers") - .unwrap() - .as_array() - .ok_or(Error::new(ErrorKind::Malformed, "`servers` should be a list", None))?; + let server_list = o.get("servers").unwrap().as_array().ok_or(Error::new( + ErrorKind::Malformed, + "`servers` should be a list", + None, + ))?; let opt_timeout = match o.get("timeout") { None => None, Some(t) => { - let val = t.as_u64() - .ok_or(Error::new(ErrorKind::Malformed, "`timeout` should be an integer", None))?; + let val = + t.as_u64() + .ok_or(Error::new(ErrorKind::Malformed, "`timeout` should be an integer", None))?; Some(Duration::from_secs(val)) } }; @@ -687,9 +704,9 @@ impl Config { } } } else if o.contains_key("server") - && o.contains_key("server_port") - && o.contains_key("password") - && o.contains_key("method") + && o.contains_key("server_port") + && o.contains_key("password") + && o.contains_key("method") { // Traditional configuration file let single_server = Config::parse_server(o, None)?; @@ -703,25 +720,29 @@ impl Config { if has_local_address && has_local_port { config.local = match o.get("local_address") { Some(local_addr) => { - let addr_str = local_addr.as_str().ok_or(Error::new(ErrorKind::Malformed, - "`local_address` should be a string", - None))?; + let addr_str = local_addr.as_str().ok_or(Error::new( + ErrorKind::Malformed, + "`local_address` should be a string", + None, + ))?; - let port = o.get("local_port") - .unwrap() - .as_u64() - .ok_or(Error::new(ErrorKind::Malformed, "`local_port` should be an integer", None))? - as u16; + let port = o.get("local_port").unwrap().as_u64().ok_or(Error::new( + ErrorKind::Malformed, + "`local_port` should be an integer", + None, + ))? as u16; match addr_str.parse::() { Ok(ip) => Some(SocketAddr::V4(SocketAddrV4::new(ip, port))), Err(..) => match addr_str.parse::() { Ok(ip) => Some(SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0))), Err(..) => { - return Err(Error::new(ErrorKind::Malformed, - "`local_address` is not a valid IP \ - address", - None)) + return Err(Error::new( + ErrorKind::Malformed, + "`local_address` is not a valid IP \ + address", + None, + )) } }, } @@ -734,27 +755,28 @@ impl Config { } if let Some(forbidden_ip_conf) = o.get("forbidden_ip") { - let forbidden_ip_arr = - forbidden_ip_conf.as_array() - .ok_or(Error::new(ErrorKind::Malformed, "`forbidden_ip` should be a list", None))?; + let forbidden_ip_arr = forbidden_ip_conf.as_array().ok_or(Error::new( + ErrorKind::Malformed, + "`forbidden_ip` should be a list", + None, + ))?; config.forbidden_ip.extend(forbidden_ip_arr.into_iter().filter_map(|x| { - let x = match x.as_str() { - Some(x) => x, - None => { - error!("Forbidden IP should be a string, but found {:?}, skipping", - x); - return None; - } - }; + let x = match x.as_str() { + Some(x) => x, + None => { + error!("Forbidden IP should be a string, but found {:?}, skipping", x); + return None; + } + }; - match x.parse::() { - Ok(sock) => Some(sock), - Err(err) => { - error!("Invalid forbidden IP {}, {:?}, skipping", x, err); - None - } - } - })); + match x.parse::() { + Ok(sock) => Some(sock), + Err(err) => { + error!("Invalid forbidden IP {}, {:?}, skipping", x, err); + None + } + } + })); } if let Some(udp_enable) = o.get("enable_udp") { @@ -773,17 +795,15 @@ impl Config { let err = Error::new(ErrorKind::Malformed, "`remote_dns` should be string", None); return Err(err); } - Some(dns) => { - match dns.parse::() { - Err(..) => { - let err = Error::new(ErrorKind::Malformed, "`remote_dns` should be IpAddr", None); - return Err(err); - } - Ok(addr) => { - config.remote_dns = Some(SocketAddr::new(addr, 53)); - } + Some(dns) => match dns.parse::() { + Err(..) => { + let err = Error::new(ErrorKind::Malformed, "`remote_dns` should be IpAddr", None); + return Err(err); } - } + Ok(addr) => { + config.remote_dns = Some(SocketAddr::new(addr, 53)); + } + }, } } @@ -804,25 +824,35 @@ impl Config { pub fn load_from_str(s: &str, config_type: ConfigType) -> Result { let object = serde_json::from_str::(s)?; - let json_object = except!(object.as_object(), - ErrorKind::JsonParsingError, - "root is not a JsonObject"); - Config::parse_json_object(json_object, match config_type { - ConfigType::Local => true, - ConfigType::Server => false, - }) + let json_object = except!( + object.as_object(), + ErrorKind::JsonParsingError, + "root is not a JsonObject" + ); + Config::parse_json_object( + json_object, + match config_type { + ConfigType::Local => true, + ConfigType::Server => false, + }, + ) } pub fn load_from_file(filename: &str, config_type: ConfigType) -> Result { let reader = &mut OpenOptions::new().read(true).open(&Path::new(filename))?; let object = serde_json::from_reader::<_, Value>(reader)?; - let json_object = except!(object.as_object(), - ErrorKind::JsonParsingError, - "root is not a JsonObject"); - Config::parse_json_object(json_object, match config_type { - ConfigType::Local => true, - ConfigType::Server => false, - }) + let json_object = except!( + object.as_object(), + ErrorKind::JsonParsingError, + "root is not a JsonObject" + ); + Config::parse_json_object( + json_object, + match config_type { + ConfigType::Local => true, + ConfigType::Server => false, + }, + ) } pub fn get_dns_config(&self) -> Option { @@ -842,13 +872,16 @@ impl Config { _ => { // Set ips directly match ds.parse::() { - Ok(ip) => Some(ResolverConfig::from_parts(None, - vec![], - NameServerConfigGroup::from_ips_clear(&[ip], - 53))), + Ok(ip) => Some(ResolverConfig::from_parts( + None, + vec![], + NameServerConfigGroup::from_ips_clear(&[ip], 53), + )), Err(..) => { - error!("Failed to parse DNS \"{}\" in config to IpAddr, fallback to system config", - ds); + error!( + "Failed to parse DNS \"{}\" in config to IpAddr, fallback to system config", + ds + ); None } } diff --git a/src/crypto/aead.rs b/src/crypto/aead.rs index 2b8457c0..3ce6fec5 100644 --- a/src/crypto/aead.rs +++ b/src/crypto/aead.rs @@ -8,11 +8,8 @@ use crypto::siv::MiscreantCipher; #[cfg(feature = "sodium")] use crypto::sodium::SodiumAeadCipher; -use ring::digest::SHA1; -use ring::hkdf; -use ring::hmac::SigningKey; - use bytes::{Bytes, BytesMut}; +use ring::{digest::SHA1, hkdf, hmac::SigningKey}; /// Encryptor API for AEAD ciphers pub trait AeadEncryptor { diff --git a/src/crypto/cipher.rs b/src/crypto/cipher.rs index 894d0df9..6671d3dd 100644 --- a/src/crypto/cipher.rs +++ b/src/crypto/cipher.rs @@ -1,10 +1,12 @@ //! Ciphers -use std::convert::From; -use std::fmt::{self, Debug, Display}; -use std::io; -use std::mem; -use std::str::{self, FromStr}; +use std::{ + convert::From, + fmt::{self, Debug, Display}, + io, + mem, + str::{self, FromStr}, +}; use bytes::{BufMut, Bytes, BytesMut}; use crypto::digest::{self, Digest, DigestType}; @@ -226,30 +228,24 @@ impl CipherType { match *self { CipherType::Table | CipherType::Plain => 0, - CipherType::Aes128Cfb1 => { - symm::Cipher::aes_128_cfb1().iv_len() - .expect("iv_len should not be None") - } - CipherType::Aes128Cfb8 => { - symm::Cipher::aes_128_cfb8().iv_len() - .expect("iv_len should not be None") - } - CipherType::Aes128Cfb | CipherType::Aes128Cfb128 => { - symm::Cipher::aes_128_cfb128().iv_len() - .expect("iv_len should not be None") - } - CipherType::Aes256Cfb1 => { - symm::Cipher::aes_256_cfb1().iv_len() - .expect("iv_len should not be None") - } - CipherType::Aes256Cfb8 => { - symm::Cipher::aes_256_cfb8().iv_len() - .expect("iv_len should not be None") - } - CipherType::Aes256Cfb | CipherType::Aes256Cfb128 => { - symm::Cipher::aes_256_cfb128().iv_len() - .expect("iv_len should not be None") - } + CipherType::Aes128Cfb1 => symm::Cipher::aes_128_cfb1() + .iv_len() + .expect("iv_len should not be None"), + CipherType::Aes128Cfb8 => symm::Cipher::aes_128_cfb8() + .iv_len() + .expect("iv_len should not be None"), + CipherType::Aes128Cfb | CipherType::Aes128Cfb128 => symm::Cipher::aes_128_cfb128() + .iv_len() + .expect("iv_len should not be None"), + CipherType::Aes256Cfb1 => symm::Cipher::aes_256_cfb1() + .iv_len() + .expect("iv_len should not be None"), + CipherType::Aes256Cfb8 => symm::Cipher::aes_256_cfb8() + .iv_len() + .expect("iv_len should not be None"), + CipherType::Aes256Cfb | CipherType::Aes256Cfb128 => symm::Cipher::aes_256_cfb128() + .iv_len() + .expect("iv_len should not be None"), CipherType::Rc4 => symm::Cipher::rc4().iv_len().expect("iv_len should not be None"), CipherType::Rc4Md5 => 16, @@ -338,6 +334,7 @@ impl CipherType { impl FromStr for CipherType { type Err = Error; + fn from_str(s: &str) -> Result { match s { CIPHER_TABLE | "" => Ok(CipherType::Table), @@ -424,8 +421,7 @@ impl Display for CipherType { #[cfg(test)] mod test_cipher { - use crypto::CryptoMode; - use crypto::{new_stream, CipherType, StreamCipher}; + use crypto::{new_stream, CipherType, CryptoMode, StreamCipher}; #[test] fn test_get_cipher() { diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index 6035ff5d..2f6451c4 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -4,11 +4,11 @@ use std::convert::From; use openssl::symm; -pub use self::aead::{ - new_aead_decryptor, new_aead_encryptor, AeadDecryptor, AeadEncryptor, BoxAeadDecryptor, BoxAeadEncryptor, +pub use self::{ + aead::{new_aead_decryptor, new_aead_encryptor, AeadDecryptor, AeadEncryptor, BoxAeadDecryptor, BoxAeadEncryptor}, + cipher::{CipherCategory, CipherResult, CipherType}, + stream::{new_stream, StreamCipher, StreamCipherVariant}, }; -pub use self::cipher::{CipherCategory, CipherResult, CipherType}; -pub use self::stream::{new_stream, StreamCipher, StreamCipherVariant}; pub mod aead; pub mod cipher; diff --git a/src/crypto/openssl.rs b/src/crypto/openssl.rs index 49096c53..1e3a1818 100644 --- a/src/crypto/openssl.rs +++ b/src/crypto/openssl.rs @@ -2,8 +2,7 @@ use std::convert::From; -use crypto::cipher; -use crypto::{CipherResult, CipherType, StreamCipher}; +use crypto::{cipher, CipherResult, CipherType, StreamCipher}; use crypto::CryptoMode; @@ -34,8 +33,10 @@ impl OpenSSLCrypto { // Panic if error occurs let cipher = symm::Crypter::new(t, From::from(mode), key, Some(iv)).unwrap(); - OpenSSLCrypto { cipher: t, - inner: cipher, } + OpenSSLCrypto { + cipher: t, + inner: cipher, + } } /// Update data @@ -80,8 +81,7 @@ impl OpenSSLCrypto { /// *Note: This behavior works just the same as the official version of shadowsocks.* /// /// ```rust -/// use shadowsocks::crypto::openssl::OpenSSLCipher; -/// use shadowsocks::crypto::{CipherType, CryptoMode, StreamCipher}; +/// use shadowsocks::crypto::{openssl::OpenSSLCipher, CipherType, CryptoMode, StreamCipher}; /// /// let method = CipherType::Aes128Cfb; /// @@ -107,7 +107,9 @@ pub struct OpenSSLCipher { impl OpenSSLCipher { /// Creates by type pub fn new(cipher_type: cipher::CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> OpenSSLCipher { - OpenSSLCipher { worker: OpenSSLCrypto::new(cipher_type, &key[..], &iv[..], mode), } + OpenSSLCipher { + worker: OpenSSLCrypto::new(cipher_type, &key[..], &iv[..], mode), + } } } diff --git a/src/crypto/rc4_md5.rs b/src/crypto/rc4_md5.rs index 090e0a96..284ebc7a 100644 --- a/src/crypto/rc4_md5.rs +++ b/src/crypto/rc4_md5.rs @@ -1,9 +1,13 @@ //! Rc4Md5 cipher definition -use crypto::digest::{self, Digest, DigestType}; -use crypto::openssl::OpenSSLCrypto; -use crypto::CryptoMode; -use crypto::{CipherResult, CipherType, StreamCipher}; +use crypto::{ + digest::{self, Digest, DigestType}, + openssl::OpenSSLCrypto, + CipherResult, + CipherType, + CryptoMode, + StreamCipher, +}; use bytes::{BufMut, BytesMut}; @@ -20,7 +24,9 @@ impl Rc4Md5Cipher { let mut key = BytesMut::with_capacity(md5_digest.digest_len()); md5_digest.digest(&mut key); - Rc4Md5Cipher { crypto: OpenSSLCrypto::new(CipherType::Rc4, &key, b"", mode), } + Rc4Md5Cipher { + crypto: OpenSSLCrypto::new(CipherType::Rc4, &key, b"", mode), + } } } @@ -43,8 +49,7 @@ unsafe impl Send for Rc4Md5Cipher {} #[cfg(test)] mod test { use super::*; - use crypto::CryptoMode; - use crypto::{CipherType, StreamCipher}; + use crypto::{CipherType, CryptoMode, StreamCipher}; #[test] fn test_rc4_md5_cipher() { @@ -56,13 +61,15 @@ mod test { let mut enc = Rc4Md5Cipher::new(key, &iv[..], CryptoMode::Encrypt); let mut encrypted_msg = Vec::new(); - enc.update(msg, &mut encrypted_msg).and_then(|_| enc.finalize(&mut encrypted_msg)) - .unwrap(); + enc.update(msg, &mut encrypted_msg) + .and_then(|_| enc.finalize(&mut encrypted_msg)) + .unwrap(); let mut dec = Rc4Md5Cipher::new(key, &iv[..], CryptoMode::Decrypt); let mut decrypted_msg = Vec::new(); - dec.update(&encrypted_msg[..], &mut decrypted_msg).and_then(|_| dec.finalize(&mut decrypted_msg)) - .unwrap(); + dec.update(&encrypted_msg[..], &mut decrypted_msg) + .and_then(|_| dec.finalize(&mut decrypted_msg)) + .unwrap(); assert_eq!(msg, &decrypted_msg[..]); } diff --git a/src/crypto/ring.rs b/src/crypto/ring.rs index 753cda99..1737f7eb 100644 --- a/src/crypto/ring.rs +++ b/src/crypto/ring.rs @@ -1,14 +1,17 @@ //! Cipher defined with Ring -use std::mem; -use std::ptr; +use std::{mem, ptr}; -use ring::aead::{open_in_place, seal_in_place, AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305, OpeningKey, SealingKey}; +use ring::aead::{open_in_place, seal_in_place, OpeningKey, SealingKey, AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305}; -use crypto::aead::{increase_nonce, make_skey}; -use crypto::cipher::Error; -use crypto::{AeadDecryptor, AeadEncryptor}; -use crypto::{CipherResult, CipherType}; +use crypto::{ + aead::{increase_nonce, make_skey}, + cipher::Error, + AeadDecryptor, + AeadEncryptor, + CipherResult, + CipherType, +}; use bytes::{BufMut, Bytes, BytesMut}; @@ -44,10 +47,12 @@ impl RingAeadCipher { let skey = make_skey(t, key, salt); let cipher = RingAeadCipher::new_variant(t, &skey, &nonce, is_seal); - RingAeadCipher { cipher: cipher, - cipher_type: t, - key: skey, - nonce: nonce, } + RingAeadCipher { + cipher: cipher, + cipher_type: t, + key: skey, + nonce: nonce, + } } fn new_variant(t: CipherType, key: &[u8], nonce: &[u8], is_seal: bool) -> RingAeadCryptoVariant { @@ -126,11 +131,13 @@ impl AeadDecryptor for RingAeadCipher { Ok(()) } Err(err) => { - error!("AEAD decrypt failed, nonce={:?}, input={:?}, tag={:?}, err: {:?}", - ByteStr::new(nonce), - ByteStr::new(&input[..tag_len]), - ByteStr::new(&input[tag_len..]), - err); + error!( + "AEAD decrypt failed, nonce={:?}, input={:?}, tag={:?}, err: {:?}", + ByteStr::new(nonce), + ByteStr::new(&input[..tag_len]), + ByteStr::new(&input[tag_len..]), + err + ); Err(Error::AeadDecryptFailed) } } diff --git a/src/crypto/siv.rs b/src/crypto/siv.rs index 0a8b4970..bcb5536a 100644 --- a/src/crypto/siv.rs +++ b/src/crypto/siv.rs @@ -4,10 +4,14 @@ use std::ptr; use miscreant::aead::{Aes128PmacSiv, Aes256PmacSiv, Algorithm}; -use crypto::aead::{increase_nonce, make_skey}; -use crypto::cipher::Error; -use crypto::{AeadDecryptor, AeadEncryptor}; -use crypto::{CipherResult, CipherType}; +use crypto::{ + aead::{increase_nonce, make_skey}, + cipher::Error, + AeadDecryptor, + AeadEncryptor, + CipherResult, + CipherType, +}; use bytes::{BufMut, BytesMut}; @@ -42,9 +46,11 @@ impl MiscreantCipher { let skey = make_skey(t, key, salt); let cipher = Self::new_variant(t, &skey); - MiscreantCipher { cipher_type: t, - cipher: cipher, - nonce: nonce, } + MiscreantCipher { + cipher_type: t, + cipher: cipher, + nonce: nonce, + } } fn new_variant(t: CipherType, key: &[u8]) -> MiscreantCryptoVariant { @@ -109,17 +115,20 @@ impl AeadDecryptor for MiscreantCipher { MiscreantCryptoVariant::Aes256(ref mut cipher) => cipher.open_in_place(&self.nonce, b"", &mut buf), }; - result.map(|buf| { - output.copy_from_slice(buf); - increase_nonce(&mut self.nonce); - }) - .map_err(|_| { - error!("AEAD decrypt failed, nonce={:?}, input={:?}, tag={:?}, err: decrypt failure", - ByteStr::new(&self.nonce), - ByteStr::new(&input[..input.len() - tag_size]), - ByteStr::new(&input[input.len() - tag_size..])); - Error::AeadDecryptFailed - }) + result + .map(|buf| { + output.copy_from_slice(buf); + increase_nonce(&mut self.nonce); + }) + .map_err(|_| { + error!( + "AEAD decrypt failed, nonce={:?}, input={:?}, tag={:?}, err: decrypt failure", + ByteStr::new(&self.nonce), + ByteStr::new(&input[..input.len() - tag_size]), + ByteStr::new(&input[input.len() - tag_size..]) + ); + Error::AeadDecryptFailed + }) } } diff --git a/src/crypto/sodium.rs b/src/crypto/sodium.rs index 7dfe49ad..3c4660fb 100644 --- a/src/crypto/sodium.rs +++ b/src/crypto/sodium.rs @@ -1,21 +1,32 @@ //! Cipher defined with libsodium -use std::ptr; -use std::sync::{Once, ONCE_INIT}; +use std::{ + ptr, + sync::{Once, ONCE_INIT}, +}; use bytes::{BufMut, Bytes, BytesMut}; use libc::{c_ulonglong, uint32_t}; use libsodium_ffi::{ - crypto_aead_xchacha20poly1305_ietf_decrypt, crypto_aead_xchacha20poly1305_ietf_encrypt, - crypto_stream_chacha20_ietf_xor_ic, crypto_stream_chacha20_xor_ic, crypto_stream_salsa20_xor_ic, - crypto_stream_xsalsa20_xor_ic, sodium_init, + crypto_aead_xchacha20poly1305_ietf_decrypt, + crypto_aead_xchacha20poly1305_ietf_encrypt, + crypto_stream_chacha20_ietf_xor_ic, + crypto_stream_chacha20_xor_ic, + crypto_stream_salsa20_xor_ic, + crypto_stream_xsalsa20_xor_ic, + sodium_init, }; -use crypto::aead::{increase_nonce, make_skey}; -use crypto::cipher::Error; -use crypto::{AeadDecryptor, AeadEncryptor}; -use crypto::{CipherResult, CipherType, StreamCipher}; +use crypto::{ + aead::{increase_nonce, make_skey}, + cipher::Error, + AeadDecryptor, + AeadEncryptor, + CipherResult, + CipherType, + StreamCipher, +}; static SODIUM_INIT_FLAG: Once = ONCE_INIT; @@ -38,13 +49,15 @@ impl SodiumStreamCipher { } SODIUM_INIT_FLAG.call_once(|| unsafe { - assert_eq!(sodium_init(), 0); - }); + assert_eq!(sodium_init(), 0); + }); - SodiumStreamCipher { cipher_type: t, - key: key.to_owned(), - iv: iv.to_owned(), - counter: 0, } + SodiumStreamCipher { + cipher_type: t, + key: key.to_owned(), + iv: iv.to_owned(), + counter: 0, + } } fn padding_len(&self) -> usize { @@ -59,12 +72,14 @@ impl SodiumStreamCipher { let mut out_buf = BytesMut::with_capacity((data.len() + padding) * 2); - crypto_stream_xor_ic(self.cipher_type, - self.counter / SODIUM_BLOCK_SIZE, - &self.iv, - &self.key, - &plain_text, - &mut out_buf)?; + crypto_stream_xor_ic( + self.cipher_type, + self.counter / SODIUM_BLOCK_SIZE, + &self.iv, + &self.key, + &plain_text, + &mut out_buf, + )?; out.put_slice(&out_buf[padding..padding + data.len()]); @@ -73,49 +88,50 @@ impl SodiumStreamCipher { } } -fn crypto_stream_xor_ic(t: CipherType, - ic: usize, - iv: &[u8], - key: &[u8], - data: &[u8], - out: &mut B) - -> CipherResult<()> { +fn crypto_stream_xor_ic( + t: CipherType, + ic: usize, + iv: &[u8], + key: &[u8], + data: &[u8], + out: &mut B, +) -> CipherResult<()> { assert!(data.len() <= unsafe { out.bytes_mut().len() }); let ret = unsafe { match t { - CipherType::ChaCha20 => { - crypto_stream_chacha20_xor_ic(out.bytes_mut().as_mut_ptr(), - data.as_ptr(), - data.len() as c_ulonglong, - iv.as_ptr(), - ic as c_ulonglong, - key.as_ptr()) - } - CipherType::ChaCha20Ietf => { - crypto_stream_chacha20_ietf_xor_ic(out.bytes_mut().as_mut_ptr(), - data.as_ptr(), - data.len() as c_ulonglong, - iv.as_ptr(), - ic as uint32_t, - key.as_ptr()) - } - CipherType::Salsa20 => { - crypto_stream_salsa20_xor_ic(out.bytes_mut().as_mut_ptr(), - data.as_ptr(), - data.len() as c_ulonglong, - iv.as_ptr(), - ic as c_ulonglong, - key.as_ptr()) - } - CipherType::XSalsa20 => { - crypto_stream_xsalsa20_xor_ic(out.bytes_mut().as_mut_ptr(), - data.as_ptr(), - data.len() as c_ulonglong, - iv.as_ptr(), - ic as c_ulonglong, - key.as_ptr()) - } + CipherType::ChaCha20 => crypto_stream_chacha20_xor_ic( + out.bytes_mut().as_mut_ptr(), + data.as_ptr(), + data.len() as c_ulonglong, + iv.as_ptr(), + ic as c_ulonglong, + key.as_ptr(), + ), + CipherType::ChaCha20Ietf => crypto_stream_chacha20_ietf_xor_ic( + out.bytes_mut().as_mut_ptr(), + data.as_ptr(), + data.len() as c_ulonglong, + iv.as_ptr(), + ic as uint32_t, + key.as_ptr(), + ), + CipherType::Salsa20 => crypto_stream_salsa20_xor_ic( + out.bytes_mut().as_mut_ptr(), + data.as_ptr(), + data.len() as c_ulonglong, + iv.as_ptr(), + ic as c_ulonglong, + key.as_ptr(), + ), + CipherType::XSalsa20 => crypto_stream_xsalsa20_xor_ic( + out.bytes_mut().as_mut_ptr(), + data.as_ptr(), + data.len() as c_ulonglong, + iv.as_ptr(), + ic as c_ulonglong, + key.as_ptr(), + ), _ => unreachable!(), } }; @@ -165,9 +181,11 @@ impl SodiumAeadCipher { let skey = make_skey(t, key, salt); - SodiumAeadCipher { cipher_type: t, - key: skey, - nonce: nonce, } + SodiumAeadCipher { + cipher_type: t, + key: skey, + nonce: nonce, + } } fn increase_nonce(&mut self) { @@ -189,15 +207,17 @@ impl AeadEncryptor for SodiumAeadCipher { let ret = match self.cipher_type { CipherType::XChaCha20IetfPoly1305 => unsafe { - crypto_aead_xchacha20poly1305_ietf_encrypt(output.as_mut_ptr(), - &mut len, - input.as_ptr(), - input.len() as c_ulonglong, - ptr::null(), - 0, - ptr::null(), - self.nonce.as_ref().as_ptr(), - self.key.as_ref().as_ptr()) + crypto_aead_xchacha20poly1305_ietf_encrypt( + output.as_mut_ptr(), + &mut len, + input.as_ptr(), + input.len() as c_ulonglong, + ptr::null(), + 0, + ptr::null(), + self.nonce.as_ref().as_ptr(), + self.key.as_ref().as_ptr(), + ) }, _ => unreachable!(), }; @@ -218,15 +238,17 @@ impl AeadDecryptor for SodiumAeadCipher { let ret = match self.cipher_type { CipherType::XChaCha20IetfPoly1305 => unsafe { - crypto_aead_xchacha20poly1305_ietf_decrypt(output.as_mut_ptr(), - &mut len, - ptr::null_mut(), - input.as_ptr(), - input.len() as c_ulonglong, - ptr::null(), - 0, - self.nonce.as_ref().as_ptr(), - self.key.as_ref().as_ptr()) + crypto_aead_xchacha20poly1305_ietf_decrypt( + output.as_mut_ptr(), + &mut len, + ptr::null_mut(), + input.as_ptr(), + input.len() as c_ulonglong, + ptr::null(), + 0, + self.nonce.as_ref().as_ptr(), + self.key.as_ref().as_ptr(), + ) }, _ => unreachable!(), }; diff --git a/src/crypto/stream.rs b/src/crypto/stream.rs index 32cdc59e..2e67242e 100644 --- a/src/crypto/stream.rs +++ b/src/crypto/stream.rs @@ -1,13 +1,15 @@ //! Stream ciphers -use crypto::cipher::{CipherCategory, CipherResult, CipherType}; -use crypto::dummy; -use crypto::openssl; -use crypto::rc4_md5; #[cfg(feature = "sodium")] use crypto::sodium; -use crypto::table; -use crypto::CryptoMode; +use crypto::{ + cipher::{CipherCategory, CipherResult, CipherType}, + dummy, + openssl, + rc4_md5, + table, + CryptoMode, +}; use bytes::BufMut; @@ -91,8 +93,10 @@ define_stream_ciphers! { /// Generate a specific Cipher with key and initialize vector pub fn new_stream(t: CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> StreamCipherVariant { - assert!(t.category() == CipherCategory::Stream, - "only allow initializing with stream cipher"); + assert!( + t.category() == CipherCategory::Stream, + "only allow initializing with stream cipher" + ); match t { CipherType::Table => StreamCipherVariant::new(table::TableCipher::new(key, mode)), diff --git a/src/crypto/table.rs b/src/crypto/table.rs index 6939f341..8567bd92 100644 --- a/src/crypto/table.rs +++ b/src/crypto/table.rs @@ -2,9 +2,12 @@ use std::io::Cursor; -use crypto::digest::{self, Digest, DigestType}; -use crypto::CryptoMode; -use crypto::{CipherResult, StreamCipher}; +use crypto::{ + digest::{self, Digest, DigestType}, + CipherResult, + CryptoMode, + StreamCipher, +}; use byteorder::{LittleEndian, ReadBytesExt}; use bytes::{BufMut, BytesMut}; @@ -35,22 +38,24 @@ impl TableCipher { table.sort_by(|x, y| (a % (*x + i)).cmp(&(a % (*y + i)))) } - TableCipher { table: match mode { - CryptoMode::Encrypt => { - let mut t = [0u8; TABLE_SIZE]; - for i in 0..TABLE_SIZE { - t[i] = table[i] as u8; - } - t - } - CryptoMode::Decrypt => { - let mut t = [0u8; TABLE_SIZE]; - for (idx, &item) in table.iter().enumerate() { - t[item as usize] = idx as u8; - } - t - } - }, } + TableCipher { + table: match mode { + CryptoMode::Encrypt => { + let mut t = [0u8; TABLE_SIZE]; + for i in 0..TABLE_SIZE { + t[i] = table[i] as u8; + } + t + } + CryptoMode::Decrypt => { + let mut t = [0u8; TABLE_SIZE]; + for (idx, &item) in table.iter().enumerate() { + t[item as usize] = idx as u8; + } + t + } + }, + } } fn process(&mut self, data: &[u8], out: &mut B) -> CipherResult<()> { diff --git a/src/lib.rs b/src/lib.rs index ecf12289..af198be5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -108,11 +108,10 @@ extern crate url; /// ShadowSocks version pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); -pub use self::config::{ClientConfig, Config, ConfigType, ServerAddr, ServerConfig}; -pub use self::relay::dns::run as run_dns; -pub use self::relay::local::run as run_local; -pub use self::relay::server::run as run_server; -pub use self::relay::tcprelay::client::Socks5Client; +pub use self::{ + config::{ClientConfig, Config, ConfigType, ServerAddr, ServerConfig}, + relay::{dns::run as run_dns, local::run as run_local, server::run as run_server, tcprelay::client::Socks5Client}, +}; pub mod config; pub mod crypto; diff --git a/src/monitor.rs b/src/monitor.rs index 3657403b..384afca3 100644 --- a/src/monitor.rs +++ b/src/monitor.rs @@ -1,14 +1,12 @@ #![allow(unused_imports)] -use std::io; -use std::process; +use std::{io, process}; use libc; use tokio; use tokio_io::IoFuture; -use futures::stream::futures_unordered; -use futures::{self, Future, Stream}; +use futures::{self, stream::futures_unordered, Future, Stream}; use plugin::Plugin; use relay::boxed_future; @@ -18,62 +16,68 @@ pub fn monitor_signal(plugins: Vec) -> impl Future Result<(), io::Error> { - error!("Plugin exited unexpectly (SIGCHLD)"); - Ok(()) - }) - .map(|_| libc::SIGCHLD) - }) - .map_err(|err| { - error!("Failed to monitor SIGCHLD, err: {:?}", err); - err - }); + let fut1 = Signal::new(libc::SIGCHLD) + .and_then(|signal| { + signal + .take(1) + .for_each(|_| -> Result<(), io::Error> { + error!("Plugin exited unexpectly (SIGCHLD)"); + Ok(()) + }) + .map(|_| libc::SIGCHLD) + }) + .map_err(|err| { + error!("Failed to monitor SIGCHLD, err: {:?}", err); + err + }); // Monitor SIGTERM, triggered if shadowsocks is exited gracefully. (Kill by user). - let fut2 = Signal::new(libc::SIGTERM).and_then(|sigterm| { - sigterm.take(1) - .for_each(|_| -> Result<(), io::Error> { - info!("Received SIGTERM, exiting."); - Ok(()) - }) - .map(|_| libc::SIGTERM) - }) - .map_err(|err| { - error!("Failed to monitor SIGTERM, err: {:?}", err); - err - }); + let fut2 = Signal::new(libc::SIGTERM) + .and_then(|sigterm| { + sigterm + .take(1) + .for_each(|_| -> Result<(), io::Error> { + info!("Received SIGTERM, exiting."); + Ok(()) + }) + .map(|_| libc::SIGTERM) + }) + .map_err(|err| { + error!("Failed to monitor SIGTERM, err: {:?}", err); + err + }); // Monitor SIGINT, triggered by CTRL-C - let fut3 = Signal::new(libc::SIGINT).and_then(|sigint| { - sigint.take(1) - .for_each(|_| -> Result<(), io::Error> { - info!("Received SIGINT, exiting."); - Ok(()) - }) - .map(|_| libc::SIGINT) - }) - .map_err(|err| { - error!("Failed to monitor SIGINT, err: {:?}", err); - err - }); + let fut3 = Signal::new(libc::SIGINT) + .and_then(|sigint| { + sigint + .take(1) + .for_each(|_| -> Result<(), io::Error> { + info!("Received SIGINT, exiting."); + Ok(()) + }) + .map(|_| libc::SIGINT) + }) + .map_err(|err| { + error!("Failed to monitor SIGINT, err: {:?}", err); + err + }); // Join them all, if any of them is triggered, kill all subprocesses and exit. futures_unordered(vec![boxed_future(fut1), boxed_future(fut2), boxed_future(fut3)]) .into_future() .then(move |r| { - // Something happened ... killing all subprocesses - info!("Killing {} plugin(s) and then ... Bye Bye :)", plugins.len()); - drop(plugins); + // Something happened ... killing all subprocesses + info!("Killing {} plugin(s) and then ... Bye Bye :)", plugins.len()); + drop(plugins); - match r { - Ok(..) => { - process::exit(0); - } - Err((err, ..)) => Err(err), - } - }) + match r { + Ok(..) => { + process::exit(0); + } + Err((err, ..)) => Err(err), + } + }) } #[cfg(windows)] @@ -86,27 +90,29 @@ pub fn monitor_signal(plugins: Vec) -> impl Future Result<(), io::Error> { - error!("Received Ctrl-C event"); - Ok(()) - }) - }) - .map_err(|err| { - error!("Failed to monitor Ctrl-C event: {:?}", err); - err - }); + let fut1 = Event::ctrl_c() + .and_then(|ev| { + ev.take(1).for_each(|_| -> Result<(), io::Error> { + error!("Received Ctrl-C event"); + Ok(()) + }) + }) + .map_err(|err| { + error!("Failed to monitor Ctrl-C event: {:?}", err); + err + }); - let fut2 = Event::ctrl_break().and_then(|ev| { - ev.take(1).for_each(|_| -> Result<(), io::Error> { - error!("Received Ctrl-Break event"); - Ok(()) - }) - }) - .map_err(|err| { - error!("Failed to monitor Ctrl-Break event: {:?}", err); - err - }); + let fut2 = Event::ctrl_break() + .and_then(|ev| { + ev.take(1).for_each(|_| -> Result<(), io::Error> { + error!("Received Ctrl-Break event"); + Ok(()) + }) + }) + .map_err(|err| { + error!("Failed to monitor Ctrl-Break event: {:?}", err); + err + }); // Join them all, if any of them is triggered, kill all subprocesses and exit. futures_unordered(vec![boxed_future(fut1), boxed_future(fut2)]) @@ -119,7 +125,7 @@ pub fn monitor_signal(plugins: Vec) -> impl Future { process::exit(libc::EXIT_FAILURE); } - Err((err, ..)) => Err(err) + Err((err, ..)) => Err(err), } }) }) @@ -130,6 +136,6 @@ pub fn monitor_signal(plugins: Vec) -> impl Future().and_then(|_| { - drop(plugins); - }) + drop(plugins); + }) } diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs index 05d52973..6156fdae 100644 --- a/src/plugin/mod.rs +++ b/src/plugin/mod.rs @@ -12,11 +12,12 @@ //! +------------+ +---------------------------+ //! ``` -use std::io; -use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener}; +use std::{ + io, + net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener}, +}; -use subprocess::Popen; -use subprocess::Result as PopenResult; +use subprocess::{Popen, Result as PopenResult}; use config::{Config, ServerAddr}; @@ -75,8 +76,10 @@ pub fn launch_plugin(config: &mut Config, mode: PluginMode) -> io::Result { let svr_addr = ServerAddr::SocketAddr(local_addr); - plugins.push(Plugin { addr: svr_addr.clone(), - process: p, }); + plugins.push(Plugin { + addr: svr_addr.clone(), + process: p, + }); // Replace addr with plugin svr_addr @@ -99,11 +102,12 @@ pub fn launch_plugin(config: &mut Config, mode: PluginMode) -> io::Result PopenResult { +fn start_plugin( + plugin: &PluginConfig, + remote: &ServerAddr, + local: &SocketAddr, + mode: PluginMode, +) -> PopenResult { if plugin.plugin == "obfsproxy" { obfs_proxy::start_plugin(plugin, remote, local, mode) } else { diff --git a/src/plugin/obfs_proxy.rs b/src/plugin/obfs_proxy.rs index 0b39d00e..64a79499 100644 --- a/src/plugin/obfs_proxy.rs +++ b/src/plugin/obfs_proxy.rs @@ -1,7 +1,6 @@ use std::net::SocketAddr; -use subprocess::Result as PopenResult; -use subprocess::{Exec, Popen}; +use subprocess::{Exec, Popen, Result as PopenResult}; use config::ServerAddr; @@ -31,13 +30,15 @@ use super::{PluginConfig, PluginMode}; /// And the rest parameters are all assembled here. /// Some old obfsproxy will not be supported as it doesn't even support /// "--data-dir" option -pub fn start_plugin(plugin: &PluginConfig, - remote: &ServerAddr, - local: &SocketAddr, - mode: PluginMode) - -> PopenResult { - let mut cmd = Exec::cmd(&plugin.plugin).arg("--data-dir") - .arg(format!("/tmp/{}_{}_{}", plugin.plugin, remote, local)); // FIXME: Not compatible in Windows +pub fn start_plugin( + plugin: &PluginConfig, + remote: &ServerAddr, + local: &SocketAddr, + mode: PluginMode, +) -> PopenResult { + let mut cmd = Exec::cmd(&plugin.plugin) + .arg("--data-dir") + .arg(format!("/tmp/{}_{}_{}", plugin.plugin, remote, local)); // FIXME: Not compatible in Windows if let Some(ref opt) = plugin.plugin_opt { for arg in opt.split(' ') { @@ -46,12 +47,16 @@ pub fn start_plugin(plugin: &PluginConfig, } let cmd = match mode { - PluginMode::Client => cmd.arg("--dest").arg(remote.to_string()) - .arg("client") - .arg(local.to_string()), - PluginMode::Server => cmd.arg("--dest").arg(local.to_string()) - .arg("server") - .arg(remote.to_string()), + PluginMode::Client => cmd + .arg("--dest") + .arg(remote.to_string()) + .arg("client") + .arg(local.to_string()), + PluginMode::Server => cmd + .arg("--dest") + .arg(local.to_string()) + .arg("server") + .arg(remote.to_string()), }; cmd.popen() diff --git a/src/plugin/ss_plugin.rs b/src/plugin/ss_plugin.rs index a18488ae..3557499f 100644 --- a/src/plugin/ss_plugin.rs +++ b/src/plugin/ss_plugin.rs @@ -1,24 +1,25 @@ use std::net::SocketAddr; -use subprocess::Result as PopenResult; -use subprocess::{Exec, NullFile, Popen}; +use subprocess::{Exec, NullFile, Popen, Result as PopenResult}; use config::ServerAddr; use super::{PluginConfig, PluginMode}; -pub fn start_plugin(plugin: &PluginConfig, - remote: &ServerAddr, - local: &SocketAddr, - _mode: PluginMode) - -> PopenResult { +pub fn start_plugin( + plugin: &PluginConfig, + remote: &ServerAddr, + local: &SocketAddr, + _mode: PluginMode, +) -> PopenResult { trace!("Start plugin \"{:?}\" remote: {}, local: {}", plugin, remote, local); - let mut exec = Exec::cmd(&plugin.plugin).env("SS_REMOTE_HOST", remote.host()) - .env("SS_REMOTE_PORT", remote.port().to_string()) - .env("SS_LOCAL_HOST", local.ip().to_string()) - .env("SS_LOCAL_PORT", local.port().to_string()) - .stdin(NullFile); + let mut exec = Exec::cmd(&plugin.plugin) + .env("SS_REMOTE_HOST", remote.host()) + .env("SS_REMOTE_PORT", remote.port().to_string()) + .env("SS_LOCAL_HOST", local.ip().to_string()) + .env("SS_LOCAL_PORT", local.port().to_string()) + .stdin(NullFile); if let Some(ref opt) = plugin.plugin_opt { exec = exec.env("SS_PLUGIN_OPTIONS", opt); diff --git a/src/relay/dns.rs b/src/relay/dns.rs index 2ddd341c..4bcd84c1 100644 --- a/src/relay/dns.rs +++ b/src/relay/dns.rs @@ -1,7 +1,6 @@ //! DNS relay -use std::io; -use std::sync::Arc; +use std::{io, sync::Arc}; use futures::Future; diff --git a/src/relay/dns_resolver.rs b/src/relay/dns_resolver.rs index 8bd185e0..baf6a349 100644 --- a/src/relay/dns_resolver.rs +++ b/src/relay/dns_resolver.rs @@ -1,14 +1,15 @@ //! Asynchronous DNS resolver -use std::io::{self, ErrorKind}; -use std::net::SocketAddr; -use std::sync::Arc; +use std::{ + io::{self, ErrorKind}, + net::SocketAddr, + sync::Arc, +}; use futures::Future; use spin::Mutex; use tokio; -use trust_dns_resolver::config::ResolverConfig; -use trust_dns_resolver::AsyncResolver; +use trust_dns_resolver::{config::ResolverConfig, AsyncResolver}; use config::Config; @@ -68,50 +69,53 @@ fn init_resolver() -> AsyncResolver { resolver } -fn inner_resolve(config: Arc, - addr: &str, - port: u16, - check_forbidden: bool) - -> impl Future, Error = io::Error> + Send { +fn inner_resolve( + config: Arc, + addr: &str, + port: u16, + check_forbidden: bool, +) -> impl Future, Error = io::Error> + Send { let owned_addr = addr.to_owned(); let owned_addr2 = owned_addr.clone(); - GLOBAL_DNS_RESOLVER.lookup_ip(addr) - .map_err(move |err| { - error!("Failed to resolve {}, err: {}", owned_addr2, err); - io::Error::new(io::ErrorKind::Other, "dns resolve error") - }) - .and_then(move |lookup_result| { - let mut vaddr = Vec::new(); - for ip in lookup_result.iter() { - if check_forbidden { - let forbidden_ip = &config.forbidden_ip; - if forbidden_ip.contains(&ip) { - debug!("Resolved {} => {}, which is skipped by forbidden_ip", - owned_addr, ip); - continue; - } - } - vaddr.push(SocketAddr::new(ip, port)); - } + GLOBAL_DNS_RESOLVER + .lookup_ip(addr) + .map_err(move |err| { + error!("Failed to resolve {}, err: {}", owned_addr2, err); + io::Error::new(io::ErrorKind::Other, "dns resolve error") + }) + .and_then(move |lookup_result| { + let mut vaddr = Vec::new(); + for ip in lookup_result.iter() { + if check_forbidden { + let forbidden_ip = &config.forbidden_ip; + if forbidden_ip.contains(&ip) { + debug!("Resolved {} => {}, which is skipped by forbidden_ip", owned_addr, ip); + continue; + } + } + vaddr.push(SocketAddr::new(ip, port)); + } - if vaddr.is_empty() { - let err = io::Error::new(ErrorKind::Other, - format!("resolved {} to empty address, all IPs are filtered", - owned_addr)); - Err(err) - } else { - debug!("Resolved {} => {:?}", owned_addr, vaddr); - Ok(vaddr) - } - }) + if vaddr.is_empty() { + let err = io::Error::new( + ErrorKind::Other, + format!("resolved {} to empty address, all IPs are filtered", owned_addr), + ); + Err(err) + } else { + debug!("Resolved {} => {:?}", owned_addr, vaddr); + Ok(vaddr) + } + }) } /// Resolve address to IP -pub fn resolve(config: Arc, - addr: &str, - port: u16, - check_forbidden: bool) - -> impl Future, Error = io::Error> + Send { +pub fn resolve( + config: Arc, + addr: &str, + port: u16, + check_forbidden: bool, +) -> impl Future, Error = io::Error> + Send { inner_resolve(config, addr, port, check_forbidden) } diff --git a/src/relay/loadbalancing/server/roundrobin.rs b/src/relay/loadbalancing/server/roundrobin.rs index e55c3fc2..a17bbf68 100644 --- a/src/relay/loadbalancing/server/roundrobin.rs +++ b/src/relay/loadbalancing/server/roundrobin.rs @@ -13,8 +13,10 @@ pub struct RoundRobin { impl RoundRobin { pub fn new(config: &Config) -> RoundRobin { - RoundRobin { servers: config.server.iter().map(|s| Arc::new(s.clone())).collect(), - index: 0usize, } + RoundRobin { + servers: config.server.iter().map(|s| Arc::new(s.clone())).collect(), + index: 0usize, + } } } diff --git a/src/relay/local.rs b/src/relay/local.rs index 0a54230d..0fea9574 100644 --- a/src/relay/local.rs +++ b/src/relay/local.rs @@ -1,17 +1,13 @@ //! Local side -use std::io; -use std::sync::Arc; +use std::{io, sync::Arc}; -use futures::stream::futures_unordered; -use futures::{Future, Stream}; +use futures::{stream::futures_unordered, Future, Stream}; use super::dns_resolver::set_dns_config; use config::Config; use plugin::{launch_plugin, PluginMode}; -use relay::boxed_future; -use relay::tcprelay::local::run as run_tcp; -use relay::udprelay::local::run as run_udp; +use relay::{boxed_future, tcprelay::local::run as run_tcp, udprelay::local::run as run_udp}; /// Relay server running under local environment. /// @@ -19,17 +15,21 @@ use relay::udprelay::local::run as run_udp; /// extern crate tokio; /// extern crate shadowsocks; /// -/// use shadowsocks::config::{Config, ServerConfig}; -/// use shadowsocks::crypto::CipherType; -/// use shadowsocks::relay::local::run; +/// use shadowsocks::{ +/// config::{Config, ServerConfig}, +/// crypto::CipherType, +/// relay::local::run, +/// }; /// /// use tokio::prelude::*; /// /// let mut config = Config::new(); /// config.local = Some("127.0.0.1:1080".parse().unwrap()); -/// config.server = vec![ServerConfig::basic("127.0.0.1:8388".parse().unwrap(), -/// "server-password".to_string(), -/// CipherType::Aes256Cfb)]; +/// config.server = vec![ServerConfig::basic( +/// "127.0.0.1:8388".parse().unwrap(), +/// "server-password".to_string(), +/// CipherType::Aes256Cfb, +/// )]; /// let fut = run(config); /// tokio::run(fut.map_err(|err| panic!("Server run failed with error {}", err))); /// ``` @@ -63,9 +63,9 @@ pub fn run(mut config: Config) -> impl Future + Se vf.push(boxed_future(mon)); vf.push(boxed_future(tcp_fut)); futures_unordered(vf).into_future().then(|res| -> io::Result<()> { - match res { - Ok(..) => Ok(()), - Err((err, ..)) => Err(err), - } - }) + match res { + Ok(..) => Ok(()), + Err((err, ..)) => Err(err), + } + }) } diff --git a/src/relay/mod.rs b/src/relay/mod.rs index 1d8b20a4..c96aa7af 100644 --- a/src/relay/mod.rs +++ b/src/relay/mod.rs @@ -13,7 +13,8 @@ pub mod udprelay; mod utils; pub fn boxed_future(f: F) -> Box + Send + 'static> - where F: Future + Send + 'static +where + F: Future + Send + 'static, { Box::new(f) } diff --git a/src/relay/server.rs b/src/relay/server.rs index c70caef0..149fa4e3 100644 --- a/src/relay/server.rs +++ b/src/relay/server.rs @@ -1,17 +1,13 @@ //! Server side -use std::io; -use std::sync::Arc; +use std::{io, sync::Arc}; -use futures::stream::futures_unordered; -use futures::{Future, Stream}; +use futures::{stream::futures_unordered, Future, Stream}; use super::dns_resolver::set_dns_config; use config::Config; use plugin::{launch_plugin, PluginMode}; -use relay::boxed_future; -use relay::tcprelay::server::run as run_tcp; -use relay::udprelay::server::run as run_udp; +use relay::{boxed_future, tcprelay::server::run as run_tcp, udprelay::server::run as run_udp}; /// Relay server running on server side. /// @@ -19,16 +15,20 @@ use relay::udprelay::server::run as run_udp; /// extern crate tokio; /// extern crate shadowsocks; /// -/// use shadowsocks::config::{Config, ServerConfig}; -/// use shadowsocks::crypto::CipherType; -/// use shadowsocks::relay::server::run; +/// use shadowsocks::{ +/// config::{Config, ServerConfig}, +/// crypto::CipherType, +/// relay::server::run, +/// }; /// /// use tokio::prelude::*; /// /// let mut config = Config::new(); -/// config.server = vec![ServerConfig::basic("127.0.0.1:8388".parse().unwrap(), -/// "server-password".to_string(), -/// CipherType::Aes256Cfb)]; +/// config.server = vec![ServerConfig::basic( +/// "127.0.0.1:8388".parse().unwrap(), +/// "server-password".to_string(), +/// CipherType::Aes256Cfb, +/// )]; /// /// let fut = run(config); /// tokio::run(fut.map_err(|err| panic!("Server run failed with error {}", err))); @@ -64,9 +64,9 @@ pub fn run(mut config: Config) -> impl Future + Se vf.push(boxed_future(tcp_fut)); futures_unordered(vf).into_future().then(|res| -> io::Result<()> { - match res { - Ok(..) => Ok(()), - Err((err, ..)) => Err(err), - } - }) + match res { + Ok(..) => Ok(()), + Err((err, ..)) => Err(err), + } + }) } diff --git a/src/relay/socks5.rs b/src/relay/socks5.rs index e6f26f4a..bda3a428 100644 --- a/src/relay/socks5.rs +++ b/src/relay/socks5.rs @@ -2,24 +2,28 @@ //! //! Implements [SOCKS Protocol Version 5](https://www.ietf.org/rfc/rfc1928.txt) proxy protocol -use std::convert::From; -use std::error; -use std::fmt::{self, Debug, Formatter}; -use std::io::{self, Cursor, Read, Write}; -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; -use std::u8; -use std::vec; +use std::{ + convert::From, + error, + fmt::{self, Debug, Formatter}, + io::{self, Cursor, Read, Write}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}, + u8, + vec, +}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use bytes::{BufMut, Bytes, BytesMut, IntoBuf}; use futures::{Async, Future, Poll}; -use tokio_io::io::read_exact; -use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_io::{io::read_exact, AsyncRead, AsyncWrite}; pub use self::consts::{ - SOCKS5_AUTH_METHOD_GSSAPI, SOCKS5_AUTH_METHOD_NONE, SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE, SOCKS5_AUTH_METHOD_PASSWORD, + SOCKS5_AUTH_METHOD_GSSAPI, + SOCKS5_AUTH_METHOD_NONE, + SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE, + SOCKS5_AUTH_METHOD_PASSWORD, }; use super::utils::{write_bytes, WriteBytes}; @@ -167,8 +171,10 @@ pub struct Error { impl Error { pub fn new(reply: Reply, message: &str) -> Error { - Error { reply: reply, - message: message.to_string(), } + Error { + reply: reply, + message: message.to_string(), + } } } @@ -265,6 +271,7 @@ impl fmt::Display for Address { impl ToSocketAddrs for Address { type Iter = vec::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { match self.clone() { Address::SocketAddress(addr) => Ok(vec![addr].into_iter()), @@ -286,7 +293,8 @@ impl From<(String, u16)> for Address { } pub struct ReadAddress - where R: AsyncRead +where + R: AsyncRead, { reader: Option, state: ReadAddressState, @@ -303,10 +311,11 @@ enum ReadAddressState { } impl Future for ReadAddress - where R: AsyncRead +where + R: AsyncRead, { - type Item = (R, Address); type Error = Error; + type Item = (R, Address); fn poll(&mut self) -> Poll { debug_assert!(self.reader.is_some()); @@ -340,13 +349,16 @@ impl Future for ReadAddress } impl ReadAddress - where R: AsyncRead +where + R: AsyncRead, { fn new(r: R) -> ReadAddress { - ReadAddress { reader: Some(r), - state: ReadAddressState::ReadingType, - buf: None, - already_read: 0, } + ReadAddress { + reader: Some(r), + state: ReadAddressState::ReadingType, + buf: None, + already_read: 0, + } } fn read_addr_type(&mut self) -> Poll<(), Error> { @@ -375,10 +387,12 @@ impl ReadAddress fn read_ipv4(&mut self) -> Poll { try_ready!(self.read_data()); let mut stream: Cursor = self.freeze_buf().into_buf(); - let v4addr = Ipv4Addr::new(stream.read_u8()?, - stream.read_u8()?, - stream.read_u8()?, - stream.read_u8()?); + let v4addr = Ipv4Addr::new( + stream.read_u8()?, + stream.read_u8()?, + stream.read_u8()?, + stream.read_u8()?, + ); let port = stream.read_u16::()?; let addr = Address::SocketAddress(SocketAddr::V4(SocketAddrV4::new(v4addr, port))); Ok(Async::Ready(addr)) @@ -387,14 +401,16 @@ impl ReadAddress fn read_ipv6(&mut self) -> Poll { try_ready!(self.read_data()); let mut stream: Cursor = self.freeze_buf().into_buf(); - let v6addr = Ipv6Addr::new(stream.read_u16::()?, - stream.read_u16::()?, - stream.read_u16::()?, - stream.read_u16::()?, - stream.read_u16::()?, - stream.read_u16::()?, - stream.read_u16::()?, - stream.read_u16::()?); + let v6addr = Ipv6Addr::new( + stream.read_u16::()?, + stream.read_u16::()?, + stream.read_u16::()?, + stream.read_u16::()?, + stream.read_u16::()?, + stream.read_u16::()?, + stream.read_u16::()?, + stream.read_u16::()?, + ); let port = stream.read_u16::()?; let addr = Address::SocketAddress(SocketAddr::V6(SocketAddrV6::new(v6addr, port, 0, 0))); @@ -539,42 +555,43 @@ pub struct TcpRequestHeader { impl TcpRequestHeader { /// Creates a request header pub fn new(cmd: Command, addr: Address) -> TcpRequestHeader { - TcpRequestHeader { command: cmd, - address: addr, } + TcpRequestHeader { + command: cmd, + address: addr, + } } /// Read from a reader pub fn read_from(r: R) -> impl Future + Send - where R: AsyncRead + Send + 'static + where + R: AsyncRead + Send + 'static, { - read_exact(r, [0u8; 3]).map_err(From::from) - .and_then(|(r, buf)| { - let ver = buf[0]; - if ver != consts::SOCKS5_VERSION { - return Err(Error::new(Reply::ConnectionRefused, - "Unsupported Socks version")); - } + read_exact(r, [0u8; 3]) + .map_err(From::from) + .and_then(|(r, buf)| { + let ver = buf[0]; + if ver != consts::SOCKS5_VERSION { + return Err(Error::new(Reply::ConnectionRefused, "Unsupported Socks version")); + } - let cmd = buf[1]; - let command = match Command::from_u8(cmd) { - Some(c) => c, - None => { - return Err(Error::new(Reply::CommandNotSupported, - "Unsupported command")) - } - }; + let cmd = buf[1]; + let command = match Command::from_u8(cmd) { + Some(c) => c, + None => return Err(Error::new(Reply::CommandNotSupported, "Unsupported command")), + }; - Ok((r, command)) - }) - .and_then(|(r, command)| { - Address::read_from(r).map(move |(conn, address)| { - let header = - TcpRequestHeader { command: command, - address: address, }; + Ok((r, command)) + }) + .and_then(|(r, command)| { + Address::read_from(r).map(move |(conn, address)| { + let header = TcpRequestHeader { + command: command, + address: address, + }; - (conn, header) - }) - }) + (conn, header) + }) + }) } /// Write data into a writer @@ -586,8 +603,10 @@ impl TcpRequestHeader { /// Writes to buffer pub fn write_to_buf(&self, buf: &mut B) { - let TcpRequestHeader { ref address, - ref command, } = *self; + let TcpRequestHeader { + ref address, + ref command, + } = *self; buf.put_slice(&[consts::SOCKS5_VERSION, command.as_u8(), 0x00]); address.write_to_buf(buf); @@ -620,35 +639,39 @@ pub struct TcpResponseHeader { impl TcpResponseHeader { /// Creates a response header pub fn new(reply: Reply, address: Address) -> TcpResponseHeader { - TcpResponseHeader { reply: reply, - address: address, } + TcpResponseHeader { + reply: reply, + address: address, + } } /// Read from a reader pub fn read_from(r: R) -> impl Future + Send - where R: AsyncRead + Send + 'static + where + R: AsyncRead + Send + 'static, { - read_exact(r, [0u8; 3]).map_err(From::from) - .and_then(|(r, buf)| { - let ver = buf[0]; - let reply_code = buf[1]; + read_exact(r, [0u8; 3]) + .map_err(From::from) + .and_then(|(r, buf)| { + let ver = buf[0]; + let reply_code = buf[1]; - if ver != consts::SOCKS5_VERSION { - return Err(Error::new(Reply::ConnectionRefused, - "Unsupported Socks version")); - } + if ver != consts::SOCKS5_VERSION { + return Err(Error::new(Reply::ConnectionRefused, "Unsupported Socks version")); + } - Ok((r, reply_code)) - }) - .and_then(|(r, reply_code)| { - Address::read_from(r).map(move |(r, address)| { - let rep = TcpResponseHeader { reply: - Reply::from_u8(reply_code), - address: address, }; + Ok((r, reply_code)) + }) + .and_then(|(r, reply_code)| { + Address::read_from(r).map(move |(r, address)| { + let rep = TcpResponseHeader { + reply: Reply::from_u8(reply_code), + address: address, + }; - (r, rep) - }) - }) + (r, rep) + }) + }) } /// Write to a writer @@ -694,21 +717,22 @@ impl HandshakeRequest { /// Read from a reader pub fn read_from(r: R) -> impl Future - where R: AsyncRead + Send + 'static + where + R: AsyncRead + Send + 'static, { - read_exact(r, [0u8, 0u8]).and_then(|(r, buf)| { - let ver = buf[0]; - let nmet = buf[1]; + read_exact(r, [0u8, 0u8]) + .and_then(|(r, buf)| { + let ver = buf[0]; + let nmet = buf[1]; - if ver != consts::SOCKS5_VERSION { - return Err(io::Error::new(io::ErrorKind::Other, - "Invalid Socks5 version")); - } + if ver != consts::SOCKS5_VERSION { + return Err(io::Error::new(io::ErrorKind::Other, "Invalid Socks5 version")); + } - Ok((r, nmet)) - }) - .and_then(|(r, nmet)| read_exact(r, vec![0u8; nmet as usize])) - .and_then(|(r, methods)| Ok((r, HandshakeRequest { methods: methods }))) + Ok((r, nmet)) + }) + .and_then(|(r, nmet)| read_exact(r, vec![0u8; nmet as usize])) + .and_then(|(r, methods)| Ok((r, HandshakeRequest { methods: methods }))) } /// Write to a writer @@ -753,18 +777,19 @@ impl HandshakeResponse { /// Read from a reader pub fn read_from(r: R) -> impl Future - where R: AsyncRead + Send + 'static + where + R: AsyncRead + Send + 'static, { read_exact(r, [0u8, 0u8]).and_then(|(r, buf)| { - let ver = buf[0]; - let met = buf[1]; + let ver = buf[0]; + let met = buf[1]; - if ver != consts::SOCKS5_VERSION { - Err(io::Error::new(io::ErrorKind::Other, "Invalid Socks5 version")) - } else { - Ok((r, HandshakeResponse { chosen_method: met })) - } - }) + if ver != consts::SOCKS5_VERSION { + Err(io::Error::new(io::ErrorKind::Other, "Invalid Socks5 version")) + } else { + Ok((r, HandshakeResponse { chosen_method: met })) + } + }) } /// Write to a writer @@ -807,20 +832,23 @@ pub struct UdpAssociateHeader { impl UdpAssociateHeader { /// Creates a header pub fn new(frag: u8, address: Address) -> UdpAssociateHeader { - UdpAssociateHeader { frag: frag, - address: address, } + UdpAssociateHeader { + frag: frag, + address: address, + } } /// Read from a reader pub fn read_from(r: R) -> impl Future + Send - where R: AsyncRead + Send + 'static + where + R: AsyncRead + Send + 'static, { read_exact(r, [0u8; 3]).map_err(From::from).and_then(|(r, buf)| { let frag = buf[2]; Address::read_from(r).map(move |(r, address)| { - let h = UdpAssociateHeader::new(frag, address); - (r, h) - }) + let h = UdpAssociateHeader::new(frag, address); + (r, h) + }) }) } diff --git a/src/relay/tcprelay/aead.rs b/src/relay/tcprelay/aead.rs index 9e24598b..d7d52965 100644 --- a/src/relay/tcprelay/aead.rs +++ b/src/relay/tcprelay/aead.rs @@ -32,9 +32,11 @@ //! +--------------+---------------+--------------+------------+ //! ``` -use std::cmp; -use std::io::{self, BufRead, Read}; -use std::u16; +use std::{ + cmp, + io::{self, BufRead, Read}, + u16, +}; use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; @@ -55,7 +57,8 @@ enum ReadingStep { /// Reader wrapper that will decrypt data automatically pub struct DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { reader: R, buffer: BytesMut, @@ -68,17 +71,20 @@ pub struct DecryptedReader } impl DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { pub fn new(r: R, t: CipherType, key: &[u8], nounce: &[u8]) -> DecryptedReader { - DecryptedReader { reader: r, - buffer: BytesMut::with_capacity(BUFFER_SIZE), - data: BytesMut::with_capacity(BUFFER_SIZE), - cipher: crypto::new_aead_decryptor(t, key, nounce), - pos: 0, - sent_final: false, - tag_size: t.tag_size(), - read_step: ReadingStep::Length, } + DecryptedReader { + reader: r, + buffer: BytesMut::with_capacity(BUFFER_SIZE), + data: BytesMut::with_capacity(BUFFER_SIZE), + cipher: crypto::new_aead_decryptor(t, key, nounce), + pos: 0, + sent_final: false, + tag_size: t.tag_size(), + read_step: ReadingStep::Length, + } } pub fn get_ref(&self) -> &R { @@ -142,12 +148,18 @@ impl DecryptedReader if len > MAX_PACKET_SIZE { use std::io::{Error, ErrorKind}; - error!("AEAD packet size must be <= {}, but received length {}", - MAX_PACKET_SIZE, len); + error!( + "AEAD packet size must be <= {}, but received length {}", + MAX_PACKET_SIZE, len + ); - let err = Error::new(ErrorKind::InvalidData, - format!("AEAD packet size must be <= {}, but received length {}", - MAX_PACKET_SIZE, len)); + let err = Error::new( + ErrorKind::InvalidData, + format!( + "AEAD packet size must be <= {}, but received length {}", + MAX_PACKET_SIZE, len + ), + ); return Err(err); } @@ -200,7 +212,8 @@ impl DecryptedReader } impl BufRead for DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { fn fill_buf(&mut self) -> io::Result<&[u8]> { while self.pos >= self.data.len() { @@ -223,7 +236,8 @@ impl BufRead for DecryptedReader } impl Read for DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { fn read(&mut self, buf: &mut [u8]) -> io::Result { let nread = { @@ -236,7 +250,8 @@ impl Read for DecryptedReader } impl DecryptedRead for DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { fn buffer_size(&self, data: &[u8]) -> usize { 2 + self.tag_size // len and len_tag @@ -248,7 +263,8 @@ impl AsyncRead for DecryptedReader where R: AsyncRead {} /// Writer wrapper that will encrypt data automatically pub struct EncryptedWriter - where W: AsyncWrite +where + W: AsyncWrite, { writer: W, cipher: BoxAeadEncryptor, @@ -256,18 +272,22 @@ pub struct EncryptedWriter } impl EncryptedWriter - where W: AsyncWrite +where + W: AsyncWrite, { /// Creates a new EncryptedWriter pub fn new(w: W, t: CipherType, key: &[u8], nonce: &[u8]) -> EncryptedWriter { - EncryptedWriter { writer: w, - cipher: crypto::new_aead_encryptor(t, key, nonce), - tag_size: t.tag_size(), } + EncryptedWriter { + writer: w, + cipher: crypto::new_aead_encryptor(t, key, nonce), + tag_size: t.tag_size(), + } } } impl EncryptedWrite for EncryptedWriter - where W: AsyncWrite +where + W: AsyncWrite, { fn write_raw(&mut self, data: &[u8]) -> io::Result { self.writer.write(data) @@ -279,8 +299,10 @@ impl EncryptedWrite for EncryptedWriter fn encrypt(&mut self, data: &[u8], buf: &mut B) -> io::Result<()> { // Data.Len is a 16-bit big-endian integer indicating the length of Data. It should be smaller than 0x3FFF. - assert!(data.len() <= MAX_PACKET_SIZE, - "Buffer size too large, AEAD encryption protocol requires buffer to be smaller than 0x3FFF"); + assert!( + data.len() <= MAX_PACKET_SIZE, + "Buffer size too large, AEAD encryption protocol requires buffer to be smaller than 0x3FFF" + ); let output_length = self.buffer_size(data); let data_length = data.len() as u16; @@ -289,8 +311,10 @@ impl EncryptedWrite for EncryptedWriter BigEndian::write_u16(&mut data_len_buf, data_length); let output_length_size = 2 + self.tag_size; - self.cipher.encrypt(&data_len_buf, unsafe { &mut buf.bytes_mut()[..output_length_size] }); - self.cipher.encrypt(data, unsafe { &mut buf.bytes_mut()[output_length_size..output_length] }); + self.cipher + .encrypt(&data_len_buf, unsafe { &mut buf.bytes_mut()[..output_length_size] }); + self.cipher + .encrypt(data, unsafe { &mut buf.bytes_mut()[output_length_size..output_length] }); unsafe { buf.advance_mut(output_length); diff --git a/src/relay/tcprelay/client.rs b/src/relay/tcprelay/client.rs index dffbb8fc..5ea70994 100644 --- a/src/relay/tcprelay/client.rs +++ b/src/relay/tcprelay/client.rs @@ -1,16 +1,24 @@ //! TCP relay client implementation -use std::io::{self, Read, Write}; -use std::net::SocketAddr; +use std::{ + io::{self, Read, Write}, + net::SocketAddr, +}; use tokio::net::TcpStream; -use tokio_io::io::flush; -use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_io::{io::flush, AsyncRead, AsyncWrite}; use futures::{self, Async, Future, Poll}; use relay::socks5::{ - self, Address, Command, HandshakeRequest, HandshakeResponse, Reply, TcpRequestHeader, TcpResponseHeader, + self, + Address, + Command, + HandshakeRequest, + HandshakeResponse, + Reply, + TcpRequestHeader, + TcpResponseHeader, }; /// Socks5 proxy client @@ -21,8 +29,9 @@ pub struct Socks5Client { impl Socks5Client { /// Connects to `addr` via `proxy` pub fn connect(addr: A, proxy: SocketAddr) -> impl Future + Send - where Address: From, - A: Send + 'static + where + Address: From, + A: Send + 'static, { futures::lazy(move || TcpStream::connect(&proxy)) .and_then(move |s| { @@ -31,41 +40,43 @@ impl Socks5Client { trace!("Client connected, going to send handshake: {:?}", hs); hs.write_to(s) - .and_then(flush) - .and_then(HandshakeResponse::read_from) - .and_then(|(s, rsp)| { - trace!("Got handshake response: {:?}", rsp); - assert_eq!(rsp.chosen_method, socks5::SOCKS5_AUTH_METHOD_NONE); - Ok(s) - }) + .and_then(flush) + .and_then(HandshakeResponse::read_from) + .and_then(|(s, rsp)| { + trace!("Got handshake response: {:?}", rsp); + assert_eq!(rsp.chosen_method, socks5::SOCKS5_AUTH_METHOD_NONE); + Ok(s) + }) }) .and_then(move |s| { // 2. Send request header let h = TcpRequestHeader::new(Command::TcpConnect, From::from(addr)); trace!("Going to connect, req: {:?}", h); h.write_to(s) - .and_then(flush) - .and_then(|s| TcpResponseHeader::read_from(s).map_err(From::from)) - .and_then(|(s, rsp)| { - trace!("Got response: {:?}", rsp); - match rsp.reply { - Reply::Succeeded => Ok(s), - r => { - let err = io::Error::new(io::ErrorKind::Other, format!("{}", r)); - Err(err) + .and_then(flush) + .and_then(|s| TcpResponseHeader::read_from(s).map_err(From::from)) + .and_then(|(s, rsp)| { + trace!("Got response: {:?}", rsp); + match rsp.reply { + Reply::Succeeded => Ok(s), + r => { + let err = io::Error::new(io::ErrorKind::Other, format!("{}", r)); + Err(err) + } } - } - }) + }) }) .map(|s| Socks5Client { stream: s }) } /// UDP Associate `addr` via `proxy` - pub fn udp_associate(addr: A, - proxy: SocketAddr) - -> impl Future + Send - where Address: From, - A: Send + 'static + pub fn udp_associate( + addr: A, + proxy: SocketAddr, + ) -> impl Future + Send + where + Address: From, + A: Send + 'static, { futures::lazy(move || TcpStream::connect(&proxy)) .and_then(move |s| { @@ -74,31 +85,31 @@ impl Socks5Client { trace!("Client connected, going to send handshake: {:?}", hs); hs.write_to(s) - .and_then(flush) - .and_then(HandshakeResponse::read_from) - .and_then(|(s, rsp)| { - trace!("Got handshake response: {:?}", rsp); - assert_eq!(rsp.chosen_method, socks5::SOCKS5_AUTH_METHOD_NONE); - Ok(s) - }) + .and_then(flush) + .and_then(HandshakeResponse::read_from) + .and_then(|(s, rsp)| { + trace!("Got handshake response: {:?}", rsp); + assert_eq!(rsp.chosen_method, socks5::SOCKS5_AUTH_METHOD_NONE); + Ok(s) + }) }) .and_then(move |s| { // 2. Send request header let h = TcpRequestHeader::new(Command::UdpAssociate, From::from(addr)); trace!("Going to connect, req: {:?}", h); h.write_to(s) - .and_then(flush) - .and_then(|s| TcpResponseHeader::read_from(s).map_err(From::from)) - .and_then(|(s, rsp)| { - trace!("Got response: {:?}", rsp); - match rsp.reply { - Reply::Succeeded => Ok((s, rsp.address)), - r => { - let err = io::Error::new(io::ErrorKind::Other, format!("{}", r)); - Err(err) + .and_then(flush) + .and_then(|s| TcpResponseHeader::read_from(s).map_err(From::from)) + .and_then(|(s, rsp)| { + trace!("Got response: {:?}", rsp); + match rsp.reply { + Reply::Succeeded => Ok((s, rsp.address)), + r => { + let err = io::Error::new(io::ErrorKind::Other, format!("{}", r)); + Err(err) + } } - } - }) + }) }) .map(|(s, a)| (Socks5Client { stream: s }, a)) } diff --git a/src/relay/tcprelay/crypto_io.rs b/src/relay/tcprelay/crypto_io.rs index 0d73ba56..fe2d338a 100644 --- a/src/relay/tcprelay/crypto_io.rs +++ b/src/relay/tcprelay/crypto_io.rs @@ -1,19 +1,26 @@ //! IO facilities for TCP relay -use std::io::{self, BufRead, Read}; -use std::mem; -use std::time::{Duration, Instant}; +use std::{ + io::{self, BufRead, Read}, + mem, + time::{Duration, Instant}, +}; use futures::{Async, Future, Poll}; use tokio::timer::Delay; -use tokio_io::io::{copy, Copy}; -use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_io::{ + io::{copy, Copy}, + AsyncRead, + AsyncWrite, +}; use bytes::{BufMut, BytesMut}; -use super::utils::{copy_timeout, copy_timeout_opt, CopyTimeout, CopyTimeoutOpt}; -use super::BUFFER_SIZE; +use super::{ + utils::{copy_timeout, copy_timeout_opt, CopyTimeout, CopyTimeoutOpt}, + BUFFER_SIZE, +}; static DUMMY_BUFFER: [u8; BUFFER_SIZE] = [0u8; BUFFER_SIZE]; @@ -27,24 +34,27 @@ pub trait DecryptedRead: BufRead + AsyncRead { /// Copies all data to `w` fn copy(self, w: W) -> Copy - where Self: Sized, - W: AsyncWrite + where + Self: Sized, + W: AsyncWrite, { copy(self, w) } /// Copies all data to `w`, return `TimedOut` if timeout reaches fn copy_timeout(self, w: W, timeout: Duration) -> CopyTimeout - where Self: Sized, - W: AsyncWrite + where + Self: Sized, + W: AsyncWrite, { copy_timeout(self, w, timeout) } /// The same as `copy_timeout`, but has optional `timeout` fn copy_timeout_opt(self, w: W, timeout: Option) -> CopyTimeoutOpt - where Self: Sized, - W: AsyncWrite + where + Self: Sized, + W: AsyncWrite, { copy_timeout_opt(self, w, timeout) } @@ -66,28 +76,32 @@ pub trait EncryptedWrite { /// Encrypt data in `buf` and write all to the writer fn write_all>(self, buf: B) -> EncryptedWriteAll - where Self: Sized + where + Self: Sized, { EncryptedWriteAll::new(self, buf) } /// Copies all data from `r` fn copy(self, r: R) -> EncryptedCopy - where Self: Sized + where + Self: Sized, { EncryptedCopy::new(r, self) } /// Copies all data from `r` with timeout fn copy_timeout(self, r: R, timeout: Duration) -> EncryptedCopyTimeout - where Self: Sized + where + Self: Sized, { EncryptedCopyTimeout::new(r, self, timeout) } /// Copies all data from `r` with optional timeout fn copy_timeout_opt(self, r: R, timeout: Option) -> EncryptedCopyOpt - where Self: Sized + where + Self: Sized, { match timeout { Some(t) => EncryptedCopyOpt::CopyTimeout(self.copy_timeout(r, t)), @@ -98,8 +112,9 @@ pub trait EncryptedWrite { /// Write all data encrypted pub enum EncryptedWriteAll - where W: EncryptedWrite, - B: AsRef<[u8]> +where + W: EncryptedWrite, + B: AsRef<[u8]>, { Writing { writer: W, @@ -112,34 +127,40 @@ pub enum EncryptedWriteAll } impl EncryptedWriteAll - where W: EncryptedWrite, - B: AsRef<[u8]> +where + W: EncryptedWrite, + B: AsRef<[u8]>, { fn new(w: W, buf: B) -> EncryptedWriteAll { let buffer_size = w.buffer_size(&DUMMY_BUFFER); - EncryptedWriteAll::Writing { writer: w, - buf: buf, - pos: 0, - enc_buf: BytesMut::with_capacity(buffer_size), - encrypted: false, } + EncryptedWriteAll::Writing { + writer: w, + buf: buf, + pos: 0, + enc_buf: BytesMut::with_capacity(buffer_size), + encrypted: false, + } } } impl Future for EncryptedWriteAll - where W: EncryptedWrite, - B: AsRef<[u8]> +where + W: EncryptedWrite, + B: AsRef<[u8]>, { - type Item = (W, B); type Error = io::Error; + type Item = (W, B); fn poll(&mut self) -> Poll { match *self { EncryptedWriteAll::Empty => panic!("poll after EncryptedWriteAll finished"), - EncryptedWriteAll::Writing { ref mut writer, - ref buf, - ref mut pos, - ref mut enc_buf, - ref mut encrypted, } => { + EncryptedWriteAll::Writing { + ref mut writer, + ref buf, + ref mut pos, + ref mut enc_buf, + ref mut encrypted, + } => { if !*encrypted { *encrypted = true; @@ -170,8 +191,9 @@ impl Future for EncryptedWriteAll /// Encrypted copy pub struct EncryptedCopy - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { reader: Option, writer: Option, @@ -183,27 +205,31 @@ pub struct EncryptedCopy } impl EncryptedCopy - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { fn new(r: R, w: W) -> EncryptedCopy { let buffer_size = w.buffer_size(&DUMMY_BUFFER); - EncryptedCopy { reader: Some(r), - writer: Some(w), - read_done: false, - amt: 0, - pos: 0, - cap: 0, - buf: BytesMut::with_capacity(buffer_size), } + EncryptedCopy { + reader: Some(r), + writer: Some(w), + read_done: false, + amt: 0, + pos: 0, + cap: 0, + buf: BytesMut::with_capacity(buffer_size), + } } } impl Future for EncryptedCopy - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { - type Item = (u64, R, W); type Error = io::Error; + type Item = (u64, R, W); fn poll(&mut self) -> Poll { let mut local_buf = [0u8; BUFFER_SIZE]; @@ -247,8 +273,9 @@ impl Future for EncryptedCopy /// Encrypted copy pub struct EncryptedCopyTimeout - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { reader: Option, writer: Option, @@ -263,21 +290,24 @@ pub struct EncryptedCopyTimeout } impl EncryptedCopyTimeout - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { fn new(r: R, w: W, dur: Duration) -> EncryptedCopyTimeout { let buffer_size = w.buffer_size(&DUMMY_BUFFER); - EncryptedCopyTimeout { reader: Some(r), - writer: Some(w), - read_done: false, - amt: 0, - pos: 0, - cap: 0, - timeout: dur, - timer: None, - read_buf: [0u8; BUFFER_SIZE], - write_buf: BytesMut::with_capacity(buffer_size), } + EncryptedCopyTimeout { + reader: Some(r), + writer: Some(w), + read_done: false, + amt: 0, + pos: 0, + cap: 0, + timeout: dur, + timer: None, + read_buf: [0u8; BUFFER_SIZE], + write_buf: BytesMut::with_capacity(buffer_size), + } } fn try_poll_timeout(&mut self) -> io::Result<()> { @@ -336,9 +366,11 @@ impl EncryptedCopyTimeout // Then, unset the previous timeout self.clear_timer(); - match self.writer.as_mut() - .unwrap() - .write_raw(&self.write_buf[self.pos..self.cap]) + match self + .writer + .as_mut() + .unwrap() + .write_raw(&self.write_buf[self.pos..self.cap]) { Ok(n) => { self.pos += n; @@ -355,11 +387,12 @@ impl EncryptedCopyTimeout } impl Future for EncryptedCopyTimeout - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { - type Item = (u64, R, W); type Error = io::Error; + type Item = (u64, R, W); fn poll(&mut self) -> Poll { loop { @@ -395,19 +428,21 @@ impl Future for EncryptedCopyTimeout /// Work for both timeout or no timeout pub enum EncryptedCopyOpt - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { Copy(EncryptedCopy), CopyTimeout(EncryptedCopyTimeout), } impl Future for EncryptedCopyOpt - where R: Read, - W: EncryptedWrite +where + R: Read, + W: EncryptedWrite, { - type Item = (u64, R, W); type Error = io::Error; + type Item = (u64, R, W); fn poll(&mut self) -> Poll { match *self { diff --git a/src/relay/tcprelay/local.rs b/src/relay/tcprelay/local.rs index 3413aacf..78765936 100644 --- a/src/relay/tcprelay/local.rs +++ b/src/relay/tcprelay/local.rs @@ -1,7 +1,6 @@ //! Relay for TCP server that running on local environment -use std::io; -use std::sync::Arc; +use std::{io, sync::Arc}; use futures::Future; diff --git a/src/relay/tcprelay/mod.rs b/src/relay/tcprelay/mod.rs index 96a4e37f..5a20e935 100644 --- a/src/relay/tcprelay/mod.rs +++ b/src/relay/tcprelay/mod.rs @@ -1,22 +1,26 @@ //! Relay for TCP implementation -use std::io::{self, BufRead, Read}; -use std::iter::{IntoIterator, Iterator}; -use std::mem; -use std::net::SocketAddr; -use std::sync::Arc; -use std::time::Duration; +use std::{ + io::{self, BufRead, Read}, + iter::{IntoIterator, Iterator}, + mem, + net::SocketAddr, + sync::Arc, + time::Duration, +}; use config::{Config, ServerAddr, ServerConfig}; use crypto::CipherCategory; -use relay::boxed_future; -use relay::dns_resolver::resolve; -use relay::socks5::Address; +use relay::{boxed_future, dns_resolver::resolve, socks5::Address}; -use tokio::net::{ConnectFuture, TcpStream}; -use tokio_io::io::{read_exact, write_all}; -use tokio_io::io::{ReadHalf, WriteHalf}; -use tokio_io::{AsyncRead, IoFuture}; +use tokio::{ + net::{tcp::ConnectFuture, TcpStream}, + timer::Timeout, +}; +use tokio_io::{ + io::{read_exact, write_all, ReadHalf, WriteHalf}, + AsyncRead, +}; use futures::{self, Async, Future, Poll}; @@ -26,8 +30,10 @@ use byte_string::ByteStr; pub use self::crypto_io::{DecryptedRead, EncryptedWrite}; -use self::aead::{DecryptedReader as AeadDecryptedReader, EncryptedWriter as AeadEncryptedWriter}; -use self::stream::{DecryptedReader as StreamDecryptedReader, EncryptedWriter as StreamEncryptedWriter}; +use self::{ + aead::{DecryptedReader as AeadDecryptedReader, EncryptedWriter as AeadEncryptedWriter}, + stream::{DecryptedReader as StreamDecryptedReader, EncryptedWriter as StreamEncryptedWriter}, +}; mod aead; pub mod client; @@ -148,11 +154,6 @@ impl From> for EncryptedHalf { } } -/// Boxed future of `DecryptedHalf` -pub type DecryptedHalfFut = IoFuture; -/// Boxed future of `EncryptedHalf` -pub type EncryptedHalfFut = IoFuture; - /// Try to connect every IPs one by one enum TcpStreamConnect> { Empty, @@ -165,23 +166,28 @@ enum TcpStreamConnect> { impl> TcpStreamConnect { fn new(iter: I) -> TcpStreamConnect { - TcpStreamConnect::Connect { last_err: None, - addr_iter: iter, - opt_stream_new: None, } + TcpStreamConnect::Connect { + last_err: None, + addr_iter: iter, + opt_stream_new: None, + } } } impl> Future for TcpStreamConnect { - type Item = TcpStream; type Error = io::Error; + type Item = TcpStream; + fn poll(&mut self) -> Poll { use std::io::ErrorKind; match *self { TcpStreamConnect::Empty => unreachable!(), - TcpStreamConnect::Connect { ref mut last_err, - ref mut addr_iter, - ref mut opt_stream_new, } => { + TcpStreamConnect::Connect { + ref mut last_err, + ref mut addr_iter, + ref mut opt_stream_new, + } => { loop { // 1. Poll before doing anything else if let Some((ref mut stream_new, ref addr)) = *opt_stream_new { @@ -209,22 +215,21 @@ impl> Future for TcpStreamConnect { match mem::replace(self, TcpStreamConnect::Empty) { TcpStreamConnect::Empty => unreachable!(), - TcpStreamConnect::Connect { last_err, .. } => { - match last_err { - None => { - let err = io::Error::new(ErrorKind::Other, "connect TCP without any addresses"); - Err(err) - } - Some(err) => Err(err), + TcpStreamConnect::Connect { last_err, .. } => match last_err { + None => { + let err = io::Error::new(ErrorKind::Other, "connect TCP without any addresses"); + Err(err) } - } + Some(err) => Err(err), + }, } } } -fn connect_proxy_server(config: Arc, - svr_cfg: Arc) - -> impl Future + Send { +fn connect_proxy_server( + config: Arc, + svr_cfg: Arc, +) -> impl Future + Send { let timeout = *svr_cfg.timeout(); trace!("Connecting to proxy {:?}, timeout: {:?}", svr_cfg.addr(), timeout); match *svr_cfg.addr() { @@ -235,9 +240,9 @@ fn connect_proxy_server(config: Arc, ServerAddr::DomainName(ref domain, port) => { let fut = { try_timeout(resolve(config.clone(), &domain[..], port, false), timeout).and_then(move |vec_ipaddr| { - let fut = TcpStreamConnect::new(vec_ipaddr.into_iter()); - try_timeout(fut, timeout) - }) + let fut = TcpStreamConnect::new(vec_ipaddr.into_iter()); + try_timeout(fut, timeout) + }) }; boxed_future(fut) } @@ -245,33 +250,49 @@ fn connect_proxy_server(config: Arc, } /// Handshake logic for ShadowSocks Client -pub fn proxy_server_handshake(remote_stream: TcpStream, - svr_cfg: Arc, - relay_addr: Address) - -> impl Future + Send { +pub fn proxy_server_handshake( + remote_stream: TcpStream, + svr_cfg: Arc, + relay_addr: Address, +) -> impl Future< + Item = ( + impl Future + Send, + impl Future + Send, + ), + Error = io::Error, +> + Send { let timeout = *svr_cfg.timeout(); proxy_handshake(remote_stream, svr_cfg).and_then(move |(r_fut, w_fut)| { - let w_fut = w_fut.and_then(move |enc_w| { - // Send relay address to remote - let mut buf = BytesMut::with_capacity(relay_addr.len()); - relay_addr.write_to_buf(&mut buf); + let w_fut = w_fut.and_then(move |enc_w| { + // Send relay address to remote + let mut buf = BytesMut::with_capacity(relay_addr.len()); + relay_addr.write_to_buf(&mut buf); - trace!("Got encrypt stream and going to send addr: {:?}, buf: {:?}", - relay_addr, - buf); + trace!( + "Got encrypt stream and going to send addr: {:?}, buf: {:?}", + relay_addr, + buf + ); - try_timeout(enc_w.write_all(buf), timeout).map(|(w, _)| w) - }); + try_timeout(enc_w.write_all(buf), timeout).map(|(w, _)| w) + }); - Ok((r_fut, boxed_future(w_fut))) - }) + Ok((r_fut, w_fut)) + }) } /// ShadowSocks Client-Server handshake protocol /// Exchange cipher IV and creates stream wrapper -pub fn proxy_handshake(remote_stream: TcpStream, - svr_cfg: Arc) - -> impl Future + Send { +pub fn proxy_handshake( + remote_stream: TcpStream, + svr_cfg: Arc, +) -> impl Future< + Item = ( + impl Future + Send, + impl Future + Send, + ), + Error = io::Error, +> + Send { futures::lazy(|| Ok(remote_stream.split())).and_then(move |(r, w)| { let timeout = svr_cfg.timeout().clone(); @@ -296,19 +317,20 @@ pub fn proxy_handshake(remote_stream: TcpStream, } }; - try_timeout(write_all(w, prev_buf), timeout).and_then( - move |(w, prev_buf)| match svr_cfg.method().category() { + try_timeout(write_all(w, prev_buf), timeout).and_then(move |(w, prev_buf)| { + match svr_cfg.method().category() { CipherCategory::Stream => { let local_iv = prev_buf; - Ok(From::from(StreamEncryptedWriter::new(w, svr_cfg.method(), svr_cfg.key(), &local_iv))) + let wtr = StreamEncryptedWriter::new(w, svr_cfg.method(), svr_cfg.key(), &local_iv); + Ok(From::from(wtr)) } CipherCategory::Aead => { let local_salt = prev_buf; let wtr = AeadEncryptedWriter::new(w, svr_cfg.method(), svr_cfg.key(), &local_salt[..]); Ok(From::from(wtr)) } - }, - ) + } + }) }; let dec = { @@ -338,60 +360,56 @@ pub fn proxy_handshake(remote_stream: TcpStream, }) }; - Ok((boxed_future(dec), boxed_future(enc))) + Ok((dec, enc)) }) } /// Establish tunnel between server and client pub fn tunnel(addr: Address, c2s: CF, s2c: SF) -> impl Future + Send - where CF: Future + Send + 'static, - SF: Future + Send + 'static +where + CF: Future + Send + 'static, + SF: Future + Send + 'static, { let addr = Arc::new(addr); let cloned_addr = addr.clone(); let c2s = c2s.then(move |res| { - match res { - Ok(..) => { - // Continue reading response from remote server - trace!("Relay {} client -> server is finished", cloned_addr); + match res { + Ok(..) => { + // Continue reading response from remote server + trace!("Relay {} client -> server is finished", cloned_addr); - Ok(TunnelDirection::Client2Server) - } - Err(err) => { - error!("Relay {} client -> server aborted: {}", cloned_addr, err); - Err(err) - } - } - }); + Ok(TunnelDirection::Client2Server) + } + Err(err) => { + error!("Relay {} client -> server aborted: {}", cloned_addr, err); + Err(err) + } + } + }); let cloned_addr = addr.clone(); let s2c = s2c.then(move |res| match res { - Ok(..) => { - trace!("Relay {} client <- server is finished", cloned_addr); + Ok(..) => { + trace!("Relay {} client <- server is finished", cloned_addr); - Ok(TunnelDirection::Server2Client) - } - Err(err) => { - error!("Relay {} client <- server aborted: {}", cloned_addr, err); - Err(err) - } - }); + Ok(TunnelDirection::Server2Client) + } + Err(err) => { + error!("Relay {} client <- server aborted: {}", cloned_addr, err); + Err(err) + } + }); c2s.select(s2c) - .and_then(move |(dir, _)| { - match dir { - TunnelDirection::Server2Client => { - trace!("Relay {} client <- server is closed, abort connection", addr) - } - TunnelDirection::Client2Server => { - trace!("Relay {} server -> client is closed, abort connection", addr) - } - } + .and_then(move |(dir, _)| { + match dir { + TunnelDirection::Server2Client => trace!("Relay {} client <- server is closed, abort connection", addr), + TunnelDirection::Client2Server => trace!("Relay {} server -> client is closed, abort connection", addr), + } - Ok(()) - }) - .map_err(|(err, _)| err) + Ok(()) + }).map_err(|(err, _)| err) } /// Read until EOF, and ignore @@ -401,8 +419,8 @@ pub enum IgnoreUntilEnd { } impl Future for IgnoreUntilEnd { - type Item = u64; type Error = io::Error; + type Item = u64; fn poll(&mut self) -> Poll { match *self { @@ -432,24 +450,57 @@ pub fn ignore_until_end(r: R) -> IgnoreUntilEnd { IgnoreUntilEnd::Pending { r: r, amt: 0 } } -fn try_timeout(fut: F, dur: Option) -> impl Future + Send - where F: Future + Send + 'static, - T: 'static +pub enum TimeoutFuture +where + T: 'static, + F: Future + Send + 'static, { + Direct(F), + Wait(Timeout), +} + +impl Future for TimeoutFuture +where + T: 'static, + F: Future + Send + 'static, +{ + type Error = io::Error; + type Item = T; + + fn poll(&mut self) -> Poll { + match *self { + TimeoutFuture::Direct(ref mut f) => f.poll(), + TimeoutFuture::Wait(ref mut f) => match f.poll() { + Ok(Async::NotReady) => Ok(Async::NotReady), + Ok(Async::Ready(x)) => Ok(Async::Ready(x)), + Err(err) => match err.into_inner() { + Some(e) => Err(e), + None => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")), + }, + }, + } + } +} + +fn try_timeout(fut: F, dur: Option) -> impl Future + Send +where + F: Future + Send + 'static, + T: 'static, +{ + use tokio::prelude::*; + match dur { - Some(dur) => boxed_future(io_timeout(fut, dur)), - None => boxed_future(fut), + Some(dur) => TimeoutFuture::Wait(fut.timeout(dur)), + None => TimeoutFuture::Direct(fut), } } fn io_timeout(fut: F, dur: Duration) -> impl Future + Send - where F: Future + Send + 'static, - T: 'static +where + F: Future + Send + 'static, + T: 'static, { use tokio::prelude::*; - fut.timeout(dur).map_err(|err| match err.into_inner() { - Some(e) => e, - None => io::Error::new(io::ErrorKind::TimedOut, "connection timed out"), - }) + TimeoutFuture::Wait(fut.timeout(dur)) } diff --git a/src/relay/tcprelay/server.rs b/src/relay/tcprelay/server.rs index 58136362..1bd2c4e7 100644 --- a/src/relay/tcprelay/server.rs +++ b/src/relay/tcprelay/server.rs @@ -1,26 +1,37 @@ //! Relay for TCP server that running on the server side -use std::io::{self, ErrorKind}; -use std::sync::Arc; -use std::time::Duration; +use std::{ + io::{self, ErrorKind}, + net::SocketAddr, + sync::Arc, + time::Duration, +}; use config::{Config, ServerConfig}; -use relay::boxed_future; -use relay::dns_resolver::resolve; -use relay::socks5::Address; -use relay::tcprelay::crypto_io::{DecryptedRead, EncryptedWrite}; +use relay::{ + boxed_future, + dns_resolver::resolve, + socks5::Address, + tcprelay::crypto_io::{DecryptedRead, EncryptedWrite}, +}; -use futures::stream::futures_unordered; -use futures::stream::Stream; -use futures::{self, Future}; +use futures::{ + self, + stream::{futures_unordered, Stream}, + Future, +}; -use tokio; -use tokio::net::{TcpListener, TcpStream}; -use tokio_io::io::{ReadHalf, WriteHalf}; -use tokio_io::AsyncRead; +use tokio::{ + self, + net::{TcpListener, TcpStream}, +}; +use tokio_io::{ + io::{ReadHalf, WriteHalf}, + AsyncRead, +}; -use super::{proxy_handshake, try_timeout, tunnel, DecryptedHalf, EncryptedHalfFut, TcpStreamConnect}; +use super::{proxy_handshake, try_timeout, tunnel, DecryptedHalf, EncryptedHalf, TcpStreamConnect}; /// Context for doing handshake with client pub struct TcpRelayClientHandshake { @@ -30,8 +41,24 @@ pub struct TcpRelayClientHandshake { } impl TcpRelayClientHandshake { + #[inline] + fn error_handshake(peer_addr: SocketAddr) -> io::Error { + io::Error::new( + ErrorKind::Other, + format!( + "failed to decode Address, may be wrong method or key, peer: {}", + peer_addr + ), + ) + } + /// Doing handshake with client - pub fn handshake(self) -> impl Future { + pub fn handshake( + self, + ) -> impl Future< + Item = TcpRelayClientPending + Send + 'static>, + Error = io::Error, + > + Send { let TcpRelayClientHandshake { s, svr_cfg, config } = self; futures::lazy(move || s.peer_addr().map(|p| (s, p))).and_then(|(s, peer_addr)| { @@ -39,89 +66,109 @@ impl TcpRelayClientHandshake { let timeout = *svr_cfg.timeout(); proxy_handshake(s, svr_cfg).and_then(move |(r_fut, w_fut)| { - r_fut.and_then(move |r| { - let fut = Address::read_from(r).map_err(move |_| { - io::Error::new(ErrorKind::Other, - format!("failed to decode Address, may be wrong method or key, peer: {}", - peer_addr)) - }); - try_timeout(fut, timeout) - }) - .map(move |(r, addr)| TcpRelayClientPending { r: r, - addr: addr, - w: w_fut, - timeout: timeout, - config: config, }) + r_fut + .and_then(move |r| { + let fut = + Address::read_from(r).map_err(move |_| TcpRelayClientHandshake::error_handshake(peer_addr)); + try_timeout(fut, timeout) + }) + .map(move |(r, addr)| TcpRelayClientPending { + r: r, + addr: addr, + w: w_fut, + timeout: timeout, + config: config, + }) }) }) } } /// Context for connecting remote -pub struct TcpRelayClientPending { +pub struct TcpRelayClientPending +where + E: Future + Send + 'static, +{ r: DecryptedHalf, addr: Address, - w: EncryptedHalfFut, + w: E, timeout: Option, config: Arc, } -impl TcpRelayClientPending { - /// Connect to the remote server - #[inline] - fn connect_remote(config: Arc, - addr: Address, - timeout: Option) - -> impl Future { - debug!("Connecting to remote {}", addr); +/// Connect to the remote server +#[inline] +fn connect_remote( + config: Arc, + addr: Address, + timeout: Option, +) -> impl Future + Send { + debug!("Connecting to remote {}", addr); - match addr { - Address::SocketAddress(saddr) => { - if config.forbidden_ip.contains(&saddr.ip()) { - let err = io::Error::new(ErrorKind::Other, - format!("{} is forbidden, failed to connect {}", saddr.ip(), saddr)); - return boxed_future(futures::done(Err(err))); - } + match addr { + Address::SocketAddress(saddr) => { + if config.forbidden_ip.contains(&saddr.ip()) { + let err = io::Error::new( + ErrorKind::Other, + format!("{} is forbidden, failed to connect {}", saddr.ip(), saddr), + ); + return boxed_future(futures::done(Err(err))); + } - let conn = TcpStream::connect(&saddr); - let fut = try_timeout(conn, timeout); - boxed_future(fut) - } - Address::DomainNameAddress(dname, port) => { - let fut = { - try_timeout(resolve(config, dname.as_str(), port, true), timeout).and_then(move |addrs| { - let conn = TcpStreamConnect::new(addrs.into_iter()); - try_timeout(conn, timeout) - }) - }; - boxed_future(fut) - } + let conn = TcpStream::connect(&saddr); + let fut = try_timeout(conn, timeout); + boxed_future(fut) + } + Address::DomainNameAddress(dname, port) => { + let fut = { + try_timeout(resolve(config, dname.as_str(), port, true), timeout).and_then(move |addrs| { + let conn = TcpStreamConnect::new(addrs.into_iter()); + try_timeout(conn, timeout) + }) + }; + boxed_future(fut) } } +} +impl TcpRelayClientPending +where + E: Future + Send + 'static, +{ /// Connect to the remote server - pub fn connect(self) -> impl Future + Send { + pub fn connect( + self, + ) -> impl Future< + Item = TcpRelayClientConnected + Send + 'static>, + Error = io::Error, + > + Send { let addr = self.addr.clone(); let client_pair = (self.r, self.w); let timeout = self.timeout; - TcpRelayClientPending::connect_remote(self.config, self.addr, self.timeout).map(move |stream| { - TcpRelayClientConnected { server: stream.split(), - client: client_pair, - addr: addr, - timeout: timeout, } + connect_remote(self.config, self.addr, self.timeout).map(move |stream| TcpRelayClientConnected { + server: stream.split(), + client: client_pair, + addr: addr, + timeout: timeout, }) } } /// Context for extablishing tunnel -pub struct TcpRelayClientConnected { +pub struct TcpRelayClientConnected +where + E: Future + Send + 'static, +{ server: (ReadHalf, WriteHalf), - client: (DecryptedHalf, EncryptedHalfFut), + client: (DecryptedHalf, E), addr: Address, timeout: Option, } -impl TcpRelayClientConnected { +impl TcpRelayClientConnected +where + E: Future + Send + 'static, +{ /// Establish tunnel #[inline] pub fn tunnel(self) -> impl Future + Send { @@ -129,16 +176,19 @@ impl TcpRelayClientConnected { let (r, w_fut) = self.client; let timeout = self.timeout; - tunnel(self.addr, - r.copy_timeout_opt(svr_w, self.timeout), - w_fut.and_then(move |w| w.copy_timeout_opt(svr_r, timeout))) + tunnel( + self.addr, + r.copy_timeout_opt(svr_w, self.timeout), + w_fut.and_then(move |w| w.copy_timeout_opt(svr_r, timeout)), + ) } } -fn handle_client(server_cfg: Arc, - config: Arc, - socket: TcpStream) - -> impl Future + Send { +fn handle_client( + server_cfg: Arc, + config: Arc, + socket: TcpStream, +) -> impl Future + Send { if let Err(err) = socket.set_keepalive(*server_cfg.timeout()) { error!("Failed to set keep alive: {:?}", err); } @@ -148,26 +198,30 @@ fn handle_client(server_cfg: Arc, } futures::lazy(move || match socket.peer_addr() { - Ok(addr) => Ok((socket, addr)), - Err(err) => { - error!("Failed to get peer_addr after accept: {}", err); - Err(()) - } - }).and_then(move |(socket, addr)| { - trace!("Got connection, addr: {}", addr); - trace!("Picked proxy server: {:?}", server_cfg); + Ok(addr) => Ok((socket, addr)), + Err(err) => { + error!("Failed to get peer_addr after accept: {}", err); + Err(()) + } + }) + .and_then(move |(socket, addr)| { + trace!("Got connection, addr: {}", addr); + trace!("Picked proxy server: {:?}", server_cfg); - let client = TcpRelayClientHandshake { s: socket, - svr_cfg: server_cfg, - config: config, }; + let client = TcpRelayClientHandshake { + s: socket, + svr_cfg: server_cfg, + config: config, + }; - client.handshake() - .and_then(|c| c.connect()) - .and_then(|c| c.tunnel()) - .map_err(move |err| { - error!("Failed to handle client ({}): {}", addr, err); - }) - }) + client + .handshake() + .and_then(|c| c.connect()) + .and_then(|c| c.tunnel()) + .map_err(move |err| { + error!("Failed to handle client ({}): {}", addr, err); + }) + }) } /// Runs the server @@ -187,32 +241,31 @@ pub fn run(config: Arc) -> impl Future + S let svr_cfg = Arc::new(svr_cfg.clone()); let config = config.clone(); - let listening = listener.incoming() - .for_each(move |socket| { - let server_cfg = svr_cfg.clone(); - let config = config.clone(); - tokio::spawn(handle_client(server_cfg, config, socket)); - Ok(()) - }) - .map_err(|err| { - error!("Server run failed: {}", err); - err - }); + let listening = listener + .incoming() + .for_each(move |socket| { + let server_cfg = svr_cfg.clone(); + let config = config.clone(); + tokio::spawn(handle_client(server_cfg, config, socket)); + Ok(()) + }) + .map_err(|err| { + error!("Server run failed: {}", err); + err + }); vec_fut.push(boxed_future(listening)); } futures_unordered(vec_fut).into_future().then(|res| match res { - Ok(..) => { - error!("One of TCP servers exited unexpectly without error"); - let err = io::Error::new(io::ErrorKind::Other, - "server exited unexpectly"); - Err(err) - } - Err((err, ..)) => { - error!("One of TCP servers exited unexpectly with error {}", - err); - Err(err) - } - }) + Ok(..) => { + error!("One of TCP servers exited unexpectly without error"); + let err = io::Error::new(io::ErrorKind::Other, "server exited unexpectly"); + Err(err) + } + Err((err, ..)) => { + error!("One of TCP servers exited unexpectly with error {}", err); + Err(err) + } + }) } diff --git a/src/relay/tcprelay/socks5_local.rs b/src/relay/tcprelay/socks5_local.rs index f345de71..0f590380 100644 --- a/src/relay/tcprelay/socks5_local.rs +++ b/src/relay/tcprelay/socks5_local.rs @@ -1,28 +1,26 @@ //! Local server that accepts SOCKS 5 protocol -use std::io; -use std::net::SocketAddr; -use std::sync::Arc; +use std::{io, net::SocketAddr, sync::Arc}; -use futures::stream::Stream; -use futures::{self, Future}; +use futures::{self, stream::Stream, Future}; -// use tokio_core::net::{TcpListener, TcpStream}; -use tokio_io::io::flush; -use tokio_io::io::{ReadHalf, WriteHalf}; -use tokio_io::AsyncRead; - -use tokio; -use tokio::net::{TcpListener, TcpStream}; +use tokio::{ + self, + net::{TcpListener, TcpStream}, +}; +use tokio_io::{ + io::{flush, ReadHalf, WriteHalf}, + AsyncRead, +}; use config::{Config, ServerConfig}; -use relay::boxed_future; -use relay::loadbalancing::server::LoadBalancer; -use relay::loadbalancing::server::RoundRobin; -use relay::socks5::{self, Address, HandshakeRequest, HandshakeResponse}; -use relay::socks5::{TcpRequestHeader, TcpResponseHeader}; -use relay::tcprelay::crypto_io::{DecryptedRead, EncryptedWrite}; +use relay::{ + boxed_future, + loadbalancing::server::{LoadBalancer, RoundRobin}, + socks5::{self, Address, HandshakeRequest, HandshakeResponse, TcpRequestHeader, TcpResponseHeader}, + tcprelay::crypto_io::{DecryptedRead, EncryptedWrite}, +}; use super::{ignore_until_end, try_timeout, tunnel}; @@ -32,12 +30,13 @@ struct UdpConfig { client_addr: SocketAddr, } -fn handle_socks5_connect(config: Arc, - (r, w): (ReadHalf, WriteHalf), - client_addr: SocketAddr, - addr: Address, - svr_cfg: Arc) - -> impl Future + Send { +fn handle_socks5_connect( + config: Arc, + (r, w): (ReadHalf, WriteHalf), + client_addr: SocketAddr, + addr: Address, + svr_cfg: Arc, +) -> impl Future + Send { let cloned_addr = addr.clone(); let cloned_svr_cfg = svr_cfg.clone(); let timeout = *svr_cfg.timeout(); @@ -53,11 +52,12 @@ fn handle_socks5_connect(config: Arc, boxed_future( try_timeout(try_timeout(header.write_to(w), timeout).and_then(flush), timeout) - .map(move |w| (svr_s, w))) + .map(move |w| (svr_s, w)), + ) } Err(err) => { - use std::io::ErrorKind; use relay::socks5::Reply; + use std::io::ErrorKind; error!("Failed to connect remote server, err: {}", err); @@ -70,7 +70,10 @@ fn handle_socks5_connect(config: Arc, let header = TcpResponseHeader::new(reply, Address::SocketAddress(client_addr)); trace!("Send header: {:?}", header); - boxed_future(try_timeout(try_timeout(header.write_to(w), timeout).and_then(flush), timeout).and_then(|_| Err(err))) + boxed_future( + try_timeout(try_timeout(header.write_to(w), timeout).and_then(flush), timeout) + .and_then(|_| Err(err)), + ) } } }) @@ -87,11 +90,12 @@ fn handle_socks5_connect(config: Arc, }) } -fn handle_socks5_client(config: Arc, - s: TcpStream, - conf: Arc, - udp_conf: UdpConfig) - -> io::Result<()> { +fn handle_socks5_client( + config: Arc, + s: TcpStream, + conf: Arc, + udp_conf: UdpConfig, +) -> io::Result<()> { if let Err(err) = s.set_keepalive(*conf.timeout()) { error!("Failed to set keep alive: {:?}", err); } @@ -112,8 +116,10 @@ fn handle_socks5_client(config: Arc, let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE); let fut = resp.write_to(w).then(|_| { warn!("Currently shadowsocks-rust does not support authentication"); - Err(io::Error::new(io::ErrorKind::Other, - "Currently shadowsocks-rust does not support authentication")) + Err(io::Error::new( + io::ErrorKind::Other, + "Currently shadowsocks-rust does not support authentication", + )) }); boxed_future(fut) } else { @@ -128,17 +134,15 @@ fn handle_socks5_client(config: Arc, .and_then(move |(r, w)| { // Fetch headers TcpRequestHeader::read_from(r).then(move |res| match res { - Ok((r, h)) => boxed_future(futures::finished((r, w, h))), - Err(err) => { - error!("Failed to get TcpRequestHeader: {}", err); - let fut = - TcpResponseHeader::new(err.reply, - Address::SocketAddress(client_addr)) - .write_to(w) - .then(|_| Err(From::from(err))); - boxed_future(fut) - } - }) + Ok((r, h)) => boxed_future(futures::finished((r, w, h))), + Err(err) => { + error!("Failed to get TcpRequestHeader: {}", err); + let fut = TcpResponseHeader::new(err.reply, Address::SocketAddress(client_addr)) + .write_to(w) + .then(|_| Err(From::from(err))); + boxed_future(fut) + } + }) }) .and_then(move |(r, w, header)| { trace!("Socks5 {:?}", header); @@ -164,9 +168,9 @@ fn handle_socks5_client(config: Arc, .write_to(w) .and_then(flush) .and_then(|_| { - // Hold the connection until it ends by its own - ignore_until_end(r).map(|_| ()) - }); + // Hold the connection until it ends by its own + ignore_until_end(r).map(|_| ()) + }); boxed_future(fut) } else { @@ -181,14 +185,14 @@ fn handle_socks5_client(config: Arc, }); tokio::spawn(fut.then(|res| match res { - Ok(..) => Ok(()), - Err(err) => { - if err.kind() != io::ErrorKind::BrokenPipe { - error!("Failed to handle client: {}", err); - } - Err(()) - } - })); + Ok(..) => Ok(()), + Err(err) => { + if err.kind() != io::ErrorKind::BrokenPipe { + error!("Failed to handle client: {}", err); + } + Err(()) + } + })); Ok(()) } @@ -201,16 +205,18 @@ pub fn run(config: Arc) -> impl Future + S info!("ShadowSocks TCP Listening on {}", local_addr); - let udp_conf = UdpConfig { enable_udp: config.enable_udp, - client_addr: local_addr, }; + let udp_conf = UdpConfig { + enable_udp: config.enable_udp, + client_addr: local_addr, + }; let mut servers = RoundRobin::new(&*config); listener.incoming().for_each(move |socket| { - let server_cfg = servers.pick_server(); + let server_cfg = servers.pick_server(); - trace!("Got connection, addr: {}", socket.peer_addr()?); - trace!("Picked proxy server: {:?}", server_cfg); + trace!("Got connection, addr: {}", socket.peer_addr()?); + trace!("Picked proxy server: {:?}", server_cfg); - handle_socks5_client(config.clone(), socket, server_cfg, udp_conf.clone()) - }) + handle_socks5_client(config.clone(), socket, server_cfg, udp_conf.clone()) + }) } diff --git a/src/relay/tcprelay/stream.rs b/src/relay/tcprelay/stream.rs index 9d20a802..382b9cd3 100644 --- a/src/relay/tcprelay/stream.rs +++ b/src/relay/tcprelay/stream.rs @@ -1,20 +1,22 @@ //! Stream protocol implementation -use std::cmp; -use std::io::{self, BufRead, Read}; +use std::{ + cmp, + io::{self, BufRead, Read}, +}; use bytes::{BufMut, BytesMut}; use crypto::{new_stream, CipherType, CryptoMode, StreamCipher, StreamCipherVariant}; use tokio_io::{AsyncRead, AsyncWrite}; -use super::BUFFER_SIZE; -use super::{DecryptedRead, EncryptedWrite}; +use super::{DecryptedRead, EncryptedWrite, BUFFER_SIZE}; const DUMMY_BUFFER: [u8; BUFFER_SIZE] = [0u8; BUFFER_SIZE]; /// Reader wrapper that will decrypt data automatically pub struct DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { reader: R, buffer: BytesMut, @@ -24,16 +26,19 @@ pub struct DecryptedReader } impl DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { pub fn new(r: R, t: CipherType, key: &[u8], iv: &[u8]) -> DecryptedReader { let cipher = new_stream(t, key, iv, CryptoMode::Decrypt); let buffer_size = cipher.buffer_size(&DUMMY_BUFFER); - DecryptedReader { reader: r, - buffer: BytesMut::with_capacity(buffer_size), - cipher: cipher, - pos: 0, - sent_final: false, } + DecryptedReader { + reader: r, + buffer: BytesMut::with_capacity(buffer_size), + cipher: cipher, + pos: 0, + sent_final: false, + } } pub fn get_ref(&self) -> &R { @@ -60,7 +65,8 @@ impl DecryptedReader } impl BufRead for DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { fn fill_buf(&mut self) -> io::Result<&[u8]> { while self.pos >= self.buffer.len() { @@ -106,7 +112,8 @@ impl BufRead for DecryptedReader } impl Read for DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { fn read(&mut self, buf: &mut [u8]) -> io::Result { let nread = { @@ -119,7 +126,8 @@ impl Read for DecryptedReader } impl DecryptedRead for DecryptedReader - where R: AsyncRead +where + R: AsyncRead, { fn buffer_size(&self, data: &[u8]) -> usize { self.cipher.buffer_size(data) @@ -130,19 +138,23 @@ impl AsyncRead for DecryptedReader where R: AsyncRead {} /// Writer wrapper that will encrypt data automatically pub struct EncryptedWriter - where W: AsyncWrite +where + W: AsyncWrite, { writer: W, cipher: StreamCipherVariant, } impl EncryptedWriter - where W: AsyncWrite +where + W: AsyncWrite, { /// Creates a new EncryptedWriter pub fn new(w: W, t: CipherType, key: &[u8], iv: &[u8]) -> EncryptedWriter { - EncryptedWriter { writer: w, - cipher: new_stream(t, key, iv, CryptoMode::Encrypt), } + EncryptedWriter { + writer: w, + cipher: new_stream(t, key, iv, CryptoMode::Encrypt), + } } fn cipher_update(&mut self, data: &[u8], buf: &mut B) -> io::Result<()> { @@ -155,7 +167,8 @@ impl EncryptedWriter } impl Drop for EncryptedWriter - where W: AsyncWrite +where + W: AsyncWrite, { fn drop(&mut self) { let mut buf = Vec::new(); @@ -168,7 +181,8 @@ impl Drop for EncryptedWriter } impl EncryptedWrite for EncryptedWriter - where W: AsyncWrite +where + W: AsyncWrite, { fn write_raw(&mut self, data: &[u8]) -> io::Result { self.writer.write(data) diff --git a/src/relay/tcprelay/utils.rs b/src/relay/tcprelay/utils.rs index 5aa6624d..504e82d5 100644 --- a/src/relay/tcprelay/utils.rs +++ b/src/relay/tcprelay/utils.rs @@ -1,11 +1,16 @@ //! Utility functions -use std::io; -use std::time::{Duration, Instant}; +use std::{ + io, + time::{Duration, Instant}, +}; use tokio::timer::Delay; -use tokio_io::io::{copy, Copy}; -use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_io::{ + io::{copy, Copy}, + AsyncRead, + AsyncWrite, +}; use futures::{Async, Future, Poll}; @@ -13,16 +18,18 @@ use super::BUFFER_SIZE; /// Copies all data from `r` to `w`, abort if timeout reaches pub fn copy_timeout(r: R, w: W, dur: Duration) -> CopyTimeout - where R: AsyncRead, - W: AsyncWrite +where + R: AsyncRead, + W: AsyncWrite, { CopyTimeout::new(r, w, dur) } /// Copies all data from `r` to `w`, abort if timeout reaches pub struct CopyTimeout - where R: AsyncRead, - W: AsyncWrite +where + R: AsyncRead, + W: AsyncWrite, { r: Option, w: Option, @@ -35,30 +42,31 @@ pub struct CopyTimeout } impl CopyTimeout - where R: AsyncRead, - W: AsyncWrite +where + R: AsyncRead, + W: AsyncWrite, { fn new(r: R, w: W, timeout: Duration) -> CopyTimeout { - CopyTimeout { r: Some(r), - w: Some(w), - timeout: timeout, - amt: 0, - timer: None, - buf: [0u8; BUFFER_SIZE], - pos: 0, - cap: 0, } + CopyTimeout { + r: Some(r), + w: Some(w), + timeout: timeout, + amt: 0, + timer: None, + buf: [0u8; BUFFER_SIZE], + pos: 0, + cap: 0, + } } fn try_poll_timeout(&mut self) -> io::Result<()> { match self.timer.as_mut() { None => Ok(()), - Some(t) => { - match t.poll() { - Err(err) => panic!("Failed to poll on timer, err: {}", err), - Ok(Async::Ready(..)) => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")), - Ok(Async::NotReady) => Ok(()), - } - } + Some(t) => match t.poll() { + Err(err) => panic!("Failed to poll on timer, err: {}", err), + Ok(Async::Ready(..)) => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")), + Ok(Async::NotReady) => Ok(()), + }, } } @@ -104,11 +112,12 @@ impl CopyTimeout } impl Future for CopyTimeout - where R: AsyncRead, - W: AsyncWrite +where + R: AsyncRead, + W: AsyncWrite, { - type Item = (u64, R, W); type Error = io::Error; + type Item = (u64, R, W); fn poll(&mut self) -> Poll { loop { @@ -146,8 +155,9 @@ impl Future for CopyTimeout /// Copies all data from `r` to `w` with optional timeout param pub fn copy_timeout_opt(r: R, w: W, dur: Option) -> CopyTimeoutOpt - where R: AsyncRead, - W: AsyncWrite +where + R: AsyncRead, + W: AsyncWrite, { match dur { Some(d) => CopyTimeoutOpt::CopyTimeout(copy_timeout(r, w, d)), @@ -162,8 +172,8 @@ pub enum CopyTimeoutOpt { } impl Future for CopyTimeoutOpt { - type Item = (u64, R, W); type Error = io::Error; + type Item = (u64, R, W); fn poll(&mut self) -> Poll { match *self { diff --git a/src/relay/udprelay/crypto_io.rs b/src/relay/udprelay/crypto_io.rs index 86de6c19..02d15e47 100644 --- a/src/relay/udprelay/crypto_io.rs +++ b/src/relay/udprelay/crypto_io.rs @@ -22,8 +22,7 @@ use std::io; -use crypto::StreamCipher; -use crypto::{self, CipherCategory, CipherType, CryptoMode}; +use crypto::{self, CipherCategory, CipherType, CryptoMode, StreamCipher}; /// Encrypt payload into ShadowSocks UDP encrypted packet pub fn encrypt_payload(t: CipherType, key: &[u8], payload: &[u8]) -> io::Result> { diff --git a/src/relay/udprelay/dns.rs b/src/relay/udprelay/dns.rs index 325ac3a4..9e6268ca 100644 --- a/src/relay/udprelay/dns.rs +++ b/src/relay/udprelay/dns.rs @@ -1,25 +1,26 @@ //! UDP DNS relay -use std::fmt; -use std::io::{self, Cursor}; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use std::sync::{Arc, Mutex}; -use std::time::Instant; +use std::{ + fmt, + io::{self, Cursor}, + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::{Arc, Mutex}, + time::Instant, +}; use dns_parser::{Packet, RRData}; -use futures::future::join_all; -use futures::stream::futures_unordered; -use futures::{self, Future, Stream}; +use futures::{self, future::join_all, stream::futures_unordered, Future, Stream}; use lru_cache::LruCache; -use tokio; -use tokio::net::UdpSocket; +use tokio::{self, net::UdpSocket}; -use super::crypto_io::{decrypt_payload, encrypt_payload}; -use super::{PacketStream, SendDgramRc, SharedUdpSocket}; +use super::{ + crypto_io::{decrypt_payload, encrypt_payload}, + PacketStream, + SendDgramRc, + SharedUdpSocket, +}; use config::{Config, ServerAddr, ServerConfig}; -use relay::boxed_future; -use relay::dns_resolver::resolve; -use relay::socks5::Address; +use relay::{boxed_future, dns_resolver::resolve, socks5::Address}; struct PrettyRRData<'a> { data: &'a RRData<'a>, @@ -38,26 +39,37 @@ impl<'a> fmt::Display for PrettyRRData<'a> { RRData::NS(ref c) => write!(f, "NS({})", c.to_string()), RRData::A(ref i) => write!(f, "A({})", i), RRData::AAAA(ref i) => write!(f, "AAAA({})", i), - RRData::SRV { priority, weight, port, target } - => write!(f, - "SRV({{priority: {}, weight: {}, port: {}, target: {}}})", - priority, - weight, - port, - target.to_string()), - RRData::SOA(ref s) - => write!(f, - "SOA({{primary_ns: {}, mailbox: {}, serial: {}, refresh: {}, retry: {}, expire: {}, minimum_ttl: {}}})", - s.primary_ns.to_string(), - s.mailbox.to_string(), - s.serial, - s.refresh, - s.retry, - s.expire, - s.minimum_ttl), + RRData::SRV { + priority, + weight, + port, + target, + } => write!( + f, + "SRV({{priority: {}, weight: {}, port: {}, target: {}}})", + priority, + weight, + port, + target.to_string() + ), + RRData::SOA(ref s) => write!( + f, + "SOA({{primary_ns: {}, mailbox: {}, serial: {}, refresh: {}, retry: {}, expire: {}, minimum_ttl: {}}})", + s.primary_ns.to_string(), + s.mailbox.to_string(), + s.serial, + s.refresh, + s.retry, + s.expire, + s.minimum_ttl + ), RRData::PTR(ref p) => write!(f, "PTR({})", p.to_string()), - RRData::MX { preference, exchange } - => write!(f, "MX({{preference: {}, exchange: {}}})", preference, exchange.to_string()), + RRData::MX { preference, exchange } => write!( + f, + "MX({{preference: {}, exchange: {}}})", + preference, + exchange.to_string() + ), RRData::TXT(t) => write!(f, "TXT({})", t), RRData::Unknown(u) => write!(f, "Unknown({:?})", u), } @@ -76,9 +88,11 @@ impl<'a> PrettyPacket<'a> { impl<'a> fmt::Display for PrettyPacket<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "Packet (id={} opcode={:?})", - self.pkt.header.id, self.pkt.header.opcode)?; + write!( + f, + "Packet (id={} opcode={:?})", + self.pkt.header.id, self.pkt.header.opcode + )?; if !self.pkt.questions.is_empty() { write!(f, " QUESTION[")?; @@ -125,10 +139,11 @@ pub fn run(config: Arc) -> impl Future + S let local_addr = *config.local.as_ref().unwrap(); futures::lazy(move || { - info!("ShadowSocks UDP DNS Listening on {}", local_addr); + info!("ShadowSocks UDP DNS Listening on {}", local_addr); - UdpSocket::bind(&local_addr) - }).and_then(move |l| listen(config, l)) + UdpSocket::bind(&local_addr) + }) + .and_then(move |l| listen(config, l)) } fn listen(config: Arc, l: UdpSocket) -> impl Future + Send { @@ -147,154 +162,151 @@ fn listen(config: Arc, l: UdpSocket) -> impl Future { - error!("One of DNS servers exited unexpectly without error"); - let err = io::Error::new(io::ErrorKind::Other, "server exited unexpectly"); - Err(err) - } - Err((err, ..)) => { - error!("One of DNS servers exited unexpectly with error {}", err); - Err(err) - } - }) - }) + join_all(svr_fut) + .and_then(move |svr_addrs| { + let mut u = Vec::with_capacity(svr_addrs.len()); + for (idx, svr_addr) in svr_addrs.into_iter().enumerate() { + let local_addr = SocketAddr::new(IpAddr::from(Ipv4Addr::new(0, 0, 0, 0)), 0); + let s = UdpSocket::bind(&local_addr)?; + let svr_cfg = Arc::new(cloned_config.server[idx].clone()); + u.push((Arc::new(Mutex::new(s)), svr_cfg, svr_addr[0])); + } + Ok(u) + }) + .and_then(move |vec_servers| { + let mut f = Vec::with_capacity(1 + vec_servers.len()); + let l = Arc::new(Mutex::new(l)); + f.push(boxed_future(handle_l2r(config, l.clone(), vec_servers.clone()))); + for (svr, cfg, _) in vec_servers { + f.push(boxed_future(handle_r2l(l.clone(), svr, cfg))) + } + futures_unordered(f).into_future().then(|res| match res { + Ok(..) => { + error!("One of DNS servers exited unexpectly without error"); + let err = io::Error::new(io::ErrorKind::Other, "server exited unexpectly"); + Err(err) + } + Err((err, ..)) => { + error!("One of DNS servers exited unexpectly with error {}", err); + Err(err) + } + }) + }) } lazy_static! { static ref GLOBAL_QUERY_ADDR: Mutex> = Mutex::new(LruCache::new(1024)); } -fn handle_l2r(config: Arc, - l: SharedUdpSocket, - server: Vec<(SharedUdpSocket, Arc, SocketAddr)>) - -> impl Future + Send { +fn handle_l2r( + config: Arc, + l: SharedUdpSocket, + server: Vec<(SharedUdpSocket, Arc, SocketAddr)>, +) -> impl Future + Send { assert!(!server.is_empty()); let mut server_idx: usize = 0; let server = Arc::new(server); PacketStream::new(l).for_each(move |(payload, src)| { - let server = server.clone(); - let config = config.clone(); - let pkt_fut = - futures::lazy(move || { - let pkt = Packet::parse(&payload[..]).map_err(|err| { - error!("Failed to parse DNS payload, err: {}", err); - io::Error::new(io::ErrorKind::Other, - "parse DNS packet failed") - })?; - - let (ref socket, ref svr_cfg, svr_addr) = server[server_idx % server.len()]; - let (ni, _) = server_idx.overflowing_add(1); - server_idx = ni; - - debug!("DNS {} -> {} {}", src, svr_cfg.addr(), PrettyPacket::new(&pkt)); - trace!("DETAIL {} -> {} {:?}", src, svr_cfg.addr(), pkt); - - let mut buf = Vec::new(); - Address::SocketAddress(config.get_remote_dns()).write_to_buf(&mut buf); - - buf.extend_from_slice(&payload); - - let socket = socket.clone(); - let id = pkt.header.id; - encrypt_payload(svr_cfg.method(), svr_cfg.key(), &buf).map(move |send_payload| { - (socket, - svr_addr, - send_payload, - id) - }) - }).and_then(move |(socket, svr_addr, send_payload, id)| { - SendDgramRc::new(socket, send_payload, svr_addr).map(move |_| { - GLOBAL_QUERY_ADDR.lock() - .unwrap() - .insert(id, (src, Instant::now())); - }) - }); - tokio::spawn(pkt_fut.then(|res| match res { - Ok(..) => Ok(()), - Err(err) => { - error!("Failed to handle local -> remote packet, err: {}", err); - Err(()) - } - })); - - Ok(()) - }) -} - -fn handle_r2l(l: SharedUdpSocket, - r: SharedUdpSocket, - svr_cfg: Arc) - -> impl Future + Send { - PacketStream::new(r).for_each(move |(payload, src)| { - let l = l.clone(); - let svr_cfg = svr_cfg.clone(); + let server = server.clone(); + let config = config.clone(); let pkt_fut = futures::lazy(move || { - decrypt_payload(svr_cfg.method(), svr_cfg.key(), &payload) - }).and_then(move |payload| { - Address::read_from(Cursor::new(payload)) - .map_err(From::from) - }).and_then(move |(cur, ..)| { - let pos = cur.position() as usize; - let payload = cur.into_inner(); - - let pkt = Packet::parse(&payload[pos..]).map_err(|err| { + let pkt = Packet::parse(&payload[..]).map_err(|err| { error!("Failed to parse DNS payload, err: {}", err); io::Error::new(io::ErrorKind::Other, "parse DNS packet failed") })?; - let payload = payload[pos..].to_vec(); + let (ref socket, ref svr_cfg, svr_addr) = server[server_idx % server.len()]; + let (ni, _) = server_idx.overflowing_add(1); + server_idx = ni; - match GLOBAL_QUERY_ADDR.lock().unwrap().remove(&pkt.header.id) { - Some((cli_addr, start_time)) => { - debug!("DNS {} <- {} {} elapsed: {:?}", cli_addr, src, PrettyPacket::new(&pkt), Instant::now() - start_time); - trace!("DETAIL {} <- {} {:?}", cli_addr, src, pkt); + debug!("DNS {} -> {} {}", src, svr_cfg.addr(), PrettyPacket::new(&pkt)); + trace!("DETAIL {} -> {} {:?}", src, svr_cfg.addr(), pkt); - Ok(Some((cli_addr, payload))) - } - None => { - error!("DNS received packet id={} opcode={:?} but found no local endpoint", - pkt.header.id, pkt.header.opcode); - Ok(None) - } - } - }).and_then(move |opt| { - match opt { - Some((cli_addr, payload)) => { - let f = SendDgramRc::new(l, payload, cli_addr) - .map(|_| ()); - boxed_future(f) - } - None => boxed_future(futures::finished(())) - } + let mut buf = Vec::new(); + Address::SocketAddress(config.get_remote_dns()).write_to_buf(&mut buf); + + buf.extend_from_slice(&payload); + + let socket = socket.clone(); + let id = pkt.header.id; + encrypt_payload(svr_cfg.method(), svr_cfg.key(), &buf) + .map(move |send_payload| (socket, svr_addr, send_payload, id)) + }) + .and_then(move |(socket, svr_addr, send_payload, id)| { + SendDgramRc::new(socket, send_payload, svr_addr).map(move |_| { + GLOBAL_QUERY_ADDR.lock().unwrap().insert(id, (src, Instant::now())); + }) }); + tokio::spawn(pkt_fut.then(|res| match res { + Ok(..) => Ok(()), + Err(err) => { + error!("Failed to handle local -> remote packet, err: {}", err); + Err(()) + } + })); - tokio::spawn(pkt_fut.then(|res| { - match res { - Ok(..) => Ok(()), - Err(err) => { - error!("Failed to handle local <- remote packet, err: {}", err); - Err(()) + Ok(()) + }) +} + +fn handle_r2l( + l: SharedUdpSocket, + r: SharedUdpSocket, + svr_cfg: Arc, +) -> impl Future + Send { + PacketStream::new(r).for_each(move |(payload, src)| { + let l = l.clone(); + let svr_cfg = svr_cfg.clone(); + let pkt_fut = futures::lazy(move || decrypt_payload(svr_cfg.method(), svr_cfg.key(), &payload)) + .and_then(move |payload| Address::read_from(Cursor::new(payload)).map_err(From::from)) + .and_then(move |(cur, ..)| { + let pos = cur.position() as usize; + let payload = cur.into_inner(); + + let pkt = Packet::parse(&payload[pos..]).map_err(|err| { + error!("Failed to parse DNS payload, err: {}", err); + io::Error::new(io::ErrorKind::Other, "parse DNS packet failed") + })?; + + let payload = payload[pos..].to_vec(); + + match GLOBAL_QUERY_ADDR.lock().unwrap().remove(&pkt.header.id) { + Some((cli_addr, start_time)) => { + debug!( + "DNS {} <- {} {} elapsed: {:?}", + cli_addr, + src, + PrettyPacket::new(&pkt), + Instant::now() - start_time + ); + trace!("DETAIL {} <- {} {:?}", cli_addr, src, pkt); + + Ok(Some((cli_addr, payload))) + } + None => { + error!( + "DNS received packet id={} opcode={:?} but found no local endpoint", + pkt.header.id, pkt.header.opcode + ); + Ok(None) + } + } + }) + .and_then(move |opt| match opt { + Some((cli_addr, payload)) => { + let f = SendDgramRc::new(l, payload, cli_addr).map(|_| ()); + boxed_future(f) } + None => boxed_future(futures::finished(())), + }); + + tokio::spawn(pkt_fut.then(|res| match res { + Ok(..) => Ok(()), + Err(err) => { + error!("Failed to handle local <- remote packet, err: {}", err); + Err(()) } })); diff --git a/src/relay/udprelay/local.rs b/src/relay/udprelay/local.rs index d739b04d..5d1770c9 100644 --- a/src/relay/udprelay/local.rs +++ b/src/relay/udprelay/local.rs @@ -1,40 +1,45 @@ //! UDP relay local server -use std::io::{self, Cursor, ErrorKind, Read}; -use std::net::SocketAddr; -use std::net::{IpAddr, Ipv4Addr}; -use std::sync::{Arc, Mutex}; -use std::time::Duration; +use std::{ + io::{self, Cursor, ErrorKind, Read}, + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::{Arc, Mutex}, + time::Duration, +}; use futures::{self, Future, Stream}; -use tokio; -use tokio::net::UdpSocket; -use tokio::util::FutureExt; +use tokio::{self, net::UdpSocket, util::FutureExt}; use config::{Config, ServerAddr, ServerConfig}; -use relay::boxed_future; -use relay::dns_resolver::resolve; -use relay::loadbalancing::server::{LoadBalancer, RoundRobin}; -use relay::socks5::{Address, UdpAssociateHeader}; +use relay::{ + boxed_future, + dns_resolver::resolve, + loadbalancing::server::{LoadBalancer, RoundRobin}, + socks5::{Address, UdpAssociateHeader}, +}; -use super::crypto_io::{decrypt_payload, encrypt_payload}; -use super::MAXIMUM_UDP_PAYLOAD_SIZE; -use super::{PacketStream, SendDgramRc}; +use super::{ + crypto_io::{decrypt_payload, encrypt_payload}, + PacketStream, + SendDgramRc, + MAXIMUM_UDP_PAYLOAD_SIZE, +}; /// Resolves server address to SocketAddr -fn resolve_server_addr(config: Arc, - svr_cfg: Arc) - -> impl Future + Send { +fn resolve_server_addr( + config: Arc, + svr_cfg: Arc, +) -> impl Future + Send { match *svr_cfg.addr() { // Return directly if it is a SocketAddr ServerAddr::SocketAddr(ref addr) => boxed_future(futures::finished(*addr)), // Resolve domain name to SocketAddr ServerAddr::DomainName(ref dname, port) => { let fut = resolve(config, dname, port, false).map(move |vec_ipaddr| { - assert!(!vec_ipaddr.is_empty()); - vec_ipaddr[0] - }); + assert!(!vec_ipaddr.is_empty()); + vec_ipaddr[0] + }); boxed_future(fut) } } @@ -74,8 +79,7 @@ fn listen(config: Arc, l: UdpSocket) -> impl Future, l: UdpSocket) -> impl Future {}, payload length {} bytes", src, addr, payload.len()); + debug!( + "UDP ASSOCIATE {} -> {}, payload length {} bytes", + src, + addr, + payload.len() + ); let to = timeout.unwrap_or(DEFAULT_TIMEOUT); let caddr = addr.clone(); - remote_udp.send_dgram(payload, &remote_addr) - .timeout(to) - .map_err(move |err| { - match err.into_inner() { - Some(e) => e, - None => { - error!("Udp associate sending datagram {} -> {} timed out in {:?}", src, caddr, to); - io::Error::new(io::ErrorKind::TimedOut, "udp send timed out") - } - } - }) - .map(|(remote_udp, _)| (remote_udp, addr)) + remote_udp + .send_dgram(payload, &remote_addr) + .timeout(to) + .map_err(move |err| match err.into_inner() { + Some(e) => e, + None => { + error!( + "Udp associate sending datagram {} -> {} timed out in {:?}", + src, caddr, to + ); + io::Error::new(io::ErrorKind::TimedOut, "udp send timed out") + } + }) + .map(|(remote_udp, _)| (remote_udp, addr)) }) .and_then(move |(remote_udp, addr)| { let buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; let to = timeout.unwrap_or(DEFAULT_TIMEOUT); let caddr = addr.clone(); - remote_udp.recv_dgram(buf) - .timeout(to) - .map_err(move |err| { - match err.into_inner() { - Some(e) => e, - None => { - error!("Udp associate waiting datagram {} <- {} timed out in {:?}", src, caddr, to); - io::Error::new(io::ErrorKind::TimedOut, "udp recv timed out") - } - } - }) - .and_then(move |(_remote_udp, buf, n, _from)| { - let svr_cfg = svr_cfg_cloned; - decrypt_payload(svr_cfg.method(), svr_cfg.key(), &buf[..n]) - }) - .map(|payload| (payload, addr)) + remote_udp + .recv_dgram(buf) + .timeout(to) + .map_err(move |err| match err.into_inner() { + Some(e) => e, + None => { + error!( + "Udp associate waiting datagram {} <- {} timed out in {:?}", + src, caddr, to + ); + io::Error::new(io::ErrorKind::TimedOut, "udp recv timed out") + } + }) + .and_then(move |(_remote_udp, buf, n, _from)| { + let svr_cfg = svr_cfg_cloned; + decrypt_payload(svr_cfg.method(), svr_cfg.key(), &buf[..n]) + }) + .map(|payload| (payload, addr)) }) .and_then(move |(payload, addr)| { Address::read_from(Cursor::new(payload)) @@ -131,7 +144,10 @@ fn listen(config: Arc, l: UdpSocket) -> impl Future, l: UdpSocket) -> impl Future) -> impl Future + S let local_addr = *config.local.as_ref().unwrap(); futures::lazy(move || { - info!("ShadowSocks UDP Listening on {}", local_addr); + info!("ShadowSocks UDP Listening on {}", local_addr); - UdpSocket::bind(&local_addr) - }).and_then(move |l| listen(config, l)) + UdpSocket::bind(&local_addr) + }) + .and_then(move |l| listen(config, l)) } diff --git a/src/relay/udprelay/mod.rs b/src/relay/udprelay/mod.rs index 8c67bfe3..51ba509b 100644 --- a/src/relay/udprelay/mod.rs +++ b/src/relay/udprelay/mod.rs @@ -37,10 +37,12 @@ //! | Fixed | Variable | //! +-------+--------------+ -use std::io; -use std::mem; -use std::net::SocketAddr; -use std::sync::{Arc, Mutex}; +use std::{ + io, + mem, + net::SocketAddr, + sync::{Arc, Mutex}, +}; use tokio::net::UdpSocket; @@ -70,14 +72,17 @@ pub struct PacketStream { impl PacketStream { /// Creates a new `PacketStream` pub fn new(udp: SharedUdpSocket) -> PacketStream { - PacketStream { udp: udp, - buf: [0u8; MAXIMUM_UDP_PAYLOAD_SIZE], } + PacketStream { + udp: udp, + buf: [0u8; MAXIMUM_UDP_PAYLOAD_SIZE], + } } } impl Stream for PacketStream { - type Item = (Vec, SocketAddr); type Error = io::Error; + type Item = (Vec, SocketAddr); + fn poll(&mut self) -> Poll, Self::Error> { let (n, addr) = try_ready!(self.udp.lock().unwrap().poll_recv_from(&mut self.buf)); Ok(Async::Ready(Some((self.buf[..n].to_vec(), addr)))) @@ -100,20 +105,27 @@ pub struct SendDgramRc> { impl> SendDgramRc { pub fn new(udp: SharedUdpSocket, buf: B, addr: SocketAddr) -> SendDgramRc { - SendDgramRc { stat: SendDgramStat::Pending { udp: udp, - buf: buf, - addr: addr, }, } + SendDgramRc { + stat: SendDgramStat::Pending { + udp: udp, + buf: buf, + addr: addr, + }, + } } } impl> Future for SendDgramRc { - type Item = (SharedUdpSocket, usize, B); type Error = io::Error; + type Item = (SharedUdpSocket, usize, B); + fn poll(&mut self) -> Poll { let n = match self.stat { - SendDgramStat::Pending { ref udp, - ref buf, - ref addr, } => try_ready!(udp.lock().unwrap().poll_send_to(buf.as_ref(), addr)), + SendDgramStat::Pending { + ref udp, + ref buf, + ref addr, + } => try_ready!(udp.lock().unwrap().poll_send_to(buf.as_ref(), addr)), SendDgramStat::Empty => unreachable!(), }; diff --git a/src/relay/udprelay/server.rs b/src/relay/udprelay/server.rs index 899a1056..f2b49ba5 100644 --- a/src/relay/udprelay/server.rs +++ b/src/relay/udprelay/server.rs @@ -1,32 +1,34 @@ //! UDP relay proxy server -use std::io::{self, Cursor, ErrorKind}; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use std::sync::{Arc, Mutex}; -use std::time::Duration; +use std::{ + io::{self, Cursor, ErrorKind}, + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::{Arc, Mutex}, + time::Duration, +}; -use futures::stream::futures_unordered; -use futures::{self, Future, Stream}; +use futures::{self, stream::futures_unordered, Future, Stream}; -use tokio; -use tokio::net::UdpSocket; -use tokio::util::FutureExt; +use tokio::{self, net::UdpSocket, util::FutureExt}; use config::{Config, ServerConfig}; -use relay::boxed_future; -use relay::dns_resolver::resolve; -use relay::socks5::Address; +use relay::{boxed_future, dns_resolver::resolve, socks5::Address}; -use super::crypto_io::{decrypt_payload, encrypt_payload}; -use super::MAXIMUM_UDP_PAYLOAD_SIZE; -use super::{PacketStream, SendDgramRc}; +use super::{ + crypto_io::{decrypt_payload, encrypt_payload}, + PacketStream, + SendDgramRc, + MAXIMUM_UDP_PAYLOAD_SIZE, +}; fn resolve_remote_addr(config: Arc, addr: Address) -> impl Future + Send { match addr { Address::SocketAddress(s) => { if config.forbidden_ip.contains(&s.ip()) { - let err = io::Error::new(ErrorKind::Other, - format!("{} is forbidden, failed to connect {}", s.ip(), s)); + let err = io::Error::new( + ErrorKind::Other, + format!("{} is forbidden, failed to connect {}", s.ip(), s), + ); return boxed_future(futures::done(Err(err))); } @@ -34,9 +36,9 @@ fn resolve_remote_addr(config: Arc, addr: Address) -> impl Future { let fut = resolve(config, &dname, port, true).map(move |vec_ipaddr| { - assert!(!vec_ipaddr.is_empty()); - vec_ipaddr[0] - }); + assert!(!vec_ipaddr.is_empty()); + vec_ipaddr[0] + }); boxed_future(fut) } } @@ -54,46 +56,47 @@ fn listen(config: Arc, svr_cfg: Arc) -> impl Future {}, payload length {} bytes", src, addr, body.len()); - Ok((addr, body)) - }) - .and_then(|(addr, body)| { - let local_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); - UdpSocket::bind(&local_addr) - .map(|remote_udp| (remote_udp, addr, body)) - }) - .and_then(|(remote_udp, addr, body)| { - resolve_remote_addr(config, addr.clone()) - .and_then(|addr| remote_udp.send_dgram(body, &addr)) - .map(|(remote_udp, _)| (remote_udp, addr)) - }) - }) - .and_then(move |(remote_udp, addr)| { - let buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; - let to = timeout.unwrap_or(Duration::from_secs(5)); - let caddr = addr.clone(); - remote_udp.recv_dgram(buf) - .timeout(to) - .map_err(move |err| { - match err.into_inner() { - Some(e) => e, - None => { - error!("Udp associate waiting datagram {} -> {} timed out in {:?}", src, caddr, to); - io::Error::new(io::ErrorKind::TimedOut, "udp recv timed out") - } - } - }) - .and_then(|(_remote_udp, buf, n, _from)| { + debug!("UDP ASSOCIATE {} -> {}, payload length {} bytes", src, addr, body.len()); + Ok((addr, body)) + }) + .and_then(|(addr, body)| { + let local_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); + UdpSocket::bind(&local_addr).map(|remote_udp| (remote_udp, addr, body)) + }) + .and_then(|(remote_udp, addr, body)| { + resolve_remote_addr(config, addr.clone()) + .and_then(|addr| remote_udp.send_dgram(body, &addr)) + .map(|(remote_udp, _)| (remote_udp, addr)) + }) + }) + .and_then(move |(remote_udp, addr)| { + let buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; + let to = timeout.unwrap_or(Duration::from_secs(5)); + let caddr = addr.clone(); + remote_udp + .recv_dgram(buf) + .timeout(to) + .map_err(move |err| match err.into_inner() { + Some(e) => e, + None => { + error!( + "Udp associate waiting datagram {} -> {} timed out in {:?}", + src, caddr, to + ); + io::Error::new(io::ErrorKind::TimedOut, "udp recv timed out") + } + }) + .and_then(|(_remote_udp, buf, n, _from)| { let svr_cfg = svr_cfg_cloned; let mut send_buf = Vec::new(); @@ -101,29 +104,30 @@ fn listen(config: Arc, svr_cfg: Arc) -> impl Future e, - None => { - error!("Udp associate sending datagram {} <- {} timed out in {:?}", src, caddr, to); - io::Error::new(io::ErrorKind::TimedOut, "udp send timed out") - } - } - }) - }) - .map(|_| ()); + let to = timeout.unwrap_or(Duration::from_secs(5)); + let caddr = addr.clone(); + SendDgramRc::new(socket, buf, src) + .timeout(to) + .map_err(move |err| match err.into_inner() { + Some(e) => e, + None => { + error!( + "Udp associate sending datagram {} <- {} timed out in {:?}", + src, caddr, to + ); + io::Error::new(io::ErrorKind::TimedOut, "udp send timed out") + } + }) + }) + .map(|_| ()); tokio::spawn(rel.map_err(|err| { - error!("Udp relay error: {}", err); - })); + error!("Udp relay error: {}", err); + })); Ok(()) }) @@ -142,16 +146,14 @@ pub fn run(config: Arc) -> impl Future + S } futures_unordered(vec_fut).into_future().then(|res| match res { - Ok(..) => { - error!("One of UDP servers exited unexpectly without error"); - let err = io::Error::new(io::ErrorKind::Other, - "server exited unexpectly"); - Err(err) - } - Err((err, ..)) => { - error!("One of UDP servers exited unexpectly with error {}", - err); - Err(err) - } - }) + Ok(..) => { + error!("One of UDP servers exited unexpectly without error"); + let err = io::Error::new(io::ErrorKind::Other, "server exited unexpectly"); + Err(err) + } + Err((err, ..)) => { + error!("One of UDP servers exited unexpectly with error {}", err); + Err(err) + } + }) } diff --git a/src/relay/utils.rs b/src/relay/utils.rs index e6124192..5bd1ddda 100644 --- a/src/relay/utils.rs +++ b/src/relay/utils.rs @@ -1,32 +1,39 @@ use std::io; use futures::{Async, Future, Poll}; -use tokio_io::io::{write_all, WriteAll}; -use tokio_io::AsyncWrite; +use tokio_io::{ + io::{write_all, WriteAll}, + AsyncWrite, +}; /// Write all bytes without returning the internal bytes buffer pub struct WriteBytes - where W: AsyncWrite, - B: AsRef<[u8]> +where + W: AsyncWrite, + B: AsRef<[u8]>, { inner: WriteAll, } impl WriteBytes - where W: AsyncWrite, - B: AsRef<[u8]> +where + W: AsyncWrite, + B: AsRef<[u8]>, { fn new(writer: W, bytes: B) -> WriteBytes { - WriteBytes { inner: write_all(writer, bytes), } + WriteBytes { + inner: write_all(writer, bytes), + } } } impl Future for WriteBytes - where W: AsyncWrite, - B: AsRef<[u8]> +where + W: AsyncWrite, + B: AsRef<[u8]>, { - type Item = W; type Error = io::Error; + type Item = W; fn poll(&mut self) -> Poll { let (w, _) = try_ready!(self.inner.poll()); diff --git a/tests/dns.rs b/tests/dns.rs index 30bf0533..1a86ff39 100644 --- a/tests/dns.rs +++ b/tests/dns.rs @@ -6,14 +6,19 @@ extern crate tokio; #[macro_use] extern crate log; -use std::collections::HashSet; -use std::net::{SocketAddr, UdpSocket}; -use std::thread; -use std::time::Duration; +use std::{ + collections::HashSet, + net::{SocketAddr, UdpSocket}, + thread, + time::Duration, +}; use dns_parser::{Builder, Packet, QueryClass, QueryType}; -use shadowsocks::config::{Config, ConfigType}; -use shadowsocks::{run_dns, run_server}; +use shadowsocks::{ + config::{Config, ConfigType}, + run_dns, + run_server, +}; use tokio::runtime::current_thread::Runtime; const CONFIG: &'static str = r#"{ @@ -35,14 +40,14 @@ fn dns_relay() { let dns_cfg = Config::load_from_str(CONFIG, ConfigType::Local).unwrap(); thread::spawn(move || { - let mut runtime = Runtime::new().expect("Failed to create Runtime"); - runtime.block_on(run_server(server_cfg)).unwrap(); - }); + let mut runtime = Runtime::new().expect("Failed to create Runtime"); + runtime.block_on(run_server(server_cfg)).unwrap(); + }); thread::spawn(move || { - let mut runtime = Runtime::new().expect("Failed to create Runtime"); - runtime.block_on(run_dns(dns_cfg)).unwrap(); - }); + let mut runtime = Runtime::new().expect("Failed to create Runtime"); + runtime.block_on(run_dns(dns_cfg)).unwrap(); + }); thread::sleep(Duration::from_secs(1)); diff --git a/tests/socks5.rs b/tests/socks5.rs index e430cf69..4cc43572 100644 --- a/tests/socks5.rs +++ b/tests/socks5.rs @@ -5,19 +5,23 @@ extern crate shadowsocks; extern crate tokio; extern crate tokio_io; -use std::net::{SocketAddr, ToSocketAddrs}; -use std::thread; -use std::time::Duration; +use std::{ + net::{SocketAddr, ToSocketAddrs}, + thread, + time::Duration, +}; use futures::Future; use tokio::runtime::current_thread::Runtime; use tokio_io::io::{flush, read_to_end, write_all}; -use shadowsocks::config::{Config, ServerConfig}; -use shadowsocks::crypto::CipherType; -use shadowsocks::relay::socks5::Address; -use shadowsocks::relay::tcprelay::client::Socks5Client; -use shadowsocks::{run_local, run_server}; +use shadowsocks::{ + config::{Config, ServerConfig}, + crypto::CipherType, + relay::{socks5::Address, tcprelay::client::Socks5Client}, + run_local, + run_server, +}; pub struct Socks5TestServer { local_addr: SocketAddr, @@ -25,26 +29,30 @@ pub struct Socks5TestServer { } impl Socks5TestServer { - pub fn new(svr_addr: S, - local_addr: L, - pwd: &'static str, - method: CipherType, - enable_udp: bool) - -> Socks5TestServer - where S: ToSocketAddrs, - L: ToSocketAddrs + pub fn new( + svr_addr: S, + local_addr: L, + pwd: &'static str, + method: CipherType, + enable_udp: bool, + ) -> Socks5TestServer + where + S: ToSocketAddrs, + L: ToSocketAddrs, { let svr_addr = svr_addr.to_socket_addrs().unwrap().next().unwrap(); let local_addr = local_addr.to_socket_addrs().unwrap().next().unwrap(); - Socks5TestServer { local_addr: local_addr, - config: { - let mut cfg = Config::new(); - cfg.local = Some(local_addr); - cfg.server = vec![ServerConfig::basic(svr_addr, pwd.to_owned(), method)]; - cfg.enable_udp = enable_udp; - cfg - }, } + Socks5TestServer { + local_addr: local_addr, + config: { + let mut cfg = Config::new(); + cfg.local = Some(local_addr); + cfg.server = vec![ServerConfig::basic(svr_addr, pwd.to_owned(), method)]; + cfg.enable_udp = enable_udp; + cfg + }, + } } pub fn client_addr(&self) -> &SocketAddr { @@ -54,17 +62,17 @@ impl Socks5TestServer { pub fn run(&self) { let svr_cfg = self.config.clone(); thread::spawn(move || { - let mut runtime = Runtime::new().expect("Failed to create Runtime"); - let fut = run_server(svr_cfg); - runtime.block_on(fut).expect("Failed to run Server"); - }); + let mut runtime = Runtime::new().expect("Failed to create Runtime"); + let fut = run_server(svr_cfg); + runtime.block_on(fut).expect("Failed to run Server"); + }); let client_cfg = self.config.clone(); thread::spawn(move || { - let mut runtime = Runtime::new().expect("Failed to create Runtime"); - let fut = run_local(client_cfg); - runtime.block_on(fut).expect("Failed to run Local"); - }); + let mut runtime = Runtime::new().expect("Failed to create Runtime"); + let fut = run_local(client_cfg); + runtime.block_on(fut).expect("Failed to run Local"); + }); thread::sleep(Duration::from_secs(1)); } @@ -83,18 +91,20 @@ fn socks5_relay_stream() { let svr = Socks5TestServer::new(SERVER_ADDR, LOCAL_ADDR, PASSWORD, METHOD, false); svr.run(); - let c = Socks5Client::connect(Address::DomainNameAddress("www.example.com".to_owned(), 80), - *svr.client_addr()); + let c = Socks5Client::connect( + Address::DomainNameAddress("www.example.com".to_owned(), 80), + *svr.client_addr(), + ); let fut = c.and_then(|c| { - let req = b"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n"; - write_all(c, req.to_vec()).and_then(|(c, _)| flush(c)) - .and_then(|c| read_to_end(c, Vec::new())) - .map(|(_, buf)| { - println!("Got reply from server: {}", - String::from_utf8(buf).unwrap()); - }) - }); + let req = b"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n"; + write_all(c, req.to_vec()) + .and_then(|(c, _)| flush(c)) + .and_then(|c| read_to_end(c, Vec::new())) + .map(|(_, buf)| { + println!("Got reply from server: {}", String::from_utf8(buf).unwrap()); + }) + }); let mut runtime = Runtime::new().expect("Failed to create Runtime"); runtime.block_on(fut).unwrap(); @@ -113,17 +123,19 @@ fn socks5_relay_aead() { let svr = Socks5TestServer::new(SERVER_ADDR, LOCAL_ADDR, PASSWORD, METHOD, false); svr.run(); - let c = Socks5Client::connect(Address::DomainNameAddress("www.example.com".to_owned(), 80), - *svr.client_addr()); + let c = Socks5Client::connect( + Address::DomainNameAddress("www.example.com".to_owned(), 80), + *svr.client_addr(), + ); let fut = c.and_then(|c| { - let req = b"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n"; - write_all(c, req.to_vec()).and_then(|(c, _)| flush(c)) - .and_then(|c| read_to_end(c, Vec::new())) - .map(|(_, buf)| { - println!("Got reply from server: {}", - String::from_utf8(buf).unwrap()); - }) - }); + let req = b"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n"; + write_all(c, req.to_vec()) + .and_then(|(c, _)| flush(c)) + .and_then(|c| read_to_end(c, Vec::new())) + .map(|(_, buf)| { + println!("Got reply from server: {}", String::from_utf8(buf).unwrap()); + }) + }); let mut runtime = Runtime::new().expect("Failed to create Runtime"); runtime.block_on(fut).unwrap(); diff --git a/tests/udp.rs b/tests/udp.rs index 1a12ef20..de7c6a69 100644 --- a/tests/udp.rs +++ b/tests/udp.rs @@ -7,22 +7,29 @@ extern crate shadowsocks; extern crate tokio; extern crate tokio_io; -use std::io::Cursor; -use std::net::SocketAddr; -use std::sync::{Arc, Barrier}; -use std::thread; -use std::time::Duration; +use std::{ + io::Cursor, + net::SocketAddr, + sync::{Arc, Barrier}, + thread, + time::Duration, +}; use bytes::{BufMut, BytesMut}; use futures::Future; use tokio::runtime::current_thread::Runtime; use tokio_io::io::read_to_end; -use shadowsocks::config::{Config, ServerConfig}; -use shadowsocks::crypto::CipherType; -use shadowsocks::relay::socks5::{Address, UdpAssociateHeader}; -use shadowsocks::relay::tcprelay::client::Socks5Client; -use shadowsocks::{run_local, run_server}; +use shadowsocks::{ + config::{Config, ServerConfig}, + crypto::CipherType, + relay::{ + socks5::{Address, UdpAssociateHeader}, + tcprelay::client::Socks5Client, + }, + run_local, + run_server, +}; const SERVER_ADDR: &'static str = "127.0.0.1:8093"; const LOCAL_ADDR: &'static str = "127.0.0.1:8291"; @@ -36,7 +43,11 @@ const METHOD: CipherType = CipherType::Aes128Cfb; fn get_config() -> Config { let mut cfg = Config::new(); cfg.local = Some(LOCAL_ADDR.parse().unwrap()); - cfg.server = vec![ServerConfig::basic(SERVER_ADDR.parse().unwrap(), PASSWORD.to_owned(), METHOD)]; + cfg.server = vec![ServerConfig::basic( + SERVER_ADDR.parse().unwrap(), + PASSWORD.to_owned(), + METHOD, + )]; cfg.enable_udp = true; cfg } @@ -47,55 +58,55 @@ fn get_client_addr() -> SocketAddr { fn start_server(bar: Arc) { thread::spawn(move || { - let mut runtime = Runtime::new().expect("Failed to create Runtime"); + let mut runtime = Runtime::new().expect("Failed to create Runtime"); - let fut = run_server(get_config()); - bar.wait(); - runtime.block_on(fut).expect("Failed to run Server"); - }); + let fut = run_server(get_config()); + bar.wait(); + runtime.block_on(fut).expect("Failed to run Server"); + }); } fn start_local(bar: Arc) { thread::spawn(move || { - let mut runtime = Runtime::new().expect("Failed to create Runtime"); + let mut runtime = Runtime::new().expect("Failed to create Runtime"); - let fut = run_local(get_config()); - bar.wait(); - runtime.block_on(fut).expect("Failed to run Local"); - }); + let fut = run_local(get_config()); + bar.wait(); + runtime.block_on(fut).expect("Failed to run Local"); + }); } fn start_udp_echo_server(bar: Arc) { use std::net::UdpSocket; thread::spawn(move || { - let l = UdpSocket::bind(UDP_ECHO_SERVER_ADDR).unwrap(); + let l = UdpSocket::bind(UDP_ECHO_SERVER_ADDR).unwrap(); - bar.wait(); + bar.wait(); - let mut buf = [0u8; 65536]; - let (amt, src) = l.recv_from(&mut buf).unwrap(); + let mut buf = [0u8; 65536]; + let (amt, src) = l.recv_from(&mut buf).unwrap(); - l.send_to(&buf[..amt], &src).unwrap(); - }); + l.send_to(&buf[..amt], &src).unwrap(); + }); } fn start_udp_request_holder(bar: Arc, addr: Address) { thread::spawn(move || { - let mut runtime = Runtime::new().expect("Failed to create Runtime"); + let mut runtime = Runtime::new().expect("Failed to create Runtime"); - let c = Socks5Client::udp_associate(addr, get_client_addr()); - let fut = c.and_then(|(c, addr)| { - assert_eq!(addr, Address::SocketAddress(LOCAL_ADDR.parse().unwrap())); + let c = Socks5Client::udp_associate(addr, get_client_addr()); + let fut = c.and_then(|(c, addr)| { + assert_eq!(addr, Address::SocketAddress(LOCAL_ADDR.parse().unwrap())); - // Holds it forever - read_to_end(c, Vec::new()).map(|_| ()) - }); + // Holds it forever + read_to_end(c, Vec::new()).map(|_| ()) + }); - bar.wait(); + bar.wait(); - runtime.block_on(fut).expect("Failed to run UDP socks5 client"); - }); + runtime.block_on(fut).expect("Failed to run UDP socks5 client"); + }); } #[test]