diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2016-12-06 23:42:22 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2016-12-06 23:42:22 +0100 |
| commit | 876441779e8bdb64abe7822969a822db81f5c7ac (patch) | |
| tree | 84d85d3371e13e6dc8dcbafc5970f204f6435c05 /src | |
| parent | 22da2098045bdf69a178eb7e4eaaaf38989235af (diff) | |
| parent | 532fb722fef76a501643f63ebc3eec4734050d25 (diff) | |
| download | mullvadvpn-876441779e8bdb64abe7822969a822db81f5c7ac.tar.xz mullvadvpn-876441779e8bdb64abe7822969a822db81f5c7ac.zip | |
Merge branch 'add-remotes'
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 3 | ||||
| -rw-r--r-- | src/net.rs | 40 | ||||
| -rw-r--r-- | src/process.rs | 61 |
3 files changed, 101 insertions, 3 deletions
diff --git a/src/lib.rs b/src/lib.rs index fec2e1da5e..c65c221aec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,9 @@ /// Working with processes. pub mod process; +/// Network primitives. +pub mod net; + #[cfg(test)] mod tests { #[test] diff --git a/src/net.rs b/src/net.rs new file mode 100644 index 0000000000..0906426f7b --- /dev/null +++ b/src/net.rs @@ -0,0 +1,40 @@ +/// Representation of a TCP or UDP endpoint. The host is represented as a String since it can be +/// both a hostname/domain as well as an IP. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RemoteAddr { + address: String, + port: u16, +} + +impl RemoteAddr { + /// Constructs a new `RemoteAddr` from the given address and port. + pub fn new(address: &str, port: u16) -> Self { + RemoteAddr { + address: address.to_owned(), + port: port, + } + } + + /// Returns the address associated with this `RemoteAddr`. + pub fn address(&self) -> &str { + &self.address + } + + /// Returns the port associated with this `RemoteAddr`. + pub fn port(&self) -> u16 { + self.port + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn remote_addr_new_and_getters() { + let remote_addr = RemoteAddr::new("a_domain", 543); + assert_eq!("a_domain", remote_addr.address()); + assert_eq!(543, remote_addr.port()); + } +} diff --git a/src/process.rs b/src/process.rs index 7143b85eb3..eb372de04e 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,3 +1,5 @@ +use net::RemoteAddr; + use std::ffi::{OsString, OsStr}; use std::io; use std::path::{Path, PathBuf}; @@ -8,6 +10,7 @@ use std::process::{Command, Child, Stdio}; pub struct OpenVpnBuilder { openvpn_bin: OsString, config: Option<PathBuf>, + remotes: Vec<RemoteAddr>, } impl OpenVpnBuilder { @@ -17,6 +20,7 @@ impl OpenVpnBuilder { OpenVpnBuilder { openvpn_bin: OsString::from(openvpn_bin.as_ref()), config: None, + remotes: vec![], } } @@ -26,10 +30,17 @@ impl OpenVpnBuilder { self } + /// Sets the addresses that OpenVPN will connect to. See OpenVPN documentation for how multiple + /// remotes are handled. + pub fn remotes(&mut self, remotes: Vec<RemoteAddr>) -> &mut Self { + self.remotes = remotes; + self + } + /// Executes the OpenVPN process as a child process, returning a handle to it. pub fn spawn(&mut self) -> io::Result<Child> { let mut command = self.create_command(); - self.apply_settings(&mut command); + command.args(&self.get_arguments()); command.spawn() } @@ -42,9 +53,53 @@ impl OpenVpnBuilder { command } - fn apply_settings(&self, command: &mut Command) { + /// Returns all arguments that the subprocess would be spawned with. + pub fn get_arguments(&self) -> Vec<OsString> { + let mut args = vec![]; if let Some(ref config) = self.config { - command.arg("--config").arg(config); + args.push(OsString::from("--config")); + args.push(OsString::from(config.as_os_str())); + } + for remote in &self.remotes { + args.push(OsString::from("--remote")); + args.push(OsString::from(remote.address())); + args.push(OsString::from(remote.port().to_string())); } + args + } +} + +#[cfg(test)] +mod tests { + use net::RemoteAddr; + use std::ffi::OsString; + use super::OpenVpnBuilder; + + #[test] + fn no_arguments() { + let args = OpenVpnBuilder::new("").get_arguments(); + assert_eq!(0, args.len()); + } + + #[test] + fn passes_one_remote() { + let remotes = vec![RemoteAddr::new("example.com", 3333)]; + + let args = OpenVpnBuilder::new("").remotes(remotes).get_arguments(); + + assert!(args.contains(&OsString::from("example.com"))); + assert!(args.contains(&OsString::from("3333"))); + } + + #[test] + fn passes_two_remotes() { + let remotes = vec![RemoteAddr::new("127.0.0.1", 998), RemoteAddr::new("fe80::1", 1337)]; + + let args = OpenVpnBuilder::new("").remotes(remotes).get_arguments(); + + assert!(args.contains(&OsString::from("127.0.0.1"))); + assert!(args.contains(&OsString::from("998"))); + assert!(args.contains(&OsString::from("fe80::1"))); + assert!(args.contains(&OsString::from("1337"))); } } |
