summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2018-09-04 17:41:06 +0200
committerLinus Färnstrand <linus@mullvad.net>2018-09-04 17:41:06 +0200
commitf645f381b95e458680ca6d64ce0d810fbe579d12 (patch)
tree917e3a92683618229178f22b8324b0fb54b27e52
parentc6cafc54057981d4794ef417a3c9b5a5265eddd3 (diff)
parent297cd3c8ec92a5802cbedd9cd0d98419b2e96246 (diff)
downloadmullvadvpn-f645f381b95e458680ca6d64ce0d810fbe579d12.tar.xz
mullvadvpn-f645f381b95e458680ca6d64ce0d810fbe579d12.zip
Merge branch 'no-relays-block'
-rw-r--r--CHANGELOG.md4
-rw-r--r--gui/packages/desktop/src/renderer/errors.js6
-rw-r--r--gui/packages/desktop/src/renderer/lib/daemon-rpc.js13
-rw-r--r--mullvad-daemon/src/main.rs134
-rw-r--r--mullvad-daemon/src/management_interface.rs63
-rw-r--r--talpid-core/src/tunnel_state_machine/blocked_state.rs3
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs46
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs44
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnected_state.rs7
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnecting_state.rs5
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs4
-rw-r--r--talpid-types/src/tunnel.rs10
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)