diff options
| -rw-r--r-- | CHANGELOG.md | 4 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/errors.js | 6 | ||||
| -rw-r--r-- | gui/packages/desktop/src/renderer/lib/daemon-rpc.js | 13 | ||||
| -rw-r--r-- | mullvad-daemon/src/main.rs | 134 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 63 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/blocked_state.rs | 3 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/connected_state.rs | 46 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/connecting_state.rs | 44 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/disconnected_state.rs | 7 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/disconnecting_state.rs | 5 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/mod.rs | 4 | ||||
| -rw-r--r-- | talpid-types/src/tunnel.rs | 10 |
12 files changed, 157 insertions, 182 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0796482bc4..c38c6fe367 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,8 +27,8 @@ Line wrap the file at 100 chars. Th - Add option to enable or disable IPv6 on the tunnel interface. - Log panics in the daemon to the log file. - Warn in the Settings screen if a new version is available. -- Enter a "blocked" state in case of connection error, which prevents leaking connections until the - user specifically requests to disconnect. +- Enter a "blocked" state in case of connection error, relay server unavailability or invalid + configuration, which prevents leaking traffic until the user specifically requests to disconnect. - Add support for Ubuntu 14.04 and other distributions that use the Upstart init system. #### Windows diff --git a/gui/packages/desktop/src/renderer/errors.js b/gui/packages/desktop/src/renderer/errors.js index ddf0c239bb..b333f66221 100644 --- a/gui/packages/desktop/src/renderer/errors.js +++ b/gui/packages/desktop/src/renderer/errors.js @@ -11,6 +11,12 @@ export class BlockedError extends Error { case 'start_tunnel_error': super('Failed to start tunnel connection'); break; + case 'no_matching_relay': + super('No relay server matches the current settings'); + break; + case 'no_account_token': + super('No account token configured'); + break; default: super(`Unknown error: ${(reason: empty)}`); } diff --git a/gui/packages/desktop/src/renderer/lib/daemon-rpc.js b/gui/packages/desktop/src/renderer/lib/daemon-rpc.js index ae2e501268..0408017d5a 100644 --- a/gui/packages/desktop/src/renderer/lib/daemon-rpc.js +++ b/gui/packages/desktop/src/renderer/lib/daemon-rpc.js @@ -41,7 +41,11 @@ const LocationSchema = object({ mullvad_exit_ip: boolean, }); -export type BlockReason = 'set_security_policy_error' | 'start_tunnel_error'; +export type BlockReason = + | 'set_security_policy_error' + | 'start_tunnel_error' + | 'no_matching_relay' + | 'no_account_token'; export type DisconnectedState = { state: 'disconnected', }; @@ -218,7 +222,12 @@ const AccountDataSchema = object({ expiry: string, }); -const allBlockReasons: Array<BlockReason> = ['set_security_policy_error', 'start_tunnel_error']; +const allBlockReasons: Array<BlockReason> = [ + 'set_security_policy_error', + 'start_tunnel_error', + 'no_matching_relay', + 'no_account_token', +]; const BlockedStateSchema = object({ state: enumeration('blocked'), details: enumeration(...allBlockReasons), diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs index 4385b3a291..ca9549bf38 100644 --- a/mullvad-daemon/src/main.rs +++ b/mullvad-daemon/src/main.rs @@ -79,8 +79,8 @@ use std::{mem, thread}; use talpid_core::mpsc::IntoSender; use talpid_core::tunnel_state_machine::{self, TunnelCommand, TunnelParameters}; -use talpid_types::net::TunnelOptions; -use talpid_types::tunnel::TunnelStateTransition; +use talpid_types::net::{TunnelEndpoint, TunnelOptions}; +use talpid_types::tunnel::{BlockReason, TunnelStateTransition}; error_chain!{ @@ -99,15 +99,7 @@ error_chain!{ description("Error in the management interface") display("Management interface error: {}", msg) } - InvalidSettings(msg: &'static str) { - description("Invalid settings") - display("Invalid Settings: {}", msg) - } - NoRelay { - description("Found no valid relays to connect to") - } } - links { TunnelError(tunnel_state_machine::Error, tunnel_state_machine::ErrorKind); } @@ -306,7 +298,7 @@ impl Daemon { pub fn run(mut self) -> Result<()> { if self.settings.get_auto_connect() { info!("Automatically connecting since auto-connect is turned on"); - self.set_target_state(TargetState::Secured)?; + self.set_target_state(TargetState::Secured); } while let Ok(event) = self.rx.recv() { self.handle_event(event)?; @@ -355,7 +347,7 @@ impl Daemon { fn handle_management_interface_event(&mut self, event: ManagementCommand) -> Result<()> { use ManagementCommand::*; match event { - SetTargetState(state) => self.on_set_target_state(state), + SetTargetState(state) => Ok(self.on_set_target_state(state)), GetState(tx) => Ok(self.on_get_state(tx)), GetCurrentLocation(tx) => Ok(self.on_get_current_location(tx)), GetAccountData(tx, account_token) => Ok(self.on_get_account_data(tx, account_token)), @@ -379,12 +371,11 @@ impl Daemon { } } - fn on_set_target_state(&mut self, new_target_state: TargetState) -> Result<()> { + fn on_set_target_state(&mut self, new_target_state: TargetState) { if self.state.is_running() { - self.set_target_state(new_target_state) + self.set_target_state(new_target_state); } else { warn!("Ignoring target state change request due to shutdown"); - Ok(()) } } @@ -447,10 +438,10 @@ impl Daemon { if account_changed { if account_token_cleared { info!("Disconnecting because account token was cleared"); - self.set_target_state(TargetState::Unsecured)?; + self.set_target_state(TargetState::Unsecured); } else { info!("Initiating tunnel restart because the account token changed"); - self.reconnect_tunnel()?; + self.reconnect_tunnel(); } } } @@ -499,7 +490,7 @@ impl Daemon { if changed { info!("Initiating tunnel restart because the relay settings changed"); - self.reconnect_tunnel()?; + self.reconnect_tunnel(); } } Err(e) => error!("{}", e.display_chain()), @@ -517,9 +508,7 @@ impl Daemon { match save_result.chain_err(|| "Unable to save settings") { Ok(settings_changed) => { if settings_changed { - self.tunnel_command_tx - .send(TunnelCommand::AllowLan(allow_lan)) - .expect("Tunnel state machine has stopped"); + self.send_tunnel_command(TunnelCommand::AllowLan(allow_lan)); } Self::oneshot_send(tx, (), "set_allow_lan response"); } @@ -575,7 +564,7 @@ impl Daemon { if settings_changed { info!("Initiating tunnel restart because the enable IPv6 setting changed"); - self.reconnect_tunnel()?; + self.reconnect_tunnel(); } } Err(e) => error!("{}", e.display_chain()), @@ -609,84 +598,71 @@ impl Daemon { /// 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<()> { + fn set_target_state(&mut self, new_state: TargetState) { if new_state != self.target_state { debug!("Target state {:?} => {:?}", self.target_state, new_state); self.target_state = new_state; - self.apply_target_state() - } else { - Ok(()) - } - } - - fn apply_target_state(&mut self) -> Result<()> { - match self.target_state { - TargetState::Secured => { - debug!("Triggering tunnel start"); - if let Err(e) = self.connect_tunnel().chain_err(|| "Failed to start tunnel") { - error!("{}", e.display_chain()); - self.current_relay = None; - self.management_interface_broadcaster.notify_error(&e); - self.set_target_state(TargetState::Unsecured)?; - } + match self.target_state { + TargetState::Secured => self.connect_tunnel(), + TargetState::Unsecured => self.disconnect_tunnel(), } - TargetState::Unsecured => self.disconnect_tunnel(), } - - Ok(()) } - fn connect_tunnel(&mut self) -> Result<()> { - let parameters = self.build_tunnel_parameters()?; - - self.tunnel_command_tx - .send(TunnelCommand::Connect(parameters)) - .expect("Tunnel state machine has stopped"); - - Ok(()) + fn connect_tunnel(&mut self) { + let command = match self.settings.get_account_token() { + None => TunnelCommand::Block(BlockReason::NoAccountToken), + Some(account_token) => match self.settings.get_relay_settings() { + RelaySettings::CustomTunnelEndpoint(custom_relay) => custom_relay + .to_tunnel_endpoint() + .chain_err(|| "Custom tunnel endpoint could not be resolved"), + RelaySettings::Normal(constraints) => self + .relay_selector + .get_tunnel_endpoint(&constraints) + .chain_err(|| "No valid relay servers match the current settings") + .map(|(relay, endpoint)| { + self.current_relay = Some(relay); + endpoint + }), + }.map(|endpoint| self.build_tunnel_parameters(account_token, endpoint)) + .map(|parameters| TunnelCommand::Connect(parameters)) + .unwrap_or_else(|error| { + error!("{}", error.display_chain()); + TunnelCommand::Block(BlockReason::NoMatchingRelay) + }), + }; + self.send_tunnel_command(command); } fn disconnect_tunnel(&mut self) { - self.tunnel_command_tx - .send(TunnelCommand::Disconnect) - .expect("Tunnel state machine has stopped"); + self.send_tunnel_command(TunnelCommand::Disconnect); } - fn reconnect_tunnel(&mut self) -> Result<()> { - match self.target_state { - TargetState::Secured => self.connect_tunnel(), - TargetState::Unsecured => Ok(()), + fn reconnect_tunnel(&mut self) { + if self.target_state == TargetState::Secured { + self.connect_tunnel() } } - fn build_tunnel_parameters(&mut self) -> Result<TunnelParameters> { - let endpoint = match self.settings.get_relay_settings() { - RelaySettings::CustomTunnelEndpoint(custom_relay) => custom_relay - .to_tunnel_endpoint() - .chain_err(|| ErrorKind::NoRelay)?, - RelaySettings::Normal(constraints) => { - let (relay, tunnel_endpoint) = self - .relay_selector - .get_tunnel_endpoint(&constraints) - .chain_err(|| ErrorKind::NoRelay)?; - self.current_relay = Some(relay); - tunnel_endpoint - } - }; - - let account_token = self - .settings - .get_account_token() - .ok_or(ErrorKind::InvalidSettings("No account token"))?; - - Ok(TunnelParameters { + fn build_tunnel_parameters( + &self, + account_token: AccountToken, + endpoint: TunnelEndpoint, + ) -> TunnelParameters { + TunnelParameters { endpoint, options: self.settings.get_tunnel_options().clone(), log_dir: self.log_dir.clone(), resource_dir: self.resource_dir.clone(), username: account_token, allow_lan: self.settings.get_allow_lan(), - }) + } + } + + fn send_tunnel_command(&mut self, command: TunnelCommand) { + self.tunnel_command_tx + .send(command) + .expect("Tunnel state machine has stopped"); } pub fn shutdown_handle(&self) -> DaemonShutdownHandle { diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index 79f74989ff..a873a39463 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -1,5 +1,3 @@ -use error_chain; - use error_chain::ChainedError; use jsonrpc_core::futures::sync::oneshot::Sender as OneshotSender; use jsonrpc_core::futures::{future, sync, Future}; @@ -17,8 +15,6 @@ use mullvad_types::relay_list::RelayList; use mullvad_types::states::TargetState; use mullvad_types::version; -use serde; - use std::collections::hash_map::Entry; use std::collections::HashMap; use std::path::PathBuf; @@ -153,16 +149,6 @@ build_rpc_trait! { #[rpc(name = "new_state_unsubscribe")] fn new_state_unsubscribe(&self, SubscriptionId) -> BoxFuture<(), Error>; } - - #[pubsub(name = "error")] { - /// Subscribes to the `error` event notifications. - #[rpc(name = "error_subscribe")] - fn error_subscribe(&self, Self::Metadata, pubsub::Subscriber<Vec<String>>); - - /// Unsubscribes from the `error` event notifications. - #[rpc(name = "error_unsubscribe")] - fn error_unsubscribe(&self, SubscriptionId) -> BoxFuture<(), Error>; - } } } @@ -212,15 +198,9 @@ pub enum ManagementCommand { Shutdown, } -#[derive(Default)] -struct ActiveSubscriptions { - new_state_subscriptions: RwLock<HashMap<SubscriptionId, pubsub::Sink<TunnelStateTransition>>>, - error_subscriptions: RwLock<HashMap<SubscriptionId, pubsub::Sink<Vec<String>>>>, -} - pub struct ManagementInterfaceServer { server: talpid_ipc::IpcServer, - subscriptions: Arc<ActiveSubscriptions>, + subscriptions: Arc<RwLock<HashMap<SubscriptionId, pubsub::Sink<TunnelStateTransition>>>>, } impl ManagementInterfaceServer { @@ -268,41 +248,22 @@ impl ManagementInterfaceServer { /// A handle that allows broadcasting messages to all subscribers of the management interface. pub struct EventBroadcaster { - subscriptions: Arc<ActiveSubscriptions>, + subscriptions: Arc<RwLock<HashMap<SubscriptionId, pubsub::Sink<TunnelStateTransition>>>>, } impl EventBroadcaster { /// Sends a new state update to all `new_state` subscribers of the management interface. pub fn notify_new_state(&self, new_state: TunnelStateTransition) { debug!("Broadcasting new state to listeners: {:?}", new_state); - self.notify(&self.subscriptions.new_state_subscriptions, new_state); - } - - /// Sends an error to all `error` subscribers of the management interface. - pub fn notify_error<E>(&self, error: &E) - where - E: error_chain::ChainedError, - { - let error_strings = error.iter().map(|e| e.to_string()).collect(); - self.notify(&self.subscriptions.error_subscriptions, error_strings); - } - - fn notify<T>( - &self, - subscriptions_lock: &RwLock<HashMap<SubscriptionId, pubsub::Sink<T>>>, - value: T, - ) where - T: serde::Serialize + Clone, - { - let subscriptions = subscriptions_lock.read().unwrap(); + let subscriptions = self.subscriptions.read().unwrap(); for sink in subscriptions.values() { - let _ = sink.notify(Ok(value.clone())).wait(); + let _ = sink.notify(Ok(new_state.clone())).wait(); } } } struct ManagementInterface<T: From<ManagementCommand> + 'static + Send> { - subscriptions: Arc<ActiveSubscriptions>, + subscriptions: Arc<RwLock<HashMap<SubscriptionId, pubsub::Sink<TunnelStateTransition>>>>, tx: Mutex<IntoSender<ManagementCommand, T>>, cache_dir: PathBuf, } @@ -644,22 +605,12 @@ impl<T: From<ManagementCommand> + 'static + Send> ManagementInterfaceApi subscriber: pubsub::Subscriber<TunnelStateTransition>, ) { trace!("new_state_subscribe"); - Self::subscribe(subscriber, &self.subscriptions.new_state_subscriptions); + Self::subscribe(subscriber, &self.subscriptions); } fn new_state_unsubscribe(&self, id: SubscriptionId) -> BoxFuture<(), Error> { trace!("new_state_unsubscribe"); - Self::unsubscribe(id, &self.subscriptions.new_state_subscriptions) - } - - fn error_subscribe(&self, _: Self::Metadata, subscriber: pubsub::Subscriber<Vec<String>>) { - trace!("error_subscribe"); - Self::subscribe(subscriber, &self.subscriptions.error_subscriptions); - } - - fn error_unsubscribe(&self, id: SubscriptionId) -> BoxFuture<(), Error> { - trace!("error_unsubscribe"); - Self::unsubscribe(id, &self.subscriptions.error_subscriptions) + Self::unsubscribe(id, &self.subscriptions) } } diff --git a/talpid-core/src/tunnel_state_machine/blocked_state.rs b/talpid-core/src/tunnel_state_machine/blocked_state.rs index f63326b800..50efb9e371 100644 --- a/talpid-core/src/tunnel_state_machine/blocked_state.rs +++ b/talpid-core/src/tunnel_state_machine/blocked_state.rs @@ -38,6 +38,9 @@ impl TunnelState for BlockedState { Ok(TunnelCommand::Disconnect) | Err(_) => { NewState(DisconnectedState::enter(shared_values, ())) } + Ok(TunnelCommand::Block(reason)) => { + NewState(BlockedState::enter(shared_values, reason)) + } _ => SameState(self), } } diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs index 02a44c8be0..0117958503 100644 --- a/talpid-core/src/tunnel_state_machine/connected_state.rs +++ b/talpid-core/src/tunnel_state_machine/connected_state.rs @@ -66,6 +66,25 @@ impl ConnectedState { use self::EventConsequence::*; match try_handle_event!(self, commands.poll()) { + Ok(TunnelCommand::AllowLan(allow_lan)) => { + self.tunnel_parameters.allow_lan = allow_lan; + + match self.set_security_policy(shared_values) { + Ok(()) => SameState(self), + Err(error) => { + error!("{}", error.display_chain()); + + NewState(DisconnectingState::enter( + shared_values, + ( + self.close_handle, + self.tunnel_close_event, + AfterDisconnect::Block(BlockReason::SetSecurityPolicyError), + ), + )) + } + } + } Ok(TunnelCommand::Connect(parameters)) => { if parameters != self.tunnel_parameters { NewState(DisconnectingState::enter( @@ -88,25 +107,14 @@ impl ConnectedState { AfterDisconnect::Nothing, ), )), - Ok(TunnelCommand::AllowLan(allow_lan)) => { - self.tunnel_parameters.allow_lan = allow_lan; - - match self.set_security_policy(shared_values) { - Ok(()) => SameState(self), - Err(error) => { - error!("{}", error.display_chain()); - - NewState(DisconnectingState::enter( - shared_values, - ( - self.close_handle, - self.tunnel_close_event, - AfterDisconnect::Block(BlockReason::SetSecurityPolicyError), - ), - )) - } - } - } + Ok(TunnelCommand::Block(reason)) => NewState(DisconnectingState::enter( + shared_values, + ( + self.close_handle, + self.tunnel_close_event, + AfterDisconnect::Block(reason), + ), + )), } } diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs index a87fa1384e..184832acaa 100644 --- a/talpid-core/src/tunnel_state_machine/connecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs @@ -175,6 +175,24 @@ impl ConnectingState { use self::EventConsequence::*; match try_handle_event!(self, commands.poll()) { + Ok(TunnelCommand::AllowLan(allow_lan)) => { + self.tunnel_parameters.allow_lan = allow_lan; + match Self::set_security_policy(shared_values, self.tunnel_endpoint, allow_lan) { + Ok(()) => SameState(self), + Err(error) => { + error!("{}", error.display_chain()); + + NewState(DisconnectingState::enter( + shared_values, + ( + self.close_handle, + self.tunnel_close_event, + AfterDisconnect::Block(BlockReason::SetSecurityPolicyError), + ), + )) + } + } + } Ok(TunnelCommand::Connect(parameters)) => { if parameters != self.tunnel_parameters { NewState(DisconnectingState::enter( @@ -197,24 +215,14 @@ impl ConnectingState { AfterDisconnect::Nothing, ), )), - Ok(TunnelCommand::AllowLan(allow_lan)) => { - self.tunnel_parameters.allow_lan = allow_lan; - match Self::set_security_policy(shared_values, self.tunnel_endpoint, allow_lan) { - Ok(()) => SameState(self), - Err(error) => { - error!("{}", error.display_chain()); - - NewState(DisconnectingState::enter( - shared_values, - ( - self.close_handle, - self.tunnel_close_event, - AfterDisconnect::Block(BlockReason::SetSecurityPolicyError), - ), - )) - } - } - } + Ok(TunnelCommand::Block(reason)) => NewState(DisconnectingState::enter( + shared_values, + ( + self.close_handle, + self.tunnel_close_event, + AfterDisconnect::Block(reason), + ), + )), } } diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs index f92630606c..80a7eb5ce0 100644 --- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs @@ -3,8 +3,8 @@ use futures::sync::mpsc; use futures::Stream; use super::{ - ConnectingState, Error, EventConsequence, SharedTunnelStateValues, TunnelCommand, TunnelState, - TunnelStateTransition, TunnelStateWrapper, + BlockedState, ConnectingState, Error, EventConsequence, SharedTunnelStateValues, TunnelCommand, + TunnelState, TunnelStateTransition, TunnelStateWrapper, }; use security::NetworkSecurity; @@ -47,6 +47,9 @@ impl TunnelState for DisconnectedState { Ok(TunnelCommand::Connect(parameters)) => { NewState(ConnectingState::enter(shared_values, parameters)) } + Ok(TunnelCommand::Block(reason)) => { + NewState(BlockedState::enter(shared_values, reason)) + } Ok(_) => SameState(self), Err(_) => Finished, } diff --git a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs index 6fbdacffe2..452b8d3ac1 100644 --- a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs @@ -33,20 +33,23 @@ impl DisconnectingState { self.after_disconnect = match after_disconnect { AfterDisconnect::Nothing => match event { Ok(TunnelCommand::Connect(parameters)) => Reconnect(parameters), + Ok(TunnelCommand::Block(reason)) => Block(reason), _ => Nothing, }, AfterDisconnect::Block(reason) => match event { Ok(TunnelCommand::Connect(parameters)) => Reconnect(parameters), Ok(TunnelCommand::Disconnect) => Nothing, + Ok(TunnelCommand::Block(new_reason)) => Block(new_reason), _ => AfterDisconnect::Block(reason), }, AfterDisconnect::Reconnect(mut tunnel_parameters) => match event { - Ok(TunnelCommand::Connect(parameters)) => Reconnect(parameters), Ok(TunnelCommand::AllowLan(allow_lan)) => { tunnel_parameters.allow_lan = allow_lan; Reconnect(tunnel_parameters) } + Ok(TunnelCommand::Connect(parameters)) => Reconnect(parameters), Ok(TunnelCommand::Disconnect) | Err(_) => Nothing, + Ok(TunnelCommand::Block(reason)) => Block(reason), }, }; diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs index 20f1529b01..433333efa0 100644 --- a/talpid-core/src/tunnel_state_machine/mod.rs +++ b/talpid-core/src/tunnel_state_machine/mod.rs @@ -18,7 +18,7 @@ use futures::{Async, Future, Poll, Stream}; use tokio_core::reactor::Core; use talpid_types::net::{TunnelEndpoint, TunnelOptions}; -use talpid_types::tunnel::TunnelStateTransition; +use talpid_types::tunnel::{BlockReason, TunnelStateTransition}; use self::blocked_state::BlockedState; use self::connected_state::{ConnectedState, ConnectedStateBootstrap}; @@ -110,6 +110,8 @@ pub enum TunnelCommand { Connect(TunnelParameters), /// Close tunnel connection. Disconnect, + /// Disconnect any open tunnel and block all network access + Block(BlockReason), } /// Information necessary to open a tunnel. diff --git a/talpid-types/src/tunnel.rs b/talpid-types/src/tunnel.rs index e5454988c5..77a1ffacb5 100644 --- a/talpid-types/src/tunnel.rs +++ b/talpid-types/src/tunnel.rs @@ -21,10 +21,14 @@ pub enum TunnelStateTransition { #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum BlockReason { - /// Failed to set security policy + /// Failed to set security policy. SetSecurityPolicyError, - /// Failed to start connection to remote server + /// Failed to start connection to remote server. StartTunnelError, + /// No relay server matching the current filter parameters. + NoMatchingRelay, + /// No account token configured. + NoAccountToken, } impl fmt::Display for BlockReason { @@ -32,6 +36,8 @@ impl fmt::Display for BlockReason { let description = match *self { BlockReason::SetSecurityPolicyError => "Failed to set security policy", BlockReason::StartTunnelError => "Failed to start connection to remote server", + BlockReason::NoMatchingRelay => "No relay server matches the current settings", + BlockReason::NoAccountToken => "No account token configured", }; write!(formatter, "{}", description) |
