summaryrefslogtreecommitdiffhomepage
path: root/talpid_core
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-05-23 15:40:48 +0200
committerLinus Färnstrand <linus@mullvad.net>2017-05-23 15:40:48 +0200
commitc2aaa4eb26af015ef949785668751cded783675d (patch)
tree63c1c854c8349400d6c50b01784053de00381e38 /talpid_core
parent54754e78fa41244f661bf76d921b35edeb6b9be8 (diff)
parentb642c63dc281746cef24a59aa01f9d30ce441ca9 (diff)
downloadmullvadvpn-c2aaa4eb26af015ef949785668751cded783675d.tar.xz
mullvadvpn-c2aaa4eb26af015ef949785668751cded783675d.zip
Merge branch 'tunnel-monitor'
Diffstat (limited to 'talpid_core')
-rw-r--r--talpid_core/src/tunnel/mod.rs104
-rw-r--r--talpid_core/src/tunnel/openvpn.rs1
2 files changed, 105 insertions, 0 deletions
diff --git a/talpid_core/src/tunnel/mod.rs b/talpid_core/src/tunnel/mod.rs
index 0b477ca1c4..c453c52056 100644
--- a/talpid_core/src/tunnel/mod.rs
+++ b/talpid_core/src/tunnel/mod.rs
@@ -1,2 +1,106 @@
+use net;
+use openvpn_ffi::OpenVpnPluginEvent;
+use process::openvpn::OpenVpnCommand;
+
/// A module for all OpenVPN related tunnel management.
pub mod openvpn;
+
+use self::openvpn::{OpenVpnEvent, OpenVpnMonitor};
+
+mod errors {
+ error_chain!{
+ errors {
+ /// An error indicating there was an error listening for events from the VPN tunnel.
+ TunnelMonitoringError {
+ description("Error while setting up or processing events from the VPN tunnel")
+ }
+ /// An error indicating that there was an error when trying to start up a VPN tunnel.
+ TunnelStartError {
+ description("Error while trying to start the tunnel")
+ }
+ }
+ }
+}
+pub use self::errors::*;
+
+
+/// Possible events from the VPN tunnel and the child process managing it.
+pub enum TunnelEvent {
+ /// Sent when the tunnel comes up and is ready for traffic.
+ Up,
+ /// Sent when the tunnel goes down.
+ Down,
+ /// Sent when the process managing the tunnel exits.
+ Shutdown,
+}
+
+impl TunnelEvent {
+ /// Converts an `OpenVpnEvent` to a `TunnelEvent`.
+ /// Returns `None` if there is no corresponding `TunnelEvent`.
+ pub fn from_openvpn_event(event: &OpenVpnEvent) -> Option<TunnelEvent> {
+ match *event {
+ OpenVpnEvent::PluginEvent(ref event, _) => Self::from_openvpn_plugin_event(event),
+ OpenVpnEvent::Shutdown(_) => Some(TunnelEvent::Shutdown),
+ }
+ }
+
+ fn from_openvpn_plugin_event(event: &OpenVpnPluginEvent) -> Option<TunnelEvent> {
+ match *event {
+ OpenVpnPluginEvent::Up => Some(TunnelEvent::Up),
+ OpenVpnPluginEvent::RoutePredown => Some(TunnelEvent::Down),
+ _ => None,
+ }
+ }
+}
+
+
+/// Abstraction for monitoring a generic VPN tunnel.
+pub struct TunnelMonitor {
+ monitor: OpenVpnMonitor,
+}
+
+impl TunnelMonitor {
+ /// Creates a new `TunnelMonitor` with the given event callback.
+ pub fn new<L>(on_event: L) -> Result<Self>
+ where L: Fn(TunnelEvent) + Send + Sync + 'static
+ {
+ let on_openvpn_event = move |openvpn_event| {
+ // FIXME: This comment must be here to make rustfmt 0.8.3 not screw up.
+ match TunnelEvent::from_openvpn_event(&openvpn_event) {
+ Some(tunnel_event) => on_event(tunnel_event),
+ None => debug!("Ignoring OpenVpnEvent {:?}", openvpn_event),
+ }
+ };
+ let monitor = openvpn::OpenVpnMonitor::new(on_openvpn_event, get_plugin_path())
+ .chain_err(|| ErrorKind::TunnelMonitoringError)?;
+ Ok(TunnelMonitor { monitor })
+ }
+
+ /// Tries to start a VPN tunnel towards the given address. Will fail if there is a tunnel
+ /// running already.
+ pub fn start(&self, remote: net::RemoteAddr) -> Result<()> {
+ let mut cmd = OpenVpnCommand::new("openvpn");
+ cmd.config(get_config_path()).remotes(remote).unwrap();
+ self.monitor.start(cmd).chain_err(|| ErrorKind::TunnelStartError)
+ }
+}
+
+
+// TODO(linus): Temporary implementation for getting plugin path during development.
+fn get_plugin_path() -> &'static str {
+ if cfg!(all(unix, not(target_os = "macos"))) {
+ "./target/debug/libtalpid_openvpn_plugin.so"
+ } else if cfg!(target_os = "macos") {
+ "./target/debug/libtalpid_openvpn_plugin.dylib"
+ } else if cfg!(windows) {
+ "./target/debug/libtalpid_openvpn_plugin.dll"
+ } else {
+ panic!("Unsupported platform");
+ }
+}
+
+// TODO(linus): Temporary implementation for getting hold of a config location.
+// Manually place a working config here or change this string in order to test
+fn get_config_path() -> &'static str {
+ "./openvpn.conf"
+}
diff --git a/talpid_core/src/tunnel/openvpn.rs b/talpid_core/src/tunnel/openvpn.rs
index bcf89e3eb0..9d366ebb4a 100644
--- a/talpid_core/src/tunnel/openvpn.rs
+++ b/talpid_core/src/tunnel/openvpn.rs
@@ -33,6 +33,7 @@ pub use self::errors::*;
/// Possible events from OpenVPN
+#[derive(Debug)]
pub enum OpenVpnEvent {
/// An event from the plugin loaded into OpenVPN.
PluginEvent(openvpn_ffi::OpenVpnPluginEvent, openvpn_ffi::OpenVpnEnv),