summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-daemon/src/main.rs8
-rw-r--r--mullvad-daemon/src/rpc_info.rs49
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)