summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2020-04-27 13:59:12 +0100
committerEmīls Piņķis <emils@mullvad.net>2020-04-27 13:59:12 +0100
commit4f1d2ba90546907e9905ac9ec72731613e559294 (patch)
tree2ad92e79d6e0c173e5b84a9cfe57102b121895f6
parentf9573c6f0360a6dcd0e334285e2ae91120234100 (diff)
parent9260448c0f523e041453f413bff4fef957753c3f (diff)
downloadmullvadvpn-4f1d2ba90546907e9905ac9ec72731613e559294.tar.xz
mullvadvpn-4f1d2ba90546907e9905ac9ec72731613e559294.zip
Merge branch 'use-rest-new-hyper'
-rw-r--r--Cargo.lock1041
-rw-r--r--README.md6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt3
-rwxr-xr-xbuild.sh1
-rw-r--r--env.bat4
-rw-r--r--env.ps15
-rwxr-xr-xenv.sh4
-rw-r--r--mullvad-cli/src/cmds/version.rs2
-rw-r--r--mullvad-daemon/src/account_history.rs12
-rw-r--r--mullvad-daemon/src/event_loop.rs38
-rw-r--r--mullvad-daemon/src/geoip.rs88
-rw-r--r--mullvad-daemon/src/lib.rs108
-rw-r--r--mullvad-daemon/src/logging.rs1
-rw-r--r--mullvad-daemon/src/management_interface.rs60
-rw-r--r--mullvad-daemon/src/relays.rs14
-rw-r--r--mullvad-daemon/src/version_check.rs13
-rw-r--r--mullvad-daemon/src/wireguard.rs64
-rw-r--r--mullvad-jni/Cargo.toml1
-rw-r--r--mullvad-jni/src/daemon_interface.rs2
-rw-r--r--mullvad-jni/src/lib.rs13
-rw-r--r--mullvad-problem-report/Cargo.toml2
-rw-r--r--mullvad-problem-report/src/lib.rs19
-rw-r--r--mullvad-rpc/Cargo.toml23
-rw-r--r--mullvad-rpc/src/bin/relay_list.rs17
-rw-r--r--mullvad-rpc/src/event_loop.rs40
-rw-r--r--mullvad-rpc/src/https_client_with_sni.rs192
-rw-r--r--mullvad-rpc/src/lib.rs433
-rw-r--r--mullvad-rpc/src/relay_list.rs337
-rw-r--r--mullvad-rpc/src/rest.rs600
-rw-r--r--mullvad-types/src/relay_list.rs7
-rw-r--r--mullvad-types/src/version.rs7
-rw-r--r--talpid-core/Cargo.toml14
-rw-r--r--talpid-core/src/offline/android.rs2
-rw-r--r--talpid-core/src/offline/linux.rs283
-rw-r--r--talpid-core/src/offline/macos.rs2
-rw-r--r--talpid-core/src/offline/mod.rs4
-rw-r--r--talpid-core/src/offline/windows.rs2
-rw-r--r--talpid-core/src/routing/android.rs2
-rw-r--r--talpid-core/src/routing/linux.rs697
-rw-r--r--talpid-core/src/routing/linux/change_listener.rs241
-rw-r--r--talpid-core/src/routing/linux/mod.rs440
-rw-r--r--talpid-core/src/routing/macos.rs6
-rw-r--r--talpid-core/src/routing/unix.rs10
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs2
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs2
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnected_state.rs2
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnecting_state.rs2
-rw-r--r--talpid-core/src/tunnel_state_machine/error_state.rs2
-rw-r--r--talpid-core/src/tunnel_state_machine/macros.rs6
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs5
-rw-r--r--talpid-types/src/net/wireguard.rs6
-rwxr-xr-xupdate-relays.sh20
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"
diff --git a/README.md b/README.md
index 692bd8c22d..0c75b4ea1a 100644
--- a/README.md
+++ b/README.md
@@ -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
)
diff --git a/build.sh b/build.sh
index 9d58f3eb9b..482ba2d385 100755
--- a/build.sh
+++ b/build.sh
@@ -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"
diff --git a/env.sh b/env.sh
index 62ab1b3132..27957509b4 100755
--- a/env.sh
+++ b/env.sh
@@ -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