diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-11-16 12:18:29 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-11-17 10:27:28 +0100 |
| commit | a9dd7f675b07d34b82aeba1f78dee1a8c68a851d (patch) | |
| tree | 67199f99f1809c6a0539d781fc1bd885d5c5eec3 | |
| parent | 25ffbf5c9b9c942b0d0b13d896f7bdd2acec2341 (diff) | |
| download | mullvadvpn-a9dd7f675b07d34b82aeba1f78dee1a8c68a851d.tar.xz mullvadvpn-a9dd7f675b07d34b82aeba1f78dee1a8c68a851d.zip | |
Use new relay constraints and relay selector
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | mullvad-daemon/Cargo.toml | 1 | ||||
| -rw-r--r-- | mullvad-daemon/src/main.rs | 214 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 91 |
4 files changed, 169 insertions, 138 deletions
diff --git a/Cargo.lock b/Cargo.lock index 717f93bddc..69ceab80f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,6 +691,7 @@ dependencies = [ "talpid-core 0.1.0", "talpid-ipc 0.1.0", "talpid-types 0.1.0", + "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/mullvad-daemon/Cargo.toml b/mullvad-daemon/Cargo.toml index 7971054df0..cb2f66d279 100644 --- a/mullvad-daemon/Cargo.toml +++ b/mullvad-daemon/Cargo.toml @@ -32,6 +32,7 @@ jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc", tag = "v7.1 uuid = { version = "0.5", features = ["v4"] } lazy_static = "0.2" rand = "0.3" +tokio-timer = "0.1" mullvad-types = { path = "../mullvad-types" } mullvad-rpc = { path = "../mullvad-rpc" } diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs index b5ec71b2a3..d2c21ce0c3 100644 --- a/mullvad-daemon/src/main.rs +++ b/mullvad-daemon/src/main.rs @@ -20,6 +20,7 @@ extern crate log; extern crate serde; #[macro_use] extern crate serde_derive; +extern crate serde_json; extern crate jsonrpc_core; #[macro_use] @@ -29,6 +30,7 @@ extern crate jsonrpc_ws_server; #[macro_use] extern crate lazy_static; extern crate rand; +extern crate tokio_timer; extern crate uuid; extern crate mullvad_rpc; @@ -39,28 +41,31 @@ extern crate talpid_types; mod cli; mod management_interface; +mod relays; mod rpc_info; mod settings; mod shutdown; mod account_history; + use app_dirs::AppInfo; use error_chain::ChainedError; use futures::Future; use jsonrpc_core::futures::sync::oneshot::Sender as OneshotSender; + use management_interface::{BoxFuture, ManagementInterfaceServer, TunnelCommand}; use mullvad_rpc::{AccountsProxy, HttpHandle}; -use mullvad_types::CustomTunnelEndpoint; + use mullvad_types::account::{AccountData, AccountToken}; -use mullvad_types::relay_constraints::{Constraint, OpenVpnConstraints, RelayConstraints, - RelayConstraintsUpdate, TunnelConstraints}; +use mullvad_types::location::Location; +use mullvad_types::relay_constraints::{RelaySettings, RelaySettingsUpdate}; +use mullvad_types::relay_list::{Relay, RelayList}; use mullvad_types::states::{DaemonState, SecurityState, TargetState}; -use rand::Rng; use std::env; use std::io; -use std::net::Ipv4Addr; -use std::path::PathBuf; +use std::net::{IpAddr, Ipv4Addr}; +use std::path::{Path, PathBuf}; use std::sync::{mpsc, Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; @@ -68,13 +73,8 @@ use std::time::{Duration, Instant}; use talpid_core::firewall::{Firewall, FirewallProxy, SecurityPolicy}; use talpid_core::mpsc::IntoSender; use talpid_core::tunnel::{self, TunnelEvent, TunnelMetadata, TunnelMonitor}; -use talpid_types::net::{Endpoint, OpenVpnParameters, TransportProtocol, TunnelEndpoint, - TunnelParameters}; +use talpid_types::net::TunnelEndpoint; -pub static APP_INFO: AppInfo = AppInfo { - name: ::CRATE_NAME, - author: "Mullvad", -}; error_chain!{ errors { @@ -105,20 +105,18 @@ error_chain!{ } lazy_static! { - // Temporary store of hardcoded relays. - static ref RELAYS: [Endpoint; 3] = [ - // se2.mullvad.net - Endpoint::new(Ipv4Addr::new(185, 213, 152, 132), 1300, TransportProtocol::Udp), - // se5.mullvad.net - Endpoint::new(Ipv4Addr::new(193, 138, 218, 135), 1300, TransportProtocol::Udp), - // se23.mullvad.net - Endpoint::new(Ipv4Addr::new(185, 65, 135, 143), 1300, TransportProtocol::Udp), - ]; static ref MIN_TUNNEL_ALIVE_TIME_MS: Duration = Duration::from_millis(1000); + static ref MAX_RELAY_CACHE_AGE: Duration = Duration::from_secs(3600); + static ref RELAY_CACHE_UPDATE_TIMEOUT: Duration = Duration::from_millis(3000); } const CRATE_NAME: &str = "mullvadd"; +static APP_INFO: AppInfo = AppInfo { + name: CRATE_NAME, + author: "Mullvad", +}; + const DATE_TIME_FORMAT_STR: &str = "%Y-%m-%d %H:%M:%S%.3f"; @@ -188,24 +186,26 @@ struct Daemon { management_interface_broadcaster: management_interface::EventBroadcaster, settings: settings::Settings, accounts_proxy: AccountsProxy<HttpHandle>, + relay_selector: relays::RelaySelector, firewall: FirewallProxy, - relay_endpoint: Option<TunnelEndpoint>, + current_relay: Option<Relay>, + tunnel_endpoint: Option<TunnelEndpoint>, tunnel_metadata: Option<TunnelMetadata>, tunnel_log: Option<PathBuf>, - - // Just for testing. A cyclic iterator iterating over the hardcoded relays, - // picking a new one for each retry. - relay_iter: std::iter::Cycle<std::iter::Cloned<std::slice::Iter<'static, Endpoint>>>, resource_dir: PathBuf, } impl Daemon { pub fn new(tunnel_log: Option<PathBuf>) -> Result<Self> { + let resource_dir = get_resource_dir(); + let rpc_http_handle = mullvad_rpc::connect().chain_err(|| "Unable to connect to RPC API")?; + + let relay_selector = Self::create_relay_selector(rpc_http_handle.clone(), &resource_dir)?; + let (tx, rx) = mpsc::channel(); let management_interface_broadcaster = Self::start_management_interface(tx.clone())?; let state = TunnelState::NotRunning; let target_state = TargetState::Unsecured; - let resource_dir = get_resource_dir(); Ok(Daemon { state, tunnel_close_handle: None, @@ -219,16 +219,33 @@ impl Daemon { tx, management_interface_broadcaster, settings: settings::Settings::load().chain_err(|| "Unable to read settings")?, - accounts_proxy: AccountsProxy::connect().chain_err(|| "Unable to connect RPC client")?, + accounts_proxy: AccountsProxy::new(rpc_http_handle), + relay_selector, firewall: FirewallProxy::new().chain_err(|| ErrorKind::FirewallError)?, - relay_endpoint: None, + current_relay: None, + tunnel_endpoint: None, tunnel_metadata: None, tunnel_log: tunnel_log, - relay_iter: RELAYS.iter().cloned().cycle(), resource_dir, }) } + fn create_relay_selector( + rpc_http_handle: mullvad_rpc::HttpHandle, + resource_dir: &Path, + ) -> Result<relays::RelaySelector> { + let mut relay_selector = relays::RelaySelector::new(rpc_http_handle, &resource_dir) + .chain_err(|| "Unable to initialize relay list cache")?; + if let Ok(elapsed) = relay_selector.get_last_updated().elapsed() { + if elapsed > *MAX_RELAY_CACHE_AGE { + if let Err(e) = relay_selector.update(*RELAY_CACHE_UPDATE_TIMEOUT) { + error!("Unable to update relay cache: {}", e.display_chain()); + } + } + } + Ok(relay_selector) + } + // 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( @@ -314,7 +331,8 @@ impl Daemon { if let Err(e) = result.chain_err(|| "Tunnel exited in an unexpected way") { error!("{}", e.display_chain()); } - self.relay_endpoint = None; + self.current_relay = None; + self.tunnel_endpoint = None; self.tunnel_metadata = None; self.tunnel_close_handle = None; self.set_state(TunnelState::NotRunning) @@ -329,13 +347,14 @@ impl Daemon { match event { SetTargetState(state) => self.on_set_target_state(state), GetState(tx) => Ok(self.on_get_state(tx)), + GetIp(tx) => Ok(self.on_get_ip(tx)), + GetCurrentLocation(tx) => Ok(self.on_get_current_location(tx)), GetAccountData(tx, account_token) => Ok(self.on_get_account_data(tx, account_token)), + GetRelayLocations(tx) => Ok(self.on_get_relay_locations(tx)), SetAccount(tx, account_token) => self.on_set_account(tx, account_token), GetAccount(tx) => Ok(self.on_get_account(tx)), - UpdateRelayConstraints(tx, constraints_update) => { - self.on_update_relay_constraints(tx, constraints_update) - } - GetRelayConstraints(tx) => Ok(self.on_get_relay_constraints(tx)), + UpdateRelaySettings(tx, update) => self.on_update_relay_settings(tx, update), + GetRelaySettings(tx) => Ok(self.on_get_relay_settings(tx)), Shutdown => self.handle_trigger_shutdown_event(), } } @@ -353,6 +372,30 @@ impl Daemon { Self::oneshot_send(tx, self.last_broadcasted_state, "current state"); } + fn on_get_ip(&self, tx: OneshotSender<IpAddr>) { + let ip = if let Some(ref relay) = self.current_relay { + IpAddr::V4(relay.ipv4_addr_exit) + } else { + IpAddr::V4(Ipv4Addr::new(1, 3, 3, 7)) + }; + Self::oneshot_send(tx, ip, "current ip"); + } + + fn on_get_current_location(&self, tx: OneshotSender<Location>) { + let location = if let Some(ref relay) = self.current_relay { + relay.location.as_ref().cloned().unwrap() + } else { + Location { + country: String::from("Narnia"), + country_code: String::from("na"), + city: String::from("Le City"), + city_code: String::from("le"), + position: [13.37, 0.0], + } + }; + Self::oneshot_send(tx, location, "current location"); + } + fn on_get_account_data( &mut self, tx: OneshotSender<BoxFuture<AccountData, mullvad_rpc::Error>>, @@ -364,6 +407,14 @@ impl Daemon { Self::oneshot_send(tx, Box::new(rpc_call), "account data") } + fn on_get_relay_locations(&mut self, tx: OneshotSender<RelayList>) { + Self::oneshot_send( + tx, + self.relay_selector.get_locations().clone(), + "relay locations", + ); + } + fn on_set_account( &mut self, @@ -391,22 +442,22 @@ impl Daemon { Self::oneshot_send(tx, self.settings.get_account_token(), "current account") } - fn on_update_relay_constraints( + fn on_update_relay_settings( &mut self, tx: OneshotSender<()>, - constraints: RelayConstraintsUpdate, + update: RelaySettingsUpdate, ) -> Result<()> { - let save_result = self.settings.update_relay_constraints(constraints); + let save_result = self.settings.update_relay_settings(update); match save_result.chain_err(|| "Unable to save settings") { - Ok(constraints_changed) => { - Self::oneshot_send(tx, (), "update_relay_constraints response"); + Ok(changed) => { + Self::oneshot_send(tx, (), "update_relay_settings response"); let tunnel_needs_restart = self.state == TunnelState::Connecting || self.state == TunnelState::Connected; - if constraints_changed && tunnel_needs_restart { - info!("Initiating tunnel restart because the relay constraints changed"); + if changed && tunnel_needs_restart { + info!("Initiating tunnel restart because the relay settings changed"); self.kill_tunnel()?; } } @@ -416,12 +467,8 @@ impl Daemon { Ok(()) } - fn on_get_relay_constraints(&self, tx: OneshotSender<RelayConstraints>) { - Self::oneshot_send( - tx, - self.settings.get_relay_constraints(), - "relay constraints", - ) + fn on_get_relay_settings(&self, tx: OneshotSender<RelaySettings>) { + Self::oneshot_send(tx, self.settings.get_relay_settings(), "relay settings") } fn oneshot_send<T>(tx: OneshotSender<T>, t: T, msg: &'static str) { @@ -505,7 +552,8 @@ impl Daemon { debug!("Triggering tunnel start"); if let Err(e) = self.start_tunnel().chain_err(|| "Failed to start tunnel") { error!("{}", e.display_chain()); - self.relay_endpoint = None; + self.current_relay = None; + self.tunnel_endpoint = None; self.management_interface_broadcaster.notify_error(&e); self.set_target_state(TargetState::Unsecured)?; } @@ -524,16 +572,30 @@ impl Daemon { ErrorKind::InvalidState ); - let relay_endpoint = self.get_relay().chain_err(|| ErrorKind::NoRelay)?; + match self.settings.get_relay_settings() { + RelaySettings::CustomTunnelEndpoint(custom_relay) => { + let tunnel_endpoint = custom_relay + .to_tunnel_endpoint() + .chain_err(|| ErrorKind::NoRelay)?; + self.tunnel_endpoint = Some(tunnel_endpoint); + } + RelaySettings::Normal(constraints) => { + let (relay, tunnel_endpoint) = self.relay_selector + .get_tunnel_endpoint(&constraints) + .chain_err(|| ErrorKind::NoRelay)?; + self.tunnel_endpoint = Some(tunnel_endpoint); + self.current_relay = Some(relay); + } + } let account_token = self.settings .get_account_token() .ok_or(ErrorKind::InvalidSettings("No account token"))?; - self.relay_endpoint = Some(relay_endpoint); self.set_security_policy()?; - let tunnel_monitor = self.spawn_tunnel_monitor(relay_endpoint, &account_token)?; + let tunnel_monitor = + self.spawn_tunnel_monitor(self.tunnel_endpoint.unwrap(), &account_token)?; self.tunnel_close_handle = Some(tunnel_monitor.close_handle()); self.spawn_tunnel_monitor_wait_thread(tunnel_monitor); @@ -541,40 +603,6 @@ impl Daemon { Ok(()) } - fn get_relay(&mut self) -> Result<TunnelEndpoint> { - let relay_constraints = self.settings.get_relay_constraints(); - - let host = match relay_constraints.host { - Constraint::Any => format!("{}", self.relay_iter.next().unwrap().address.ip()), - Constraint::Only(host) => host, - }; - - match relay_constraints.tunnel { - TunnelConstraints::OpenVpn(constraints) => self.get_openvpn_relay(host, constraints), - } - } - - fn get_openvpn_relay( - &mut self, - host: String, - constraints: OpenVpnConstraints, - ) -> Result<TunnelEndpoint> { - let protocol = match constraints.protocol { - Constraint::Any => TransportProtocol::Udp, - Constraint::Only(protocol) => protocol, - }; - let port = match constraints.port { - Constraint::Any => randomize_port(protocol), - Constraint::Only(port) => port, - }; - - CustomTunnelEndpoint { - host, - tunnel: TunnelParameters::OpenVpn(OpenVpnParameters { port, protocol }), - }.to_tunnel_endpoint() - .chain_err(|| "Unable to construct a valid relay") - } - fn spawn_tunnel_monitor( &self, tunnel_endpoint: TunnelEndpoint, @@ -633,7 +661,7 @@ impl Daemon { } fn set_security_policy(&mut self) -> Result<()> { - let policy = match (self.relay_endpoint, self.tunnel_metadata.as_ref()) { + let policy = match (self.tunnel_endpoint, self.tunnel_metadata.as_ref()) { (Some(relay), None) => SecurityPolicy::Connecting(relay.to_endpoint()), (Some(relay), Some(tunnel_metadata)) => { SecurityPolicy::Connected(relay.to_endpoint(), tunnel_metadata.clone()) @@ -736,18 +764,6 @@ fn log_version() { ) } -fn randomize_port(protocol: TransportProtocol) -> u16 { - let pool: Vec<u16> = if protocol == TransportProtocol::Udp { - vec![1194, 1195, 1196, 1197, 1300, 1301, 1302] - } else { - vec![80, 443] - }; - - *rand::thread_rng() - .choose(&pool) - .expect("no ports to randomize from") -} - fn get_resource_dir() -> PathBuf { match env::current_exe() { Ok(mut path) => { diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index 95e5c99833..f0cfac7fd7 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -9,16 +9,17 @@ use jsonrpc_pubsub::{PubSubHandler, PubSubMetadata, Session, SubscriptionId}; use jsonrpc_ws_server; use mullvad_rpc; use mullvad_types::account::{AccountData, AccountToken}; -use mullvad_types::location::{CountryCode, Location}; +use mullvad_types::location::Location; -use mullvad_types::relay_constraints::{RelayConstraints, RelayConstraintsUpdate}; +use mullvad_types::relay_constraints::{RelaySettings, RelaySettingsUpdate}; +use mullvad_types::relay_list::RelayList; use mullvad_types::states::{DaemonState, TargetState}; use serde; use std::collections::HashMap; use std::collections::hash_map::Entry; -use std::net::{IpAddr, Ipv4Addr}; +use std::net::IpAddr; use std::sync::{Arc, Mutex, RwLock}; use std::sync::atomic::{AtomicBool, Ordering}; use talpid_core::mpsc::IntoSender; @@ -47,8 +48,8 @@ build_rpc_trait! { fn get_account_data(&self, Self::Metadata, AccountToken) -> BoxFuture<AccountData, Error>; /// Returns available countries. - #[rpc(name = "get_countries")] - fn get_countries(&self) -> Result<HashMap<CountryCode, String>, Error>; + #[rpc(meta, name = "get_relay_locations")] + fn get_relay_locations(&self, Self::Metadata) -> BoxFuture<RelayList, Error>; /// Set which account to connect with. #[rpc(meta, name = "set_account")] @@ -59,18 +60,18 @@ build_rpc_trait! { fn get_account(&self, Self::Metadata) -> BoxFuture<Option<AccountToken>, Error>; /// Update constraints put on the type of tunnel connection to use - #[rpc(meta, name = "update_relay_constraints")] - fn update_relay_constraints( + #[rpc(meta, name = "update_relay_settings")] + fn update_relay_settings( &self, - Self::Metadata, RelayConstraintsUpdate + Self::Metadata, RelaySettingsUpdate ) -> BoxFuture<(), Error>; /// Update constraints put on the type of tunnel connection to use - #[rpc(meta, name = "get_relay_constraints")] - fn get_relay_constraints( + #[rpc(meta, name = "get_relay_settings")] + fn get_relay_settings( &self, Self::Metadata - ) -> BoxFuture<RelayConstraints, Error>; + ) -> BoxFuture<RelaySettings, Error>; /// Set if the client should automatically establish a tunnel on start or not. #[rpc(meta, name = "set_autoconnect")] @@ -91,13 +92,13 @@ build_rpc_trait! { fn get_state(&self, Self::Metadata) -> BoxFuture<DaemonState, Error>; /// Returns the current public IP of this computer. - #[rpc(name = "get_ip")] - fn get_ip(&self) -> Result<IpAddr, Error>; + #[rpc(meta, name = "get_public_ip")] + fn get_public_ip(&self, Self::Metadata) -> BoxFuture<IpAddr, Error>; /// Performs a geoIP lookup and returns the current location as perceived by the public /// internet. - #[rpc(name = "get_location")] - fn get_location(&self) -> Result<Location, Error>; + #[rpc(meta, name = "get_current_location")] + fn get_current_location(&self, Self::Metadata) -> BoxFuture<Location, Error>; /// Makes the daemon exit its main loop and quit. #[rpc(meta, name = "shutdown")] @@ -140,19 +141,25 @@ pub enum TunnelCommand { SetTargetState(TargetState), /// Request the current state. GetState(OneshotSender<DaemonState>), + /// Get the current IP as viewed from the internet. + GetIp(OneshotSender<IpAddr>), + /// Get the current geographical location. + GetCurrentLocation(OneshotSender<Location>), /// Request the metadata for an account. GetAccountData( OneshotSender<BoxFuture<AccountData, mullvad_rpc::Error>>, AccountToken, ), + /// Get the list of countries and cities where there are relays. + GetRelayLocations(OneshotSender<RelayList>), /// Set which account token to use for subsequent connection attempts. SetAccount(OneshotSender<()>, Option<AccountToken>), /// Request the current account token being used. GetAccount(OneshotSender<Option<AccountToken>>), /// Place constraints on the type of tunnel and relay - UpdateRelayConstraints(OneshotSender<()>, RelayConstraintsUpdate), + UpdateRelaySettings(OneshotSender<()>, RelaySettingsUpdate), /// Read the constraints put on the tunnel and relay - GetRelayConstraints(OneshotSender<RelayConstraints>), + GetRelaySettings(OneshotSender<RelaySettings>), /// Makes the daemon exit the main loop and quit. Shutdown, } @@ -373,9 +380,13 @@ impl<T: From<TunnelCommand> + 'static + Send> ManagementInterfaceApi for Managem Box::new(future) } - fn get_countries(&self) -> Result<HashMap<CountryCode, String>, Error> { - trace!("get_countries"); - Ok(HashMap::new()) + fn get_relay_locations(&self, meta: Self::Metadata) -> BoxFuture<RelayList, Error> { + trace!("get_relay_locations"); + try_future!(self.check_auth(&meta)); + let (tx, rx) = sync::oneshot::channel(); + let future = self.send_command_to_daemon(TunnelCommand::GetRelayLocations(tx)) + .and_then(|_| rx.map_err(|_| Error::internal_error())); + Box::new(future) } fn set_account( @@ -413,26 +424,26 @@ impl<T: From<TunnelCommand> + 'static + Send> ManagementInterfaceApi for Managem Box::new(future) } - fn update_relay_constraints( + fn update_relay_settings( &self, meta: Self::Metadata, - constraints_update: RelayConstraintsUpdate, + constraints_update: RelaySettingsUpdate, ) -> BoxFuture<(), Error> { - trace!("update_relay_constraints"); + trace!("update_relay_settings"); try_future!(self.check_auth(&meta)); let (tx, rx) = sync::oneshot::channel(); - let message = TunnelCommand::UpdateRelayConstraints(tx, constraints_update); + let message = TunnelCommand::UpdateRelaySettings(tx, constraints_update); let future = self.send_command_to_daemon(message) .and_then(|_| rx.map_err(|_| Error::internal_error())); Box::new(future) } - fn get_relay_constraints(&self, meta: Self::Metadata) -> BoxFuture<RelayConstraints, Error> { - trace!("get_relay_constraints"); + fn get_relay_settings(&self, meta: Self::Metadata) -> BoxFuture<RelaySettings, Error> { + trace!("get_relay_settings"); try_future!(self.check_auth(&meta)); let (tx, rx) = sync::oneshot::channel(); - let future = self.send_command_to_daemon(TunnelCommand::GetRelayConstraints(tx)) + let future = self.send_command_to_daemon(TunnelCommand::GetRelaySettings(tx)) .and_then(|_| rx.map_err(|_| Error::internal_error())); Box::new(future) } @@ -464,20 +475,22 @@ impl<T: From<TunnelCommand> + 'static + Send> ManagementInterfaceApi for Managem Box::new(future) } - fn get_ip(&self) -> Result<IpAddr, Error> { - trace!("get_ip"); - Ok(IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4))) + fn get_public_ip(&self, meta: Self::Metadata) -> BoxFuture<IpAddr, Error> { + trace!("get_public_ip"); + try_future!(self.check_auth(&meta)); + let (tx, rx) = sync::oneshot::channel(); + let future = self.send_command_to_daemon(TunnelCommand::GetIp(tx)) + .and_then(|_| rx.map_err(|_| Error::internal_error())); + Box::new(future) } - fn get_location(&self) -> Result<Location, Error> { - trace!("get_location"); - Ok(Location { - country: String::from("narnia"), - country_code: String::from("na"), - city: String::from("Le city"), - city_code: String::from("le"), - position: [1.0, 2.0], - }) + fn get_current_location(&self, meta: Self::Metadata) -> BoxFuture<Location, Error> { + trace!("get_current_location"); + try_future!(self.check_auth(&meta)); + let (tx, rx) = sync::oneshot::channel(); + let future = self.send_command_to_daemon(TunnelCommand::GetCurrentLocation(tx)) + .and_then(|_| rx.map_err(|_| Error::internal_error())); + Box::new(future) } fn shutdown(&self, meta: Self::Metadata) -> BoxFuture<(), Error> { |
