diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-05-19 08:03:55 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-05-19 08:03:55 +0200 |
| commit | 5a29ec07f4d0bc41da0b64435ff156ff37e88c22 (patch) | |
| tree | d406200f56af2118901d657b7efa26886fed3e38 | |
| parent | 2f2c5b853ab376948e61e9f371cc724ac07ab5bb (diff) | |
| parent | 927888f8767f814f98c666af854ba03a09909897 (diff) | |
| download | mullvadvpn-5a29ec07f4d0bc41da0b64435ff156ff37e88c22.tar.xz mullvadvpn-5a29ec07f4d0bc41da0b64435ff156ff37e88c22.zip | |
Merge branch 'openvpn-event-dispatcher'
| -rw-r--r-- | Cargo.lock | 14 | ||||
| -rw-r--r-- | openvpn_ffi/src/lib.rs | 5 | ||||
| -rw-r--r-- | openvpn_ffi/src/parse.rs | 2 | ||||
| -rw-r--r-- | talpid_core/Cargo.toml | 2 | ||||
| -rw-r--r-- | talpid_core/src/lib.rs | 7 | ||||
| -rw-r--r-- | talpid_core/src/process/openvpn.rs | 3 | ||||
| -rw-r--r-- | talpid_core/src/tunnel/mod.rs | 2 | ||||
| -rw-r--r-- | talpid_core/src/tunnel/openvpn.rs | 79 |
8 files changed, 105 insertions, 9 deletions
diff --git a/Cargo.lock b/Cargo.lock index abbcc79fb3..e6c6467ec7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,7 +218,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=bind-zero#098cbc458d3f53b0ffa6a044674cf4379ec77ba2" +source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#6d4061524f7760347dd04fb49e7471eaac26e976" 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)", @@ -230,7 +230,7 @@ dependencies = [ [[package]] name = "jsonrpc-macros" version = "7.0.0" -source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#098cbc458d3f53b0ffa6a044674cf4379ec77ba2" +source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#6d4061524f7760347dd04fb49e7471eaac26e976" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=bind-zero)", "jsonrpc-pubsub 7.0.0 (git+https://github.com/faern/jsonrpc?branch=bind-zero)", @@ -240,7 +240,7 @@ dependencies = [ [[package]] name = "jsonrpc-pubsub" version = "7.0.0" -source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#098cbc458d3f53b0ffa6a044674cf4379ec77ba2" +source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#6d4061524f7760347dd04fb49e7471eaac26e976" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=bind-zero)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "jsonrpc-server-utils" version = "7.0.0" -source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#098cbc458d3f53b0ffa6a044674cf4379ec77ba2" +source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#6d4061524f7760347dd04fb49e7471eaac26e976" 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=bind-zero)", @@ -262,7 +262,7 @@ dependencies = [ [[package]] name = "jsonrpc-ws-server" version = "7.0.0" -source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#098cbc458d3f53b0ffa6a044674cf4379ec77ba2" +source = "git+https://github.com/faern/jsonrpc?branch=bind-zero#6d4061524f7760347dd04fb49e7471eaac26e976" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/faern/jsonrpc?branch=bind-zero)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/faern/jsonrpc?branch=bind-zero)", @@ -595,6 +595,8 @@ dependencies = [ "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "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=bind-zero)", + "jsonrpc-macros 7.0.0 (git+https://github.com/faern/jsonrpc?branch=bind-zero)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "openvpn_ffi 0.1.0", "talpid_ipc 0.1.0", @@ -745,7 +747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" version = "0.7.1" -source = "git+https://github.com/faern/ws-rs?branch=arbitrary-handshake-responses#3a8c5ae37e0ff5aab4c0ad656a160eb0bf78f5c1" +source = "git+https://github.com/faern/ws-rs?branch=arbitrary-handshake-responses#25fba2181064f987a748ca90d65c604ffcc86dd6" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/openvpn_ffi/src/lib.rs b/openvpn_ffi/src/lib.rs index 00e0d58031..934eb091df 100644 --- a/openvpn_ffi/src/lib.rs +++ b/openvpn_ffi/src/lib.rs @@ -12,6 +12,7 @@ extern crate serde_derive; extern crate assert_matches; +use std::collections::HashMap; use std::os::raw::c_int; mod structs; @@ -29,6 +30,10 @@ error_chain!{ } +/// Type definition for environment variables from OpenVPN +pub type OpenVpnEnv = HashMap<String, String>; + + // Return values. Returned from the plugin to OpenVPN to indicate success or failure. Can also // Accept (success) or decline (error) an operation, such as incoming client connection attempt. pub const OPENVPN_PLUGIN_FUNC_SUCCESS: c_int = 0; diff --git a/openvpn_ffi/src/parse.rs b/openvpn_ffi/src/parse.rs index 787883fd70..6d0c42c06f 100644 --- a/openvpn_ffi/src/parse.rs +++ b/openvpn_ffi/src/parse.rs @@ -52,7 +52,7 @@ pub unsafe fn string_array(mut ptr: *const *const c_char) -> Result<Vec<String>> /// # Segfaults /// /// Uses `string_array` internally and will segfault for the same reasons as that function. -pub unsafe fn env(envptr: *const *const c_char) -> Result<HashMap<String, String>> { +pub unsafe fn env(envptr: *const *const c_char) -> Result<::OpenVpnEnv> { let mut map = HashMap::new(); for string in string_array(envptr)? { let mut iter = string.splitn(2, '='); diff --git a/talpid_core/Cargo.toml b/talpid_core/Cargo.toml index c098d204d9..18c998cf93 100644 --- a/talpid_core/Cargo.toml +++ b/talpid_core/Cargo.toml @@ -8,6 +8,8 @@ description = "Core backend functionality of the Mullvad VPN client" duct = "0.8" error-chain = "0.10" log = "0.3" +jsonrpc-core = { git = "https://github.com/faern/jsonrpc", branch = "bind-zero" } +jsonrpc-macros = { git = "https://github.com/faern/jsonrpc", branch = "bind-zero" } [dependencies.talpid_ipc] path = "../talpid_ipc" diff --git a/talpid_core/src/lib.rs b/talpid_core/src/lib.rs index 1a10532787..8a053bffa8 100644 --- a/talpid_core/src/lib.rs +++ b/talpid_core/src/lib.rs @@ -13,11 +13,18 @@ extern crate log; #[macro_use] extern crate error_chain; +extern crate jsonrpc_core; +#[macro_use] +extern crate jsonrpc_macros; extern crate talpid_ipc; +extern crate openvpn_ffi; /// Working with processes. pub mod process; /// Network primitives. pub mod net; + +/// Abstracts over different VPN tunnel technologies +pub mod tunnel; diff --git a/talpid_core/src/process/openvpn.rs b/talpid_core/src/process/openvpn.rs index d565b085a8..5d40d8e42c 100644 --- a/talpid_core/src/process/openvpn.rs +++ b/talpid_core/src/process/openvpn.rs @@ -6,7 +6,6 @@ use duct; use net::{RemoteAddr, ToRemoteAddrs}; -use std::collections::HashMap; use std::ffi::{OsStr, OsString}; use std::fmt; use std::io; @@ -127,7 +126,7 @@ fn write_argument(fmt: &mut fmt::Formatter, arg: &str) -> fmt::Result { /// Possible events from OpenVPN pub enum OpenVpnEvent { /// An event from the plugin loaded into OpenVPN. - PluginEvent(talpid_ipc::Result<(openvpn_ffi::OpenVpnPluginEvent, HashMap<String, String>)>), + PluginEvent(talpid_ipc::Result<(openvpn_ffi::OpenVpnPluginEvent, openvpn_ffi::OpenVpnEnv)>), /// The OpenVPN process exited. Containing the result of waiting for the process. Shutdown(io::Result<process::ExitStatus>), } diff --git a/talpid_core/src/tunnel/mod.rs b/talpid_core/src/tunnel/mod.rs new file mode 100644 index 0000000000..0b477ca1c4 --- /dev/null +++ b/talpid_core/src/tunnel/mod.rs @@ -0,0 +1,2 @@ +/// A module for all OpenVPN related tunnel management. +pub mod openvpn; diff --git a/talpid_core/src/tunnel/openvpn.rs b/talpid_core/src/tunnel/openvpn.rs new file mode 100644 index 0000000000..35361bb1fd --- /dev/null +++ b/talpid_core/src/tunnel/openvpn.rs @@ -0,0 +1,79 @@ +use jsonrpc_core::{Error, IoHandler}; +use openvpn_ffi::{OpenVpnEnv, OpenVpnPluginEvent}; + +use talpid_ipc; + +/// IPC server for listening to events coming from plugin loaded into OpenVPN. +pub struct OpenVpnEventDispatcher { + server: talpid_ipc::IpcServer, +} + +impl OpenVpnEventDispatcher { + /// Construct and start the IPC server with the given event listener callback. + pub fn start<L>(on_event: L) -> talpid_ipc::Result<Self> + where L: Fn(OpenVpnPluginEvent, OpenVpnEnv) + Send + Sync + 'static + { + let rpc = OpenVpnEventApiImpl { on_event }; + let mut io = IoHandler::new(); + io.extend_with(rpc.to_delegate()); + let server = talpid_ipc::IpcServer::start(io.into())?; + Ok(OpenVpnEventDispatcher { server }) + } + + /// Returns the local address this server is listening on. + pub fn address(&self) -> &str { + self.server.address() + } + + /// Consumes the server and waits for it to finish. + pub fn wait(self) -> talpid_ipc::Result<()> { + self.server.wait() + } +} + + +mod api { + use super::*; + build_rpc_trait! { + pub trait OpenVpnEventApi { + #[rpc(name = "openvpn_event")] + fn openvpn_event(&self, OpenVpnPluginEvent, OpenVpnEnv) -> Result<(), Error>; + } + } +} +use self::api::*; + +struct OpenVpnEventApiImpl<L> + where L: Fn(OpenVpnPluginEvent, OpenVpnEnv) + Send + Sync + 'static +{ + on_event: L, +} + +impl<L> OpenVpnEventApi for OpenVpnEventApiImpl<L> + where L: Fn(OpenVpnPluginEvent, OpenVpnEnv) + Send + Sync + 'static +{ + fn openvpn_event(&self, event: OpenVpnPluginEvent, env: OpenVpnEnv) -> Result<(), Error> { + debug!("OpenVPN event {:?}", event); + (self.on_event)(event, env); + Ok(()) + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[ignore] + fn openvpn_event_dispatcher_server() { + let server = OpenVpnEventDispatcher::start( + |event, env| { + println!("event: {:?}. env: {:?}", event, env); + }, + ) + .unwrap(); + println!("plugin server listening on {}", server.address()); + server.wait().unwrap(); + } +} |
