diff options
| -rw-r--r-- | mullvad-daemon/src/main.rs | 8 | ||||
| -rw-r--r-- | mullvad-daemon/src/rpc_info.rs | 49 |
2 files changed, 56 insertions, 1 deletions
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs index 50fc5d1991..f07138b8ff 100644 --- a/mullvad-daemon/src/main.rs +++ b/mullvad-daemon/src/main.rs @@ -84,6 +84,9 @@ use std::fs; error_chain!{ errors { + DaemonIsAlreadyRunning { + description("Another instance of the daemon is already running") + } /// The client is in the wrong state for the requested operation. Optimally the code should /// be written in such a way so such states can't exist. InvalidState { @@ -284,6 +287,11 @@ impl Daemon { event_tx: IntoSender<TunnelCommand, DaemonEvent>, require_auth: bool, ) -> Result<ManagementInterfaceServer> { + ensure!( + !rpc_info::is_another_instance_running(), + ErrorKind::DaemonIsAlreadyRunning + ); + let shared_secret = if require_auth { Some(uuid::Uuid::new_v4().to_string()) } else { diff --git a/mullvad-daemon/src/rpc_info.rs b/mullvad-daemon/src/rpc_info.rs index b5b35fa8f7..71c551d0db 100644 --- a/mullvad-daemon/src/rpc_info.rs +++ b/mullvad-daemon/src/rpc_info.rs @@ -1,6 +1,10 @@ use std::fs::{self, File, OpenOptions}; -use std::io::{self, Write}; +use std::io::{self, BufRead, BufReader, Write}; use std::path::{Path, PathBuf}; +use std::result; + +use mullvad_types::states::DaemonState; +use talpid_ipc::WsIpcClient; error_chain! { errors { @@ -28,8 +32,21 @@ lazy_static! { } +/// Checks if there is another instance of the daemon running. +/// +/// Tries to connect to another daemon and perform a simple RPC call. If it fails, assumes the +/// other daemon has stopped. +pub fn is_another_instance_running() -> bool { + let rpc_file_exists = RPC_ADDRESS_FILE_PATH.as_path().exists(); + + rpc_file_exists && other_daemon_responds() +} + /// Writes down the RPC connection info to some API to a file. pub fn write(rpc_address: &str, shared_secret: &str) -> Result<()> { + // Remove any existent RPC address file first + let _ = remove(); + open_file(RPC_ADDRESS_FILE_PATH.as_path()) .and_then(|mut file| write!(file, "{}\n{}\n", rpc_address, shared_secret)) .chain_err(|| ErrorKind::WriteFailed(RPC_ADDRESS_FILE_PATH.to_owned()))?; @@ -46,6 +63,36 @@ pub fn remove() -> Result<()> { .chain_err(|| ErrorKind::RemoveFailed(RPC_ADDRESS_FILE_PATH.to_owned())) } +fn other_daemon_responds() -> bool { + if let Err(message) = call_other_daemon() { + info!("{}; assuming it has stopped", message); + false + } else { + true + } +} + +fn call_other_daemon() -> result::Result<(), String> { + let method = "get_state"; + let args: [u8; 0] = []; + let address = read_rpc_file().map_err(|_| "Failed to read RPC address file of other daemon")?; + // TODO: Authenticate with server + let mut rpc_client = + WsIpcClient::new(address).map_err(|_| "Failed to connect to other daemon")?; + let _: DaemonState = rpc_client + .call(method, &args) + .map_err(|_| "Failed to execute RPC call to other daemon")?; + Ok(()) +} + +fn read_rpc_file() -> io::Result<String> { + let file = File::open(RPC_ADDRESS_FILE_PATH.as_path())?; + let mut reader = BufReader::new(file); + let mut address = String::new(); + reader.read_line(&mut address)?; + Ok(address) +} + fn open_file(path: &Path) -> io::Result<File> { let file = OpenOptions::new() .write(true) |
