diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2020-04-27 13:59:12 +0100 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2020-04-27 13:59:12 +0100 |
| commit | 4f1d2ba90546907e9905ac9ec72731613e559294 (patch) | |
| tree | 2ad92e79d6e0c173e5b84a9cfe57102b121895f6 | |
| parent | f9573c6f0360a6dcd0e334285e2ae91120234100 (diff) | |
| parent | 9260448c0f523e041453f413bff4fef957753c3f (diff) | |
| download | mullvadvpn-4f1d2ba90546907e9905ac9ec72731613e559294.tar.xz mullvadvpn-4f1d2ba90546907e9905ac9ec72731613e559294.zip | |
Merge branch 'use-rest-new-hyper'
53 files changed, 3192 insertions, 1717 deletions
diff --git a/Cargo.lock b/Cargo.lock index 68c1f82969..ed1d957d0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,11 +41,6 @@ dependencies = [ ] [[package]] -name = "antidote" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "approx" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -79,11 +74,30 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "async-stream" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "async-stream-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-stream-impl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -93,13 +107,18 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "backtrace" version = "0.3.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -109,25 +128,21 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.9.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "bitflags" @@ -158,6 +173,11 @@ dependencies = [ ] [[package]] +name = "bumpalo" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -172,6 +192,11 @@ dependencies = [ ] [[package]] +name = "bytes" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "c2-chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -210,7 +235,7 @@ name = "chrono" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -271,7 +296,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -280,6 +314,11 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "crossbeam-deque" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -319,6 +358,14 @@ dependencies = [ ] [[package]] +name = "ct-logs" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "ctrlc" version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -376,7 +423,7 @@ name = "dbus" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "libdbus-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -435,7 +482,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -445,7 +492,7 @@ name = "duct" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "shared_child 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -496,7 +543,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -506,7 +553,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -561,7 +608,7 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -572,19 +619,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "fsevent" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -598,7 +632,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -626,12 +660,94 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "futures-cpupool" -version = "0.1.8" +name = "futures" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-executor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-io" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-sink" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures01" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -653,7 +769,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -687,6 +803,24 @@ dependencies = [ ] [[package]] +name = "h2" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -700,6 +834,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "http" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "http-body" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "httparse" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -714,46 +867,42 @@ dependencies = [ [[package]] name = "hyper" -version = "0.11.27" +version = "0.13.5" 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.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "hyper-openssl" -version = "0.5.0" +name = "hyper-rustls" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-openssl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls-native-certs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -762,13 +911,21 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "indexmap" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "inotify" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -776,7 +933,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -789,7 +946,7 @@ name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -846,6 +1003,14 @@ dependencies = [ ] [[package]] +name = "js-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "jsonrpc-client-core" version = "0.5.0" source = "git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b#68aac55b6ddff5e1242594b54f7f9149fe215ff7" @@ -873,19 +1038,6 @@ dependencies = [ ] [[package]] -name = "jsonrpc-client-http" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "jsonrpc-client-ipc" version = "0.5.0" source = "git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b#68aac55b6ddff5e1242594b54f7f9149fe215ff7" @@ -1017,11 +1169,6 @@ dependencies = [ ] [[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1033,7 +1180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.65" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1045,19 +1192,6 @@ dependencies = [ ] [[package]] -name = "linked-hash-map" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "linked_hash_set" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "lock_api" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1103,7 +1237,7 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1120,20 +1254,16 @@ dependencies = [ ] [[package]] -name = "mime" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "mio" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1148,7 +1278,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1158,7 +1288,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1169,8 +1299,8 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1198,7 +1328,7 @@ name = "mnl" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mnl-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1208,7 +1338,7 @@ name = "mnl-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1253,7 +1383,7 @@ dependencies = [ "jsonrpc-macros 8.0.1 (git+https://github.com/mullvad/jsonrpc?branch=mullvad-fork)", "jsonrpc-pubsub 8.0.1 (git+https://github.com/mullvad/jsonrpc?branch=mullvad-fork)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "mullvad-ipc-client 0.1.0", @@ -1315,6 +1445,7 @@ dependencies = [ "mullvad-daemon 2020.4.0-beta2", "mullvad-paths 0.1.0", "mullvad-problem-report 2020.4.0-beta2", + "mullvad-rpc 0.1.0", "mullvad-types 0.1.0", "talpid-core 0.1.0", "talpid-types 0.1.0", @@ -1338,13 +1469,13 @@ dependencies = [ "duct 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "err-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures01 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "mullvad-paths 0.1.0", "mullvad-rpc 0.1.0", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rs-release 0.1.7 (git+https://github.com/mullvad/rs-release?branch=snailquote-unescape)", "talpid-types 0.1.0", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winres 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1358,18 +1489,22 @@ dependencies = [ "err-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-openssl 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-client-http 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mullvad-types 0.1.0", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "talpid-types 0.1.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-openssl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "urlencoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1396,7 +1531,7 @@ dependencies = [ "jsonrpc-client-core 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)", "jsonrpc-client-ipc 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)", "jsonrpc-client-pubsub 0.1.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "mullvad-ipc-client 0.1.0", "mullvad-paths 0.1.0", "mullvad-types 0.1.0", @@ -1437,49 +1572,69 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "netlink-packet" -version = "0.1.1" -source = "git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5#f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" +name = "netlink-packet-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "netlink-sys 0.1.0 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-packet-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "netlink-packet-route" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-packet-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-packet-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "netlink-proto" -version = "0.1.1" -source = "git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5#f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "netlink-packet 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", - "netlink-sys 0.1.0 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-packet-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "netlink-sys" -version = "0.1.0" -source = "git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5#f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1489,7 +1644,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "err-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nftnl-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1500,7 +1655,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1512,7 +1667,7 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1524,7 +1679,7 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1536,7 +1691,7 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1556,8 +1711,8 @@ dependencies = [ "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1593,7 +1748,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1602,29 +1757,9 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "openssl" -version = "0.10.25" +name = "openssl-probe" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.9.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "openvpn-plugin" @@ -1650,7 +1785,7 @@ name = "os_pipe" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1703,7 +1838,7 @@ name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1717,7 +1852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1725,9 +1860,24 @@ dependencies = [ ] [[package]] -name = "percent-encoding" -version = "1.0.1" +name = "paste" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "pfctl" @@ -1739,10 +1889,38 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ioctl-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pin-project-internal 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] +name = "pin-project-lite" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "pkg-config" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1812,6 +1990,16 @@ dependencies = [ ] [[package]] +name = "proc-macro-hack" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro-nested" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1855,20 +2043,11 @@ dependencies = [ [[package]] name = "rand" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1881,7 +2060,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1892,7 +2071,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1910,7 +2089,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1984,7 +2163,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1996,7 +2175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2080,14 +2259,6 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "relay" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2109,6 +2280,20 @@ version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "ring" +version = "0.16.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "rs-release" version = "0.1.7" source = "git+https://github.com/mullvad/rs-release?branch=snailquote-unescape#88b2afb04c3b2b1b76f27d8b8d48cd52facd292a" @@ -2118,15 +2303,14 @@ dependencies = [ [[package]] name = "rtnetlink" -version = "0.1.1" -source = "git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5#f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "netlink-packet 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", - "netlink-proto 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", + "netlink-packet-route 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-proto 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2158,6 +2342,29 @@ dependencies = [ ] [[package]] +name = "rustls" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustls-native-certs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "rustversion" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2173,11 +2380,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "safemem" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "same-file" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2186,6 +2388,15 @@ dependencies = [ ] [[package]] +name = "schannel" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "scoped-tls" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2201,6 +2412,36 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "sct" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2246,7 +2487,7 @@ name = "shared_child" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2260,7 +2501,7 @@ name = "signal-hook" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2270,7 +2511,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2279,7 +2520,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2294,11 +2535,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "smallvec" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2316,12 +2552,17 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2414,7 +2655,7 @@ name = "syntex_errors" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2436,7 +2677,7 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2460,18 +2701,14 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "take" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "talpid-core" version = "0.1.0" dependencies = [ + "async-stream 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2480,18 +2717,19 @@ dependencies = [ "err-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "jnix 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.2 (git+https://github.com/mullvad/jsonrpc?branch=mullvad-fork)", "jsonrpc-macros 8.0.1 (git+https://github.com/mullvad/jsonrpc?branch=mullvad-fork)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mnl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "netlink-packet 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", - "netlink-proto 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", - "netlink-sys 0.1.0 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", + "netlink-packet-route 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-proto 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "nftnl 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2503,13 +2741,14 @@ dependencies = [ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rtnetlink 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", + "rtnetlink 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "system-configuration 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "talpid-ipc 0.1.0", "talpid-types 0.1.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2582,7 +2821,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2627,7 +2866,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2639,7 +2878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2656,6 +2895,25 @@ dependencies = [ ] [[package]] +name = "tokio" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.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" @@ -2674,7 +2932,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2728,22 +2986,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-openssl" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "tokio-process" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2751,9 +2999,9 @@ dependencies = [ "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2762,23 +3010,6 @@ dependencies = [ ] [[package]] -name = "tokio-proto" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "tokio-reactor" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2787,7 +3018,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2807,6 +3038,17 @@ dependencies = [ ] [[package]] +name = "tokio-rustls" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "tokio-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2820,8 +3062,8 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2847,7 +3089,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2896,7 +3138,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (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.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2910,9 +3152,9 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (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.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2920,6 +3162,32 @@ dependencies = [ ] [[package]] +name = "tokio-util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "toml" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2928,8 +3196,13 @@ dependencies = [ ] [[package]] +name = "tower-service" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "try-lock" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2939,7 +3212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ioctl-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2953,14 +3226,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unicase" -version = "2.5.1" -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-segmentation" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3004,6 +3269,16 @@ dependencies = [ ] [[package]] +name = "untrusted" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "urlencoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "utf8-ranges" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3017,11 +3292,6 @@ dependencies = [ ] [[package]] -name = "vcpkg" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3053,12 +3323,11 @@ dependencies = [ [[package]] name = "want" -version = "0.0.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3067,11 +3336,78 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "wasm-bindgen" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bumpalo 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "web-sys" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "js-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "which" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3226,25 +3562,29 @@ dependencies = [ "checksum android_log-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e" "checksum android_logger 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d96559804dc237dd6bfac8391fb4f6139812596c98185f696bd7c87724f733db" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" "checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum ascii 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" "checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" +"checksum async-stream 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22068c0c19514942eefcfd4daf8976ef1aad84e61539f95cd200c35202f80af5" +"checksum async-stream-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" +"checksum bumpalo 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" "checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" @@ -3257,11 +3597,14 @@ dependencies = [ "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" "checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f" "checksum curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" "checksum darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfbcb0c5961907597a7d1148e3af036268f2b773886b8bb3eeb1e1281d3d3d6" @@ -3288,28 +3631,39 @@ dependencies = [ "checksum fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "29d26fa0f4d433d1956746e66ec10d6bf4d6c8b93cd39965cceea7f7cc78c7dd" "checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" +"checksum futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" +"checksum futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +"checksum futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" +"checksum futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +"checksum futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" +"checksum futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" +"checksum futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +"checksum futures01 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef8cbbf52909170053540c6c05a62433ddb60662dabee714e2a882caa864f22" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90d069fe6beb9be359ef505650b3f73228c5591a3c4b1f32be2f4f44459ffa3a" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +"checksum h2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" +"checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" +"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)" = "34a590ca09d341e94cddf8e5af0bbccde205d5fbc2fa3c09dd67c7f85cea59d7" -"checksum hyper-openssl 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0800c7b541e9b5be3e3cf8c8773d2fdb33975d07551fa1279d90e154c18db4d8" +"checksum hyper 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14" +"checksum hyper-rustls 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac965ea399ec3a25ac7d13b8affd4b8f39325cca00858ddf5eb29b79e6b14b08" "checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum ioctl-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2c4b26352496eaaa8ca7cfa9bd99e93419d3f7983dc6e99c2a35fe9e33504a" @@ -3320,9 +3674,9 @@ dependencies = [ "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" "checksum jnix 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cd26c8a9ccd3b8c1d47e17f290237ae1c4bd3a89ef31fafc61bc09804cc2b1ec" "checksum jnix-macros 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a819d1d2905045ab6da444b4aa612e82a028508e6148acd9b61ce4985b4d6f8f" +"checksum js-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" "checksum jsonrpc-client-core 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)" = "<none>" "checksum jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f29cb249837420fb0cee7fb0fbf1d22679e121b160e71bb5e0d90b9df241c23e" -"checksum jsonrpc-client-http 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e642eb74423b9dfcb4512fda167148746b76f788a823cd712fadf409f31d302" "checksum jsonrpc-client-ipc 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)" = "<none>" "checksum jsonrpc-client-pubsub 0.1.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)" = "<none>" "checksum jsonrpc-client-utils 0.1.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)" = "<none>" @@ -3334,13 +3688,10 @@ dependencies = [ "checksum jsonrpc-server-utils 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "513e981828a4953ea7ddbb64c24d15d4983ecf6900dc1cd36f257d61c27138d5" "checksum jsonrpc-server-utils 8.0.1 (git+https://github.com/mullvad/jsonrpc?branch=mullvad-fork)" = "<none>" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" "checksum libdbus-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc12a3bc971424edbbf7edaf6e5740483444db63aa8e23d3751ff12a30f306f0" -"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7c91c4c7bbeb4f2f7c4e5be11e6a05bd6830bc37249c47ce1ad86ad453ff9c" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" @@ -3349,8 +3700,7 @@ dependencies = [ "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" -"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" @@ -3360,9 +3710,11 @@ dependencies = [ "checksum mnl-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5302035599c722b3a5b92a6502ff73c501dc6d100c53b89f0fae0cb932a37122" "checksum natord 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum netlink-packet 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)" = "<none>" -"checksum netlink-proto 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)" = "<none>" -"checksum netlink-sys 0.1.0 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)" = "<none>" +"checksum netlink-packet-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9cdae99aa0db00bffb58886de3cdba39d07164cec467867f162827872e3ed957" +"checksum netlink-packet-route 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "472467595d208fb94b0e8f70b1155c14b51eeb784713b4845344b501a8297a11" +"checksum netlink-packet-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca26de3f3fe7cc09a925255291049c65699a95db6f124fa8019dc0bb396fdaff" +"checksum netlink-proto 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "844a78a78bee85b99686973856e57ce339ef2490660305d26e35bb74a672ad15" +"checksum netlink-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aee128bb9bcc04f426d9b5e0bf3077726776b5b41770a3b2e4db5f52295625bf" "checksum nftnl 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3727d1e8c1c9af88857f46539c3030693158a2a7586056b8cab6ded523bf7aa" "checksum nftnl-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dba134c9b125b7d7c13d813388aaeb2aeeba60fb1eb702799163fb845086ca33" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" @@ -3375,8 +3727,7 @@ dependencies = [ "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" -"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" -"checksum openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)" = "ba24190c8f0805d3bd2ce028f439fe5af1d55882bbe6261bed1dbc93b50dd6b1" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openvpn-plugin 0.3.0 (git+https://github.com/mullvad/openvpn-plugin-rs?branch=auth-failed-event)" = "<none>" "checksum os_pipe 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "81e8dfa4c69d7bde595e9a940fcf1d7f60966d3fce8a8c4cad67c60e35ea2a11" "checksum os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db4d06355a7090ce852965b2d08e11426c315438462638c6d721448d0b47aa22" @@ -3386,8 +3737,13 @@ dependencies = [ "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab4fb1930692d1b6a9cfabdde3d06ea0a7d186518e2f4d67660d8970e2fa647a" +"checksum paste-impl 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "a62486e111e571b1e93b710b61e8f493c0013be39629b714cb166bdb06aa5a8a" "checksum pfctl 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4410511aea78cbc7b1d192315034607be78537336590ebfc7fc92496768c45af" +"checksum pin-project 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f6a7f5eee6292c559c793430c55c00aea9d3b3d1905e855806ca4d7253426a2" +"checksum pin-project-internal 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a" +"checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" +"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" "checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" "checksum pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df28acf2fcc77436dd2b91a9a0c2bb617f9ca5f2acefee1a4135058b9f9801f" "checksum pnet_macros 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d228096fd739d4e3e60dee9e1e4f07d9ae0f3f309c876834192538748e561e4" @@ -3396,13 +3752,14 @@ dependencies = [ "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" "checksum proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" +"checksum proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" +"checksum proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" -"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -3426,23 +3783,28 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" -"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum rgb 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2089e4031214d129e201f8c3c8c2fe97cd7322478a0d1cdf78e7029b0042efdb" +"checksum ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" "checksum rs-release 0.1.7 (git+https://github.com/mullvad/rs-release?branch=snailquote-unescape)" = "<none>" -"checksum rtnetlink 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)" = "<none>" +"checksum rtnetlink 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f802e53265ca90edd3cfc59a3ceb2c30d655da6a1a6b954684d51977633ef5fd" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" +"checksum rustls-native-certs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" "checksum rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" +"checksum schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +"checksum security-framework 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a" +"checksum security-framework-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f" "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.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" @@ -3455,10 +3817,10 @@ dependencies = [ "checksum simple-signal 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "53f7da44adcc42667d57483bd93f81295f27d66897804b757573b61b6f13288b" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum snailquote 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc3e2894a343234fb8a8653cf9d49ef6aea44e6581612ca311c91c4bd356dec4" "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" @@ -3475,7 +3837,6 @@ dependencies = [ "checksum syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7628a0506e8f9666fdabb5f265d0059b059edac9a3f810bda077abb5d826bd8d" "checksum system-configuration 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df3dc3e701a89dd6764083d19f048b57ec01c26d0904ff8108a507059a6462e6" "checksum system-configuration-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bfd906a2882d54084bfdf517bf03892ac06820f1c0a3d37e48609f334798ad99" -"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" @@ -3483,6 +3844,7 @@ dependencies = [ "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" @@ -3490,11 +3852,10 @@ dependencies = [ "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-named-pipes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d282d483052288b2308ba5ee795f5673b159c9bdf63c385a05609da782a5eae" -"checksum tokio-openssl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4646ae1fd623393de3d796ea53af75acd02938dd5579544fbd6d236d041978a6" "checksum tokio-process 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afbd6ef1b8cc2bd2c2b580d882774d443ebb1c6ceefe35ba9ea4ab586c89dbe8" -"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" "checksum tokio-retry 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c03755b956458582182941061def32b8123a26c98b08fc6ddcf49ae89d18f33" +"checksum tokio-rustls 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4adb8b3e5f86b707f1b54e7c15b6de52617a823608ccda98a15d3a24222f265a" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" "checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" @@ -3504,12 +3865,14 @@ dependencies = [ "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" "checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" -"checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2" +"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum tun 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9c381483a1daa36ccc3452223bdcb3dbea7ad407d1ede80496b87707368ba755" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" -"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" @@ -3518,16 +3881,24 @@ dependencies = [ "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" +"checksum urlencoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3df3561629a8bb4c57e5a2e4c43348d9e29c7c29d9b1c4c1f47166deca8f37ed" "checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" -"checksum want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a05d9d966753fa4b5c8db73fcab5eed4549cfe0e1e4e66911e5564a0085c35d1" +"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +"checksum wasm-bindgen-backend 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +"checksum wasm-bindgen-macro 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +"checksum wasm-bindgen-macro-support 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +"checksum wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" +"checksum web-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" +"checksum webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" "checksum which 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5475d47078209a02e60614f7ba5e645ef3ed60f771920ac1906d7c1cc65024c8" "checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" @@ -279,13 +279,9 @@ sections. ## Building and running mullvad-daemon on desktop -1. Firstly, one should source `env.sh` to set the default environment variables. - One can also source the variables on Powershell with `env.ps1`, - however most of our scripts require bash. +1. Firstly, on MacOS and Linux, one should source `env.sh` to set the default environment variables. ```bash source env.sh - # Or if you use Powershell: - . .\env.ps1 ``` 1. If you are on Windows, then you have to build the C++ libraries before compiling the daemon: diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt index dab1b0b7ae..40a87ac4b6 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt @@ -35,7 +35,7 @@ class AppVersionInfoCache( val latest get() = appVersionInfo?.latest val isSupported - get() = appVersionInfo?.currentIsSupported ?: true + get() = appVersionInfo?.supported ?: true val isOutdated: Boolean get() { diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt index 0c41090f3f..2fe8b9d3ed 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt @@ -1,7 +1,8 @@ package net.mullvad.mullvadvpn.model data class AppVersionInfo( - val currentIsSupported: Boolean, + val supported: Boolean, val latestStable: String, + val latestBeta: String, val latest: String ) @@ -210,6 +210,7 @@ fi ./update-relays.sh + pushd "$SCRIPT_DIR/gui" echo "Installing JavaScript dependencies..." diff --git a/env.bat b/env.bat deleted file mode 100644 index 44483bf993..0000000000 --- a/env.bat +++ /dev/null @@ -1,4 +0,0 @@ -SET SCRIPT_DIR=%~dp0 -SET OPENSSL_STATIC=1 -SET OPENSSL_LIB_DIR=%SCRIPT_DIR%\dist-assets\binaries\x86_64-pc-windows-msvc -SET OPENSSL_INCLUDE_DIR=%SCRIPT_DIR%\dist-assets\binaries\x86_64-pc-windows-msvc\include diff --git a/env.ps1 b/env.ps1 deleted file mode 100644 index 0f8899e404..0000000000 --- a/env.ps1 +++ /dev/null @@ -1,5 +0,0 @@ -$SCRIPT_DIR = split-path -parent $MyInvocation.MyCommand.Definition - -$env:OPENSSL_STATIC="1" -$env:OPENSSL_LIB_DIR="$SCRIPT_DIR\dist-assets\binaries\x86_64-pc-windows-msvc" -$env:OPENSSL_INCLUDE_DIR="$SCRIPT_DIR\dist-assets\binaries\x86_64-pc-windows-msvc\include" @@ -39,7 +39,3 @@ case "$TARGET" in exit 1 ;; esac - -export OPENSSL_STATIC="1" -export OPENSSL_LIB_DIR="$SCRIPT_DIR/dist-assets/binaries/$TARGET" -export OPENSSL_INCLUDE_DIR="$SCRIPT_DIR/dist-assets/binaries/$TARGET/include" diff --git a/mullvad-cli/src/cmds/version.rs b/mullvad-cli/src/cmds/version.rs index 99df7b6d19..606ad4972c 100644 --- a/mullvad-cli/src/cmds/version.rs +++ b/mullvad-cli/src/cmds/version.rs @@ -17,7 +17,7 @@ impl Command for Version { let current_version = rpc.get_current_version()?; println!("Current version: {}", current_version); let version_info = rpc.get_version_info()?; - println!("\tIs supported: {}", version_info.current_is_supported); + println!("\tIs supported: {}", version_info.supported); let settings = rpc.get_settings()?; let is_updated = if settings.show_beta_releases.unwrap_or(false) { diff --git a/mullvad-daemon/src/account_history.rs b/mullvad-daemon/src/account_history.rs index ea8f23757a..56ebc6dc17 100644 --- a/mullvad-daemon/src/account_history.rs +++ b/mullvad-daemon/src/account_history.rs @@ -5,7 +5,7 @@ use futures::{ future::{self, Executor, Future}, sync::oneshot, }; -use mullvad_rpc::{HttpHandle, WireguardKeyProxy}; +use mullvad_rpc::{rest::MullvadRestHandle, WireguardKeyProxy}; use mullvad_types::{account::AccountToken, wireguard::WireguardData}; use std::{ collections::VecDeque, @@ -38,7 +38,7 @@ static ACCOUNT_HISTORY_LIMIT: usize = 3; pub struct AccountHistory { file: io::BufWriter<fs::File>, accounts: VecDeque<AccountEntry>, - rpc_handle: HttpHandle, + rpc_handle: MullvadRestHandle, tokio_remote: Remote, } @@ -46,7 +46,7 @@ pub struct AccountHistory { impl AccountHistory { pub fn new( cache_dir: &Path, - rpc_handle: HttpHandle, + rpc_handle: MullvadRestHandle, tokio_remote: Remote, ) -> Result<AccountHistory> { let mut options = fs::OpenOptions::new(); @@ -152,8 +152,7 @@ impl AccountHistory { wg_data: &WireguardData, ) -> impl Future<Item = (), Error = ()> { let mut rpc = WireguardKeyProxy::new(self.rpc_handle.clone()); - rpc.remove_wg_key(String::from(account), wg_data.private_key.public_key()) - .map(|removed| log::debug!("Key existed on account: {}", removed)) + rpc.remove_wireguard_key(String::from(account), &wg_data.private_key.public_key()) .map_err(|e| log::error!("Failed to remove WireGuard key: {}", e)) } @@ -216,8 +215,7 @@ impl AccountHistory { for entry in self.accounts.iter() { if let Some(wg_data) = &entry.wireguard { let fut = rpc - .remove_wg_key(entry.account.clone(), wg_data.private_key.public_key()) - .map(|_| ()) + .remove_wireguard_key(entry.account.clone(), &wg_data.private_key.public_key()) .map_err(|e| log::error!("Failed to remove WireGuard key: {}", e)); removal_futures.push(fut); } diff --git a/mullvad-daemon/src/event_loop.rs b/mullvad-daemon/src/event_loop.rs new file mode 100644 index 0000000000..238b9f4eef --- /dev/null +++ b/mullvad-daemon/src/event_loop.rs @@ -0,0 +1,38 @@ +use futures::{sync::oneshot, Future}; +use std::thread; +use tokio_core::reactor::{Core, Remote}; + +pub struct CoreHandle { + /// Remote used to spawn futures on the daemon's event loop. + pub remote: Remote, + /// A sender that will cause the event loop to stop once it's dropped. + shutdown_tx: Option<oneshot::Sender<()>>, +} + +impl Drop for CoreHandle { + fn drop(&mut self) { + if let Some(shutdown_tx) = self.shutdown_tx.take() { + if shutdown_tx.send(()).is_err() { + log::error!("Core already shut down"); + } + } + } +} + +/// Panics if a new tokio event loop can't be spawned. +pub fn spawn() -> CoreHandle { + let (tx, rx) = oneshot::channel(); + let (shutdown_tx, shutdown_rx) = oneshot::channel(); + thread::spawn(move || { + let mut core = Core::new().expect("Failed to spawn event loop"); + let remote = core.remote(); + let _ = tx.send(remote); + let _ = core.run(shutdown_rx); + }); + let remote = rx.wait().expect("Failed to spawn event loop"); + + CoreHandle { + remote, + shutdown_tx: Some(shutdown_tx), + } +} diff --git a/mullvad-daemon/src/geoip.rs b/mullvad-daemon/src/geoip.rs index 5be502f0a9..5cc3085bfe 100644 --- a/mullvad-daemon/src/geoip.rs +++ b/mullvad-daemon/src/geoip.rs @@ -1,69 +1,53 @@ use futures::{self, Future}; -use mullvad_rpc; +use mullvad_rpc::{self, rest::RequestServiceHandle}; use mullvad_types::location::{AmIMullvad, GeoIpLocation}; -use serde_json; const URI_V4: &str = "https://ipv4.am.i.mullvad.net/json"; const URI_V6: &str = "https://ipv6.am.i.mullvad.net/json"; -#[derive(err_derive::Error, Debug)] -pub enum Error { - /// Unable to send request to HTTP client. - #[error(display = "Unable to send GeoIP request to HTTP client")] - SendRequestError, - - /// The request was dropped without any response - #[error(display = "The GeoIP request was dropped without any response")] - NoResponse, - - /// Error in the HTTP client when requesting GeoIP - #[error(display = "Failed to request GeoIP")] - Transport(#[error(source)] mullvad_rpc::rest::Error), - - /// Failed to deserialize GeoIP response - #[error(display = "Failed to deserialize GeoIP response")] - Deserialize(#[error(source)] serde_json::error::Error), -} - - pub fn send_location_request( - request_sender: mullvad_rpc::rest::RequestSender, -) -> impl Future<Item = GeoIpLocation, Error = Error> { + request_sender: RequestServiceHandle, +) -> impl Future<Item = GeoIpLocation, Error = mullvad_rpc::rest::Error> { let v4_future = send_location_request_internal(URI_V4, request_sender.clone()).map(GeoIpLocation::from); let v6_future = send_location_request_internal(URI_V6, request_sender).map(GeoIpLocation::from); - v4_future.then(|v4_result| { - v6_future.then(|v6_result| match (v4_result, v6_result) { - (Ok(mut v4), Ok(v6)) => { - v4.ipv6 = v6.ipv6; - v4.mullvad_exit_ip = v4.mullvad_exit_ip && v6.mullvad_exit_ip; - Ok(v4) - } - (Ok(v4), Err(e)) => { - log::debug!("Unable to fetch IPv6 GeoIP location: {}", e); - Ok(v4) - } - (Err(e), Ok(v6)) => { - log::debug!("Unable to fetch IPv4 GeoIP location: {}", e); - Ok(v6) - } - (Err(e_v4), Err(_)) => Err(e_v4), - }) - }) + v4_future.then( + |v4_result: Result<GeoIpLocation, mullvad_rpc::rest::Error>| { + v6_future.then( + |v6_result: Result<GeoIpLocation, mullvad_rpc::rest::Error>| match ( + v4_result, v6_result, + ) { + (Ok(mut v4), Ok(v6)) => { + v4.ipv6 = v6.ipv6; + v4.mullvad_exit_ip = v4.mullvad_exit_ip && v6.mullvad_exit_ip; + Ok(v4) + } + (Ok(v4), Err(e)) => { + log::debug!("Unable to fetch IPv6 GeoIP location: {}", e); + Ok(v4) + } + (Err(e), Ok(v6)) => { + log::debug!("Unable to fetch IPv4 GeoIP location: {}", e); + Ok(v6) + } + (Err(e_v4), Err(_)) => Err(e_v4), + }, + ) + }, + ) } fn send_location_request_internal( uri: &'static str, - request_sender: mullvad_rpc::rest::RequestSender, -) -> impl Future<Item = AmIMullvad, Error = Error> { - let (response_tx, response_rx) = futures::sync::oneshot::channel(); - let request = mullvad_rpc::rest::create_get_request(uri.parse().unwrap()); - - futures::Sink::send(request_sender, (request, response_tx)) - .map_err(|_| Error::SendRequestError) - .and_then(|_| response_rx.map_err(|_| Error::NoResponse)) - .and_then(|response_result| response_result.map_err(Error::Transport)) - .and_then(|response| serde_json::from_slice(&response).map_err(Error::Deserialize)) + service: RequestServiceHandle, +) -> impl Future<Item = AmIMullvad, Error = mullvad_rpc::rest::Error> { + let future_service = service.clone(); + let future = async move { + let request = mullvad_rpc::rest::RestRequest::get(uri)?; + let response = future_service.request(request).await?; + mullvad_rpc::rest::deserialize_body(response).await + }; + service.compat_spawn(future) } diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 6dd6812dd2..f39d6a5a79 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -27,7 +27,7 @@ use futures::{ Future, Stream, }; use log::{debug, error, info, warn}; -use mullvad_rpc::{AccountsProxy, HttpHandle, WireguardKeyProxy}; +use mullvad_rpc::AccountsProxy; use mullvad_types::{ account::{AccountData, AccountToken, VoucherSubmission}, endpoint::MullvadEndpoint, @@ -71,6 +71,7 @@ use talpid_types::{ mod wireguard; const TARGET_START_STATE_FILE: &str = "target-start-state.json"; +mod event_loop; /// FIXME(linus): This is here just because the futures crate has deprecated it and jsonrpc_core /// did not introduce their own yet (https://github.com/paritytech/jsonrpc/pull/196). @@ -89,10 +90,7 @@ pub enum Error { InitIoEventLoop(#[error(source)] io::Error), #[error(display = "Unable to create RPC client")] - InitRpcClient(#[error(source)] mullvad_rpc::HttpError), - - #[error(display = "Unable to create am.i.mullvad client")] - InitHttpsClient(#[error(source)] mullvad_rpc::rest::Error), + InitRpcFactory(#[error(source)] mullvad_rpc::Error), #[error(display = "Unable to load account history with wireguard key cache")] LoadAccountHistory(#[error(source)] account_history::Error), @@ -147,17 +145,17 @@ pub enum DaemonCommand { GetState(oneshot::Sender<TunnelState>), /// Get the current geographical location. GetCurrentLocation(oneshot::Sender<Option<GeoIpLocation>>), - CreateNewAccount(oneshot::Sender<std::result::Result<String, mullvad_rpc::Error>>), + CreateNewAccount(oneshot::Sender<std::result::Result<String, mullvad_rpc::rest::Error>>), /// Request the metadata for an account. GetAccountData( - oneshot::Sender<BoxFuture<AccountData, mullvad_rpc::Error>>, + oneshot::Sender<BoxFuture<AccountData, mullvad_rpc::rest::Error>>, AccountToken, ), /// Request www auth token for an account - GetWwwAuthToken(oneshot::Sender<BoxFuture<String, mullvad_rpc::Error>>), + GetWwwAuthToken(oneshot::Sender<BoxFuture<String, mullvad_rpc::rest::Error>>), /// Submit voucher to add time to the current account. Returns time added in seconds SubmitVoucher( - oneshot::Sender<BoxFuture<VoucherSubmission, mullvad_rpc::Error>>, + oneshot::Sender<BoxFuture<VoucherSubmission, mullvad_rpc::rest::Error>>, String, ), /// Request account history @@ -244,7 +242,7 @@ pub(crate) enum InternalDaemonEvent { /// New Account created NewAccountEvent( AccountToken, - oneshot::Sender<Result<String, mullvad_rpc::Error>>, + oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>, ), /// The background job fetching new `AppVersionInfo`s got a new info object. NewAppVersionInfo(AppVersionInfo), @@ -439,11 +437,11 @@ pub struct Daemon<L: EventListener> { event_listener: L, settings: SettingsPersister, account_history: account_history::AccountHistory, - wg_key_proxy: WireguardKeyProxy<HttpHandle>, - accounts_proxy: AccountsProxy<HttpHandle>, - https_handle: mullvad_rpc::rest::RequestSender, + accounts_proxy: AccountsProxy, + rpc_runtime: mullvad_rpc::MullvadRpcRuntime, + rpc_handle: mullvad_rpc::rest::MullvadRestHandle, wireguard_key_manager: wireguard::KeyManager, - tokio_remote: tokio_core::reactor::Remote, + core_handle: event_loop::CoreHandle, relay_selector: relays::RelaySelector, last_generated_relay: Option<Relay>, last_generated_bridge_relay: Option<Relay>, @@ -471,20 +469,11 @@ where let (tunnel_state_machine_shutdown_tx, tunnel_state_machine_shutdown_signal) = oneshot::channel(); - let mut rpc_manager = mullvad_rpc::MullvadRpcFactory::with_cache_dir(&cache_dir, &ca_path); - - let (rpc_handle, https_handle, tokio_remote) = - mullvad_rpc::event_loop::create(move |core| { - let handle = core.handle(); - let rpc = rpc_manager.new_connection_on_event_loop(&handle); - let https_handle = mullvad_rpc::rest::create_https_client(&ca_path, &handle); - let remote = core.remote(); - (rpc, https_handle, remote) - }) - .map_err(Error::InitIoEventLoop)?; + let mut rpc_runtime = mullvad_rpc::MullvadRpcRuntime::with_cache_dir(&cache_dir, &ca_path) + .map_err(Error::InitRpcFactory)?; + let rpc_handle = rpc_runtime.mullvad_rest_handle(); - let rpc_handle = rpc_handle.map_err(Error::InitRpcClient)?; - let https_handle = https_handle.map_err(Error::InitHttpsClient)?; + let core_handle = event_loop::spawn(); let relay_list_listener = event_listener.clone(); let on_relay_list_update = move |relay_list: &RelayList| { @@ -506,7 +495,7 @@ where internal_event_tx.to_specialized_sender(), app_version_info.clone(), ); - tokio_remote.spawn(|_| version_check_future); + core_handle.remote.spawn(|_| version_check_future); let mut settings = SettingsPersister::load(&settings_dir); @@ -517,7 +506,7 @@ where let account_history = account_history::AccountHistory::new( &cache_dir, rpc_handle.clone(), - tokio_remote.clone(), + core_handle.remote.clone(), ) .map_err(Error::LoadAccountHistory)?; @@ -561,7 +550,7 @@ where let wireguard_key_manager = wireguard::KeyManager::new( internal_event_tx.clone(), rpc_handle.clone(), - tokio_remote.clone(), + core_handle.remote.clone(), ); // Attempt to download a fresh relay list @@ -591,11 +580,11 @@ where event_listener, settings, account_history, - wg_key_proxy: WireguardKeyProxy::new(rpc_handle.clone()), - accounts_proxy: AccountsProxy::new(rpc_handle), - https_handle, + rpc_runtime, + accounts_proxy: AccountsProxy::new(rpc_handle.clone()), + rpc_handle, wireguard_key_manager, - tokio_remote, + core_handle, relay_selector, last_generated_relay: None, last_generated_bridge_relay: None, @@ -703,6 +692,17 @@ where } fn handle_tunnel_state_transition(&mut self, tunnel_state_transition: TunnelStateTransition) { + match &tunnel_state_transition { + TunnelStateTransition::Disconnected + | TunnelStateTransition::Connected(_) + | TunnelStateTransition::Error(_) => { + // Reset the RPCs so that they fail immediately after the underlying socket gets + // invalidated due to the tunnel either coming up or breaking. + self.rpc_handle.service().reset(); + } + _ => (), + }; + let tunnel_state = match tunnel_state_transition { TunnelStateTransition::Disconnected => TunnelState::Disconnected, TunnelStateTransition::Connecting(endpoint) => TunnelState::Connecting { @@ -719,6 +719,7 @@ where TunnelStateTransition::Error(error_state) => TunnelState::Error(error_state), }; + self.unschedule_reconnect(); debug!("New tunnel state: {:?}", tunnel_state); @@ -1063,7 +1064,7 @@ where fn handle_new_account_event( &mut self, new_token: AccountToken, - tx: oneshot::Sender<Result<String, mullvad_rpc::Error>>, + tx: oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>, ) { match self.set_account(Some(new_token.clone())) { Ok(_) => { @@ -1106,7 +1107,7 @@ where Self::oneshot_send(tx, self.tunnel_state.clone(), "current state"); } - fn on_get_current_location(&self, tx: oneshot::Sender<Option<GeoIpLocation>>) { + fn on_get_current_location(&mut self, tx: oneshot::Sender<Option<GeoIpLocation>>) { use self::TunnelState::*; let get_location: Box<dyn Future<Item = Option<GeoIpLocation>, Error = ()> + Send> = match &self.tunnel_state { @@ -1131,13 +1132,13 @@ where } }; - self.tokio_remote.spawn(move |_| { + self.core_handle.remote.spawn(move |_| { get_location.map(|location| Self::oneshot_send(tx, location, "current location")) }); } - fn get_geo_location(&self) -> impl Future<Item = GeoIpLocation, Error = ()> { - let https_handle = self.https_handle.clone(); + fn get_geo_location(&mut self) -> impl Future<Item = GeoIpLocation, Error = ()> { + let https_handle = self.rpc_runtime.rest_handle(); geoip::send_location_request(https_handle).map_err(|e| { warn!("Unable to fetch GeoIP location: {}", e.display_chain()); @@ -1166,7 +1167,10 @@ where }) } - fn on_create_new_account(&mut self, tx: oneshot::Sender<Result<String, mullvad_rpc::Error>>) { + fn on_create_new_account( + &mut self, + tx: oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>, + ) { let daemon_tx = self.tx.clone(); let future = self .accounts_proxy @@ -1184,14 +1188,14 @@ where Ok(()) }); - if self.tokio_remote.execute(future).is_err() { + if self.core_handle.remote.execute(future).is_err() { log::error!("Failed to spawn future for creating a new account"); } } fn on_get_account_data( &mut self, - tx: oneshot::Sender<BoxFuture<AccountData, mullvad_rpc::Error>>, + tx: oneshot::Sender<BoxFuture<AccountData, mullvad_rpc::rest::Error>>, account_token: AccountToken, ) { let rpc_call = self @@ -1203,7 +1207,7 @@ where fn on_get_www_auth_token( &mut self, - tx: oneshot::Sender<BoxFuture<String, mullvad_rpc::Error>>, + tx: oneshot::Sender<BoxFuture<String, mullvad_rpc::rest::Error>>, ) { if let Some(account_token) = self.settings.get_account_token() { let rpc_call = self.accounts_proxy.get_www_auth_token(account_token); @@ -1213,7 +1217,7 @@ where fn on_submit_voucher( &mut self, - tx: oneshot::Sender<BoxFuture<VoucherSubmission, mullvad_rpc::Error>>, + tx: oneshot::Sender<BoxFuture<VoucherSubmission, mullvad_rpc::rest::Error>>, voucher: String, ) { if let Some(account_token) = self.settings.get_account_token() { @@ -1647,7 +1651,10 @@ where Ok(keygen_event) } Err(wireguard::Error::TooManyKeys) => Ok(KeygenEvent::TooManyKeys), - Err(e) => Err(format!("Failed to generate new key - {}", e)), + Err(e) => Err(format!( + "Failed to generate new key - {}", + e.display_chain_with_msg("Failed to generate new wireguard key:") + )), } }; @@ -1698,13 +1705,14 @@ where }; let fut = self - .wg_key_proxy - .check_wg_key(account, public_key) - .map(|is_valid| { + .wireguard_key_manager + .verify_wireguard_key(account, public_key) + .and_then(|is_valid| { Self::oneshot_send(tx, is_valid, "verify_wireguard_key response"); + Ok(()) }) - .map_err(|e| log::error!("Failed to verify wireguard key - {}", e)); - if let Err(e) = self.tokio_remote.execute(fut) { + .map_err(|e: wireguard::Error| log::error!("Failed to verify wireguard key - {}", e)); + if let Err(e) = self.core_handle.remote.execute(fut) { log::error!("Failed to spawn a future to verify wireguard key: {:?}", e); } } diff --git a/mullvad-daemon/src/logging.rs b/mullvad-daemon/src/logging.rs index 887ddd1268..35395833ae 100644 --- a/mullvad-daemon/src/logging.rs +++ b/mullvad-daemon/src/logging.rs @@ -39,6 +39,7 @@ pub const SILENCED_CRATES: &[&str] = &[ "mio", "hyper", "rtnetlink", + "rustls", "netlink_proto", "netlink_sys", "iproute2", diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index 00254472be..84c5db8570 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -7,7 +7,7 @@ use jsonrpc_ipc_server; use jsonrpc_macros::{build_rpc_trait, metadata, pubsub}; use jsonrpc_pubsub::{PubSubHandler, PubSubMetadata, Session, SubscriptionId}; use mullvad_paths; -use mullvad_rpc; +use mullvad_rpc::{rest::Error as RestError, StatusCode}; use mullvad_types::{ account::{AccountData, AccountToken, VoucherSubmission}, location::GeoIpLocation, @@ -26,6 +26,11 @@ use talpid_ipc; use talpid_types::ErrorExt; use uuid; +pub const INVALID_VOUCHER_CODE: i64 = -400; +pub const VOUCHER_USED_ALREADY_CODE: i64 = -401; +pub const INVALID_ACCOUNT_CODE: i64 = -200; + + build_rpc_trait! { pub trait ManagementInterfaceApi { type Metadata; @@ -306,18 +311,16 @@ impl ManagementInterface { future::result(self.tx.send(command)).map_err(|_| Error::internal_error()) } - /// Converts the given error to an error that can be given to the caller of the API. - /// Will let any actual RPC error through as is, any other error is changed to an internal - /// error. - fn map_rpc_error(error: &mullvad_rpc::Error) -> Error { - match error.kind() { - mullvad_rpc::ErrorKind::JsonRpcError(ref rpc_error) => { - // We have to manually copy the error since we have different - // versions of the jsonrpc_core library at the moment. + /// Converts a REST API error for an account into a JSONRPC error for the JSONRPC client. + fn map_rest_account_error(error: RestError) -> Error { + match error { + RestError::ApiError(status, message) + if status == StatusCode::UNAUTHORIZED || status == StatusCode::FORBIDDEN => + { Error { - code: ErrorCode::from(rpc_error.code.code()), - message: rpc_error.message.clone(), - data: rpc_error.data.clone(), + code: ErrorCode::from(INVALID_ACCOUNT_CODE), + message, + data: None, } } _ => Error::internal_error(), @@ -335,7 +338,7 @@ impl ManagementInterfaceApi for ManagementInterface { .and_then(|_| rx.map_err(|_| Error::internal_error())) .and_then(|result| match result { Ok(account_token) => Ok(account_token), - Err(e) => Err(Self::map_rpc_error(&e)), + Err(_) => Err(Error::internal_error()), }); Box::new(future) @@ -352,12 +355,12 @@ impl ManagementInterfaceApi for ManagementInterface { .send_command_to_daemon(DaemonCommand::GetAccountData(tx, account_token)) .and_then(|_| rx.map_err(|_| Error::internal_error())) .and_then(|rpc_future| { - rpc_future.map_err(|error: mullvad_rpc::Error| { + rpc_future.map_err(|error: RestError| { log::error!( "Unable to get account data from API: {}", error.display_chain() ); - Self::map_rpc_error(&error) + Self::map_rest_account_error(error) }) }); Box::new(future) @@ -370,12 +373,12 @@ impl ManagementInterfaceApi for ManagementInterface { .send_command_to_daemon(DaemonCommand::GetWwwAuthToken(tx)) .and_then(|_| rx.map_err(|_| Error::internal_error())) .and_then(|rpc_future| { - rpc_future.map_err(|error: mullvad_rpc::Error| { + rpc_future.map_err(|error: mullvad_rpc::rest::Error| { log::error!( "Unable to get account data from API: {}", error.display_chain() ); - Self::map_rpc_error(&error) + Self::map_rest_account_error(error) }) }); Box::new(future) @@ -391,7 +394,28 @@ impl ManagementInterfaceApi for ManagementInterface { let future = self .send_command_to_daemon(DaemonCommand::SubmitVoucher(tx, voucher)) .and_then(|_| rx.map_err(|_| Error::internal_error())) - .and_then(|f| f.map_err(|e| Self::map_rpc_error(&e))); + .and_then(|f| { + f.map_err(|e| match e { + RestError::ApiError(StatusCode::BAD_REQUEST, message) => { + match &message.as_str() { + &mullvad_rpc::INVALID_VOUCHER => Error { + code: ErrorCode::from(INVALID_VOUCHER_CODE), + message, + data: None, + }, + + &mullvad_rpc::VOUCHER_USED => Error { + code: ErrorCode::from(VOUCHER_USED_ALREADY_CODE), + message, + data: None, + }, + + _ => Error::internal_error(), + } + } + _ => Error::internal_error(), + }) + }); Box::new(future) } diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs index 25a3b8eb40..94e6c66cf9 100644 --- a/mullvad-daemon/src/relays.rs +++ b/mullvad-daemon/src/relays.rs @@ -3,7 +3,7 @@ use chrono::{DateTime, Local}; use futures::Future; -use mullvad_rpc::{HttpHandle, RelayListProxy}; +use mullvad_rpc::{rest::MullvadRestHandle, RelayListProxy}; use mullvad_types::{ endpoint::MullvadEndpoint, location::Location, @@ -52,7 +52,7 @@ pub enum Error { WriteRelayCache(#[error(source)] io::Error), #[error(display = "Failed to download the list of relays")] - Download(#[error(source)] mullvad_rpc::Error), + Download(#[error(source)] mullvad_rpc::rest::Error), #[error(display = "Timed out when trying to download the list of relays")] DownloadTimeout, @@ -155,7 +155,7 @@ impl RelaySelector { /// Returns a new `RelaySelector` backed by relays cached on disk. Use the `update` method /// to refresh the relay list from the internet. pub fn new( - rpc_handle: HttpHandle, + rpc_handle: MullvadRestHandle, on_update: impl Fn(&RelayList) + Send + 'static, resource_dir: &Path, cache_dir: &Path, @@ -783,7 +783,7 @@ impl RelaySelector { type RelayListUpdaterHandle = mpsc::Sender<()>; struct RelayListUpdater { - rpc_client: RelayListProxy<HttpHandle>, + rpc_client: RelayListProxy, cache_path: PathBuf, parsed_relays: Arc<Mutex<ParsedRelays>>, on_update: Box<dyn Fn(&RelayList)>, @@ -792,7 +792,7 @@ struct RelayListUpdater { impl RelayListUpdater { pub fn spawn( - rpc_handle: HttpHandle, + rpc_handle: MullvadRestHandle, cache_path: PathBuf, parsed_relays: Arc<Mutex<ParsedRelays>>, on_update: Box<dyn Fn(&RelayList) + Send + 'static>, @@ -807,7 +807,7 @@ impl RelayListUpdater { } fn new( - rpc_handle: HttpHandle, + rpc_handle: MullvadRestHandle, cache_path: PathBuf, parsed_relays: Arc<Mutex<ParsedRelays>>, on_update: Box<dyn Fn(&RelayList)>, @@ -879,7 +879,7 @@ impl RelayListUpdater { } fn download_relay_list(&mut self) -> Result<RelayList, Error> { - let download_future = self.rpc_client.relay_list_v3().map_err(Error::Download); + let download_future = self.rpc_client.relay_list().map_err(Error::Download); let relay_list = Timer::default() .timeout(download_future, DOWNLOAD_TIMEOUT) .wait()?; diff --git a/mullvad-daemon/src/version_check.rs b/mullvad-daemon/src/version_check.rs index 754509b407..7a4446708d 100644 --- a/mullvad-daemon/src/version_check.rs +++ b/mullvad-daemon/src/version_check.rs @@ -1,6 +1,6 @@ use crate::{version::PRODUCT_VERSION, DaemonEventSender}; use futures::{Async, Future, Poll}; -use mullvad_rpc::{AppVersionProxy, HttpHandle}; +use mullvad_rpc::{rest::MullvadRestHandle, AppVersionProxy}; use mullvad_types::version::AppVersionInfo; use serde::{Deserialize, Serialize}; use std::{ @@ -68,7 +68,7 @@ pub enum Error { DownloadTimeout, #[error(display = "Failed to check the latest app version")] - Download(#[error(source)] mullvad_rpc::Error), + Download(#[error(source)] mullvad_rpc::rest::Error), #[error(display = "Clearing version check cache due to a version mismatch")] CacheVersionMismatch, @@ -82,7 +82,7 @@ impl<T> From<TimeoutError<T>> for Error { pub(crate) struct VersionUpdater { - version_proxy: AppVersionProxy<HttpHandle>, + version_proxy: AppVersionProxy, cache_path: PathBuf, update_sender: DaemonEventSender<AppVersionInfo>, last_app_version_info: AppVersionInfo, @@ -97,7 +97,7 @@ enum VersionUpdaterState { impl VersionUpdater { pub fn new( - rpc_handle: HttpHandle, + rpc_handle: MullvadRestHandle, cache_dir: PathBuf, update_sender: DaemonEventSender<AppVersionInfo>, last_app_version_info: AppVersionInfo, @@ -123,7 +123,7 @@ impl VersionUpdater { ) -> Box<dyn Future<Item = AppVersionInfo, Error = Error> + Send + 'static> { let download_future = self .version_proxy - .app_version_check(&PRODUCT_VERSION.to_owned(), PLATFORM) + .version_check(PRODUCT_VERSION.to_owned(), PLATFORM) .map_err(Error::Download); let future = Timer::default().timeout(download_future, DOWNLOAD_TIMEOUT); Box::new(future) @@ -226,8 +226,9 @@ pub fn load_cache(cache_dir: &Path) -> AppVersionInfo { ); // If we don't have a cache, start out with sane defaults. AppVersionInfo { - current_is_supported: true, + supported: true, latest_stable: PRODUCT_VERSION.to_owned(), + latest_beta: PRODUCT_VERSION.to_owned(), latest: PRODUCT_VERSION.to_owned(), } } diff --git a/mullvad-daemon/src/wireguard.rs b/mullvad-daemon/src/wireguard.rs index 9b234dfaab..5cc4b9be7d 100644 --- a/mullvad-daemon/src/wireguard.rs +++ b/mullvad-daemon/src/wireguard.rs @@ -1,7 +1,7 @@ use crate::{account_history::AccountHistory, DaemonEventSender, InternalDaemonEvent}; use chrono::offset::Utc; use futures::{future::Executor, stream::Stream, sync::oneshot, Async, Future, Poll}; -use jsonrpc_client_core::Error as JsonRpcError; +use mullvad_rpc::rest::{Error as RestError, MullvadRestHandle}; use mullvad_types::account::AccountToken; pub use mullvad_types::wireguard::*; use std::time::Duration; @@ -17,8 +17,6 @@ use tokio_retry::{ }; use tokio_timer; -const TOO_MANY_KEYS_ERROR_CODE: i64 = -703; - /// Default automatic key rotation const DEFAULT_AUTOMATIC_KEY_ROTATION: Duration = Duration::from_secs(7 * 24 * 60 * 60); /// How long to wait before reattempting to rotate keys on failure @@ -31,8 +29,8 @@ const KEY_CHECK_INTERVAL: Duration = Duration::from_secs(60); pub enum Error { #[error(display = "Failed to spawn future")] ExectuionError, - #[error(display = "Unexpected RPC error")] - RpcError(#[error(source)] jsonrpc_client_core::Error), + #[error(display = "Unexpected HTTP request error")] + RestError(#[error(source)] mullvad_rpc::rest::Error), #[error(display = "Account already has maximum number of keys")] TooManyKeys, #[error(display = "Failed to create rotation timer")] @@ -43,7 +41,7 @@ pub type Result<T> = std::result::Result<T, Error>; pub struct KeyManager { daemon_tx: DaemonEventSender, - http_handle: mullvad_rpc::HttpHandle, + http_handle: MullvadRestHandle, tokio_remote: Remote, current_job: Option<CancelHandle>, @@ -54,7 +52,7 @@ pub struct KeyManager { impl KeyManager { pub(crate) fn new( daemon_tx: DaemonEventSender, - http_handle: mullvad_rpc::HttpHandle, + http_handle: MullvadRestHandle, tokio_remote: Remote, ) -> Self { Self { @@ -149,6 +147,25 @@ impl KeyManager { )) } + /// Verifies whether a key is valid or not. + pub fn verify_wireguard_key( + &self, + account: AccountToken, + key: talpid_types::net::wireguard::PublicKey, + ) -> impl Future<Item = bool, Error = Error> { + let mut rpc = mullvad_rpc::WireguardKeyProxy::new(self.http_handle.clone()); + rpc.get_wireguard_key(account, &key) + .then(|response| match response { + Ok(_) => Ok(true), + Err(mullvad_rpc::rest::Error::ApiError(status, _code)) + if status == mullvad_rpc::StatusCode::NOT_FOUND => + { + Ok(false) + } + Err(err) => Err(Self::map_rpc_error(err)), + }) + } + /// Generate a new private key asynchronously. The new keys will be sent to the daemon channel. pub fn generate_key_async(&mut self, account: AccountToken) -> Result<()> { @@ -160,11 +177,9 @@ impl KeyManager { .max_delay(Duration::from_secs(60 * 60)) .map(jitter); - let should_retry = |err: &jsonrpc_client_core::Error| -> bool { - match err.kind() { - jsonrpc_client_core::ErrorKind::JsonRpcError(err) - if err.code.code() == TOO_MANY_KEYS_ERROR_CODE => - { + let should_retry = |err: &RestError| -> bool { + match err { + RestError::ApiError(_status, code) if code == mullvad_rpc::KEY_LIMIT_REACHED => { false } _ => true, @@ -225,13 +240,13 @@ impl KeyManager { &self, account: AccountToken, private_key: PrivateKey, - ) -> Box<dyn FnMut() -> Box<dyn Future<Item = WireguardData, Error = JsonRpcError> + Send> + Send> + ) -> Box<dyn FnMut() -> Box<dyn Future<Item = WireguardData, Error = RestError> + Send> + Send> { let mut rpc = mullvad_rpc::WireguardKeyProxy::new(self.http_handle.clone()); let public_key = private_key.public_key(); let push_future = - move || -> Box<dyn Future<Item = WireguardData, Error = JsonRpcError> + Send> { + move || -> Box<dyn Future<Item = WireguardData, Error = RestError> + Send> { let key = private_key.clone(); Box::new(rpc.push_wg_key(account.clone(), public_key.clone()).map( move |addresses| WireguardData { @@ -245,7 +260,7 @@ impl KeyManager { } fn replace_key_rpc( - http_handle: mullvad_rpc::HttpHandle, + http_handle: MullvadRestHandle, account: AccountToken, old_key: PublicKey, new_key: PrivateKey, @@ -261,13 +276,16 @@ impl KeyManager { }) } - fn map_rpc_error(err: jsonrpc_client_core::Error) -> Error { - match err.kind() { + fn map_rpc_error(err: mullvad_rpc::rest::Error) -> Error { + match &err { // TODO: Consider handling the invalid account case too. - jsonrpc_client_core::ErrorKind::JsonRpcError(err) if err.code.code() == -703 => { + mullvad_rpc::rest::Error::ApiError(status, message) + if *status == mullvad_rpc::StatusCode::BAD_REQUEST + && message == mullvad_rpc::KEY_LIMIT_REACHED => + { Error::TooManyKeys } - _ => Error::RpcError(err), + _ => Error::RestError(err), } } @@ -290,7 +308,7 @@ impl KeyManager { fn next_automatic_rotation( daemon_tx: DaemonEventSender, - http_handle: mullvad_rpc::HttpHandle, + http_handle: MullvadRestHandle, public_key: PublicKey, rotation_interval_secs: u64, account_token: AccountToken, @@ -330,7 +348,7 @@ impl KeyManager { fn create_automatic_rotation( daemon_tx: DaemonEventSender, - http_handle: mullvad_rpc::HttpHandle, + http_handle: MullvadRestHandle, public_key: PublicKey, rotation_interval_secs: u64, account_token: AccountToken, @@ -355,8 +373,8 @@ impl KeyManager { } Err(e) => { log::error!( - "Key rotation failed: {}. Retrying in {} seconds", - e, + "{}. Retrying in {} seconds", + e.display_chain_with_msg("Key rotation failed:"), AUTOMATIC_ROTATION_RETRY_DELAY.as_secs(), ); Ok(old_public_key) diff --git a/mullvad-jni/Cargo.toml b/mullvad-jni/Cargo.toml index 6122b03edc..de207328b9 100644 --- a/mullvad-jni/Cargo.toml +++ b/mullvad-jni/Cargo.toml @@ -25,5 +25,6 @@ mullvad-daemon = { path = "../mullvad-daemon" } mullvad-paths = { path = "../mullvad-paths" } mullvad-problem-report = { path = "../mullvad-problem-report" } mullvad-types = { path = "../mullvad-types" } +mullvad-rpc = { path = "../mullvad-rpc" } talpid-core = { path = "../talpid-core" } talpid-types = { path = "../talpid-types" } diff --git a/mullvad-jni/src/daemon_interface.rs b/mullvad-jni/src/daemon_interface.rs index 8c9ec1329f..6a7c1e118a 100644 --- a/mullvad-jni/src/daemon_interface.rs +++ b/mullvad-jni/src/daemon_interface.rs @@ -23,7 +23,7 @@ pub enum Error { NoSender, #[error(display = "Error performing RPC with the remote API")] - RpcError(#[error(source)] jsonrpc_client_core::Error), + RpcError(#[error(source)] mullvad_rpc::rest::Error), } type Result<T> = std::result::Result<T, Error>; diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs index b3996ee507..89a4a4e1a0 100644 --- a/mullvad-jni/src/lib.rs +++ b/mullvad-jni/src/lib.rs @@ -17,6 +17,7 @@ use jnix::{ FromJava, IntoJava, JnixEnv, }; use mullvad_daemon::{exception_logging, logging, version, Daemon, DaemonCommandChannel}; +use mullvad_rpc::rest::Error as RestError; use mullvad_types::account::AccountData; use std::{ path::{Path, PathBuf}, @@ -62,13 +63,11 @@ impl From<Result<AccountData, daemon_interface::Error>> for GetAccountDataResult match result { Ok(account_data) => GetAccountDataResult::Ok(account_data), Err(error) => match error { - daemon_interface::Error::RpcError(jsonrpc_client_core::Error( - jsonrpc_client_core::ErrorKind::JsonRpcError(jsonrpc_core::Error { - code: jsonrpc_core::ErrorCode::ServerError(-200), - .. - }), - _, - )) => GetAccountDataResult::InvalidAccount, + daemon_interface::Error::RpcError(RestError::ApiError(status, _code)) + if status == mullvad_rpc::StatusCode::NOT_FOUND => + { + GetAccountDataResult::InvalidAccount + } daemon_interface::Error::RpcError(_) => GetAccountDataResult::RpcError, _ => GetAccountDataResult::OtherError, }, diff --git a/mullvad-problem-report/Cargo.toml b/mullvad-problem-report/Cargo.toml index 4a5ed7b09f..0817eba3f7 100644 --- a/mullvad-problem-report/Cargo.toml +++ b/mullvad-problem-report/Cargo.toml @@ -12,9 +12,9 @@ clap = "2.25" dirs = "2.0" env_logger = "0.7" err-derive = "0.2.1" +futures01 = { version = "0.1", crate = "futures" } lazy_static = "1.0" regex = "1.0" -tokio-core = "0.1" uuid = { version = "0.7", features = ["v4"] } mullvad-paths = { path = "../mullvad-paths" } diff --git a/mullvad-problem-report/src/lib.rs b/mullvad-problem-report/src/lib.rs index bac11df5dc..cf37e6cb0f 100644 --- a/mullvad-problem-report/src/lib.rs +++ b/mullvad-problem-report/src/lib.rs @@ -1,5 +1,6 @@ #![deny(rust_2018_idioms)] +use futures01::Future; use lazy_static::lazy_static; use regex::Regex; use std::{ @@ -12,7 +13,6 @@ use std::{ path::{Path, PathBuf}, }; use talpid_types::ErrorExt; -use tokio_core::reactor::Core; pub mod metadata; @@ -62,11 +62,11 @@ pub enum Error { source: io::Error, }, - #[error(display = "Unable to create JSON-RPC 2.0 client")] - CreateRpcClientError(#[error(source)] mullvad_rpc::HttpError), + #[error(display = "Unable to create REST client")] + CreateRpcClientError(#[error(source)] mullvad_rpc::Error), #[error(display = "Error during RPC call")] - SendRpcError(#[error(source)] mullvad_rpc::Error), + SendRpcError(#[error(source)] mullvad_rpc::rest::Error), } /// These are errors that can happen during problem report collection. @@ -265,14 +265,13 @@ pub fn send_problem_report( let ca_path = mullvad_paths::resources::get_api_ca_path(); - let mut core = Core::new().unwrap(); - let mut rpc_manager = mullvad_rpc::MullvadRpcFactory::new(ca_path); - let rpc_http_handle = rpc_manager - .new_connection_on_event_loop(&core.handle()) + let mut rpc_manager = mullvad_rpc::MullvadRpcRuntime::new(ca_path.as_ref()) .map_err(Error::CreateRpcClientError)?; - let mut rpc_client = mullvad_rpc::ProblemReportProxy::new(rpc_http_handle); + let rpc_client = mullvad_rpc::ProblemReportProxy::new(rpc_manager.mullvad_rest_handle()); - core.run(rpc_client.problem_report(user_email, user_message, &report_content, &metadata)) + rpc_client + .problem_report(user_email, user_message, &report_content, &metadata) + .wait() .map_err(Error::SendRpcError) } diff --git a/mullvad-rpc/Cargo.toml b/mullvad-rpc/Cargo.toml index 47a4040f87..a88c75aff2 100644 --- a/mullvad-rpc/Cargo.toml +++ b/mullvad-rpc/Cargo.toml @@ -10,16 +10,20 @@ publish = false [dependencies] chrono = { version = "0.4", features = ["serde"] } err-derive = "0.2.1" -futures = "0.1.15" -jsonrpc-client-core = "0.5" -jsonrpc-client-http = "0.5" +futures = { version = "0.3", features = [ "default", "compat" ] } +futures01 = { package = "futures", version = "0.1" } +http = "0.2" +hyper = "0.13" +ipnetwork = "0.15" +log = "0.4" +serde = "1" serde_json = "1.0" -tokio-core = "0.1" -hyper = "0.11" -hyper-openssl = "0.5" +hyper-rustls = "0.20" +tokio = { version = "0.2", features = [ "time", "rt-threaded", "net", "io-std", "io-driver" ] } +tokio-rustls = "0.13" tokio-service = "0.1" -tokio-openssl = "0.2" -log = "0.4" +urlencoding = "1" +webpki = { version = "0.21", features = [] } mullvad-types = { path = "../mullvad-types" } talpid-types = { path = "../talpid-types" } @@ -27,3 +31,6 @@ talpid-types = { path = "../talpid-types" } [dev-dependencies] filetime = "0.2" tempfile = "3.0" + +[[bin]] +name = "relay_list" diff --git a/mullvad-rpc/src/bin/relay_list.rs b/mullvad-rpc/src/bin/relay_list.rs new file mode 100644 index 0000000000..330d53bc11 --- /dev/null +++ b/mullvad-rpc/src/bin/relay_list.rs @@ -0,0 +1,17 @@ +/// Intended to be used to pre-load a relay list when creating an installer for the Mullvad VPN +/// app. +use futures01::future::Future; +use mullvad_rpc::{MullvadRpcRuntime, RelayListProxy}; + +fn main() { + let mut runtime = MullvadRpcRuntime::new("dist-assets/api_root_ca.pem".as_ref()) + .expect("Failed to load runtime"); + + let relay_list_request = RelayListProxy::new(runtime.mullvad_rest_handle()).relay_list(); + + let relay_list = relay_list_request + .wait() + .expect("Failed to fetch relay list"); + + println!("{}", serde_json::to_string_pretty(&relay_list).unwrap()); +} diff --git a/mullvad-rpc/src/event_loop.rs b/mullvad-rpc/src/event_loop.rs index b4e026ce9b..ea93de2493 100644 --- a/mullvad-rpc/src/event_loop.rs +++ b/mullvad-rpc/src/event_loop.rs @@ -1,32 +1,14 @@ -use std::{io, thread}; -use tokio_core::reactor::Core; +use tokio::runtime::{Builder, Runtime}; -/// Creates a new tokio event loop on a new thread, runs the provided `init` closure on the thread -/// and sends back the result. -/// Used to spawn futures on the core in the separate thread and be able to return sendable handles. -pub fn create<F, T>(init: F) -> io::Result<T> -where - F: FnOnce(&mut Core) -> T + Send + 'static, - T: Send + 'static, -{ - let (tx, rx) = std::sync::mpsc::channel(); - thread::spawn(move || match create_core(init) { - Err(e) => tx.send(Err(e)).unwrap(), - Ok((mut core, out)) => { - tx.send(Ok(out)).unwrap(); - loop { - core.turn(None); - } - } - }); - rx.recv().unwrap() -} +/// Creates a new tokio runtime to be exclusively used for HTTP requests. +// FIXME: Remove this once the daemon has migrated. +pub fn create_runtime() -> Result<Runtime, crate::Error> { + let runtime = Builder::new() + .threaded_scheduler() + .core_threads(2) + .enable_all() + .thread_name("mullvad-rpc-event-loop") + .build(); -fn create_core<F, T>(init: F) -> io::Result<(Core, T)> -where - F: FnOnce(&mut Core) -> T + Send + 'static, -{ - let mut core = Core::new()?; - let out = init(&mut core); - Ok((core, out)) + runtime.map_err(crate::Error::TokioRuntimeError) } diff --git a/mullvad-rpc/src/https_client_with_sni.rs b/mullvad-rpc/src/https_client_with_sni.rs index 3f62372e73..a73bc19f39 100644 --- a/mullvad-rpc/src/https_client_with_sni.rs +++ b/mullvad-rpc/src/https_client_with_sni.rs @@ -1,81 +1,81 @@ -use futures::{Future, Poll}; -use hyper::{ - client::{Client, Connect, HttpConnector}, - Body, Uri, -}; -use hyper_openssl::openssl::ssl::{SslConnector, SslMethod}; -use jsonrpc_client_http::ClientCreator; +use http::uri::Scheme; +use hyper::{client::HttpConnector, service::Service, Uri}; +use hyper_rustls::MaybeHttpsStream; use std::{ - fmt, io, - path::{Path, PathBuf}, + fmt, + fs::File, + future::Future, + io::{self, BufReader}, + path::Path, + pin::Pin, str, sync::Arc, + task::{Context, Poll}, }; -use tokio_core::reactor::Handle; -use tokio_openssl::{SslConnectorExt, SslStream}; -use tokio_service::Service; +use tokio_rustls::rustls; +use webpki::DNSNameRef; -pub use hyper_openssl::openssl::error::ErrorStack; -pub struct HttpsClientWithSni { - sni_hostname: String, - ca_path: Box<Path>, -} +#[derive(err_derive::Error, Debug)] +#[error(no_from)] +pub enum Error { + #[error(display = "Failed to parse cert file")] + CertError, -impl HttpsClientWithSni { - pub fn new<P: Into<PathBuf>>(sni_hostname: String, ca_path: P) -> Self { - HttpsClientWithSni { - sni_hostname, - ca_path: ca_path.into().into_boxed_path(), - } - } -} + #[error(display = "Root certificate error")] + RootCertError(webpki::Error), -impl ClientCreator for HttpsClientWithSni { - type Connect = HttpsConnectorWithSni<HttpConnector>; - type Error = ErrorStack; + #[error(display = "Failed to read cert file")] + ReadCertError(#[error(source)] io::Error), - fn create(&self, handle: &Handle) -> Result<Client<Self::Connect, Body>, Self::Error> { - let mut connector = HttpsConnectorWithSni::new(&self.ca_path, handle)?; - connector.set_sni_hostname(Some(self.sni_hostname.clone())); - let client = Client::configure() - .keep_alive(false) - .connector(connector) - .build(handle); - Ok(client) - } + #[error(display = "Failed to read trust anchor")] + ReadRootError(#[error(source)] io::Error), } /// A Connector for the `https` scheme. #[derive(Clone)] -pub struct HttpsConnectorWithSni<T> { +pub struct HttpsConnectorWithSni { sni_hostname: Option<String>, - http: T, - tls: Arc<SslConnector>, + http: HttpConnector, + tls: Arc<rustls::ClientConfig>, } -impl HttpsConnectorWithSni<HttpConnector> { +impl HttpsConnectorWithSni { /// Construct a new HttpsConnectorWithSni. /// /// Takes number of DNS worker threads. /// /// This uses hyper's default `HttpConnector`, and default `TlsConnector`. /// If you wish to use something besides the defaults, use `From::from`. - pub fn new<P: AsRef<Path>>(ca_path: P, handle: &Handle) -> Result<Self, ErrorStack> { - let mut http = HttpConnector::new(crate::DNS_THREADS, handle); + pub fn new<P: AsRef<Path>>(ca_path: P) -> Result<Self, Error> { + let mut http = HttpConnector::new(); http.enforce_http(false); - let mut ssl_builder = SslConnector::builder(SslMethod::tls())?; - ssl_builder.set_ca_file(ca_path)?; - let ssl = ssl_builder.build(); - Ok(HttpsConnectorWithSni::from((http, ssl))) + let mut config = rustls::ClientConfig::new(); + config.enable_sni = true; + config.root_store = Self::read_cert_store(ca_path)?; + + Ok(HttpsConnectorWithSni::from((http, config))) + } + + fn read_cert_store(ca_path: impl AsRef<Path>) -> Result<rustls::RootCertStore, Error> { + let mut cert_store = rustls::RootCertStore::empty(); + + + let cert_file = File::open(ca_path).map_err(Error::ReadCertError)?; + let mut cert_reader = BufReader::new(&cert_file); + let (_num_certs_added, num_failures) = cert_store + .add_pem_file(&mut cert_reader) + .map_err(|_| Error::CertError)?; + // add_pem_file() returns an Ok(i32, i32), where the second integer represents the amount + // of errors encountered. Go figure. + if num_failures > 0 { + return Err(Error::CertError); + } + + Ok(cert_store) } -} -impl<T> HttpsConnectorWithSni<T> -where - T: Connect, -{ /// Configure a hostname to use with SNI. /// /// Configures the TLS connection handshake to request a certificate for a given domain, @@ -85,8 +85,8 @@ where } } -impl<T> From<(T, SslConnector)> for HttpsConnectorWithSni<T> { - fn from(args: (T, SslConnector)) -> HttpsConnectorWithSni<T> { +impl From<(HttpConnector, rustls::ClientConfig)> for HttpsConnectorWithSni { + fn from(args: (HttpConnector, rustls::ClientConfig)) -> HttpsConnectorWithSni { HttpsConnectorWithSni { sni_hostname: None, http: args.0, @@ -95,68 +95,54 @@ impl<T> From<(T, SslConnector)> for HttpsConnectorWithSni<T> { } } -impl<T> fmt::Debug for HttpsConnectorWithSni<T> { +impl fmt::Debug for HttpsConnectorWithSni { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("HttpsConnectorWithSni").finish() } } -impl<T: Connect> Service for HttpsConnectorWithSni<T> { - type Request = Uri; - type Response = SslStream<T::Output>; +impl Service<Uri> for HttpsConnectorWithSni { + type Response = MaybeHttpsStream<tokio::net::TcpStream>; type Error = io::Error; - type Future = HttpsConnecting<T::Output>; + type Future = + Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>; - fn call(&self, uri: Uri) -> Self::Future { - if uri.scheme() != Some("https") { - return HttpsConnecting(Box::new(::futures::future::err(io::Error::new( - io::ErrorKind::InvalidInput, - "invalid url, not https", - )))); - } - let maybe_host = self - .sni_hostname - .as_ref() - .map(String::as_str) - .or_else(|| uri.host()) - .map(str::to_owned); - let host = match maybe_host { - Some(host) => host, - None => { - return HttpsConnecting(Box::new(::futures::future::err(io::Error::new( - io::ErrorKind::InvalidInput, - "invalid url, missing host", - )))); - } - }; - let connecting = self.http.connect(uri); - let tls = self.tls.clone(); - - let fut = connecting.and_then(move |tcp| { - tls.connect_async(&host, tcp) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) - }); - HttpsConnecting(Box::new(fut)) + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + Poll::Ready(Ok(())) } -} -type BoxedFut<T> = Box<dyn Future<Item = SslStream<T>, Error = io::Error>>; + fn call(&mut self, uri: Uri) -> Self::Future { + let tls_connector: tokio_rustls::TlsConnector = self.tls.clone().into(); + let mut http = self.http.clone(); + let sni_hostname = self + .sni_hostname + .clone() + .or_else(|| uri.host().map(str::to_owned)) + .ok_or_else(|| { + io::Error::new(io::ErrorKind::InvalidInput, "invalid url, missing host") + }); -/// A Future representing work to connect to a URL, and a TLS handshake. -pub struct HttpsConnecting<T>(BoxedFut<T>); + let fut = async move { + if uri.scheme() != Some(&Scheme::HTTPS) { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "invalid url, not https", + )); + } + let hostname = sni_hostname?; + let host = DNSNameRef::try_from_ascii_str(&hostname) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid hostname"))?; + let connection = http + .call(uri) + .await + .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; + let tls_connection = tls_connector.connect(host, connection).await?; -impl<T> Future for HttpsConnecting<T> { - type Item = SslStream<T>; - type Error = io::Error; + Ok(MaybeHttpsStream::Https(tls_connection)) + }; - fn poll(&mut self) -> Poll<Self::Item, Self::Error> { - self.0.poll() - } -} -impl<T> fmt::Debug for HttpsConnecting<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("HttpsConnecting") + Box::pin(fut) } } diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs index f7b4d086f1..949f8c76f8 100644 --- a/mullvad-rpc/src/lib.rs +++ b/mullvad-rpc/src/lib.rs @@ -1,24 +1,19 @@ #![deny(rust_2018_idioms)] use chrono::{offset::Utc, DateTime}; -use jsonrpc_client_core::{expand_params, jsonrpc_client}; -use jsonrpc_client_http::{header::Host, HttpTransport, HttpTransportBuilder}; +use futures01::future::Future as Future01; +use hyper::Method; use mullvad_types::{ account::{AccountToken, VoucherSubmission}, - relay_list::RelayList, version, }; use std::{ collections::BTreeMap, net::{IpAddr, Ipv4Addr}, - path::{Path, PathBuf}, - time::Duration, + path::Path, }; use talpid_types::net::wireguard; -use tokio_core::reactor::Handle; -pub use jsonrpc_client_core::{Error, ErrorKind}; -pub use jsonrpc_client_http::{Error as HttpError, HttpHandle}; pub mod event_loop; pub mod rest; @@ -27,123 +22,405 @@ mod cached_dns_resolver; use crate::cached_dns_resolver::CachedDnsResolver; mod https_client_with_sni; -use crate::https_client_with_sni::{HttpsClientWithSni, HttpsConnectorWithSni}; +use crate::https_client_with_sni::HttpsConnectorWithSni; + +mod relay_list; +pub use hyper::StatusCode; +pub use relay_list::RelayListProxy; -/// Number of threads in the thread pool doing DNS resolutions. -/// Since DNS is resolved via blocking syscall they must be run on separate threads. -const DNS_THREADS: usize = 2; const API_HOST: &str = "api.mullvad.net"; -const RPC_TIMEOUT: Duration = Duration::from_secs(10); pub const API_IP_CACHE_FILENAME: &str = "api-ip-address.txt"; const API_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(193, 138, 218, 78)); /// A type that helps with the creation of RPC connections. -pub struct MullvadRpcFactory { +pub struct MullvadRpcRuntime { cached_dns_resolver: CachedDnsResolver, - ca_path: PathBuf, + https_connector: HttpsConnectorWithSni, + runtime: tokio::runtime::Runtime, +} + +#[derive(err_derive::Error, Debug)] +pub enum Error { + #[error(display = "Failed to construct a connector")] + ConnectorError(#[error(source)] https_client_with_sni::Error), + #[error(display = "Failed to construct a rest client")] + RestError(#[error(source)] rest::Error), + #[error(display = "Failed to spawn a tokio runtime")] + TokioRuntimeError(#[error(source)] tokio::io::Error), } -impl MullvadRpcFactory { - /// Create a new `MullvadRpcFactory`. - pub fn new<P: Into<PathBuf>>(ca_path: P) -> Self { - MullvadRpcFactory { +impl MullvadRpcRuntime { + /// Create a new `MullvadRpcRuntime`. + pub fn new(ca_path: &Path) -> Result<Self, Error> { + let https_connector = + HttpsConnectorWithSni::new(&ca_path).map_err(Error::ConnectorError)?; + Ok(MullvadRpcRuntime { cached_dns_resolver: CachedDnsResolver::new(API_HOST.to_owned(), None, API_IP), - ca_path: ca_path.into(), - } + runtime: event_loop::create_runtime()?, + https_connector, + }) } - /// Create a new `MullvadRpcFactory` using the specified cache directory. - pub fn with_cache_dir<P: Into<PathBuf>>(cache_dir: &Path, ca_path: P) -> Self { + /// Create a new `MullvadRpcRuntime` using the specified cache directory. + pub fn with_cache_dir(cache_dir: &Path, ca_path: &Path) -> Result<Self, Error> { let cache_file = cache_dir.join(API_IP_CACHE_FILENAME); let cached_dns_resolver = CachedDnsResolver::new(API_HOST.to_owned(), Some(cache_file), API_IP); - MullvadRpcFactory { + let https_connector = + HttpsConnectorWithSni::new(&ca_path).map_err(Error::ConnectorError)?; + + Ok(MullvadRpcRuntime { cached_dns_resolver, - ca_path: ca_path.into(), + runtime: event_loop::create_runtime()?, + https_connector, + }) + } + + /// Creates a new request service and returns a handle to it. + fn new_request_service(&mut self, sni_hostname: Option<String>) -> rest::RequestServiceHandle { + let mut https_connector = self.https_connector.clone(); + https_connector.set_sni_hostname(sni_hostname); + + let service = rest::RequestService::new(https_connector, self.runtime.handle().clone()); + let handle = service.handle(); + self.runtime.spawn(service.into_future()); + handle + } + + /// Returns a request factory initialized to create requests for the master API + pub fn mullvad_rest_handle(&mut self) -> rest::MullvadRestHandle { + let service = self.new_request_service(Some(API_HOST.to_owned())); + let ip = self.cached_dns_resolver.resolve(); + let factory = + rest::RequestFactory::new(API_HOST.to_owned(), Some(ip), Some("app".to_owned())); + + rest::MullvadRestHandle { service, factory } + } + + /// Returns a new request service handle + pub fn rest_handle(&mut self) -> rest::RequestServiceHandle { + self.new_request_service(None) + } +} + +impl Drop for MullvadRpcRuntime { + fn drop(&mut self) { + if let Ok(runtime) = event_loop::create_runtime() { + let old_runtime = std::mem::replace(&mut self.runtime, runtime); + old_runtime.shutdown_timeout(std::time::Duration::from_secs(1)); } } +} - /// Create and returns a `HttpHandle` running on the given core handle. - pub fn new_connection_on_event_loop( - &mut self, - handle: &Handle, - ) -> Result<HttpHandle, HttpError> { - self.setup_connection(move |transport| transport.shared(handle)) +pub struct AccountsProxy { + handle: rest::MullvadRestHandle, +} + +#[derive(serde::Deserialize)] +struct AccountResponse { + token: AccountToken, + expires: DateTime<Utc>, +} +pub const VOUCHER_USED: &str = "VOUCHER_USED"; +pub const INVALID_VOUCHER: &str = "INVALID_VOUCHER"; +pub const MISSING_ARGUMENT: &str = "MISSING_ARGUMENT"; + +impl AccountsProxy { + pub fn new(handle: rest::MullvadRestHandle) -> Self { + Self { handle } } - fn setup_connection<F>(&mut self, create_transport: F) -> Result<HttpHandle, HttpError> - where - F: FnOnce( - HttpTransportBuilder<HttpsClientWithSni>, - ) -> jsonrpc_client_http::Result<HttpTransport>, - { - let client = HttpsClientWithSni::new(API_HOST.to_owned(), self.ca_path.clone()); - let transport_builder = HttpTransportBuilder::with_client(client).timeout(RPC_TIMEOUT); + pub fn get_expiry( + &self, + account: AccountToken, + ) -> impl Future01<Item = DateTime<Utc>, Error = rest::Error> { + let service = self.handle.service.clone(); + + let response = rest::send_request( + &self.handle.factory, + service, + "/v1/me", + Method::GET, + Some(account), + StatusCode::OK, + ); + self.handle.service.compat_spawn(async move { + let account: AccountResponse = rest::deserialize_body(response.await?).await?; + Ok(account.expires) + }) + } + + pub fn create_account(&mut self) -> impl Future01<Item = AccountToken, Error = rest::Error> { + let service = self.handle.service.clone(); + let response = rest::send_request( + &self.handle.factory, + service, + "/v1/accounts", + Method::POST, + None, + StatusCode::CREATED, + ); + + self.handle.service.compat_spawn(async move { + let account: AccountResponse = rest::deserialize_body(response.await?).await?; + Ok(account.token) + }) + } + + pub fn submit_voucher( + &mut self, + account_token: AccountToken, + voucher_code: String, + ) -> impl Future01<Item = VoucherSubmission, Error = rest::Error> { + #[derive(serde::Serialize)] + struct VoucherSubmission { + voucher_code: String, + } - let transport = create_transport(transport_builder)?; - let api_uri = self.api_uri(); - log::debug!("Using API URI {}", api_uri); - let mut handle = transport.handle(&api_uri)?; + let service = self.handle.service.clone(); + let submission = VoucherSubmission { voucher_code }; - handle.set_header(Host::new(API_HOST, None)); + let response = rest::post_request_with_json( + &self.handle.factory, + service, + "/v1/submit-voucher", + &submission, + Some(account_token), + StatusCode::OK, + ); - Ok(handle) + self.handle + .service + .compat_spawn(async move { rest::deserialize_body(response.await?).await }) } - fn api_uri(&mut self) -> String { - let ip = self.cached_dns_resolver.resolve().to_string(); - format!("https://{}/rpc/", ip) + pub fn get_www_auth_token( + &self, + account: AccountToken, + ) -> impl Future01<Item = String, Error = rest::Error> { + #[derive(serde::Deserialize)] + struct AuthTokenResponse { + auth_token: String, + } + + let service = self.handle.service.clone(); + let response = rest::send_request( + &self.handle.factory, + service, + "/v1/www-auth-token", + Method::POST, + Some(account), + StatusCode::OK, + ); + + let future = async move { + let response: AuthTokenResponse = rest::deserialize_body(response.await?).await?; + Ok(response.auth_token) + }; + + self.handle.service.compat_spawn(future) } } -jsonrpc_client!(pub struct AccountsProxy { - pub fn create_account(&mut self) -> RpcRequest<AccountToken>; - pub fn get_expiry(&mut self, account_token: AccountToken) -> RpcRequest<DateTime<Utc>>; - pub fn get_www_auth_token(&mut self, account_token: AccountToken) -> RpcRequest<String>; - pub fn submit_voucher(&mut self, account_token: AccountToken, voucher: String) -> RpcRequest<VoucherSubmission>; -}); +pub struct ProblemReportProxy { + handle: rest::MullvadRestHandle, +} + +impl ProblemReportProxy { + pub fn new(handle: rest::MullvadRestHandle) -> Self { + Self { handle } + } -jsonrpc_client!(pub struct ProblemReportProxy { pub fn problem_report( - &mut self, + &self, email: &str, message: &str, log: &str, - metadata: &BTreeMap<String, String>) - -> RpcRequest<()>; -}); + metadata: &BTreeMap<String, String>, + ) -> impl Future01<Item = (), Error = rest::Error> { + #[derive(serde::Serialize)] + struct ProblemReport { + address: String, + message: String, + log: String, + metadata: BTreeMap<String, String>, + } -jsonrpc_client!(pub struct RelayListProxy { - pub fn relay_list_v3(&mut self) -> RpcRequest<RelayList>; -}); + let report = ProblemReport { + address: email.to_owned(), + message: message.to_owned(), + log: log.to_owned(), + metadata: metadata.clone(), + }; + + let service = self.handle.service.clone(); + + let request = rest::post_request_with_json( + &self.handle.factory, + service, + "/v1/problem-report", + &report, + None, + StatusCode::NO_CONTENT, + ); + + self.handle.service.compat_spawn(async move { + request.await?; + Ok(()) + }) + } +} + +pub struct AppVersionProxy { + handle: rest::MullvadRestHandle, +} + +impl AppVersionProxy { + pub fn new(handle: rest::MullvadRestHandle) -> Self { + Self { handle } + } + + pub fn version_check( + &self, + version: version::AppVersion, + platform: &str, + ) -> impl Future01<Item = mullvad_types::version::AppVersionInfo, Error = rest::Error> { + let service = self.handle.service.clone(); + + let request = rest::send_request( + &self.handle.factory, + service, + &format!("/v1/releases/{}/{}", platform, version), + Method::GET, + None, + StatusCode::OK, + ); + self.handle + .service + .compat_spawn(async move { rest::deserialize_body(request.await?).await }) + } +} + + +/// Error code for when an account has too many keys. Returned when trying to push a new key. +pub const KEY_LIMIT_REACHED: &str = "KEY_LIMIT_REACHED"; +pub struct WireguardKeyProxy { + handle: rest::MullvadRestHandle, +} + + +impl WireguardKeyProxy { + pub fn new(handle: rest::MullvadRestHandle) -> Self { + Self { handle } + } -jsonrpc_client!(pub struct AppVersionProxy { - pub fn app_version_check(&mut self, version: &version::AppVersion, platform: &str) -> RpcRequest<version::AppVersionInfo>; -}); -jsonrpc_client!(pub struct WireguardKeyProxy { pub fn push_wg_key( &mut self, account_token: AccountToken, - public_key: wireguard::PublicKey - ) -> RpcRequest<mullvad_types::wireguard::AssociatedAddresses>; + public_key: wireguard::PublicKey, + ) -> impl Future01<Item = mullvad_types::wireguard::AssociatedAddresses, Error = rest::Error> + { + #[derive(serde::Serialize)] + struct PublishRequest { + pubkey: wireguard::PublicKey, + } + + let service = self.handle.service.clone(); + let body = PublishRequest { pubkey: public_key }; + + let request = rest::post_request_with_json( + &self.handle.factory, + service, + &"/v1/wireguard-keys", + &body, + Some(account_token), + StatusCode::CREATED, + ); + self.handle + .service + .compat_spawn(async move { rest::deserialize_body(request.await?).await }) + } + pub fn replace_wg_key( &mut self, account_token: AccountToken, - old_key: wireguard::PublicKey, - new_key: wireguard::PublicKey - ) -> RpcRequest<mullvad_types::wireguard::AssociatedAddresses>; - pub fn check_wg_key( + old: wireguard::PublicKey, + new: wireguard::PublicKey, + ) -> impl Future01<Item = mullvad_types::wireguard::AssociatedAddresses, Error = rest::Error> + { + #[derive(serde::Serialize)] + struct ReplacementRequest { + old: wireguard::PublicKey, + new: wireguard::PublicKey, + } + + let service = self.handle.service.clone(); + let body = ReplacementRequest { old, new }; + + let request = rest::post_request_with_json( + &self.handle.factory, + service, + &"/v1/replace-wireguard-key", + &body, + Some(account_token), + StatusCode::CREATED, + ); + + self.handle + .service + .compat_spawn(async move { rest::deserialize_body(request.await?).await }) + } + + pub fn get_wireguard_key( &mut self, account_token: AccountToken, - public_key: wireguard::PublicKey - ) -> RpcRequest<bool>; - pub fn remove_wg_key( + key: &wireguard::PublicKey, + ) -> impl Future01<Item = mullvad_types::wireguard::AssociatedAddresses, Error = rest::Error> + { + let service = self.handle.service.clone(); + + let request = rest::send_request( + &self.handle.factory, + service, + &format!( + "/v1/wireguard-keys/{}", + urlencoding::encode(&key.to_base64()) + ), + Method::GET, + Some(account_token), + StatusCode::OK, + ); + self.handle + .service + .compat_spawn(async move { rest::deserialize_body(request.await?).await }) + } + + pub fn remove_wireguard_key( &mut self, account_token: AccountToken, - public_key: wireguard::PublicKey - ) -> RpcRequest<bool>; -}); + key: &wireguard::PublicKey, + ) -> impl Future01<Item = (), Error = rest::Error> { + let service = self.handle.service.clone(); + + let request = rest::send_request( + &self.handle.factory, + service, + &format!( + "/v1/wireguard-keys/{}", + urlencoding::encode(&key.to_base64()) + ), + Method::DELETE, + Some(account_token), + StatusCode::NO_CONTENT, + ); + + self.handle.service.compat_spawn(async move { + let _ = request.await?; + Ok(()) + }) + } +} diff --git a/mullvad-rpc/src/relay_list.rs b/mullvad-rpc/src/relay_list.rs new file mode 100644 index 0000000000..cd1d33f576 --- /dev/null +++ b/mullvad-rpc/src/relay_list.rs @@ -0,0 +1,337 @@ +/// A module dedicated to retrieving the relay list from the master API. +use crate::rest; + +use hyper::{Method, StatusCode}; +use mullvad_types::{location, relay_list}; +use talpid_types::net::wireguard; + +use std::{ + collections::BTreeMap, + net::{Ipv4Addr, Ipv6Addr}, + time::Duration, +}; + +/// Fetches relay list from https://api.mullvad.net/v1/relays +pub struct RelayListProxy { + handle: rest::MullvadRestHandle, +} + +const RELAY_LIST_TIMEOUT: Duration = Duration::from_secs(15); + +impl RelayListProxy { + /// Construct a new relay list rest client + pub fn new(handle: rest::MullvadRestHandle) -> Self { + Self { handle } + } + + /// Fetch the relay list + pub fn relay_list( + &self, + ) -> impl futures01::future::Future<Item = relay_list::RelayList, Error = rest::Error> { + let service = self.handle.service.clone(); + let request = self.handle.factory.request("/v1/relays", Method::GET); + + let future = async move { + let mut request = request?; + request.set_timeout(RELAY_LIST_TIMEOUT); + + let response = service.request(request).await?; + if response.status() != StatusCode::OK { + return rest::handle_error_response(response).await; + } + Ok(rest::deserialize_body::<ServerRelayList>(response) + .await? + .into_relay_list()) + }; + self.handle.service.compat_spawn(future) + } +} + + +#[derive(Debug, serde::Deserialize)] +struct ServerRelayList { + locations: BTreeMap<String, Location>, + openvpn: OpenVpn, + wireguard: Wireguard, + bridge: Bridges, +} + +impl ServerRelayList { + fn into_relay_list(self) -> relay_list::RelayList { + let mut countries = BTreeMap::new(); + let Self { + locations, + openvpn, + wireguard, + bridge, + } = self; + + for (code, location) in locations.into_iter() { + match split_location_code(&code) { + Some((country_code, city_code)) => { + let country = countries + .entry(country_code.to_string()) + .or_insert_with(|| location_to_country(&location, country_code.to_owned())); + country + .cities + .push(location_to_city(&location, city_code.to_owned())); + } + None => { + log::error!("Bad location code - {}", code); + continue; + } + } + } + + + Self::add_openvpn_relays(&mut countries, openvpn); + Self::add_wireguard_relays(&mut countries, wireguard); + Self::add_bridge_relays(&mut countries, bridge); + + + relay_list::RelayList { + countries: countries + .into_iter() + .map(|(_key, country)| country) + .collect(), + } + } + + fn add_openvpn_relays( + countries: &mut BTreeMap<String, relay_list::RelayListCountry>, + openvpn: OpenVpn, + ) { + let openvpn_endpoint_data = openvpn.ports; + for openvpn_relay in openvpn.relays.into_iter() { + if let Some((country_code, city_code)) = split_location_code(&openvpn_relay.location) { + if let Some(country) = countries.get_mut(country_code) { + if let Some(city) = country + .cities + .iter_mut() + .find(|city| city.code == city_code) + { + let location = location::Location { + country: country.name.clone(), + country_code: country.code.clone(), + city: city.name.clone(), + city_code: city.code.clone(), + latitude: city.latitude, + longitude: city.longitude, + }; + match city + .relays + .iter_mut() + .find(|r| r.hostname == openvpn_relay.hostname) + { + Some(relay) => relay.tunnels.openvpn = openvpn_endpoint_data.clone(), + None => { + let mut relay = relay(openvpn_relay, location); + relay.tunnels.openvpn = openvpn_endpoint_data.clone(); + city.relays.push(relay); + } + }; + } + }; + } + } + } + + fn add_wireguard_relays( + countries: &mut BTreeMap<String, relay_list::RelayListCountry>, + wireguard: Wireguard, + ) { + let Wireguard { + port_ranges, + ipv4_gateway, + ipv6_gateway, + relays, + } = wireguard; + + let wireguard_endpoint_data = + |public_key: wireguard::PublicKey| relay_list::WireguardEndpointData { + port_ranges: port_ranges.clone(), + ipv4_gateway, + ipv6_gateway, + public_key, + }; + + for wireguard_relay in relays { + if let Some((country_code, city_code)) = + split_location_code(&wireguard_relay.relay.location) + { + if let Some(country) = countries.get_mut(country_code) { + if let Some(city) = country + .cities + .iter_mut() + .find(|city| city.code == city_code) + { + let location = location::Location { + country: country.name.clone(), + country_code: country.code.clone(), + city: city.name.clone(), + city_code: city.code.clone(), + latitude: city.latitude, + longitude: city.longitude, + }; + match city + .relays + .iter_mut() + .find(|r| r.hostname == wireguard_relay.relay.hostname) + { + Some(relay) => relay + .tunnels + .wireguard + .push(wireguard_endpoint_data(wireguard_relay.public_key)), + None => { + let mut relay = relay(wireguard_relay.relay, location); + relay.ipv6_addr_in = Some(wireguard_relay.ipv6_addr_in); + relay.tunnels.wireguard = + vec![wireguard_endpoint_data(wireguard_relay.public_key)]; + city.relays.push(relay); + } + }; + } + }; + } + } + } + + fn add_bridge_relays( + countries: &mut BTreeMap<String, relay_list::RelayListCountry>, + bridges: Bridges, + ) { + let Bridges { + relays, + shadowsocks, + } = bridges; + + for bridge_relay in relays { + if let Some((country_code, city_code)) = split_location_code(&bridge_relay.location) { + if let Some(country) = countries.get_mut(country_code) { + if let Some(city) = country + .cities + .iter_mut() + .find(|city| city.code == city_code) + { + let location = location::Location { + country: country.name.clone(), + country_code: country.code.clone(), + city: city.name.clone(), + city_code: city.code.clone(), + latitude: city.latitude, + longitude: city.longitude, + }; + + match city + .relays + .iter_mut() + .find(|r| r.hostname == bridge_relay.hostname) + { + Some(relay) => { + relay.bridges.shadowsocks = shadowsocks.clone(); + } + None => { + let mut relay = relay(bridge_relay, location); + relay.bridges.shadowsocks = shadowsocks.clone(); + city.relays.push(relay); + } + }; + } + }; + } + } + } +} + + +/// Splits a location code into a country code and a city code. The input is expected to be in a +/// format like `se-mma`, with `se` being the country code, `mma` being the city code. +fn split_location_code(location: &str) -> Option<(&str, &str)> { + let mut parts = location.split('-'); + let country = parts.next()?; + let city = parts.next()?; + + Some((country, city)) +} + +fn location_to_country(location: &Location, code: String) -> relay_list::RelayListCountry { + relay_list::RelayListCountry { + cities: vec![], + name: location.country.clone(), + code, + } +} + +fn location_to_city(location: &Location, code: String) -> relay_list::RelayListCity { + relay_list::RelayListCity { + name: location.city.clone(), + code, + latitude: location.latitude, + longitude: location.longitude, + relays: vec![], + } +} + +fn relay(relay: Relay, location: location::Location) -> relay_list::Relay { + relay_list::Relay { + hostname: relay.hostname, + ipv4_addr_in: relay.ipv4_addr_in, + ipv6_addr_in: None, + include_in_country: relay.include_in_country, + active: relay.active, + owned: relay.owned, + provider: relay.provider, + weight: relay.weight, + tunnels: Default::default(), + bridges: Default::default(), + location: Some(location), + } +} + +#[derive(Debug, serde::Deserialize)] +struct Location { + city: String, + country: String, + latitude: f64, + longitude: f64, +} + +#[derive(Debug, serde::Deserialize)] +struct OpenVpn { + ports: Vec<relay_list::OpenVpnEndpointData>, + relays: Vec<Relay>, +} + +#[derive(Debug, serde::Deserialize)] +struct Relay { + hostname: String, + active: bool, + owned: bool, + location: String, + provider: String, + ipv4_addr_in: Ipv4Addr, + weight: u64, + include_in_country: bool, +} + +#[derive(Debug, serde::Deserialize)] +struct Wireguard { + port_ranges: Vec<(u16, u16)>, + ipv4_gateway: Ipv4Addr, + ipv6_gateway: Ipv6Addr, + relays: Vec<WireGuardRelay>, +} + +#[derive(Debug, serde::Deserialize)] +struct WireGuardRelay { + #[serde(flatten)] + relay: Relay, + ipv6_addr_in: Ipv6Addr, + public_key: wireguard::PublicKey, +} + +#[derive(Debug, serde::Deserialize)] +struct Bridges { + shadowsocks: Vec<relay_list::ShadowsocksEndpointData>, + relays: Vec<Relay>, +} diff --git a/mullvad-rpc/src/rest.rs b/mullvad-rpc/src/rest.rs index e6acb7ddb9..c93cccff15 100644 --- a/mullvad-rpc/src/rest.rs +++ b/mullvad-rpc/src/rest.rs @@ -1,80 +1,568 @@ -use crate::HttpsConnectorWithSni; use futures::{ - future, - sync::{mpsc, oneshot}, - Future, Stream, + channel::{mpsc, oneshot}, + future::{self, Either}, + sink::SinkExt, + stream::StreamExt, + TryFutureExt, }; -use hyper::{client::Client, Request, StatusCode, Uri}; -use hyper_openssl::openssl::error::ErrorStack; -use std::path::Path; -use tokio_core::reactor::Handle; +use futures01::Future as OldFuture; +use hyper::{ + client::{connect::Connect, Client}, + header::{self, HeaderValue}, + Method, Uri, +}; +use std::{collections::BTreeMap, future::Future, mem, net::IpAddr, str::FromStr, time::Duration}; +use tokio::runtime::Handle; + +pub use hyper::StatusCode; + +pub type Request = hyper::Request<hyper::Body>; +pub type Response = hyper::Response<hyper::Body>; pub type Result<T> = std::result::Result<T, Error>; +const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10); +/// Describes all the ways a REST request can fail #[derive(err_derive::Error, Debug)] pub enum Error { + #[error(display = "Request cancelled")] + Cancelled(CancelErr), + + #[error(display = "Hyper error")] + HyperError(#[error(source)] hyper::Error), + + #[error(display = "Invalid header value")] + InvalidHeaderError(#[error(source)] http::header::InvalidHeaderValue), + + #[error(display = "HTTP error")] + HttpError(#[error(source)] http::Error), + + #[error(display = "Request timed out")] + TimeoutError(#[error(source)] tokio::time::Elapsed), + + #[error(display = "Timer error")] + TimerError(#[error(source)] tokio::time::Error), + + #[error(display = "Deserialization error")] + DeserializationError, + + #[error(display = "Failed to send request to rest client")] + SendError, + + #[error(display = "Failed to receive response from rest client")] + ReceiveError, + + /// Serde error + #[error(display = "Serialization error")] + Serde(#[error(source)] serde_json::Error), + /// When the http status code of the response is not 200 OK. #[error(display = "Http error. Status code {}", _0)] - HttpError(StatusCode), - - /// An error occured in Hyper. - #[error(display = "Error in HTTP client")] - Hyper(#[error(source)] hyper::Error), + ApiError(StatusCode, String), /// The string given was not a valid URI. #[error(display = "Not a valid URI")] - Uri(#[error(source)] hyper::error::UriError), + UriError(#[error(source)] http::uri::InvalidUri), - /// Error in OpenSSL - #[error(display = "Error in OpenSSL")] - OpenSsl(#[error(source)] ErrorStack), + #[error(display = "Failed to spawn future in a backwards-compatible fashion")] + SpawnError(#[error(source)] tokio::task::JoinError), } +/// A service that executes HTTP requests, allowing for on-demand termination of all in-flight +/// requests +pub(crate) struct RequestService<C> { + command_tx: mpsc::Sender<RequestCommand>, + command_rx: mpsc::Receiver<RequestCommand>, + client: hyper::Client<C, hyper::Body>, + connector: C, + handle: Handle, + next_id: u64, + in_flight_requests: BTreeMap<u64, CancelHandle>, +} -pub type RequestSender = mpsc::UnboundedSender<(Request, oneshot::Sender<Result<Vec<u8>>>)>; -type RequestReceiver = mpsc::UnboundedReceiver<(Request, oneshot::Sender<Result<Vec<u8>>>)>; +impl<C: Connect + Clone + Send + Sync + 'static> RequestService<C> { + /// Constructs a new request service. + pub fn new(connector: C, handle: Handle) -> RequestService<C> { + let client = Self::new_client(connector.clone()); -pub fn create_https_client<P: AsRef<Path>>(ca_path: P, handle: &Handle) -> Result<RequestSender> { - let connector = HttpsConnectorWithSni::new(ca_path, handle)?; - let client = Client::configure() - .keep_alive(false) - .connector(connector) - .build(handle); + let (command_tx, command_rx) = mpsc::channel(1); + Self { + command_tx, + command_rx, + client, + in_flight_requests: BTreeMap::new(), + next_id: 0, + connector, + handle, + } + } - let (request_tx, request_rx) = mpsc::unbounded(); - handle.spawn(create_request_processing_future(request_rx, client)); - Ok(request_tx) + /// Constructs a handle + pub fn handle(&self) -> RequestServiceHandle { + RequestServiceHandle { + tx: self.command_tx.clone(), + handle: self.handle.clone(), + } + } + + fn new_client(connector: C) -> Client<C, hyper::Body> { + Client::builder().pool_max_idle_per_host(0).build(connector) + } + + fn process_command(&mut self, command: RequestCommand) { + match command { + RequestCommand::NewRequest(request, completion_tx) => { + let id = self.id(); + let mut tx = self.command_tx.clone(); + let timeout = request.timeout(); + + let (request_future, cancel_handle) = Cancellable::new( + self.client + .request(request.into_request()) + .map_err(Error::from), + ); + + let future = async move { + let response = tokio::time::timeout( + timeout, + request_future.into_future().map_err(Error::Cancelled), + ) + .await + .map_err(Error::TimeoutError); + + let response = flatten_result(flatten_result(response)); + + if completion_tx.send(response).is_err() { + log::trace!( + "Failed to send response to caller, caller channel is shut down" + ); + } + let _ = tx.send(RequestCommand::RequestFinished(id)).await; + }; + + + self.handle.spawn(future); + self.in_flight_requests.insert(id, cancel_handle); + } + + RequestCommand::RequestFinished(id) => { + self.in_flight_requests.remove(&id); + } + + RequestCommand::Reset => { + self.reset(); + } + } + } + + fn reset(&mut self) { + let old_requests = mem::replace(&mut self.in_flight_requests, BTreeMap::new()); + for (_, cancel_handle) in old_requests.into_iter() { + cancel_handle.cancel(); + } + let _ = mem::replace(&mut self.client, Self::new_client(self.connector.clone())); + self.next_id = 0; + } + + fn id(&mut self) -> u64 { + let id = self.next_id; + self.next_id = id.wrapping_add(1); + id + } + + pub async fn into_future(mut self) { + while let Some(command) = self.command_rx.next().await { + self.process_command(command); + } + } } -fn create_request_processing_future<CC: hyper::client::Connect>( - request_rx: RequestReceiver, - client: Client<CC, hyper::Body>, -) -> Box<dyn Future<Item = (), Error = ()>> { - let f = request_rx.for_each(move |(request, response_tx)| { - log::trace!("Sending request to {}", request.uri()); - client - .request(request) - .from_err() - .and_then(|response: hyper::Response| { - if response.status() == hyper::StatusCode::Ok { - future::ok(response) - } else { - future::err(Error::HttpError(response.status()).into()) - } - }) - .and_then(|response: hyper::Response| response.body().concat2().from_err()) - .map(|response_chunk| response_chunk.to_vec()) - .then(move |response_result| { - if response_tx.send(response_result).is_err() { - log::warn!("Unable to send response back to caller"); - } - Ok(()) - }) - }); - Box::new(f) as Box<dyn Future<Item = (), Error = ()>> + +#[derive(Clone)] +/// A handle to interact with a spawned `RequestService`. +pub struct RequestServiceHandle { + tx: mpsc::Sender<RequestCommand>, + handle: Handle, +} + +impl RequestServiceHandle { + /// Resets the corresponding RequestService, dropping all in-flight requests. + pub fn reset(&self) { + let mut tx = self.tx.clone(); + let (done_tx, done_rx) = oneshot::channel(); + + self.handle.spawn(async move { + let _ = tx.send(RequestCommand::Reset).await; + let _ = done_tx.send(()); + }); + + let _ = futures::executor::block_on(done_rx); + } + + /// Submits a `RestRequest` for exectuion to the request service. + pub async fn request(&self, request: RestRequest) -> Result<Response> { + let (completion_tx, completion_rx) = oneshot::channel(); + let mut tx = self.tx.clone(); + tx.send(RequestCommand::NewRequest(request, completion_tx)) + .await + .map_err(|_| Error::SendError)?; + + + completion_rx.await.map_err(|_| Error::ReceiveError)? + } + + /// Spawns a future on the hyper runtime returning an old-style future that can be spawned on + /// any runtime + pub fn compat_spawn<T: Send + std::fmt::Debug + 'static>( + &self, + future: impl Future<Output = Result<T>> + Send + 'static, + ) -> impl futures01::Future<Item = T, Error = Error> { + let (tx, rx) = futures01::sync::oneshot::channel(); + let _ = self.handle.spawn(async move { + let result = future.await; + let _ = tx.send(result); + }); + + + rx.map_err(|_| Error::Cancelled(CancelErr(()))).flatten() + } + + /// Spawns a future on the RPC runtime. + pub fn spawn<T: Send + 'static>(&self, future: impl Future<Output = T> + Send + 'static) { + let _ = self.handle.spawn(future); + } +} + +#[derive(Debug)] +enum RequestCommand { + NewRequest( + RestRequest, + oneshot::Sender<std::result::Result<Response, Error>>, + ), + RequestFinished(u64), + Reset, +} + + +/// A REST request that is sent to the RequestService to be executed. +#[derive(Debug)] +pub struct RestRequest { + request: Request, + timeout: Duration, + auth: Option<HeaderValue>, +} + +impl RestRequest { + /// Constructs a GET request with the given URI. Returns an error if the URI is not valid. + pub fn get(uri: &str) -> Result<Self> { + let uri = hyper::Uri::from_str(&uri).map_err(Error::UriError)?; + + let mut builder = http::request::Builder::new() + .method(Method::GET) + .header(header::ACCEPT, HeaderValue::from_static("application/json")); + if let Some(host) = uri.host() { + builder = builder.header(header::HOST, HeaderValue::from_str(&host)?); + }; + + let request = builder + .uri(uri) + .body(hyper::Body::empty()) + .map_err(Error::HttpError)?; + + + Ok(RestRequest { + timeout: DEFAULT_TIMEOUT, + auth: None, + request, + }) + } + + /// Set the auth header with the following format: `Token $auth`. + pub fn set_auth(&mut self, auth: Option<String>) -> Result<()> { + let header = match auth { + Some(auth) => Some( + HeaderValue::from_str(&format!("Token {}", auth)) + .map_err(Error::InvalidHeaderError)?, + ), + None => None, + }; + + self.auth = header; + Ok(()) + } + + /// Sets timeout for the request. + pub fn set_timeout(&mut self, timeout: Duration) { + self.timeout = timeout; + } + + /// Retrieves timeout + pub fn timeout(&self) -> Duration { + self.timeout + } + + /// Converts into a `hyper::Request<hyper::Body>` + fn into_request(self) -> Request { + let Self { + mut request, auth, .. + } = self; + if let Some(auth) = auth { + request.headers_mut().insert(header::AUTHORIZATION, auth); + } + request + } + + /// Returns the URI of the request + pub fn uri(&self) -> &Uri { + self.request.uri() + } +} + +impl From<Request> for RestRequest { + fn from(request: Request) -> Self { + Self { + request, + timeout: DEFAULT_TIMEOUT, + auth: None, + } + } +} + +#[derive(serde::Deserialize)] +pub struct ErrorResponse { + pub code: String, +} + +#[derive(Clone)] +pub struct RequestFactory { + host: String, + address: Option<IpAddr>, + path_prefix: Option<String>, +} + + +impl RequestFactory { + pub fn new(host: String, address: Option<IpAddr>, path_prefix: Option<String>) -> Self { + Self { + host, + address, + path_prefix, + } + } + + pub fn request(&self, path: &str, method: Method) -> Result<RestRequest> { + self.hyper_request(path, method).map(RestRequest::from) + } + + pub fn get(&self, path: &str) -> Result<RestRequest> { + self.hyper_request(path, Method::GET).map(RestRequest::from) + } + + pub fn post(&self, path: &str) -> Result<RestRequest> { + self.hyper_request(path, Method::POST) + .map(RestRequest::from) + } + + pub fn post_json<S: serde::Serialize>(&self, path: &str, body: &S) -> Result<RestRequest> { + let mut request = self.hyper_request(path, Method::POST)?; + + let json_body = serde_json::to_string(&body)?; + let body_length = json_body.as_bytes().len() as u64; + *request.body_mut() = json_body.into_bytes().into(); + + let headers = request.headers_mut(); + headers.insert( + header::CONTENT_LENGTH, + HeaderValue::from_str(&body_length.to_string()).map_err(Error::InvalidHeaderError)?, + ); + headers.insert( + header::CONTENT_TYPE, + HeaderValue::from_static("application/json"), + ); + + Ok(RestRequest::from(request)) + } + + pub fn delete(&self, path: &str) -> Result<RestRequest> { + self.hyper_request(path, Method::DELETE) + .map(RestRequest::from) + } + + fn hyper_request(&self, path: &str, method: Method) -> Result<Request> { + let uri = self.get_uri(path)?; + let request = http::request::Builder::new() + .method(method) + .uri(uri) + .header(header::ACCEPT, HeaderValue::from_static("application/json")) + .header(header::HOST, self.host.clone()); + + request.body(hyper::Body::empty()).map_err(Error::HttpError) + } + + fn get_uri(&self, path: &str) -> Result<Uri> { + let host: &dyn std::fmt::Display = &self + .address + .map(|addr| addr.to_string()) + .unwrap_or_else(|| self.host.clone()); + let prefix = self.path_prefix.as_ref().map(AsRef::as_ref).unwrap_or(""); + let uri = format!("https://{}/{}{}", host, prefix, path); + hyper::Uri::from_str(&uri).map_err(Error::UriError) + } +} + + +#[derive(Debug)] +pub struct CancelErr(()); + +pub struct Cancellable<F: Future> { + rx: oneshot::Receiver<()>, + f: F, +} + +pub struct CancelHandle { + tx: oneshot::Sender<()>, +} + +impl CancelHandle { + fn cancel(self) { + let _ = self.tx.send(()); + } +} + + +impl<F> Cancellable<F> +where + F: Future + Unpin, +{ + fn new(f: F) -> (Self, CancelHandle) { + let (tx, rx) = oneshot::channel(); + (Self { f, rx }, CancelHandle { tx }) + } + + async fn into_future(self) -> std::result::Result<F::Output, CancelErr> { + match future::select(self.rx, self.f).await { + Either::Left(_) => Err(CancelErr(())), + Either::Right((value, _)) => Ok(value), + } + } +} + +pub fn get_request<T: serde::de::DeserializeOwned>( + factory: &RequestFactory, + service: RequestServiceHandle, + uri: &str, + auth: Option<String>, + expected_status: hyper::StatusCode, +) -> impl Future<Output = Result<Response>> { + let request = factory.get(uri); + async move { + let mut request = request?; + request.set_auth(auth)?; + let response = service.request(request).await?; + parse_rest_response(response, expected_status).await + } +} + +pub fn send_request( + factory: &RequestFactory, + service: RequestServiceHandle, + uri: &str, + method: Method, + auth: Option<String>, + expected_status: hyper::StatusCode, +) -> impl Future<Output = Result<Response>> { + let request = factory.request(uri, method); + + async move { + let mut request = request?; + request.set_auth(auth)?; + let response = service.request(request).await?; + parse_rest_response(response, expected_status).await + } +} + +pub fn post_request_with_json<B: serde::Serialize>( + factory: &RequestFactory, + service: RequestServiceHandle, + uri: &str, + body: &B, + auth: Option<String>, + expected_status: hyper::StatusCode, +) -> impl Future<Output = Result<Response>> { + let request = factory.post_json(uri, body); + async move { + let mut request = request?; + request.set_auth(auth)?; + let response = service.request(request).await?; + parse_rest_response(response, expected_status).await + } +} + + +pub async fn deserialize_body<T: serde::de::DeserializeOwned>(mut response: Response) -> Result<T> { + let body_length: usize = response + .headers() + .get(header::CONTENT_LENGTH) + .and_then(|header_value| header_value.to_str().ok()) + .and_then(|length| length.parse::<usize>().ok()) + .unwrap_or(0); + + let mut body: Vec<u8> = Vec::with_capacity(body_length); + while let Some(chunk) = response.body_mut().next().await { + body.extend(&chunk?); + } + + serde_json::from_slice(&body).map_err(Error::Serde) +} + +pub async fn parse_rest_response( + response: Response, + expected_status: hyper::StatusCode, +) -> Result<Response> { + let status = response.status(); + if status != expected_status { + return handle_error_response(response).await; + } + + Ok(response) +} + + +pub async fn handle_error_response<T>(response: Response) -> Result<T> { + let error_message = match response.status() { + hyper::StatusCode::NOT_FOUND => "Not found", + hyper::StatusCode::METHOD_NOT_ALLOWED => "Method not allowed", + status => { + let err: ErrorResponse = deserialize_body(response).await?; + + return Err(Error::ApiError(status, err.code)); + } + }; + Err(Error::ApiError(response.status(), error_message.to_owned())) +} + +#[derive(Clone)] +pub struct MullvadRestHandle { + pub(crate) service: RequestServiceHandle, + pub(crate) factory: RequestFactory, +} + +impl MullvadRestHandle { + pub fn service(&self) -> RequestServiceHandle { + self.service.clone() + } + + pub fn factory(&self) -> &RequestFactory { + &self.factory + } } -pub fn create_get_request(uri: Uri) -> Request { - Request::new(hyper::Method::Get, uri) +fn flatten_result<T, E>( + result: std::result::Result<std::result::Result<T, E>, E>, +) -> std::result::Result<T, E> { + match result { + Ok(value) => value, + Err(err) => Err(err), + } } diff --git a/mullvad-types/src/relay_list.rs b/mullvad-types/src/relay_list.rs index a086dd108c..7277b922ca 100644 --- a/mullvad-types/src/relay_list.rs +++ b/mullvad-types/src/relay_list.rs @@ -60,16 +60,21 @@ pub struct Relay { #[cfg_attr(target_os = "android", jnix(skip))] pub ipv4_addr_in: Ipv4Addr, #[cfg_attr(target_os = "android", jnix(skip))] + pub ipv6_addr_in: Option<Ipv6Addr>, + #[cfg_attr(target_os = "android", jnix(skip))] pub include_in_country: bool, pub active: bool, #[cfg_attr(target_os = "android", jnix(skip))] + pub owned: bool, + #[cfg_attr(target_os = "android", jnix(skip))] + pub provider: String, + #[cfg_attr(target_os = "android", jnix(skip))] pub weight: u64, #[serde(skip_serializing_if = "RelayTunnels::is_empty", default)] pub tunnels: RelayTunnels, #[serde(skip_serializing_if = "RelayBridges::is_empty", default)] #[cfg_attr(target_os = "android", jnix(skip))] pub bridges: RelayBridges, - #[serde(skip)] #[cfg_attr(target_os = "android", jnix(skip))] pub location: Option<Location>, } diff --git a/mullvad-types/src/version.rs b/mullvad-types/src/version.rs index 5cb66fd50e..1603c7752b 100644 --- a/mullvad-types/src/version.rs +++ b/mullvad-types/src/version.rs @@ -14,11 +14,14 @@ pub struct AppVersionInfo { /// * Software bundled with this version, such as OpenVPN or OpenSSL, has known security /// issues, so using it is no longer recommended. /// The user should really upgrade when this is false. - pub current_is_supported: bool, + pub supported: bool, + /// Latest version + pub latest: AppVersion, + /// Latest stable version pub latest_stable: AppVersion, /// Equal to `latest_stable` when the newest release is a stable release. But will contain /// beta versions when those are out for testing. - pub latest: AppVersion, + pub latest_beta: AppVersion, } pub type AppVersion = String; diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index 6d7c5effe5..3e85b7dfe5 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -12,7 +12,8 @@ atty = "0.2" cfg-if = "0.1" duct = "0.13" err-derive = "0.2.1" -futures = "0.1" +futures01 = { package = "futures", version = "0.1" } +futures = { package = "futures", version = "0.3", features = [ "compat" ]} hex = "0.4" ipnetwork = "0.15" jsonrpc-core = { git = "https://github.com/mullvad/jsonrpc", branch = "mullvad-fork" } @@ -50,10 +51,13 @@ dbus = "0.6" failure = "0.1" notify = "4.0" resolv-conf = "0.6.1" -rtnetlink = { git = "https://github.com/mullvad/netlink", rev = "f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" } -netlink-proto = { git = "https://github.com/mullvad/netlink", rev = "f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" } -netlink-packet = { git = "https://github.com/mullvad/netlink", rev = "f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" } -netlink-sys = { git = "https://github.com/mullvad/netlink", rev = "f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5" } +async-stream = "0.2" +rtnetlink = "0.2" +netlink-packet-route = "0.2" +netlink-proto = "0.2" +netlink-sys = "0.2" +futures = { package = "futures", version = "0.3" } +tokio02 = { package = "tokio", version = "0.2", features = [ "rt-core", "rt-threaded"] } nftnl = { version = "0.3", features = ["nftnl-1-1-0"] } mnl = { version = "0.2.0", features = ["mnl-1-0-4"] } which = { version = "3.1", default-features = false } diff --git a/talpid-core/src/offline/android.rs b/talpid-core/src/offline/android.rs index 4fa45112d6..3863415cfb 100644 --- a/talpid-core/src/offline/android.rs +++ b/talpid-core/src/offline/android.rs @@ -1,5 +1,5 @@ use crate::tunnel_state_machine::TunnelCommand; -use futures::sync::mpsc::UnboundedSender; +use futures01::sync::mpsc::UnboundedSender; use jnix::{ jni::{ self, diff --git a/talpid-core/src/offline/linux.rs b/talpid-core/src/offline/linux.rs index b75f187505..0b6526f0e5 100644 --- a/talpid-core/src/offline/linux.rs +++ b/talpid-core/src/offline/linux.rs @@ -1,178 +1,173 @@ use crate::tunnel_state_machine::TunnelCommand; -use futures::{future::Either, sync::mpsc::UnboundedSender, Future, Stream}; -use log::{error, warn}; -use netlink_packet::{ - AddressMessage, LinkInfo, LinkInfoKind, LinkLayerType, LinkMessage, LinkNla, NetlinkMessage, +use futures::{StreamExt, TryStreamExt}; +use futures01::sync::mpsc::UnboundedSender; +use netlink_packet_route::{ + constants::{ARPHRD_LOOPBACK, ARPHRD_NONE, IFF_LOWER_UP, IFF_UP}, + rtnl::link::nlas::{Info as LinkInfo, InfoKind, Nla as LinkNla}, + LinkMessage, }; use netlink_sys::SocketAddr; use rtnetlink::{ constants::{RTMGRP_IPV4_IFADDR, RTMGRP_IPV6_IFADDR, RTMGRP_LINK, RTMGRP_NOTIFY}, - Connection, Handle, + Handle, }; -use std::{collections::BTreeSet, io, sync::Weak, thread}; -use talpid_types::ErrorExt; +use std::{collections::BTreeSet, io, sync::Weak}; pub type Result<T> = std::result::Result<T, Error>; +const EVENT_LOOP_THREAD_NAME: &str = "mullvad-offline-detection-event-loop"; + #[derive(err_derive::Error, Debug)] #[error(no_from)] pub enum Error { #[error(display = "Failed to get list of IP links")] GetLinksError(#[error(source)] failure::Compat<rtnetlink::Error>), + #[error(display = "Failed to get list of IP addresses")] + GetAddressesError(#[error(source)] failure::Compat<rtnetlink::Error>), + #[error(display = "Failed to connect to netlink socket")] NetlinkConnectionError(#[error(source)] io::Error), + #[error(display = "Failed to connect to bind to netlink socket")] + BindError(#[error(source)] io::Error), + #[error(display = "Failed to start listening on netlink socket")] NetlinkBindError(#[error(source)] io::Error), - #[error(display = "Error while communicating on the netlink socket")] - NetlinkError(#[error(source)] netlink_proto::Error), - #[error(display = "Error while processing netlink messages")] MonitorNetlinkError, #[error(display = "Netlink connection has unexpectedly disconnected")] NetlinkDisconnected, -} - -pub struct MonitorHandle; - -pub fn spawn_monitor(sender: Weak<UnboundedSender<TunnelCommand>>) -> Result<MonitorHandle> { - let socket = SocketAddr::new( - 0, - RTMGRP_NOTIFY | RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR, - ); - let (mut connection, _, messages) = rtnetlink::new_connection_with_messages().unwrap(); - connection - .socket_mut() - .bind(&socket) - .map_err(Error::NetlinkBindError)?; - - let link_monitor = LinkMonitor::new(sender); - - thread::spawn(|| { - if let Err(error) = monitor_event_loop(connection, messages, link_monitor) { - error!( - "{}", - error.display_chain_with_msg("Error running link monitor event loop") - ); - } - }); - - Ok(MonitorHandle) + #[error(display = "Failed to initialize event loop")] + EventLoopError(#[error(source)] io::Error), } -fn is_offline() -> bool { - check_if_offline().unwrap_or_else(|error| { - warn!( - "{}", - error.display_chain_with_msg("Failed to check for internet connection") - ); - false - }) +pub struct MonitorHandle { + handle: rtnetlink::Handle, + runtime: tokio02::runtime::Runtime, } impl MonitorHandle { - pub fn is_offline(&self) -> bool { - is_offline() + pub fn is_offline(&mut self) -> bool { + match self.runtime.block_on(check_offline_state(&self.handle)) { + Ok(is_offline) => is_offline, + Err(err) => { + log::error!( + "Failed to verify offline state: {}. Presuming connectivity", + err + ); + false + } + } } } -/// Checks if there are no running links or that none of the running links have IP addresses -/// assigned to them. -fn check_if_offline() -> Result<bool> { - let mut connection = NetlinkConnection::new()?; - let interfaces = connection.running_interfaces()?; +pub fn spawn_monitor(sender: Weak<UnboundedSender<TunnelCommand>>) -> Result<MonitorHandle> { + let mut runtime = tokio02::runtime::Builder::new() + .threaded_scheduler() + .core_threads(1) + .enable_all() + .thread_name(EVENT_LOOP_THREAD_NAME) + .build() + .map_err(Error::EventLoopError)?; - if interfaces.is_empty() { - Ok(true) - } else { - // Check if the current IP addresses are not assigned to any one of the running interfaces - Ok(connection - .addresses()? - .into_iter() - .all(|address| !interfaces.contains(&address.header.index))) - } -} + let (connection, handle, mut messages) = runtime.block_on(async move { + let (mut connection, handle, messages) = + rtnetlink::new_connection().map_err(Error::NetlinkConnectionError)?; -struct NetlinkConnection { - connection: Option<Connection>, - handle: Handle, -} + let mgroup_flags = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_LINK | RTMGRP_NOTIFY; + let addr = SocketAddr::new(0, mgroup_flags); -impl NetlinkConnection { - /// Open a connection on the netlink socket. - pub fn new() -> Result<Self> { - let (connection, handle) = - rtnetlink::new_connection().map_err(Error::NetlinkConnectionError)?; + connection + .socket_mut() + .bind(&addr) + .map_err(Error::BindError)?; - Ok(NetlinkConnection { - connection: Some(connection), - handle, - }) - } + Ok((connection, handle, messages)) + })?; - /// List all IP addresses assigned to all interfaces. - pub fn addresses(&mut self) -> Result<Vec<AddressMessage>> { - self.execute_request(self.handle.address().get().execute().collect()) - } + // Connection will be closed once the runtime is dropped + let _ = runtime.spawn(connection); + let mut is_offline = runtime.block_on(check_offline_state(&handle))?; - /// List all links registered on the system. - fn links(&mut self) -> Result<Vec<LinkMessage>> { - self.execute_request(self.handle.link().get().execute().collect()) - } + let monitor_handle = MonitorHandle { + handle: handle.clone(), + runtime, + }; - /// List all unique interface indices that have a running link. - pub fn running_interfaces(&mut self) -> Result<BTreeSet<u32>> { - let links = self.links()?; - Ok(links - .into_iter() - .filter(link_provides_connectivity) - .map(|link| link.header.index) - .collect()) - } + let _ = monitor_handle.runtime.spawn(async move { + while let Some(_new_message) = messages.next().await { + match sender.upgrade() { + Some(sender) => { + let new_offline_state = check_offline_state(&handle).await.unwrap_or(false); + if new_offline_state != is_offline { + is_offline = new_offline_state; + let _ = sender.unbounded_send(TunnelCommand::IsOffline(is_offline)); + } + } + None => return, + } + } + }); - /// Helper function to execute an asynchronous request synchronously. - fn execute_request<R>(&mut self, request: R) -> Result<R::Item> - where - R: Future<Error = rtnetlink::Error>, + + Ok(monitor_handle) +} + +async fn check_offline_state(handle: &Handle) -> Result<bool> { + let mut link_request = handle.link().get().execute(); + let mut links = BTreeSet::new(); + while let Some(link) = link_request + .try_next() + .await + .map_err(failure::Fail::compat) + .map_err(Error::GetLinksError)? { - let connection = self.connection.take().ok_or(Error::NetlinkDisconnected)?; + if link_provides_connectivity(&link) { + links.insert(link.header.index); + } + } + + if links.is_empty() { + return Ok(true); + } - let (result, connection) = match connection.select2(request).wait() { - Ok(Either::A(_)) => return Err(Error::NetlinkDisconnected), - Err(Either::A((error, _))) => return Err(Error::NetlinkError(error)), - Ok(Either::B((links, connection))) => (Ok(links), connection), - Err(Either::B((error, connection))) => ( - Err(Error::GetLinksError(failure::Fail::compat(error))), - connection, - ), - }; + let mut address_request = handle.address().get().execute(); - self.connection = Some(connection); - result + while let Some(address) = address_request + .try_next() + .await + .map_err(failure::Fail::compat) + .map_err(Error::GetAddressesError)? + { + if links.contains(&address.header.index) { + return Ok(false); + } } + Ok(true) } + +// TODO: Improve by allowing bridge links to provide connectivity, will require route checking. fn link_provides_connectivity(link: &LinkMessage) -> bool { // Some tunnels have the link layer type set to None - link.header.link_layer_type != LinkLayerType::Loopback - && link.header.link_layer_type != LinkLayerType::None - && link.header.link_layer_type != LinkLayerType::Irda - && link.header.flags.is_running() + link.header.link_layer_type != ARPHRD_NONE + && link.header.link_layer_type != ARPHRD_LOOPBACK + && (link.header.flags & IFF_UP > 0 || link.header.flags & IFF_LOWER_UP > 0) && !is_virtual_interface(link) } fn is_virtual_interface(link: &LinkMessage) -> bool { for nla in link.nlas.iter() { - if let LinkNla::LinkInfo(link_info) = nla { - for info in link_info.iter() { + if let LinkNla::Info(info_nlas) = nla { + for info in info_nlas.iter() { // LinkInfo::Kind seems to only be set when the link is actually virtual if let LinkInfo::Kind(ref kind) = info { - use LinkInfoKind::*; + use InfoKind::*; return match kind { Dummy | Bridge | Tun | Nlmon | IpTun => true, _ => false, @@ -183,59 +178,3 @@ fn is_virtual_interface(link: &LinkMessage) -> bool { } false } - -fn monitor_event_loop( - connection: Connection, - channel: impl Stream<Item = NetlinkMessage, Error = ()>, - mut link_monitor: LinkMonitor, -) -> Result<()> { - let monitor = channel - .for_each(|_message| { - link_monitor.update(); - Ok(()) - }) - .map_err(|_| Error::MonitorNetlinkError); - - // Under normal circumstances, this runs forever. - let result = connection - .map_err(Error::NetlinkError) - .join(monitor) - .wait() - .map(|_| ()); - // But if it fails, it should fail open. - link_monitor.reset(); - result -} - -struct LinkMonitor { - is_offline: bool, - sender: Weak<UnboundedSender<TunnelCommand>>, -} - -impl LinkMonitor { - pub fn new(sender: Weak<UnboundedSender<TunnelCommand>>) -> Self { - let is_offline = is_offline(); - - LinkMonitor { is_offline, sender } - } - - pub fn update(&mut self) { - self.set_is_offline(is_offline()); - } - - fn set_is_offline(&mut self, is_offline: bool) { - if self.is_offline != is_offline { - self.is_offline = is_offline; - if let Some(sender) = self.sender.upgrade() { - let _ = sender.unbounded_send(TunnelCommand::IsOffline(is_offline)); - } - } - } - - /// Allow the offline check to fail open. - fn reset(&mut self) { - if let Some(sender) = self.sender.upgrade() { - let _ = sender.unbounded_send(TunnelCommand::IsOffline(false)); - } - } -} diff --git a/talpid-core/src/offline/macos.rs b/talpid-core/src/offline/macos.rs index ab9fee3b38..fa0cd3c906 100644 --- a/talpid-core/src/offline/macos.rs +++ b/talpid-core/src/offline/macos.rs @@ -1,5 +1,5 @@ use crate::tunnel_state_machine::TunnelCommand; -use futures::sync::mpsc::UnboundedSender; +use futures01::sync::mpsc::UnboundedSender; use log::{debug, trace}; use std::{ sync::{mpsc, Weak}, diff --git a/talpid-core/src/offline/mod.rs b/talpid-core/src/offline/mod.rs index 268193407e..5cda6290a3 100644 --- a/talpid-core/src/offline/mod.rs +++ b/talpid-core/src/offline/mod.rs @@ -1,5 +1,5 @@ use crate::tunnel_state_machine::TunnelCommand; -use futures::sync::mpsc::UnboundedSender; +use futures01::sync::mpsc::UnboundedSender; use std::sync::Weak; #[cfg(target_os = "android")] use talpid_types::android::AndroidContext; @@ -25,7 +25,7 @@ pub use self::imp::Error; pub struct MonitorHandle(imp::MonitorHandle); impl MonitorHandle { - pub fn is_offline(&self) -> bool { + pub fn is_offline(&mut self) -> bool { self.0.is_offline() } } diff --git a/talpid-core/src/offline/windows.rs b/talpid-core/src/offline/windows.rs index 1b685fe8c9..c7a86e4073 100644 --- a/talpid-core/src/offline/windows.rs +++ b/talpid-core/src/offline/windows.rs @@ -1,5 +1,5 @@ use crate::{logging::windows::log_sink, tunnel_state_machine::TunnelCommand, winnet}; -use futures::sync::mpsc::UnboundedSender; +use futures01::sync::mpsc::UnboundedSender; use parking_lot::Mutex; use std::{ ffi::c_void, diff --git a/talpid-core/src/routing/android.rs b/talpid-core/src/routing/android.rs index e7697ba350..a10d9d711d 100644 --- a/talpid-core/src/routing/android.rs +++ b/talpid-core/src/routing/android.rs @@ -1,4 +1,4 @@ -use futures::{sync::oneshot, Async, Future}; +use futures01::{sync::oneshot, Async, Future}; use ipnetwork::IpNetwork; use std::collections::HashMap; diff --git a/talpid-core/src/routing/linux.rs b/talpid-core/src/routing/linux.rs new file mode 100644 index 0000000000..248e02c4f3 --- /dev/null +++ b/talpid-core/src/routing/linux.rs @@ -0,0 +1,697 @@ +use crate::routing::{NetNode, Node, Route}; + +use ipnetwork::IpNetwork; +use std::{ + collections::{BTreeMap, HashMap, HashSet}, + io, + net::IpAddr, +}; + +use futures01::sync::oneshot as old_oneshot; + +use futures::{ + channel::mpsc::UnboundedReceiver, compat::Future01CompatExt, future::FutureExt, StreamExt, + TryStreamExt, +}; + + +use netlink_packet_route::{ + link::{nlas::Nla as LinkNla, LinkMessage}, + route::{nlas::Nla as RouteNla, RouteHeader, RouteMessage}, + rtnl::{ + constants::{RTN_UNICAST, RTPROT_STATIC, RT_SCOPE_UNIVERSE, RT_TABLE_MAIN}, + RouteFlags, + }, + NetlinkMessage, NetlinkPayload, RtnlMessage, +}; +use netlink_sys::SocketAddr; +use rtnetlink::{ + constants::{RTMGRP_IPV4_ROUTE, RTMGRP_IPV6_ROUTE, RTMGRP_LINK, RTMGRP_NOTIFY}, + Handle, IpVersion, +}; + +use libc::{AF_INET, AF_INET6}; + + +pub type Result<T> = std::result::Result<T, Error>; + +/// Errors that can happen in the Linux routing integration +#[derive(err_derive::Error, Debug)] +#[error(no_from)] +pub enum Error { + /// Failed to add route. + #[error(display = "Failed to add route")] + FailedToAddRoute(#[error(source)] io::Error), + + /// Failed to remove route. + #[error(display = "Failed to remove route")] + FailedToRemoveRoute(#[error(source)] io::Error), + + /// Error while running "ip route". + #[error(display = "Error while running \"ip route\"")] + FailedToRunIp(#[error(source)] io::Error), + + /// Invocation of `ip route` ended with a non-zero exit code + #[error(display = "ip returend a non-zero exit code")] + ErrorIpFailed, + + /// Received unexpected output from `ip route` + #[error(display = "Received unexpected output from \"ip\"")] + UnexpectedOutput, + + /// No default route exists + #[error(display = "No default route in \"ip route\" output")] + NoDefaultRoute, + + /// Route table change stream failed. + #[error(display = "Route change listener failed")] + NetlinkConnectionError(#[error(source)] failure::Compat<rtnetlink::Error>), + + #[error(display = "Failed to open a netlink connection")] + ConnectError(#[error(source)] io::Error), + + #[error(display = "Failed to bind netlink socket")] + BindError(#[error(source)] io::Error), + + #[error(display = "Netlink error")] + NetlinkError(#[error(source)] failure::Compat<rtnetlink::Error>), + + #[error(display = "Route without a valid node")] + InvalidRoute, + + #[error(display = "Invalid length of byte buffer for IP address")] + InvalidIpBytes, + + #[error(display = "Invalid network prefix")] + InvalidNetworkPrefix(#[error(source)] ipnetwork::IpNetworkError), + + #[error(display = "Failed to initialize event loop")] + EventLoopError(#[error(source)] io::Error), + + #[error(display = "Unknown device index - {}", _0)] + UnknownDeviceIndex(u32), +} + +pub struct RouteManagerImpl { + shutdown_rx: old_oneshot::Receiver<old_oneshot::Sender<()>>, + manager: RouteManagerImplInner, + runtime: tokio02::runtime::Runtime, +} + +impl RouteManagerImpl { + /// Creates a new RouteManagerImplInner. + pub fn new( + required_routes: HashMap<IpNetwork, NetNode>, + shutdown_rx: old_oneshot::Receiver<old_oneshot::Sender<()>>, + ) -> Result<Self> { + let mut runtime = tokio02::runtime::Builder::new() + .basic_scheduler() + .core_threads(1) + .enable_all() + .thread_name("mullvad-route-manager-event-loop") + .build() + .map_err(Error::EventLoopError)?; + + let manager = runtime.block_on(RouteManagerImplInner::new(required_routes))?; + + Ok(Self { + shutdown_rx, + runtime, + manager, + }) + } + + pub fn wait(self) -> Result<()> { + let Self { + shutdown_rx, + mut runtime, + manager, + } = self; + runtime.block_on(manager.into_future(shutdown_rx)) + } +} + +pub struct RouteManagerImplInner { + handle: Handle, + messages: UnboundedReceiver<(NetlinkMessage<RtnlMessage>, SocketAddr)>, + iface_map: BTreeMap<u32, String>, + + // currently added routes + added_routes: HashSet<Route>, + // default route tracking + // destinations that should be routed through the default route + required_default_routes: HashSet<IpNetwork>, + default_routes: HashSet<Route>, + best_default_node_v4: Option<Node>, + best_default_node_v6: Option<Node>, +} + +impl RouteManagerImplInner { + pub async fn new(required_routes: HashMap<IpNetwork, NetNode>) -> Result<Self> { + let (mut connection, handle, messages) = + rtnetlink::new_connection().map_err(Error::ConnectError)?; + + let mgroup_flags = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK | RTMGRP_NOTIFY; + let addr = SocketAddr::new(0, mgroup_flags); + connection + .socket_mut() + .bind(&addr) + .map_err(Error::BindError)?; + + tokio02::spawn(connection); + + let iface_map = Self::initialize_link_map(&handle).await?; + + + let mut required_normal_routes = HashSet::new(); + let mut required_default_routes = HashSet::new(); + + for (destination, node) in required_routes { + match node { + NetNode::RealNode(node) => { + required_normal_routes.insert(Route::new(node, destination)); + } + NetNode::DefaultNode => { + required_default_routes.insert(destination); + } + } + } + + + let mut monitor = Self { + iface_map, + handle, + messages, + + required_default_routes, + added_routes: HashSet::new(), + + default_routes: HashSet::new(), + best_default_node_v4: None, + best_default_node_v6: None, + }; + + monitor.default_routes = monitor.get_default_routes().await?; + monitor.best_default_node_v4 = + Self::pick_best_default_node(&monitor.default_routes, IpVersion::V4); + monitor.best_default_node_v6 = + Self::pick_best_default_node(&monitor.default_routes, IpVersion::V6); + + + for normal_route in required_normal_routes.into_iter() { + monitor.add_route(normal_route).await?; + } + + for prefix in monitor.required_default_routes.clone().into_iter() { + if let (false, _, Some(default_node)) | (true, Some(default_node), _) = ( + prefix.is_ipv4(), + &monitor.best_default_node_v4, + &monitor.best_default_node_v6, + ) { + // best to pick a single node identifier rather than device + ip + let route = Route::new(default_node.clone(), prefix); + monitor.add_route(route).await?; + } + } + Ok(monitor) + } + + async fn get_default_routes(&self) -> Result<HashSet<Route>> { + let mut routes = self.get_default_routes_inner(IpVersion::V4).await?; + routes.extend(self.get_default_routes_inner(IpVersion::V6).await?); + Ok(routes) + } + + async fn get_default_routes_inner(&self, version: IpVersion) -> Result<HashSet<Route>> { + let mut routes = HashSet::new(); + let mut route_request = self.handle.route().get(version).execute(); + if let Some(route) = route_request + .try_next() + .await + .map_err(failure::Fail::compat) + .map_err(Error::NetlinkError)? + { + if route.header.destination_prefix_length == 0 { + if let Some(default_route) = self.parse_route_message(route)? { + routes.insert(default_route); + } + } + }; + Ok(routes) + } + + async fn initialize_link_map(handle: &rtnetlink::Handle) -> Result<BTreeMap<u32, String>> { + let mut link_map = BTreeMap::new(); + let mut link_request = handle.link().get().execute(); + while let Some(link) = link_request + .try_next() + .await + .map_err(failure::Fail::compat) + .map_err(Error::NetlinkError)? + { + if let Some((idx, link_name)) = Self::map_iface_name_to_idx(link) { + link_map.insert(idx, link_name); + } + } + + Ok(link_map) + } + + fn find_iface_idx(&self, iface_name: &str) -> Option<u32> { + self.iface_map + .iter() + .find(|(_idx, name)| name.as_str() == iface_name) + .map(|(idx, _name)| *idx) + } + + + async fn process_new_route(&mut self, route: Route) -> Result<()> { + if route.prefix.prefix() == 0 { + self.default_routes.insert(route); + self.update_default_routes().await?; + } + Ok(()) + } + + async fn process_deleted_route(&mut self, route: Route) -> Result<()> { + if route.prefix.prefix() == 0 { + self.default_routes.remove(&route); + self.update_default_routes().await?; + } + if self.added_routes.contains(&route) { + self.added_routes.remove(&route); + } + Ok(()) + } + + async fn update_default_routes(&mut self) -> Result<()> { + let new_best_v4 = Self::pick_best_default_node(&self.default_routes, IpVersion::V4); + if self.best_default_node_v4 != new_best_v4 && new_best_v4.is_some() { + let new_node = new_best_v4.unwrap(); + let old_node = self.best_default_node_v4.take(); + let v4_destinations: Vec<_> = self + .required_default_routes + .iter() + .filter(|ip| ip.is_ipv4()) + .cloned() + .collect(); + for destination in v4_destinations { + let new_route = Route::new(new_node.clone(), destination); + if let Some(old_node) = &old_node { + let old_route = Route::new(old_node.clone(), destination); + if let Err(e) = self.delete_route(&old_route).await { + log::error!("Failed to remove old route {} - {}", &old_route, e); + } + } + if let Err(e) = self.add_route(new_route).await { + log::error!("Failed to add new route {} - {}", &new_node, e); + } + } + self.best_default_node_v4 = Some(new_node); + } + + let new_best_v6 = Self::pick_best_default_node(&self.default_routes, IpVersion::V6); + if self.best_default_node_v6 != new_best_v6 && new_best_v6.is_some() { + let new_node = new_best_v6.unwrap(); + let old_node = self.best_default_node_v6.take(); + let v6_destinations: Vec<_> = self + .required_default_routes + .iter() + .filter(|ip| !ip.is_ipv4()) + .cloned() + .collect(); + + for destination in v6_destinations { + let new_route = Route::new(new_node.clone(), destination); + if let Some(old_node) = &old_node { + let old_route = Route::new(old_node.clone(), destination); + + if let Err(e) = self.delete_route(&old_route).await { + log::error!("Failed to remove old route {} - {}", &old_route, e); + } + } + if let Err(e) = self.add_route(new_route).await { + log::error!("Failed to add new route {} - {}", &new_node, e); + } + } + self.best_default_node_v6 = Some(new_node); + } + + Ok(()) + } + + fn pick_best_default_node(routes: &HashSet<Route>, version: IpVersion) -> Option<Node> { + // Pick the route with the lowest metric - thus the most favourable route. + routes + .iter() + .filter(|route| route.prefix.is_ipv4() == (version == IpVersion::V4)) + .fold( + None, + |best_route: Option<Route>, next_route| match best_route { + Some(current_best) => { + if current_best.metric.unwrap_or(0) > next_route.metric.unwrap_or(0) { + Some(next_route.clone()) + } else { + Some(current_best) + } + } + None => Some(next_route.clone()), + }, + ) + .map(|route| route.node) + } + + async fn cleanup_routes(&mut self) { + for route in self.added_routes.drain().collect::<Vec<_>>().iter() { + if let Err(e) = self.delete_route(&route).await { + if let Error::NetlinkError(err) = &e { + if let rtnetlink::ErrorKind::NetlinkError(msg) = err.get_ref().kind() { + // -3 means that the route doesn't exist anymore anyway + if msg.code == -3 { + continue; + } + } + } + log::error!("Failed to remove route - {} - {}", route, e); + } + } + } + + + pub async fn into_future( + mut self, + shutdown_rx: futures01::sync::oneshot::Receiver<futures01::sync::oneshot::Sender<()>>, + ) -> Result<()> { + futures::select! { + shutdown_signal = shutdown_rx.compat().fuse() => { + log::trace!("Shutting down route manager"); + self.cleanup_routes().await; + log::trace!("Route manager done"); + if let Ok(shutdown_signal) = shutdown_signal { + let _ = shutdown_signal.send(()); + } + return Ok(()); + }, + (route_change, socket) = self.messages.select_next_some().fuse() => { + self.process_netlink_message(route_change).await?; + } + }; + Ok(()) + } + + async fn process_netlink_message(&mut self, msg: NetlinkMessage<RtnlMessage>) -> Result<()> { + match msg.payload { + NetlinkPayload::InnerMessage(RtnlMessage::NewLink(new_link)) => { + if let Some((idx, name)) = Self::map_iface_name_to_idx(new_link) { + self.iface_map.insert(idx, name); + } + } + NetlinkPayload::InnerMessage(RtnlMessage::DelLink(old_link)) => { + if let Some((idx, _)) = Self::map_iface_name_to_idx(old_link) { + self.iface_map.remove(&idx); + } + } + + NetlinkPayload::InnerMessage(RtnlMessage::NewRoute(new_route)) => { + if let Some(new_route) = self.parse_route_message(new_route)? { + self.process_new_route(new_route).await?; + } + } + NetlinkPayload::InnerMessage(RtnlMessage::DelRoute(old_route)) => { + if let Some(deletion) = self.parse_route_message(old_route)? { + self.process_deleted_route(deletion).await?; + } + } + _ => (), + }; + Ok(()) + } + + // Tries to coax a Route out of a RouteMessage, but only if it's a route from the main routing + // table + // TODO: Change to account for different routing tables. + fn parse_route_message(&self, msg: RouteMessage) -> Result<Option<Route>> { + if msg.header.table != RT_TABLE_MAIN { + return Ok(None); + } + + + let mut prefix = None; + let mut node_addr = None; + let mut device = None; + let mut metric = None; + let mut gateway = None; + + let destination_length = msg.header.destination_prefix_length; + let af_spec = msg.header.address_family; + + for nla in msg.nlas.iter() { + match nla { + RouteNla::Oif(device_idx) => { + match self.iface_map.get(&device_idx) { + Some(device_name) => device = Some(device_name.to_string()), + None => { + return Err(Error::UnknownDeviceIndex(*device_idx)); + } + }; + } + + RouteNla::Via(addr) => { + node_addr = Self::parse_ip(&addr).map(Some)?; + } + + RouteNla::Destination(addr) => { + prefix = Self::parse_ip(&addr) + .and_then(|ip| { + ipnetwork::IpNetwork::new(ip, destination_length) + .map_err(Error::InvalidNetworkPrefix) + }) + .map(Some)?; + } + + // gateway NLAs indicate that this is actually a default route + RouteNla::Gateway(gateway_ip) => { + gateway = Self::parse_ip(&gateway_ip).map(Some)?; + } + + RouteNla::Priority(priority) => { + metric = Some(*priority); + } + _ => continue, + } + } + + // when a gateway is specified but prefix is none, then this is a default route + if prefix.is_none() && gateway.is_some() { + prefix = match af_spec as i32 { + AF_INET => Some("0.0.0.0/0".parse().expect("failed to parse ipnetwork")), + AF_INET6 => Some("::/0".parse().expect("failed to parse ipnetwork")), + _ => None, + }; + } + + if device.is_none() && node_addr.is_none() || prefix.is_none() { + return Err(Error::InvalidRoute); + } + + + let node = Node { + ip: node_addr.or(gateway), + device, + }; + + Ok(Some(Route { + node, + prefix: prefix.unwrap(), + metric, + })) + } + + fn map_iface_name_to_idx(msg: LinkMessage) -> Option<(u32, String)> { + let index = msg.header.index; + for nla in msg.nlas { + if let LinkNla::IfName(name) = nla { + return Some((index, name)); + } + } + None + } + + fn parse_ip(bytes: &[u8]) -> Result<IpAddr> { + if bytes.len() == 4 { + let mut ipv4_bytes = [0u8; 4]; + ipv4_bytes.copy_from_slice(bytes); + Ok(IpAddr::from(ipv4_bytes)) + } else if bytes.len() == 16 { + let mut ipv6_bytes = [0u8; 16]; + ipv6_bytes.copy_from_slice(bytes); + Ok(IpAddr::from(ipv6_bytes)) + } else { + log::error!("Expected either 4 or 16 bytes, got {} bytes", bytes.len()); + Err(Error::InvalidIpBytes) + } + } + + async fn delete_route(&self, route: &Route) -> Result<()> { + let mut route_message = RouteMessage { + header: RouteHeader { + address_family: if route.prefix.is_ipv4() { + AF_INET as u8 + } else { + AF_INET6 as u8 + }, + source_prefix_length: 0, + destination_prefix_length: route.prefix.prefix(), + tos: 0u8, + table: RT_TABLE_MAIN, + protocol: RTPROT_STATIC, + scope: RT_SCOPE_UNIVERSE, + kind: RTN_UNICAST, + flags: RouteFlags::empty(), + }, + nlas: vec![RouteNla::Destination(ip_to_bytes(route.prefix.ip()))], + }; + if let Some(interface_name) = route.node.get_device() { + if let Some(iface_idx) = self.find_iface_idx(interface_name) { + route_message.nlas.push(RouteNla::Oif(iface_idx)); + } + } + + if let Some(gateway) = route.node.get_address() { + let gateway_nla = if route.node.get_device().is_some() { + RouteNla::Gateway(ip_to_bytes(gateway)) + } else { + RouteNla::Via(ip_to_bytes(gateway)) + }; + route_message.nlas.push(gateway_nla); + } + + + self.handle + .route() + .del(route_message) + .execute() + .await + .map_err(failure::Fail::compat) + .map_err(Error::NetlinkError) + } + + async fn add_route(&mut self, route: Route) -> Result<()> { + let add_message = match &route.prefix { + IpNetwork::V4(v4_prefix) => { + let mut add_message = self + .handle + .route() + .add_v4() + .destination_prefix(v4_prefix.ip(), v4_prefix.prefix()); + + if v4_prefix.size() > 1 { + add_message = add_message.scope(RT_SCOPE_LINK) + } + + if let Some(IpAddr::V4(node_address)) = route.node.get_address() { + add_message = add_message.gateway(node_address); + } + + if let Some(interface_name) = route.node.get_device() { + if let Some(iface_idx) = self.find_iface_idx(interface_name) { + add_message = add_message.output_interface(iface_idx); + } + } + + add_message.message_mut().clone() + } + + IpNetwork::V6(v6_prefix) => { + let mut add_message = self + .handle + .route() + .add_v6() + .destination_prefix(v6_prefix.ip(), v6_prefix.prefix()); + + if v6_prefix.size() > 1 { + add_message = add_message.scope(RT_SCOPE_LINK) + } + + if let Some(IpAddr::V6(node_address)) = route.node.get_address() { + add_message = add_message.gateway(node_address); + } + + if let Some(interface_name) = route.node.get_device() { + if let Some(iface_idx) = self.find_iface_idx(interface_name) { + add_message = add_message.output_interface(iface_idx); + } + } + + add_message.message_mut().clone() + } + }; + + // Need to modify the request in place to set the correct flags to be able to replace any + // existing routes - self.handle.route().add_v4().execute() sets the NLM_F_EXCL flag which + // will make the request fail if a route with the same destination already exists. + use netlink_packet_route::constants::*; + let mut req = NetlinkMessage::from(RtnlMessage::NewRoute(add_message)); + req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE; + + let mut response = self + .handle + .request(req) + .map_err(failure::Fail::compat) + .map_err(Error::NetlinkError)?; + + while let Some(message) = response.next().await { + if let NetlinkPayload::Error(err) = message.payload { + let compat_err = + failure::Fail::compat(rtnetlink::ErrorKind::NetlinkError(err).into()); + return Err(Error::NetlinkError(compat_err)); + } + } + self.added_routes.insert(route.clone()); + Ok(()) + } +} + +impl Drop for RouteManagerImplInner { + fn drop(&mut self) { + futures::executor::block_on(self.cleanup_routes()) + } +} + +fn ip_to_bytes(addr: IpAddr) -> Vec<u8> { + match addr { + IpAddr::V4(addr) => addr.octets().to_vec(), + IpAddr::V6(addr) => addr.octets().to_vec(), + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::collections::HashMap; + + + /// Tests if dropping inside a tokio runtime panics + #[test] + fn test_drop_in_executor() { + let mut runtime = tokio02::runtime::Runtime::new().expect("Failed to initialize runtime"); + runtime.block_on(async { + let manager = RouteManagerImplInner::new(HashMap::new()) + .await + .expect("Failed to initialize route manager"); + std::mem::drop(manager); + }); + } + + /// Tests if dropping outside a runtime panics + #[test] + fn test_drop() { + let mut runtime = tokio02::runtime::Runtime::new().expect("Failed to initialize runtime"); + let manager = runtime.block_on(async { + RouteManagerImplInner::new(HashMap::new()) + .await + .expect("Failed to initialize route manager") + }); + std::mem::drop(manager); + } +} diff --git a/talpid-core/src/routing/linux/change_listener.rs b/talpid-core/src/routing/linux/change_listener.rs deleted file mode 100644 index 82608a59a7..0000000000 --- a/talpid-core/src/routing/linux/change_listener.rs +++ /dev/null @@ -1,241 +0,0 @@ -use crate::routing::{Node, Route}; - -use super::RouteChange; -use futures::{future::Either, sync::mpsc, Async, Future, Stream}; -use std::{collections::BTreeMap, io, net::IpAddr}; - -use netlink_packet::{ - LinkMessage, LinkNla, NetlinkMessage, NetlinkPayload, RouteMessage, RouteNla, RtnlMessage, -}; -use netlink_sys::SocketAddr; -use rtnetlink::constants::{ - AF_INET, AF_INET6, RTMGRP_IPV4_ROUTE, RTMGRP_IPV6_ROUTE, RTMGRP_LINK, RTMGRP_NOTIFY, -}; - -#[derive(err_derive::Error, Debug)] -#[error(no_from)] -pub enum Error { - #[error(display = "Netlink connection failed")] - NetlinkError(#[error(source)] failure::Compat<rtnetlink::Error>), - #[error(display = "Netlink protocol error")] - NetlinkProtocolError(#[error(source)] failure::Compat<netlink_proto::Error>), - #[error(display = "Failed to open a netlink connection")] - ConnectError(#[error(source)] io::Error), - #[error(display = "Route without a valid node")] - InvalidRoute, - #[error(display = "Invalid length of byte buffer for IP address")] - InvalidIpBytes, - #[error(display = "Invalid network prefix")] - InvalidNetworkPrefix(#[error(source)] ipnetwork::IpNetworkError), - #[error(display = "Unknown device index - {}", _0)] - UnknownDeviceIndex(u32), - #[error(display = "Failed to bind netlink socket")] - BindError(#[error(source)] io::Error), - #[error(display = "Netlink connection stopped sending messages")] - NetlinkConnectionClosed, -} - -type Result<T> = std::result::Result<T, Error>; - -pub(super) struct RouteChangeListener { - connection: rtnetlink::Connection, - messages: mpsc::UnboundedReceiver<NetlinkMessage>, - iface_map: BTreeMap<u32, String>, -} - -impl RouteChangeListener { - pub fn new() -> Result<Self> { - let (mut connection, handle, messages) = - rtnetlink::new_connection_with_messages().map_err(Error::ConnectError)?; - - let mgroup_flags = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK | RTMGRP_NOTIFY; - let addr = SocketAddr::new(0, mgroup_flags); - connection - .socket_mut() - .bind(&addr) - .map_err(Error::BindError)?; - - let (iface_map, connection) = Self::initialize_link_map(connection, handle)?; - - Ok(Self { - connection, - messages, - iface_map, - }) - } - - fn map_netlink_to_route_change(&mut self, msg: NetlinkMessage) -> Result<Option<RouteChange>> { - match msg.payload { - NetlinkPayload::Rtnl(RtnlMessage::NewLink(new_link)) => { - if let Some((idx, name)) = Self::map_iface_name_to_idx(new_link) { - self.iface_map.insert(idx, name); - } - Ok(None) - } - NetlinkPayload::Rtnl(RtnlMessage::DelLink(old_link)) => { - if let Some((idx, _)) = Self::map_iface_name_to_idx(old_link) { - self.iface_map.remove(&idx); - } - Ok(None) - } - - NetlinkPayload::Rtnl(RtnlMessage::NewRoute(new_route)) => { - self.get_route(new_route).map(RouteChange::Add).map(Some) - } - NetlinkPayload::Rtnl(RtnlMessage::DelRoute(old_route)) => { - self.get_route(old_route).map(RouteChange::Remove).map(Some) - } - _ => Ok(None), - } - } - - // Tries to coax a Route out of a RouteMessage - fn get_route(&self, msg: RouteMessage) -> Result<Route> { - let mut prefix = None; - let mut node_addr = None; - let mut device = None; - let mut metric = None; - let mut gateway = None; - - let destination_length = msg.header.destination_length; - let af_spec = msg.header.address_family; - - for nla in msg.nlas.iter() { - match nla { - RouteNla::Oif(device_idx) => { - match self.iface_map.get(&device_idx) { - Some(device_name) => device = Some(device_name.to_string()), - None => { - return Err(Error::UnknownDeviceIndex(*device_idx)); - } - }; - } - - RouteNla::Via(addr) => { - node_addr = Self::parse_ip(&addr).map(Some)?; - } - - RouteNla::Destination(addr) => { - prefix = Self::parse_ip(&addr) - .and_then(|ip| { - ipnetwork::IpNetwork::new(ip, destination_length) - .map_err(Error::InvalidNetworkPrefix) - }) - .map(Some)?; - } - - // gateway NLAs indicate that this is actually a default route - RouteNla::Gateway(gateway_ip) => { - gateway = Self::parse_ip(&gateway_ip).map(Some)?; - } - - RouteNla::Priority(priority) => { - metric = Some(*priority); - } - _ => continue, - } - } - - // when a gateway is specified but prefix is none, then this is a default route - if prefix.is_none() && gateway.is_some() { - prefix = match af_spec as u16 { - AF_INET => Some("0.0.0.0/0".parse().expect("failed to parse ipnetwork")), - AF_INET6 => Some("::/0".parse().expect("failed to parse ipnetwork")), - _ => None, - }; - } - - if device.is_none() && node_addr.is_none() || prefix.is_none() { - return Err(Error::InvalidRoute); - } - - - let node = Node { - ip: node_addr, - device, - }; - - Ok(Route { - node, - prefix: prefix.unwrap(), - metric, - }) - } - - fn map_iface_name_to_idx(msg: LinkMessage) -> Option<(u32, String)> { - let index = msg.header.index; - for nla in msg.nlas { - match nla { - LinkNla::IfName(name) => return Some((index, name)), - _ => continue, - } - } - None - } - - fn parse_ip(bytes: &[u8]) -> Result<IpAddr> { - if bytes.len() == 4 { - let mut ipv4_bytes = [0u8; 4]; - ipv4_bytes.copy_from_slice(bytes); - Ok(IpAddr::from(ipv4_bytes)) - } else if bytes.len() == 16 { - let mut ipv6_bytes = [0u8; 16]; - ipv6_bytes.copy_from_slice(bytes); - Ok(IpAddr::from(ipv6_bytes)) - } else { - log::error!("Expected either 4 or 16 bytes, got {} bytes", bytes.len()); - Err(Error::InvalidIpBytes) - } - } - - pub fn initialize_link_map( - connection: rtnetlink::Connection, - handle: rtnetlink::Handle, - ) -> Result<(BTreeMap<u32, String>, rtnetlink::Connection)> { - let request = handle - .link() - .get() - .execute() - .filter_map(Self::map_iface_name_to_idx) - .collect(); - - match connection.select2(request).wait() { - Ok(Either::A(_)) => Err(Error::NetlinkConnectionClosed), - Err(Either::A((error, _))) => { - Err(Error::NetlinkProtocolError(failure::Fail::compat(error))) - } - Ok(Either::B((links, connection))) => Ok((links.into_iter().collect(), connection)), - Err(Either::B((error, _))) => Err(Error::NetlinkError(failure::Fail::compat(error))), - } - } -} - -impl Stream for RouteChangeListener { - type Item = RouteChange; - type Error = Error; - - fn poll(&mut self) -> Result<Async<Option<RouteChange>>> { - self.connection - .poll() - .map_err(failure::Fail::compat) - .map_err(Error::NetlinkProtocolError)?; - - loop { - match futures::try_ready!(self - .messages - .poll() - .map_err(|_| Error::NetlinkConnectionClosed)) - { - Some(message) => { - if let Some(route_change) = self.map_netlink_to_route_change(message)? { - return Ok(Async::Ready(Some(route_change))); - }; - continue; - } - None => { - return Err(Error::NetlinkConnectionClosed); - } - } - } - } -} diff --git a/talpid-core/src/routing/linux/mod.rs b/talpid-core/src/routing/linux/mod.rs deleted file mode 100644 index cdc57c87e1..0000000000 --- a/talpid-core/src/routing/linux/mod.rs +++ /dev/null @@ -1,440 +0,0 @@ -use crate::routing::{NetNode, Node, Route}; - -use ipnetwork::IpNetwork; -use std::{ - collections::{HashMap, HashSet}, - io, - process::{Command, Stdio}, -}; - -mod change_listener; -use change_listener::{Error as RouteChangeListenerError, RouteChangeListener}; - -use futures::{sync::oneshot, Async, Future, Stream}; - -pub type Result<T> = std::result::Result<T, Error>; - -/// Errors that can happen in the Linux routing integration -#[derive(err_derive::Error, Debug)] -#[error(no_from)] -pub enum Error { - /// Failed to add route. - #[error(display = "Failed to add route")] - FailedToAddRoute(#[error(source)] io::Error), - - /// Failed to remove route. - #[error(display = "Failed to remove route")] - FailedToRemoveRoute(#[error(source)] io::Error), - - /// Error while running "ip route". - #[error(display = "Error while running \"ip route\"")] - FailedToRunIp(#[error(source)] io::Error), - - /// Invocation of `ip route` ended with a non-zero exit code - #[error(display = "ip returend a non-zero exit code")] - ErrorIpFailed, - - /// Received unexpected output from `ip route` - #[error(display = "Received unexpected output from \"ip\"")] - UnexpectedOutput, - - /// No default route exists - #[error(display = "No default route in \"ip route\" output")] - NoDefaultRoute, - - /// Route table change stream failed. - #[error(display = "Route change listener failed")] - ChangeListenerError(#[error(source)] RouteChangeListenerError), - - /// Route table change stream failed. - #[error(display = "Route change listener closed unexpectedly")] - ChangeListenerClosed, -} - -pub struct RouteManagerImpl { - changes: RouteChangeListener, - - // currently added routes - added_routes: HashSet<Route>, - // default route tracking - // destinations that should be routed through the default route - required_default_routes: HashSet<IpNetwork>, - default_routes: HashSet<Route>, - best_default_node_v4: Option<Node>, - best_default_node_v6: Option<Node>, - - // if the stop channel is set, the future should wind down - remove added routes and send a - // signal. - shutdown_finished_tx: Option<oneshot::Sender<()>>, - shutdown_rx: oneshot::Receiver<oneshot::Sender<()>>, - should_shut_down: bool, -} - -impl RouteManagerImpl { - /// Creates a new RouteManager. - pub fn new( - required_routes: HashMap<IpNetwork, NetNode>, - shutdown_rx: oneshot::Receiver<oneshot::Sender<()>>, - ) -> Result<Self> { - let changes = RouteChangeListener::new().map_err(Error::ChangeListenerError)?; - - let mut required_normal_routes = HashSet::new(); - let mut required_default_routes = HashSet::new(); - - for (destination, node) in required_routes { - match node { - NetNode::RealNode(node) => { - required_normal_routes.insert(Route::new(node, destination)); - } - NetNode::DefaultNode => { - required_default_routes.insert(destination); - } - } - } - - let default_routes = Self::get_default_routes()?; - - let best_default_node_v4 = Self::pick_best_default_node(&default_routes, true); - let best_default_node_v6 = Self::pick_best_default_node(&default_routes, false); - - let mut monitor = Self { - changes, - - required_default_routes, - added_routes: HashSet::new(), - - default_routes, - best_default_node_v4, - best_default_node_v6, - - shutdown_finished_tx: None, - shutdown_rx, - should_shut_down: false, - }; - for normal_route in required_normal_routes.iter() { - monitor.add_route(&normal_route)?; - } - - for prefix in monitor.required_default_routes.clone().into_iter() { - if let (false, _, Some(default_node)) | (true, Some(default_node), _) = ( - prefix.is_ipv4(), - &monitor.best_default_node_v4, - &monitor.best_default_node_v6, - ) { - // best to pick a single node identifier rather than device + ip - let route = Route::new(default_node.clone(), prefix); - monitor.add_route(&route)?; - } - } - Ok(monitor) - } - - fn process_route_table_change(&mut self) -> Result<()> { - loop { - let change = self.changes.poll().map_err(Error::ChangeListenerError)?; - match change { - Async::NotReady => return Ok(()), - Async::Ready(Some(RouteChange::Add(route))) => self.process_new_route(route), - Async::Ready(Some(RouteChange::Remove(route))) => self.process_deleted_route(route), - Async::Ready(None) => return Err(Error::ChangeListenerClosed), - } - } - } - - fn process_new_route(&mut self, route: Route) { - if route.prefix.prefix() == 0 { - self.default_routes.insert(route); - self.update_default_routes(); - } - } - - fn process_deleted_route(&mut self, route: Route) { - if route.prefix.prefix() == 0 { - self.update_default_routes(); - } - } - - fn update_default_routes(&mut self) { - let new_best_v4 = Self::pick_best_default_node(&self.default_routes, true); - if self.best_default_node_v4 != new_best_v4 && new_best_v4.is_some() { - let new_node = new_best_v4.unwrap(); - let old_node = self.best_default_node_v4.take(); - let v4_destinations: Vec<_> = self - .required_default_routes - .iter() - .filter(|ip| ip.is_ipv4()) - .cloned() - .collect(); - for destination in v4_destinations { - let new_route = Route::new(new_node.clone(), destination); - if let Some(old_node) = &old_node { - let old_route = Route::new(old_node.clone(), destination); - if let Err(e) = self.delete_route(&old_route) { - log::error!("Failed to remove old route {} - {}", &old_route, e); - } - } - if let Err(e) = self.add_route(&new_route) { - log::error!("Failed to add new route {} - {}", &new_node, e); - } - } - self.best_default_node_v4 = Some(new_node); - } - - let new_best_v6 = Self::pick_best_default_node(&self.default_routes, false); - if self.best_default_node_v6 != new_best_v6 && new_best_v6.is_some() { - let new_node = new_best_v6.unwrap(); - let old_node = self.best_default_node_v6.take(); - let v6_destinations: Vec<_> = self - .required_default_routes - .iter() - .filter(|ip| !ip.is_ipv4()) - .cloned() - .collect(); - - for destination in v6_destinations { - let new_route = Route::new(new_node.clone(), destination); - if let Some(old_node) = &old_node { - let old_route = Route::new(old_node.clone(), destination); - - if let Err(e) = self.delete_route(&old_route) { - log::error!("Failed to remove old route {} - {}", &old_route, e); - } - } - if let Err(e) = self.add_route(&new_route) { - log::error!("Failed to add new route {} - {}", &new_node, e); - } - } - self.best_default_node_v6 = Some(new_node); - } - } - - fn pick_best_default_node(routes: &HashSet<Route>, v4: bool) -> Option<Node> { - // Pick the route with the lowest metric - thus the most favourable route. - routes - .iter() - .filter(|route| route.prefix.is_ipv4() == v4) - .fold( - None, - |best_route: Option<Route>, next_route| match best_route { - Some(current_best) => { - if current_best.metric.unwrap_or(0) > next_route.metric.unwrap_or(0) { - Some(next_route.clone()) - } else { - Some(current_best) - } - } - None => Some(next_route.clone()), - }, - ) - .map(|route| route.node) - } - - fn route_cmd(action: &str, route: &Route) -> Command { - let mut cmd = Command::new("ip"); - - cmd.arg(ip_vers(&route)) - .arg("route") - .arg(action) - .arg(route.prefix.to_string()); - - if let Some(addr) = route.node.get_address() { - cmd.arg("via").arg(addr.to_string()); - }; - if let Some(device) = route.node.get_device() { - cmd.arg("dev").arg(device); - }; - if let Some(metric) = route.metric { - cmd.arg("metric").arg(metric.to_string()); - }; - - cmd - } - - fn run_cmd(mut cmd: Command, err: impl Fn(io::Error) -> Error) -> Result<()> { - log::trace!("running cmd - {:?}", &cmd); - let status = cmd.status().map_err(|e| err(e))?; - match status.code() { - Some(0) => Ok(()), - Some(i) => Err(err(io::Error::new( - io::ErrorKind::Other, - format!("exit status {}", i), - ))), - None => Err(err(io::Error::new( - io::ErrorKind::Other, - "interrupted by signal", - ))), - } - } - - fn get_default_routes_inner(ip_version: IpVersion) -> Result<Vec<Route>> { - let mut cmd = Command::new("ip"); - cmd.arg(ip_version.to_route_arg()).arg("route").arg("show"); - - cmd.stdout(Stdio::piped()) - .output() - .map_err(Error::FailedToRunIp) - .and_then(move |output| { - let output_lines = String::from_utf8(output.stdout.clone()) - .map_err(|_| Error::UnexpectedOutput)?; - Ok(output_lines - .lines() - .filter_map(|line| { - if line.starts_with("default") { - parse_ip_route_show_line(line, ip_version) - } else { - None - } - }) - .collect()) - }) - } - - /// Adds routes to the system routing table. - fn add_route(&mut self, route: &Route) -> Result<()> { - let cmd = Self::route_cmd("replace", route); - Self::run_cmd(cmd, Error::FailedToAddRoute)?; - self.added_routes.insert(route.clone()); - Ok(()) - } - - /// Removes previously set routes. If routes were set for specific tables, the whole tables - /// will be removed. - fn delete_route(&mut self, route: &Route) -> Result<()> { - let cmd = Self::route_cmd("delete", route); - Self::run_cmd(cmd, Error::FailedToRemoveRoute)?; - self.added_routes.remove(route); - Ok(()) - } - - fn cleanup_routes(&mut self) { - for route in self.added_routes.drain().collect::<Vec<_>>().iter() { - if let Err(e) = self.delete_route(&route) { - log::error!("Failed to remove route - {} - {}", route, e); - } - } - } - - - /// Retrieves the gateway for the default route - fn get_default_routes() -> Result<HashSet<Route>> { - let v4_routes = Self::get_default_routes_inner(IpVersion::V4)?; - let v6_routes = Self::get_default_routes_inner(IpVersion::V6)?; - Ok(v4_routes.into_iter().chain(v6_routes.into_iter()).collect()) - } -} - -#[derive(Debug, Copy, Clone)] -enum IpVersion { - V4, - V6, -} - -impl IpVersion { - fn to_route_arg(self) -> &'static str { - match self { - IpVersion::V4 => "-4", - IpVersion::V6 => "-6", - } - } -} - -impl Future for RouteManagerImpl { - type Item = (); - type Error = Error; - fn poll(&mut self) -> Result<Async<()>> { - if !self.should_shut_down { - match self.shutdown_rx.poll() { - Ok(Async::NotReady) => (), - Ok(Async::Ready(tx)) => { - self.should_shut_down = true; - self.shutdown_finished_tx = Some(tx); - } - Err(_) => { - self.should_shut_down = true; - } - }; - self.process_route_table_change()?; - } - if self.should_shut_down { - self.cleanup_routes(); - if let Some(tx) = self.shutdown_finished_tx.take() { - if tx.send(()).is_err() { - log::error!("RouteManagerHandle already stopped"); - } - } - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } - } -} - -impl Drop for RouteManagerImpl { - fn drop(&mut self) { - self.cleanup_routes(); - } -} - -// intended to parse lines sucha as the following: -// default via 192.168.1.1 dev wlp61s0 proto dhcp metric 600 -fn parse_ip_route_show_line(line: &str, ip_version: IpVersion) -> Option<Route> { - let mut node_ip = None; - let mut device = None; - let mut metric = None; - - let mut tokens = line.split_whitespace(); - let prefix_str = tokens.next()?; - let prefix = match prefix_str { - "default" => match ip_version { - IpVersion::V4 => "0.0.0.0/0".parse().unwrap(), - IpVersion::V6 => "::/0".parse().unwrap(), - }, - prefix_str => prefix_str.parse().ok()?, - }; - - let tokens: Vec<&str> = tokens.collect(); - for pair in tokens.chunks(2) { - if pair.len() != 2 { - log::error!("unexpected output from ip"); - break; - } - let kind = pair[0]; - let value = pair[1]; - - match kind { - "via" => node_ip = value.parse().ok(), - "dev" => device = Some(value.to_string()), - "metric" => metric = value.parse().ok(), - _ => continue, - }; - } - - if node_ip.is_none() && device.is_none() { - None - } else { - let node = Node { - ip: node_ip, - device, - }; - - Some(Route { - node, - prefix, - metric, - }) - } -} - -fn ip_vers(route: &Route) -> &'static str { - if route.prefix.is_ipv4() { - "-4" - } else { - "-6" - } -} - -#[derive(Debug, PartialEq)] -enum RouteChange { - Add(Route), - Remove(Route), -} diff --git a/talpid-core/src/routing/macos.rs b/talpid-core/src/routing/macos.rs index 1d02d87de1..1d364b43f3 100644 --- a/talpid-core/src/routing/macos.rs +++ b/talpid-core/src/routing/macos.rs @@ -8,7 +8,7 @@ use std::{ process::{Command, ExitStatus, Stdio}, }; -use futures::{stream, sync::oneshot, Async, Future, IntoFuture, Stream}; +use futures01::{stream, sync::oneshot, Async, Future, IntoFuture, Stream}; use tokio_process::{Child, CommandExt}; @@ -208,7 +208,7 @@ impl RouteManagerImpl { .arg(ip_vers(destination)) .arg(destination.to_string()); - futures::lazy(move || cmd.spawn_async().into_future().and_then(|f| f)) + futures01::lazy(move || cmd.spawn_async().into_future().and_then(|f| f)) .map_err(Error::FailedToRemoveRoute) } @@ -226,7 +226,7 @@ impl RouteManagerImpl { cmd.arg("-interface").arg(device); } - futures::lazy(move || cmd.spawn_async().into_future().and_then(|f| f)) + futures01::lazy(move || cmd.spawn_async().into_future().and_then(|f| f)) .map_err(Error::FailedToAddRoute) } diff --git a/talpid-core/src/routing/unix.rs b/talpid-core/src/routing/unix.rs index 146c371ceb..dffd6c21b4 100644 --- a/talpid-core/src/routing/unix.rs +++ b/talpid-core/src/routing/unix.rs @@ -2,16 +2,16 @@ #![cfg_attr(target_os = "windows", allow(dead_code))] // TODO: remove the allow(dead_code) for android once it's up to scratch. use super::NetNode; -use futures::{sync::oneshot, Future}; +use futures01::{sync::oneshot, Future}; use ipnetwork::IpNetwork; -use std::collections::HashMap; +use std::{collections::HashMap, sync::mpsc::sync_channel}; #[cfg(target_os = "macos")] #[path = "macos.rs"] mod imp; #[cfg(target_os = "linux")] -#[path = "linux/mod.rs"] +#[path = "linux.rs"] mod imp; #[cfg(target_os = "android")] @@ -47,7 +47,7 @@ impl RouteManager { /// routes. pub fn new(required_routes: HashMap<IpNetwork, NetNode>) -> Result<Self, Error> { let (tx, rx) = oneshot::channel(); - let (start_tx, start_rx) = oneshot::channel(); + let (start_tx, start_rx) = sync_channel(1); std::thread::spawn( move || match imp::RouteManagerImpl::new(required_routes, rx) { @@ -62,7 +62,7 @@ impl RouteManager { } }, ); - match start_rx.wait() { + match start_rx.recv() { Ok(Ok(())) => Ok(Self { tx: Some(tx) }), Ok(Err(e)) => Err(e), Err(_) => Err(Error::RoutingManagerThreadPanic), diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs index 1c0407a615..47bc8d0f36 100644 --- a/talpid-core/src/tunnel_state_machine/connected_state.rs +++ b/talpid-core/src/tunnel_state_machine/connected_state.rs @@ -6,7 +6,7 @@ use crate::{ firewall::FirewallPolicy, tunnel::{CloseHandle, TunnelEvent, TunnelMetadata}, }; -use futures::{ +use futures01::{ sync::{mpsc, oneshot}, Async, Future, Stream, }; diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs index 77608c4c3d..204d1e5ebb 100644 --- a/talpid-core/src/tunnel_state_machine/connecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs @@ -9,7 +9,7 @@ use crate::{ self, tun_provider::TunProvider, CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor, }, }; -use futures::{ +use futures01::{ sync::{mpsc, oneshot}, Async, Future, Stream, }; diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs index 0eb02252dd..0ad48366d9 100644 --- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs @@ -3,7 +3,7 @@ use super::{ TunnelState, TunnelStateTransition, TunnelStateWrapper, }; use crate::firewall::FirewallPolicy; -use futures::{sync::mpsc, Stream}; +use futures01::{sync::mpsc, Stream}; use talpid_types::ErrorExt; /// No tunnel is running. diff --git a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs index c07ecbf8f7..21e3198978 100644 --- a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs @@ -3,7 +3,7 @@ use super::{ TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper, }; use crate::tunnel::CloseHandle; -use futures::{ +use futures01::{ sync::{mpsc, oneshot}, Async, Future, Stream, }; diff --git a/talpid-core/src/tunnel_state_machine/error_state.rs b/talpid-core/src/tunnel_state_machine/error_state.rs index b1bf5183b2..692a69b3d3 100644 --- a/talpid-core/src/tunnel_state_machine/error_state.rs +++ b/talpid-core/src/tunnel_state_machine/error_state.rs @@ -3,7 +3,7 @@ use super::{ TunnelState, TunnelStateTransition, TunnelStateWrapper, }; use crate::firewall::FirewallPolicy; -use futures::{sync::mpsc, Stream}; +use futures01::{sync::mpsc, Stream}; use talpid_types::{ tunnel::{self as talpid_tunnel, ErrorStateCause}, ErrorExt, diff --git a/talpid-core/src/tunnel_state_machine/macros.rs b/talpid-core/src/tunnel_state_machine/macros.rs index 332d518de5..deccd29fdd 100644 --- a/talpid-core/src/tunnel_state_machine/macros.rs +++ b/talpid-core/src/tunnel_state_machine/macros.rs @@ -10,9 +10,9 @@ macro_rules! try_handle_event { ($same_state:expr, $event:expr) => { match $event { - Ok(futures::Async::Ready(Some(event))) => Ok(event), - Ok(futures::Async::Ready(None)) => Err(None), - Ok(futures::Async::NotReady) => { + Ok(futures01::Async::Ready(Some(event))) => Ok(event), + Ok(futures01::Async::Ready(None)) => Err(None), + Ok(futures01::Async::NotReady) => { return crate::tunnel_state_machine::EventConsequence::NoEvents($same_state); } Err(error) => Err(Some(error)), diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs index 5379a76740..baf52c4b2b 100644 --- a/talpid-core/src/tunnel_state_machine/mod.rs +++ b/talpid-core/src/tunnel_state_machine/mod.rs @@ -21,7 +21,8 @@ use crate::{ offline, tunnel::tun_provider::TunProvider, }; -use futures::{ + +use futures01::{ sync::{mpsc, oneshot}, Async, Future, Poll, Stream, }; @@ -78,7 +79,7 @@ pub fn spawn( ) -> Result<Arc<mpsc::UnboundedSender<TunnelCommand>>, Error> { let (command_tx, command_rx) = mpsc::unbounded(); let command_tx = Arc::new(command_tx); - let offline_monitor = offline::spawn_monitor( + let mut offline_monitor = offline::spawn_monitor( Arc::downgrade(&command_tx), #[cfg(target_os = "android")] android_context.clone(), diff --git a/talpid-types/src/net/wireguard.rs b/talpid-types/src/net/wireguard.rs index 33f06af911..9e6e6290bd 100644 --- a/talpid-types/src/net/wireguard.rs +++ b/talpid-types/src/net/wireguard.rs @@ -141,6 +141,10 @@ impl PublicKey { pub fn as_bytes(&self) -> &[u8; 32] { self.0.as_bytes() } + + pub fn to_base64(&self) -> String { + base64::encode(self.as_bytes()) + } } @@ -196,7 +200,7 @@ impl fmt::Debug for PublicKey { impl fmt::Display for PublicKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", &base64::encode(self.0.as_bytes())) + write!(f, "{}", &self.to_base64()) } } diff --git a/update-relays.sh b/update-relays.sh index 711afe342a..2a2fde13fe 100755 --- a/update-relays.sh +++ b/update-relays.sh @@ -1,23 +1,5 @@ #!/usr/bin/env bash echo "Updating relay list..." -set +e -read -d '' JSONRPC_CODE <<-JSONRPC_CODE -var buff = ""; -process.stdin.on('data', function (chunk) { - buff += chunk; -}) -process.stdin.on('end', function () { - var obj = JSON.parse(buff); - var output = JSON.stringify(obj.result, null, ' '); - process.stdout.write(output); -}) -JSONRPC_CODE set -e - -JSONRPC_RESPONSE="$(curl -X POST \ - --fail \ - -H "Content-Type: application/json" \ - -d '{"jsonrpc": "2.0", "id": "0", "method": "relay_list_v3"}' \ - https://api.mullvad.net/rpc/)" -echo $JSONRPC_RESPONSE | node -e "$JSONRPC_CODE" > dist-assets/relays.json +cargo run -p mullvad-rpc --bin relay_list > dist-assets/relays.json |
