summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-06-16 15:25:19 +0200
committerLinus Färnstrand <linus@mullvad.net>2017-06-16 15:25:19 +0200
commit44346a5d28264ef15915336096a4e0d622d662ec (patch)
tree11f80ee610fb2e3ee73a8361ef5d03491bdb8830
parent42bf586735f093b086a8c109cf7d9d664b8f849c (diff)
parentf642c9b3acb2b3d041634ec877b60c496198e5c1 (diff)
downloadmullvadvpn-44346a5d28264ef15915336096a4e0d622d662ec.tar.xz
mullvadvpn-44346a5d28264ef15915336096a4e0d622d662ec.zip
Merge branch 'daemon-struct' into master-new-daemon
-rw-r--r--Cargo.lock108
-rw-r--r--Cargo.toml2
-rw-r--r--mullvad_daemon/Cargo.toml5
-rw-r--r--mullvad_daemon/src/main.rs325
-rw-r--r--mullvad_daemon/src/states.rs2
-rw-r--r--talpid_core/Cargo.toml1
-rw-r--r--talpid_core/src/lib.rs2
-rw-r--r--talpid_core/src/tunnel/mod.rs2
-rw-r--r--talpid_core/src/tunnel/openvpn.rs32
9 files changed, 364 insertions, 115 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f86b13f7c3..c960739c60 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,26 +18,11 @@ dependencies = [
]
[[package]]
-name = "ansi_term"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "assert_matches"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "atty"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "backtrace"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -66,11 +51,6 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "bitflags"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "byteorder"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -90,21 +70,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "clap"
-version = "2.23.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "dbghelp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -205,7 +170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jsonrpc-core"
version = "7.0.0"
-source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#8c47e034f05b8e42d3440078b758dd732e85894c"
+source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#e5da3f069fb14f9a90278f09a1841f9149af541b"
dependencies = [
"futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -217,7 +182,7 @@ dependencies = [
[[package]]
name = "jsonrpc-macros"
version = "7.0.0"
-source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#8c47e034f05b8e42d3440078b758dd732e85894c"
+source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#e5da3f069fb14f9a90278f09a1841f9149af541b"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
"jsonrpc-pubsub 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
@@ -227,7 +192,7 @@ dependencies = [
[[package]]
name = "jsonrpc-pubsub"
version = "7.0.0"
-source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#8c47e034f05b8e42d3440078b758dd732e85894c"
+source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#e5da3f069fb14f9a90278f09a1841f9149af541b"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -237,7 +202,7 @@ dependencies = [
[[package]]
name = "jsonrpc-server-utils"
version = "7.0.0"
-source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#8c47e034f05b8e42d3440078b758dd732e85894c"
+source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#e5da3f069fb14f9a90278f09a1841f9149af541b"
dependencies = [
"globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
@@ -249,7 +214,7 @@ dependencies = [
[[package]]
name = "jsonrpc-ws-server"
version = "7.0.0"
-source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#8c47e034f05b8e42d3440078b758dd732e85894c"
+source = "git+https://github.com/faern/jsonrpc?branch=ws-close-handle#e5da3f069fb14f9a90278f09a1841f9149af541b"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
@@ -267,6 +232,11 @@ dependencies = [
]
[[package]]
+name = "lazy_static"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "lazycell"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -337,10 +307,13 @@ dependencies = [
"jsonrpc-macros 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
"jsonrpc-pubsub 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
"jsonrpc-ws-server 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "talpid_core 0.0.0",
"talpid_ipc 0.1.0",
+ "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -527,11 +500,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "strsim"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "syn"
version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -550,17 +518,6 @@ dependencies = [
]
[[package]]
-name = "talpid_cli"
-version = "0.0.0"
-dependencies = [
- "clap 2.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "talpid_core 0.0.0",
-]
-
-[[package]]
name = "talpid_core"
version = "0.0.0"
dependencies = [
@@ -569,6 +526,7 @@ dependencies = [
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
"jsonrpc-macros 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"openvpn_ffi 0.1.0",
@@ -593,16 +551,6 @@ dependencies = [
]
[[package]]
-name = "term_size"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "thread-id"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -659,16 +607,6 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "unicode-segmentation"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -696,9 +634,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "vec_map"
-version = "0.7.0"
+name = "uuid"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "void"
@@ -742,17 +683,13 @@ dependencies = [
[metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
-"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57"
-"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
-"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
"checksum bytes 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3941933da81d8717b427c2ddc2d73567cd15adb6c57514a2726d9ee598a5439a"
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
-"checksum clap 2.23.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf1114886d7cde2d6448517161d7db8d681a9a1c09f7d210f0b0864e48195f6"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum duct 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f3154a9285e24d7c3aba0dca9a13adf2ba6160cce3490b157c8b37a0f80e85"
@@ -772,6 +709,7 @@ dependencies = [
"checksum jsonrpc-server-utils 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)" = "<none>"
"checksum jsonrpc-ws-server 7.0.0 (git+https://github.com/faern/jsonrpc?branch=ws-close-handle)" = "<none>"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
@@ -802,23 +740,19 @@ dependencies = [
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
"checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
-"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)" = "171b739972d9a1bfb169e8077238b51f9ebeaae4ff6e08072f7ba386a8802da2"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "99e958104a67877907c1454386d5482fe8e965a55d60be834a15a44328e7dc76"
"checksum tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "48f55df1341bb92281f229a6030bc2abffde2c7a44c6d6b802b7687dd8be0775"
"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032"
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
-"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
-"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
-"checksum vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897"
+"checksum uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d0f5103675a280a926ec2f9b7bcc2ef49367df54e8c570c3311fec919f9a8b"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/Cargo.toml b/Cargo.toml
index ec561b5566..ebdd8443ac 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,2 +1,2 @@
[workspace]
-members = ["mullvad_daemon", "talpid_openvpn_plugin", "openvpn_ffi", "talpid_cli", "talpid_ipc"]
+members = ["mullvad_daemon", "talpid_openvpn_plugin", "openvpn_ffi", "talpid_ipc"]
diff --git a/mullvad_daemon/Cargo.toml b/mullvad_daemon/Cargo.toml
index d98c32b0b1..ce2ffafa98 100644
--- a/mullvad_daemon/Cargo.toml
+++ b/mullvad_daemon/Cargo.toml
@@ -15,9 +15,10 @@ jsonrpc-macros = { git = "https://github.com/faern/jsonrpc", branch = "ws-close-
jsonrpc-pubsub = { git = "https://github.com/faern/jsonrpc", branch = "ws-close-handle" }
jsonrpc-ws-server = { git = "https://github.com/faern/jsonrpc", branch = "ws-close-handle" }
uuid = { version = "0.5", features = ["v4"] }
+lazy_static = "0.2"
-[dependencies.talpid_ipc]
-path = "../talpid_ipc"
+talpid_core = { path = "../talpid_core" }
+talpid_ipc = { path = "../talpid_ipc" }
[dev-dependencies]
assert_matches = "1.0"
diff --git a/mullvad_daemon/src/main.rs b/mullvad_daemon/src/main.rs
index 95033b1564..fa1db7765c 100644
--- a/mullvad_daemon/src/main.rs
+++ b/mullvad_daemon/src/main.rs
@@ -8,37 +8,330 @@ extern crate serde;
#[macro_use]
extern crate serde_derive;
-extern crate talpid_ipc;
-
extern crate jsonrpc_core;
extern crate jsonrpc_pubsub;
#[macro_use]
extern crate jsonrpc_macros;
extern crate jsonrpc_ws_server;
+extern crate uuid;
+#[macro_use]
+extern crate lazy_static;
+
+extern crate talpid_core;
+extern crate talpid_ipc;
+
+mod management_interface;
+mod states;
+
+use management_interface::{ManagementInterfaceServer, TunnelCommand};
+use states::{SecurityState, TargetState};
+
+use std::sync::{Arc, Mutex, mpsc};
+use std::thread;
+
+use talpid_core::net::RemoteAddr;
+use talpid_core::tunnel::{self, TunnelEvent, TunnelMonitor};
+
+error_chain!{
+ errors {
+ /// The client is in the wrong state for the requested operation. Optimally the code should
+ /// be written in such a way so such states can't exist.
+ InvalidState {
+ description("Client is in an invalid state for the requested operation")
+ }
+ TunnelError(msg: &'static str) {
+ description("Error in the tunnel monitor")
+ display("Tunnel monitor error: {}", msg)
+ }
+ ManagementInterfaceError(msg: &'static str) {
+ description("Error in the management interface")
+ display("Management interface error: {}", msg)
+ }
+ }
+}
+
+lazy_static! {
+ // Temporary store of hardcoded remotes.
+ static ref REMOTES: [RemoteAddr; 3] = [
+ RemoteAddr::new("se5.mullvad.net", 1300),
+ RemoteAddr::new("se6.mullvad.net", 1300),
+ RemoteAddr::new("se7.mullvad.net", 1300),
+ ];
+}
+
+pub enum DaemonEvent {
+ TunnelEvent(TunnelEvent),
+ TunnelExit(tunnel::Result<()>),
+ ManagementInterfaceEvent(TunnelCommand),
+ ManagementInterfaceExit(talpid_ipc::Result<()>),
+}
+
+impl From<TunnelEvent> for DaemonEvent {
+ fn from(tunnel_event: TunnelEvent) -> Self {
+ DaemonEvent::TunnelEvent(tunnel_event)
+ }
+}
+
+impl From<TunnelCommand> for DaemonEvent {
+ fn from(tunnel_command: TunnelCommand) -> Self {
+ DaemonEvent::ManagementInterfaceEvent(tunnel_command)
+ }
+}
+
+/// Represents the internal state of the actual tunnel.
+// TODO(linus): Put the tunnel::CloseHandle into this state, so it can't exist when not running.
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum TunnelState {
+ /// No tunnel is running.
+ NotRunning,
+ /// The tunnel has been started, but it is not established/functional.
+ Down,
+ /// The tunnel is up and working.
+ Up,
+}
+
+impl TunnelState {
+ pub fn as_security_state(&self) -> SecurityState {
+ match *self {
+ TunnelState::Up => SecurityState::Secured,
+ _ => SecurityState::Unsecured,
+ }
+ }
+}
+
+
+struct Daemon {
+ state: TunnelState,
+ last_broadcasted_state: SecurityState,
+ target_state: TargetState,
+ rx: mpsc::Receiver<DaemonEvent>,
+ tx: mpsc::Sender<DaemonEvent>,
+ tunnel_close_handle: Option<tunnel::CloseHandle>,
+ management_interface_broadcaster: management_interface::EventBroadcaster,
+
+ // Just for testing. A cyclic iterator iterating over the hardcoded remotes,
+ // picking a new one for each retry.
+ remote_iter: std::iter::Cycle<std::iter::Cloned<std::slice::Iter<'static, RemoteAddr>>>,
+}
+
+impl Daemon {
+ pub fn new() -> Result<Self> {
+ let (tx, rx) = mpsc::channel();
+ let management_interface_broadcaster = Self::start_management_interface(tx.clone())?;
+ Ok(
+ Daemon {
+ state: TunnelState::NotRunning,
+ last_broadcasted_state: SecurityState::Unsecured,
+ target_state: TargetState::Unsecured,
+ rx,
+ tx,
+ tunnel_close_handle: None,
+ management_interface_broadcaster,
+ remote_iter: REMOTES.iter().cloned().cycle(),
+ },
+ )
+ }
+
+ // Starts the management interface and spawns a thread that will process it.
+ // Returns a handle that allows notifying all subscribers on events.
+ fn start_management_interface(event_tx: mpsc::Sender<DaemonEvent>)
+ -> Result<management_interface::EventBroadcaster> {
+ let server = Self::start_management_interface_server(event_tx.clone())?;
+ let event_broadcaster = server.event_broadcaster();
+ Self::spawn_management_interface_wait_thread(server, event_tx);
+ Ok(event_broadcaster)
+ }
+
+ fn start_management_interface_server(event_tx: mpsc::Sender<DaemonEvent>)
+ -> Result<ManagementInterfaceServer> {
+ let server =
+ ManagementInterfaceServer::start(event_tx.clone())
+ .chain_err(|| ErrorKind::ManagementInterfaceError("Failed to start server"),)?;
+ info!(
+ "Mullvad management interface listening on {}",
+ server.address()
+ );
+ Ok(server)
+ }
+
+ fn spawn_management_interface_wait_thread(server: ManagementInterfaceServer,
+ exit_tx: mpsc::Sender<DaemonEvent>) {
+ thread::spawn(
+ move || {
+ let result = server.wait();
+ debug!("Mullvad management interface shut down");
+ let _ = exit_tx.send(DaemonEvent::ManagementInterfaceExit(result));
+ },
+ );
+ }
+
+ /// Consume the `Daemon` and run the main event loop. Blocks until an error happens.
+ pub fn run(mut self) -> Result<()> {
+ while let Ok(event) = self.rx.recv() {
+ self.handle_event(event)?;
+ }
+ Ok(())
+ }
+
+ fn handle_event(&mut self, event: DaemonEvent) -> Result<()> {
+ use DaemonEvent::*;
+ match event {
+ TunnelEvent(event) => Ok(self.handle_tunnel_event(event)),
+ TunnelExit(result) => self.handle_tunnel_exit(result),
+ ManagementInterfaceEvent(event) => self.handle_management_interface_event(event),
+ ManagementInterfaceExit(result) => self.handle_management_interface_exit(result),
+ }
+ }
+
+ fn handle_tunnel_event(&mut self, tunnel_event: TunnelEvent) {
+ info!("Tunnel event: {:?}", tunnel_event);
+ let new_state = match tunnel_event {
+ TunnelEvent::Up => TunnelState::Up,
+ TunnelEvent::Down => TunnelState::Down,
+ };
+ self.set_state(new_state);
+ }
+
+ fn handle_tunnel_exit(&mut self, result: tunnel::Result<()>) -> Result<()> {
+ self.tunnel_close_handle = None;
+ if let Err(e) = result {
+ log_error("Tunnel exited in an unexpected way", e);
+ }
+ self.set_state(TunnelState::NotRunning);
+ self.apply_target_state()
+ }
+
+ fn handle_management_interface_event(&mut self, event: TunnelCommand) -> Result<()> {
+ match event {
+ TunnelCommand::SetTargetState(state) => self.set_target_state(state)?,
+ TunnelCommand::GetState(tx) => {
+ if let Err(_) = tx.send(self.last_broadcasted_state) {
+ warn!("Unable to send current state to management interface client",);
+ }
+ }
+ }
+ Ok(())
+ }
+
+ fn handle_management_interface_exit(&self, result: talpid_ipc::Result<()>) -> Result<()> {
+ let error = ErrorKind::ManagementInterfaceError("Server exited unexpectedly");
+ match result {
+ Ok(()) => Err(error.into()),
+ e => e.chain_err(|| error),
+ }
+ }
+
+ /// Update the state of the client. If it changed, notify the subscribers.
+ fn set_state(&mut self, new_state: TunnelState) {
+ if new_state != self.state {
+ self.state = new_state;
+ let new_security_state = self.state.as_security_state();
+ if self.last_broadcasted_state != new_security_state {
+ self.last_broadcasted_state = new_security_state;
+ self.management_interface_broadcaster.notify_new_state(new_security_state);
+ }
+ }
+ }
+
+ /// Set the target state of the client. If it changed trigger the operations needed to progress
+ /// towards that state.
+ fn set_target_state(&mut self, new_state: TargetState) -> Result<()> {
+ if new_state != self.target_state {
+ self.target_state = new_state;
+ self.apply_target_state()
+ } else {
+ Ok(())
+ }
+ }
-pub mod ipc_api;
-pub mod mock_ipc;
+ fn apply_target_state(&mut self) -> Result<()> {
+ match (self.target_state, self.state) {
+ (TargetState::Secured, TunnelState::NotRunning) => {
+ debug!("Triggering tunnel start");
+ self.start_tunnel()
+ }
+ (TargetState::Unsecured, TunnelState::Down) |
+ (TargetState::Unsecured, TunnelState::Up) => {
+ if let Some(close_handle) = self.tunnel_close_handle.take() {
+ debug!("Triggering tunnel stop");
+ // This close operation will block until the tunnel is dead.
+ close_handle
+ .close()
+ .chain_err(|| ErrorKind::TunnelError("Unable to kill tunnel"))
+ } else {
+ Ok(())
+ }
+ }
+ (target_state, state) => {
+ trace!(
+ "apply_target_state does nothing on TargetState::{:?} TunnelState::{:?}",
+ target_state,
+ state
+ );
+ Ok(())
+ }
+ }
+ }
+
+ fn start_tunnel(&mut self) -> Result<()> {
+ ensure!(
+ self.state == TunnelState::NotRunning,
+ ErrorKind::InvalidState
+ );
+ let remote = self.remote_iter.next().unwrap();
+ let tunnel_monitor = self.spawn_tunnel_monitor(remote)?;
+ self.tunnel_close_handle = Some(tunnel_monitor.close_handle());
+ self.spawn_tunnel_monitor_wait_thread(tunnel_monitor);
+
+ self.set_state(TunnelState::Down);
+ Ok(())
+ }
+
+ fn spawn_tunnel_monitor(&self, remote: RemoteAddr) -> Result<TunnelMonitor> {
+ // Must wrap the channel in a Mutex because TunnelMonitor forces the closure to be Sync
+ let event_tx = Arc::new(Mutex::new(self.tx.clone()));
+ let on_tunnel_event = move |event| {
+ let _ = event_tx.lock().unwrap().send(DaemonEvent::TunnelEvent(event));
+ };
+ TunnelMonitor::new(remote, on_tunnel_event)
+ .chain_err(|| ErrorKind::TunnelError("Unable to start tunnel monitor"))
+ }
+
+ fn spawn_tunnel_monitor_wait_thread(&self, tunnel_monitor: TunnelMonitor) {
+ let error_tx = self.tx.clone();
+ thread::spawn(
+ move || {
+ let result = tunnel_monitor.wait();
+ let _ = error_tx.send(DaemonEvent::TunnelExit(result));
+ trace!("Tunnel monitor thread exit");
+ },
+ );
+ }
+}
+
+
+fn log_error<E>(msg: &str, error: E)
+ where E: error_chain::ChainedError
+{
+ error!("{}: {}", msg, error);
+ for e in error.iter().skip(1) {
+ error!("Caused by {}", e);
+ }
+}
-error_chain!{}
quick_main!(run);
fn run() -> Result<()> {
init_logger()?;
- let server = start_ipc()?;
- info!("Mullvad daemon listening on {}", server.address());
- main_loop(server)
+ let daemon = Daemon::new().chain_err(|| "Unable to initialize daemon")?;
+ daemon.run()?;
+
+ debug!("Mullvad daemon is quitting");
+ Ok(())
}
fn init_logger() -> Result<()> {
env_logger::init().chain_err(|| "Failed to bootstrap logging system")
}
-
-fn start_ipc() -> Result<mock_ipc::IpcServer> {
- mock_ipc::IpcServer::start().chain_err(|| "Failed to start IPC server")
-}
-
-fn main_loop(server: mock_ipc::IpcServer) -> Result<()> {
- server.wait().chain_err(|| "Error while waiting for server to process")
-}
diff --git a/mullvad_daemon/src/states.rs b/mullvad_daemon/src/states.rs
index e50015c53b..10e543c58a 100644
--- a/mullvad_daemon/src/states.rs
+++ b/mullvad_daemon/src/states.rs
@@ -14,7 +14,7 @@ pub enum SecurityState {
/// Represents the state the client strives towards.
/// When in `Secured`, the client should keep the computer from leaking and try to
/// establish a VPN tunnel if it is not up.
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TargetState {
Unsecured,
Secured,
diff --git a/talpid_core/Cargo.toml b/talpid_core/Cargo.toml
index 4b3afa4d80..573cc0b328 100644
--- a/talpid_core/Cargo.toml
+++ b/talpid_core/Cargo.toml
@@ -8,6 +8,7 @@ description = "Core backend functionality of the Mullvad VPN client"
duct = "0.9.1"
error-chain = "0.10"
log = "0.3"
+lazy_static = "0.2"
jsonrpc-core = { git = "https://github.com/faern/jsonrpc", branch = "ws-close-handle" }
jsonrpc-macros = { git = "https://github.com/faern/jsonrpc", branch = "ws-close-handle" }
diff --git a/talpid_core/src/lib.rs b/talpid_core/src/lib.rs
index 8a053bffa8..5496d038ce 100644
--- a/talpid_core/src/lib.rs
+++ b/talpid_core/src/lib.rs
@@ -9,6 +9,8 @@ extern crate assert_matches;
extern crate duct;
#[macro_use]
+extern crate lazy_static;
+#[macro_use]
extern crate log;
#[macro_use]
diff --git a/talpid_core/src/tunnel/mod.rs b/talpid_core/src/tunnel/mod.rs
index 3c955c563d..aead09b13b 100644
--- a/talpid_core/src/tunnel/mod.rs
+++ b/talpid_core/src/tunnel/mod.rs
@@ -90,7 +90,7 @@ pub struct CloseHandle(OpenVpnCloseHandle);
impl CloseHandle {
/// Closes the underlying tunnel, making the `TunnelMonitor::wait` method return.
- pub fn close(&self) -> io::Result<()> {
+ pub fn close(self) -> io::Result<()> {
self.0.close()
}
}
diff --git a/talpid_core/src/tunnel/openvpn.rs b/talpid_core/src/tunnel/openvpn.rs
index cf33484f38..08c2c14a32 100644
--- a/talpid_core/src/tunnel/openvpn.rs
+++ b/talpid_core/src/tunnel/openvpn.rs
@@ -2,14 +2,14 @@ use duct;
use jsonrpc_core::{Error, IoHandler};
use openvpn_ffi::{OpenVpnEnv, OpenVpnPluginEvent};
use process::openvpn::OpenVpnCommand;
-use std::io;
+use std::io;
use std::path::Path;
-use std::process;
use std::result::Result as StdResult;
use std::sync::{Arc, mpsc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
+use std::time::Duration;
use talpid_ipc;
@@ -31,6 +31,11 @@ mod errors {
pub use self::errors::*;
+lazy_static!{
+ static ref OPENVPN_DIE_TIMEOUT: Duration = Duration::from_secs(2);
+}
+
+
/// Struct for monitoring an OpenVPN process.
pub struct OpenVpnMonitor {
child: Arc<duct::Handle>,
@@ -105,7 +110,7 @@ impl OpenVpnMonitor {
/// returned this returns the earliest result.
fn wait_result(&mut self) -> WaitResult {
let child_wait_handle = self.child.clone();
- let child_kill_handle = self.child.clone();
+ let child_close_handle = self.close_handle();
let event_dispatcher = self.event_dispatcher.take().unwrap();
let dispatcher_handle = event_dispatcher.close_handle();
@@ -123,7 +128,7 @@ impl OpenVpnMonitor {
move || {
let result = event_dispatcher.wait();
dispatcher_tx.send(WaitResult::EventDispatcher(result)).unwrap();
- let _ = child_kill_handle.kill();
+ let _ = child_close_handle.close();
},
);
@@ -141,15 +146,28 @@ pub struct OpenVpnCloseHandle {
impl OpenVpnCloseHandle {
/// Kills the underlying OpenVPN process, making the `OpenVpnMonitor::wait` method return.
- pub fn close(&self) -> io::Result<()> {
- self.closed.store(true, Ordering::SeqCst);
+ pub fn close(self) -> io::Result<()> {
+ if !self.closed.swap(true, Ordering::SeqCst) {
+ self.kill_openvpn()
+ } else {
+ Ok(())
+ }
+ }
+
+ #[cfg(unix)]
+ fn kill_openvpn(self) -> io::Result<()> {
+ ::process::unix::nice_kill(self.child, *OPENVPN_DIE_TIMEOUT)
+ }
+
+ #[cfg(not(unix))]
+ fn kill_openvpn(self) -> io::Result<()> {
self.child.kill()
}
}
/// Internal enum to differentiate between if the child process or the event dispatcher died first.
enum WaitResult {
- Child(io::Result<process::ExitStatus>),
+ Child(io::Result<::std::process::ExitStatus>),
EventDispatcher(talpid_ipc::Result<()>),
}