diff options
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 26 | ||||
| -rw-r--r-- | mullvad-types/src/states.rs | 10 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/connected_state.rs | 18 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/connecting_state.rs | 36 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/disconnected_state.rs | 6 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/disconnecting_state.rs | 20 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/error_state.rs (renamed from talpid-core/src/tunnel_state_machine/blocked_state.rs) | 45 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/mod.rs | 12 | ||||
| -rw-r--r-- | talpid-types/src/tunnel.rs | 41 |
9 files changed, 125 insertions, 89 deletions
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index e78649ac63..aabcbb6952 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -64,7 +64,7 @@ use talpid_core::{ use talpid_types::android::AndroidContext; use talpid_types::{ net::{openvpn, TransportProtocol, TunnelParameters}, - tunnel::{BlockReason, ParameterGenerationError, TunnelStateTransition}, + tunnel::{ErrorStateCause, ParameterGenerationError, TunnelStateTransition}, ErrorExt, }; @@ -565,7 +565,7 @@ where TunnelStateTransition::Disconnecting(after_disconnect) => { TunnelState::Disconnecting(after_disconnect) } - TunnelStateTransition::Blocked(reason) => TunnelState::Blocked(reason.clone()), + TunnelStateTransition::Error(error_state) => TunnelState::Error(error_state.clone()), }; self.unschedule_reconnect(); @@ -573,10 +573,20 @@ where debug!("New tunnel state: {:?}", tunnel_state); match tunnel_state { TunnelState::Disconnected => self.state.disconnected(), - TunnelState::Blocked(ref reason) => { - info!("Blocking all network connections, reason: {}", reason); + TunnelState::Error(ref error_state) => { + if error_state.is_blocking() { + info!( + "Blocking all network connections, reason: {}", + error_state.cause() + ); + } else { + error!( + "FAILED TO BLOCK NETWORK CONNECTIONS, ENTERED ERROR STATE BECAUSE: {}", + error_state.cause() + ); + } - if let BlockReason::AuthFailed(_) = reason { + if let ErrorStateCause::AuthFailed(_) = error_state.cause() { self.schedule_reconnect(Duration::from_secs(60)) } } @@ -925,7 +935,7 @@ where } fn on_reconnect(&mut self) { - if self.target_state == TargetState::Secured || self.tunnel_state.is_blocked() { + if self.target_state == TargetState::Secured || self.tunnel_state.is_in_error_state() { self.connect_tunnel(); } else { debug!("Ignoring reconnect command. Currently not in secured state"); @@ -955,7 +965,7 @@ where .map(Some), ) } - Blocked(..) => { + Error(..) => { // We are not online at all at this stage so no location data is available. Box::new(future::result(Ok(None))) } @@ -1485,7 +1495,7 @@ where /// progress towards that state. /// Returns an error if trying to set secured state, but no account token is present. fn set_target_state(&mut self, new_state: TargetState) { - if new_state != self.target_state || self.tunnel_state.is_blocked() { + if new_state != self.target_state || self.tunnel_state.is_in_error_state() { debug!("Target state {:?} => {:?}", self.target_state, new_state); self.target_state = new_state; match self.target_state { diff --git a/mullvad-types/src/states.rs b/mullvad-types/src/states.rs index e905f329c5..805210a7aa 100644 --- a/mullvad-types/src/states.rs +++ b/mullvad-types/src/states.rs @@ -4,7 +4,7 @@ use jnix::IntoJava; use serde::{Deserialize, Serialize}; use talpid_types::{ net::TunnelEndpoint, - tunnel::{ActionAfterDisconnect, BlockReason}, + tunnel::{ActionAfterDisconnect, ErrorState}, }; /// Represents the state the client strives towards. @@ -34,14 +34,14 @@ pub enum TunnelState { location: Option<GeoIpLocation>, }, Disconnecting(ActionAfterDisconnect), - Blocked(BlockReason), + Error(ErrorState), } impl TunnelState { - /// Returns true if the tunnel state is the blocked state. - pub fn is_blocked(&self) -> bool { + /// Returns true if the tunnel state is in the error state. + pub fn is_in_error_state(&self) -> bool { match self { - TunnelState::Blocked(_) => true, + TunnelState::Error(_) => true, _ => false, } } diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs index fd26b20bc3..3ce80db030 100644 --- a/talpid-core/src/tunnel_state_machine/connected_state.rs +++ b/talpid-core/src/tunnel_state_machine/connected_state.rs @@ -1,5 +1,5 @@ use super::{ - AfterDisconnect, BlockedState, ConnectingState, DisconnectingState, EventConsequence, + AfterDisconnect, ConnectingState, DisconnectingState, ErrorState, EventConsequence, SharedTunnelStateValues, TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper, }; use crate::{ @@ -12,7 +12,7 @@ use futures::{ }; use talpid_types::{ net::{Endpoint, TunnelParameters}, - tunnel::BlockReason, + tunnel::ErrorStateCause, ErrorExt, }; @@ -20,7 +20,7 @@ pub struct ConnectedStateBootstrap { pub metadata: TunnelMetadata, pub tunnel_events: mpsc::UnboundedReceiver<TunnelEvent>, pub tunnel_parameters: TunnelParameters, - pub tunnel_close_event: Option<oneshot::Receiver<Option<BlockReason>>>, + pub tunnel_close_event: Option<oneshot::Receiver<Option<ErrorStateCause>>>, pub close_handle: Option<CloseHandle>, } @@ -29,7 +29,7 @@ pub struct ConnectedState { metadata: TunnelMetadata, tunnel_events: mpsc::UnboundedReceiver<TunnelEvent>, tunnel_parameters: TunnelParameters, - tunnel_close_event: Option<oneshot::Receiver<Option<BlockReason>>>, + tunnel_close_event: Option<oneshot::Receiver<Option<ErrorStateCause>>>, close_handle: Option<CloseHandle>, } @@ -123,7 +123,7 @@ impl ConnectedState { ); self.disconnect( shared_values, - AfterDisconnect::Block(BlockReason::SetFirewallPolicyError), + AfterDisconnect::Block(ErrorStateCause::SetFirewallPolicyError), ) } } @@ -137,7 +137,7 @@ impl ConnectedState { if is_offline { self.disconnect( shared_values, - AfterDisconnect::Block(BlockReason::IsOffline), + AfterDisconnect::Block(ErrorStateCause::IsOffline), ) } else { SameState(self) @@ -183,7 +183,7 @@ impl ConnectedState { match poll_result { Ok(Async::Ready(block_reason)) => { if let Some(reason) = block_reason { - return NewState(BlockedState::enter(shared_values, reason)); + return NewState(ErrorState::enter(shared_values, reason)); } } Ok(Async::NotReady) => return NoEvents(self), @@ -217,7 +217,7 @@ impl TunnelState for ConnectedState { ( connected_state.close_handle, connected_state.tunnel_close_event, - AfterDisconnect::Block(BlockReason::SetFirewallPolicyError), + AfterDisconnect::Block(ErrorStateCause::SetFirewallPolicyError), ), ) } else if let Err(error) = connected_state.set_dns(shared_values) { @@ -230,7 +230,7 @@ impl TunnelState for ConnectedState { ( connected_state.close_handle, connected_state.tunnel_close_event, - AfterDisconnect::Block(BlockReason::SetDnsError), + AfterDisconnect::Block(ErrorStateCause::SetDnsError), ), ) } else { diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs index 67036ea98e..01e39b0ebc 100644 --- a/talpid-core/src/tunnel_state_machine/connecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs @@ -1,5 +1,5 @@ use super::{ - AfterDisconnect, BlockedState, ConnectedState, ConnectedStateBootstrap, DisconnectingState, + AfterDisconnect, ConnectedState, ConnectedStateBootstrap, DisconnectingState, ErrorState, EventConsequence, SharedTunnelStateValues, TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper, }; @@ -22,7 +22,7 @@ use std::{ }; use talpid_types::{ net::{openvpn, TunnelParameters}, - tunnel::BlockReason, + tunnel::ErrorStateCause, ErrorExt, }; @@ -34,7 +34,7 @@ const MIN_TUNNEL_ALIVE_TIME: Duration = Duration::from_millis(1000); pub struct ConnectingState { tunnel_events: mpsc::UnboundedReceiver<TunnelEvent>, tunnel_parameters: TunnelParameters, - tunnel_close_event: Option<oneshot::Receiver<Option<BlockReason>>>, + tunnel_close_event: Option<oneshot::Receiver<Option<ErrorStateCause>>>, close_handle: Option<CloseHandle>, retry_attempt: u32, } @@ -92,7 +92,7 @@ impl ConnectingState { fn spawn_tunnel_monitor_wait_thread( tunnel_monitor: TunnelMonitor, - ) -> Option<oneshot::Receiver<Option<BlockReason>>> { + ) -> Option<oneshot::Receiver<Option<ErrorStateCause>>> { let (tunnel_close_event_tx, tunnel_close_event_rx) = oneshot::channel(); thread::spawn(move || { @@ -120,7 +120,7 @@ impl ConnectingState { Some(tunnel_close_event_rx) } - fn wait_for_tunnel_monitor(tunnel_monitor: TunnelMonitor) -> Option<BlockReason> { + fn wait_for_tunnel_monitor(tunnel_monitor: TunnelMonitor) -> Option<ErrorStateCause> { match tunnel_monitor.wait() { Ok(_) => None, Err(error) => match error { @@ -135,7 +135,7 @@ impl ConnectingState { "{}", error.display_chain_with_msg("TAP adapter problem detected") ); - Some(BlockReason::TapAdapterProblem) + Some(ErrorStateCause::TapAdapterProblem) } error => { warn!( @@ -183,7 +183,7 @@ impl ConnectingState { ( self.close_handle, self.tunnel_close_event, - AfterDisconnect::Block(BlockReason::SetFirewallPolicyError), + AfterDisconnect::Block(ErrorStateCause::SetFirewallPolicyError), ), )) } @@ -201,7 +201,7 @@ impl ConnectingState { ( self.close_handle, self.tunnel_close_event, - AfterDisconnect::Block(BlockReason::IsOffline), + AfterDisconnect::Block(ErrorStateCause::IsOffline), ), )) } else { @@ -248,7 +248,7 @@ impl ConnectingState { ( self.close_handle, self.tunnel_close_event, - AfterDisconnect::Block(BlockReason::AuthFailed(reason)), + AfterDisconnect::Block(ErrorStateCause::AuthFailed(reason)), ), )), Ok(TunnelEvent::Up(metadata)) => NewState(ConnectedState::enter( @@ -282,7 +282,7 @@ impl ConnectingState { match poll_result { Ok(Async::Ready(block_reason)) => { if let Some(reason) = block_reason { - return EventConsequence::NewState(BlockedState::enter(shared_values, reason)); + return EventConsequence::NewState(ErrorState::enter(shared_values, reason)); } } Ok(Async::NotReady) => return EventConsequence::NoEvents(self), @@ -333,13 +333,15 @@ impl TunnelState for ConnectingState { retry_attempt: u32, ) -> (TunnelStateWrapper, TunnelStateTransition) { if shared_values.is_offline { - return BlockedState::enter(shared_values, BlockReason::IsOffline); + return ErrorState::enter(shared_values, ErrorStateCause::IsOffline); } match shared_values .tunnel_parameters_generator .generate(retry_attempt) { - Err(err) => BlockedState::enter(shared_values, BlockReason::TunnelParameterError(err)), + Err(err) => { + ErrorState::enter(shared_values, ErrorStateCause::TunnelParameterError(err)) + } Ok(tunnel_parameters) => { if let Err(error) = Self::set_firewall_policy(shared_values, &tunnel_parameters) { error!( @@ -348,7 +350,7 @@ impl TunnelState for ConnectingState { "Failed to apply firewall policy for connecting state" ) ); - BlockedState::enter(shared_values, BlockReason::StartTunnelError) + ErrorState::enter(shared_values, ErrorStateCause::StartTunnelError) } else { #[cfg(target_os = "android")] { @@ -394,10 +396,12 @@ impl TunnelState for ConnectingState { error.display_chain_with_msg("Failed to start tunnel") ); let block_reason = match error { - tunnel::Error::EnableIpv6Error => BlockReason::Ipv6Unavailable, - _ => BlockReason::StartTunnelError, + tunnel::Error::EnableIpv6Error => { + ErrorStateCause::Ipv6Unavailable + } + _ => ErrorStateCause::StartTunnelError, }; - BlockedState::enter(shared_values, block_reason) + ErrorState::enter(shared_values, 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 6b95548ddd..f183a7c78c 100644 --- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs @@ -1,5 +1,5 @@ use super::{ - BlockedState, ConnectingState, EventConsequence, SharedTunnelStateValues, TunnelCommand, + ConnectingState, ErrorState, EventConsequence, SharedTunnelStateValues, TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper, }; use crate::firewall::FirewallPolicy; @@ -76,9 +76,7 @@ impl TunnelState for DisconnectedState { SameState(self) } Ok(TunnelCommand::Connect) => NewState(ConnectingState::enter(shared_values, 0)), - Ok(TunnelCommand::Block(reason)) => { - NewState(BlockedState::enter(shared_values, reason)) - } + Ok(TunnelCommand::Block(reason)) => NewState(ErrorState::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 733a6e2448..d18fdeb6ee 100644 --- a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs @@ -1,5 +1,5 @@ use super::{ - BlockedState, ConnectingState, DisconnectedState, EventConsequence, SharedTunnelStateValues, + ConnectingState, DisconnectedState, ErrorState, EventConsequence, SharedTunnelStateValues, TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper, }; use crate::tunnel::CloseHandle; @@ -9,14 +9,14 @@ use futures::{ }; use std::thread; use talpid_types::{ - tunnel::{ActionAfterDisconnect, BlockReason}, + tunnel::{ActionAfterDisconnect, ErrorStateCause}, ErrorExt, }; /// This state is active from when we manually trigger a tunnel kill until the tunnel wait /// operation (TunnelExit) returned. pub struct DisconnectingState { - exited: Option<oneshot::Receiver<Option<BlockReason>>>, + exited: Option<oneshot::Receiver<Option<ErrorStateCause>>>, after_disconnect: AfterDisconnect, } @@ -58,7 +58,7 @@ impl DisconnectingState { } Ok(TunnelCommand::IsOffline(is_offline)) => { shared_values.is_offline = is_offline; - if !is_offline && reason == BlockReason::IsOffline { + if !is_offline && reason == ErrorStateCause::IsOffline { AfterDisconnect::Reconnect(0) } else { AfterDisconnect::Block(reason) @@ -81,7 +81,7 @@ impl DisconnectingState { Ok(TunnelCommand::IsOffline(is_offline)) => { shared_values.is_offline = is_offline; if is_offline { - AfterDisconnect::Block(BlockReason::IsOffline) + AfterDisconnect::Block(ErrorStateCause::IsOffline) } else { AfterDisconnect::Reconnect(retry_attempt) } @@ -117,16 +117,16 @@ impl DisconnectingState { fn after_disconnect( self, - block_reason: Option<BlockReason>, + block_reason: Option<ErrorStateCause>, shared_values: &mut SharedTunnelStateValues, ) -> (TunnelStateWrapper, TunnelStateTransition) { if let Some(reason) = block_reason { - return BlockedState::enter(shared_values, reason); + return ErrorState::enter(shared_values, reason); } match self.after_disconnect { AfterDisconnect::Nothing => DisconnectedState::enter(shared_values, ()), - AfterDisconnect::Block(reason) => BlockedState::enter(shared_values, reason), + AfterDisconnect::Block(cause) => ErrorState::enter(shared_values, cause), AfterDisconnect::Reconnect(retry_attempt) => { ConnectingState::enter(shared_values, retry_attempt) } @@ -137,7 +137,7 @@ impl DisconnectingState { impl TunnelState for DisconnectingState { type Bootstrap = ( Option<CloseHandle>, - Option<oneshot::Receiver<Option<BlockReason>>>, + Option<oneshot::Receiver<Option<ErrorStateCause>>>, AfterDisconnect, ); @@ -180,7 +180,7 @@ impl TunnelState for DisconnectingState { /// Which state should be transitioned to after disconnection is complete. pub enum AfterDisconnect { Nothing, - Block(BlockReason), + Block(ErrorStateCause), Reconnect(u32), } diff --git a/talpid-core/src/tunnel_state_machine/blocked_state.rs b/talpid-core/src/tunnel_state_machine/error_state.rs index bdf054ab2c..9d8402997d 100644 --- a/talpid-core/src/tunnel_state_machine/blocked_state.rs +++ b/talpid-core/src/tunnel_state_machine/error_state.rs @@ -4,21 +4,25 @@ use super::{ }; use crate::firewall::FirewallPolicy; use futures::{sync::mpsc, Stream}; -use talpid_types::{tunnel::BlockReason, ErrorExt}; +use talpid_types::{ + tunnel::{self as talpid_tunnel, ErrorStateCause}, + ErrorExt, +}; /// No tunnel is running and all network connections are blocked. -pub struct BlockedState { - block_reason: BlockReason, +pub struct ErrorState { + block_reason: ErrorStateCause, } -impl BlockedState { - fn set_firewall_policy(shared_values: &mut SharedTunnelStateValues) -> Option<BlockReason> { +impl ErrorState { + /// Returns true if firewall policy was applied successfully + fn set_firewall_policy(shared_values: &mut SharedTunnelStateValues) -> bool { let policy = FirewallPolicy::Blocked { allow_lan: shared_values.allow_lan, }; match shared_values.firewall.apply_policy(policy) { - Ok(()) => None, + Ok(()) => true, Err(error) => { log::error!( "{}", @@ -26,15 +30,16 @@ impl BlockedState { "Failed to apply firewall policy for blocked state" ) ); - Some(BlockReason::SetFirewallPolicyError) + false } } } + /// Returns true if a new tunnel device was successfully created. #[cfg(target_os = "android")] - fn create_blocking_tun(shared_values: &mut SharedTunnelStateValues) -> Option<BlockReason> { + fn create_blocking_tun(shared_values: &mut SharedTunnelStateValues) -> bool { match shared_values.tun_provider.create_tun_if_closed() { - Ok(()) => None, + Ok(()) => true, Err(error) => { log::error!( "{}", @@ -42,28 +47,28 @@ impl BlockedState { "Failed to open tunnel adapter to drop packets for blocked state" ) ); - Some(BlockReason::SetFirewallPolicyError) + false } } } } -impl TunnelState for BlockedState { - type Bootstrap = BlockReason; +impl TunnelState for ErrorState { + type Bootstrap = ErrorStateCause; fn enter( shared_values: &mut SharedTunnelStateValues, block_reason: Self::Bootstrap, ) -> (TunnelStateWrapper, TunnelStateTransition) { - let block_reason = Self::set_firewall_policy(shared_values).unwrap_or_else(|| block_reason); + #[cfg(not(target_os = "android"))] + let is_blocking = Self::set_firewall_policy(shared_values); #[cfg(target_os = "android")] - let block_reason = Self::create_blocking_tun(shared_values).unwrap_or_else(|| block_reason); - + let is_blocking = Self::create_blocking_tun(shared_values); ( - TunnelStateWrapper::from(BlockedState { + TunnelStateWrapper::from(ErrorState { block_reason: block_reason.clone(), }), - TunnelStateTransition::Blocked(block_reason), + TunnelStateTransition::Error(talpid_tunnel::ErrorState::new(block_reason, is_blocking)), ) } @@ -86,7 +91,7 @@ impl TunnelState for BlockedState { } Ok(TunnelCommand::IsOffline(is_offline)) => { shared_values.is_offline = is_offline; - if !is_offline && self.block_reason == BlockReason::IsOffline { + if !is_offline && self.block_reason == ErrorStateCause::IsOffline { NewState(ConnectingState::enter(shared_values, 0)) } else { SameState(self) @@ -96,9 +101,7 @@ impl TunnelState for BlockedState { Ok(TunnelCommand::Disconnect) | Err(_) => { NewState(DisconnectedState::enter(shared_values, ())) } - Ok(TunnelCommand::Block(reason)) => { - NewState(BlockedState::enter(shared_values, reason)) - } + Ok(TunnelCommand::Block(reason)) => NewState(ErrorState::enter(shared_values, reason)), } } } diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs index b86795491d..76bd62a1d4 100644 --- a/talpid-core/src/tunnel_state_machine/mod.rs +++ b/talpid-core/src/tunnel_state_machine/mod.rs @@ -1,18 +1,18 @@ #[macro_use] mod macros; -mod blocked_state; mod connected_state; mod connecting_state; mod disconnected_state; mod disconnecting_state; +mod error_state; use self::{ - blocked_state::BlockedState, connected_state::{ConnectedState, ConnectedStateBootstrap}, connecting_state::ConnectingState, disconnected_state::DisconnectedState, disconnecting_state::{AfterDisconnect, DisconnectingState}, + error_state::ErrorState, }; use crate::{ dns::DnsMonitor, @@ -32,7 +32,7 @@ use std::{ use talpid_types::android::AndroidContext; use talpid_types::{ net::TunnelParameters, - tunnel::{BlockReason, ParameterGenerationError, TunnelStateTransition}, + tunnel::{ErrorStateCause, ParameterGenerationError, TunnelStateTransition}, ErrorExt, }; use tokio_core::reactor::Core; @@ -182,7 +182,7 @@ pub enum TunnelCommand { /// Close tunnel connection. Disconnect, /// Disconnect any open tunnel and block all network access - Block(BlockReason), + Block(ErrorStateCause), } /// Asynchronous handling of the tunnel state machine. @@ -297,7 +297,7 @@ impl<T: TunnelState> From<EventConsequence<T>> for TunnelStateMachineAction { pub trait TunnelParametersGenerator: Send + 'static { /// Given the number of consecutive failed retry attempts, it should yield a `TunnelParameters` /// to establish a tunnel with. - /// If this returns `None` then the state machine goes into the `Blocked` state. + /// If this returns `None` then the state machine goes into the `Error` state. fn generate( &mut self, retry_attempt: u32, @@ -427,6 +427,6 @@ state_wrapper! { Connecting(ConnectingState), Connected(ConnectedState), Disconnecting(DisconnectingState), - Blocked(BlockedState), + Error(ErrorState), } } diff --git a/talpid-types/src/tunnel.rs b/talpid-types/src/tunnel.rs index 9ab3ed6d36..fad6be14a4 100644 --- a/talpid-types/src/tunnel.rs +++ b/talpid-types/src/tunnel.rs @@ -18,7 +18,7 @@ pub enum TunnelStateTransition { /// Disconnecting tunnel. Disconnecting(ActionAfterDisconnect), /// Tunnel is disconnected but secured by blocking all connections. - Blocked(BlockReason), + Error(ErrorState), } /// Action that will be taken after disconnection is complete. @@ -32,22 +32,43 @@ pub enum ActionAfterDisconnect { Reconnect, } -impl TunnelStateTransition { - pub fn is_blocked(&self) -> bool { - match self { - TunnelStateTransition::Blocked(_) => true, - _ => false, - } +/// Error state +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.tunnel"))] +pub struct ErrorState { + /// Reason why the tunnel state machine ended up in the error state + cause: ErrorStateCause, + /// Indicates whether the daemon is currently blocking all traffic. This _should_ always be + /// true - in the case it is not, the user should be notified that no traffic is being blocked. + /// A false value means there was a serious error and the intended security properties are not + /// being upheld. + is_blocking: bool, +} + +impl ErrorState { + pub fn new(cause: ErrorStateCause, is_blocking: bool) -> Self { + Self { cause, is_blocking } + } + + pub fn is_blocking(&self) -> bool { + self.is_blocking + } + + pub fn cause(&self) -> &ErrorStateCause { + &self.cause } } + /// Reason for entering the blocked state. #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] #[serde(tag = "reason", content = "details")] #[cfg_attr(target_os = "android", derive(IntoJava))] #[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.tunnel"))] -pub enum BlockReason { +pub enum ErrorStateCause { /// Authentication with remote server failed. AuthFailed(Option<String>), /// Failed to configure IPv6 because it's disabled in the platform. @@ -86,9 +107,9 @@ pub enum ParameterGenerationError { CustomTunnelHostResultionError, } -impl fmt::Display for BlockReason { +impl fmt::Display for ErrorStateCause { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use self::BlockReason::*; + use self::ErrorStateCause::*; let description = match *self { AuthFailed(ref reason) => { return write!( |
