summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-daemon/src/lib.rs49
1 files changed, 43 insertions, 6 deletions
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 27ae019cf0..24276a439d 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -45,7 +45,7 @@ use settings::Settings;
#[cfg(not(target_os = "android"))]
use std::path::Path;
use std::{
- fs::File,
+ fs::{self, File},
io,
marker::PhantomData,
mem,
@@ -128,6 +128,12 @@ pub enum Error {
#[cfg(target_os = "windows")]
#[error(display = "Failed to read dir entries")]
ReadDirError(#[error(source)] io::Error),
+
+ #[error(display = "Failed to read cached target tunnel state")]
+ ReadCachedTargetState(#[error(source)] serde_json::Error),
+
+ #[error(display = "Failed to open cached target tunnel state")]
+ OpenCachedTargetState(#[error(source)] io::Error),
}
/// Enum representing commands that can be sent to the daemon.
@@ -513,6 +519,26 @@ where
)
.map_err(Error::LoadAccountHistory)?;
+ // Restore the tunnel to a previous state
+ let target_cache = cache_dir.join(TARGET_START_STATE_FILE);
+ let cached_target_state: Option<TargetState> = match File::open(&target_cache) {
+ Ok(handle) => serde_json::from_reader(io::BufReader::new(handle))
+ .map(Some)
+ .map_err(Error::ReadCachedTargetState),
+ Err(e) => {
+ if e.kind() == io::ErrorKind::NotFound {
+ Ok(None)
+ } else {
+ Err(Error::OpenCachedTargetState(e))
+ }
+ }
+ }?;
+ if cached_target_state.is_some() {
+ let _ = fs::remove_file(target_cache).map_err(|e| {
+ error!("Cannot delete target tunnel state cache: {}", e);
+ });
+ }
+
let tunnel_parameters_generator = MullvadTunnelParametersGenerator {
tx: internal_event_tx.clone(),
};
@@ -539,10 +565,23 @@ where
// Attempt to download a fresh relay list
relay_selector.update();
+ let initial_target_state = if settings.get_account_token().is_some() {
+ if settings.get_auto_connect() {
+ // Note: Auto-connect overrides the cached target state
+ info!("Automatically connecting since auto-connect is turned on");
+ TargetState::Secured
+ } else {
+ info!("Restoring cached target state");
+ cached_target_state.unwrap_or(TargetState::Unsecured)
+ }
+ } else {
+ TargetState::Unsecured
+ };
+
let mut daemon = Daemon {
tunnel_command_tx,
tunnel_state: TunnelState::Disconnected,
- target_state: TargetState::Unsecured,
+ target_state: initial_target_state,
state: DaemonExecutionState::Running,
rx: internal_event_rx.wait(),
tx: internal_event_tx,
@@ -586,9 +625,8 @@ where
/// Consume the `Daemon` and run the main event loop. Blocks until an error happens or a
/// shutdown event is received.
pub fn run(mut self) -> Result<(), Error> {
- if self.settings.get_auto_connect() && self.settings.get_account_token().is_some() {
- info!("Automatically connecting since auto-connect is turned on");
- self.set_target_state(TargetState::Secured);
+ if self.target_state == TargetState::Secured {
+ self.connect_tunnel();
}
while let Some(Ok(event)) = self.rx.next() {
self.handle_event(event);
@@ -1755,7 +1793,6 @@ where
#[cfg(not(target_os = "android"))]
fn clear_directory(path: &Path) -> Result<(), Error> {
- use std::fs;
#[cfg(not(target_os = "windows"))]
{
fs::remove_dir_all(path)