summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--mullvad-cli/src/cmds/mod.rs4
-rw-r--r--mullvad-cli/src/cmds/shutdown.rs20
-rw-r--r--mullvad-cli/src/rpc.rs15
-rw-r--r--mullvad-daemon/src/main.rs2
-rw-r--r--mullvad-daemon/src/management_interface.rs12
-rw-r--r--mullvad-daemon/src/rpc_info.rs12
7 files changed, 55 insertions, 12 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a710c238a9..0b8d31c2a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
## [Unreleased]
+### Added
+- Possibility to shut down the daemon via an RPC call.
## [2017.1-beta2] - 2017-09-27
diff --git a/mullvad-cli/src/cmds/mod.rs b/mullvad-cli/src/cmds/mod.rs
index 8061344b96..0104185543 100644
--- a/mullvad-cli/src/cmds/mod.rs
+++ b/mullvad-cli/src/cmds/mod.rs
@@ -16,6 +16,9 @@ pub use self::disconnect::Disconnect;
mod custom_relay;
pub use self::custom_relay::CustomRelay;
+mod shutdown;
+pub use self::shutdown::Shutdown;
+
/// Returns a map of all available subcommands with their name as key.
pub fn get_commands() -> HashMap<&'static str, Box<Command>> {
let commands: Vec<Box<Command>> = vec![
@@ -24,6 +27,7 @@ pub fn get_commands() -> HashMap<&'static str, Box<Command>> {
Box::new(Connect),
Box::new(Disconnect),
Box::new(CustomRelay),
+ Box::new(Shutdown),
];
let mut map = HashMap::new();
for cmd in commands {
diff --git a/mullvad-cli/src/cmds/shutdown.rs b/mullvad-cli/src/cmds/shutdown.rs
new file mode 100644
index 0000000000..4a334da5a5
--- /dev/null
+++ b/mullvad-cli/src/cmds/shutdown.rs
@@ -0,0 +1,20 @@
+use {Command, Result};
+use clap;
+
+use rpc;
+
+pub struct Shutdown;
+
+impl Command for Shutdown {
+ fn name(&self) -> &'static str {
+ "shutdown"
+ }
+
+ fn clap_subcommand(&self) -> clap::App<'static, 'static> {
+ clap::SubCommand::with_name(self.name()).about("Makes the backend daemon quit")
+ }
+
+ fn run(&self, _matches: &clap::ArgMatches) -> Result<()> {
+ rpc::call("shutdown", &[] as &[u8; 0])
+ }
+}
diff --git a/mullvad-cli/src/rpc.rs b/mullvad-cli/src/rpc.rs
index 16a23bda94..5e14cdf195 100644
--- a/mullvad-cli/src/rpc.rs
+++ b/mullvad-cli/src/rpc.rs
@@ -2,7 +2,7 @@ use {Result, ResultExt};
use serde;
use std::fs::{File, Metadata};
-use std::io::{self, Read};
+use std::io::{self, BufRead, BufReader};
use std::path::{Path, PathBuf};
use talpid_ipc::WsIpcClient;
@@ -20,7 +20,7 @@ where
T: serde::Serialize,
O: for<'de> serde::Deserialize<'de>,
{
- let address = read_rpc_address().chain_err(|| "Unable to read RPC address")?;
+ let (address, _shared_secret) = read_rpc_address().chain_err(|| "Unable to read RPC address")?;
info!("Using RPC address {}", address);
let mut rpc_client = WsIpcClient::new(address).chain_err(|| "Unable to create RPC client")?;
rpc_client
@@ -41,16 +41,19 @@ lazy_static! {
static ref RPC_ADDRESS_FILE_PATH: PathBuf = ::std::env::temp_dir().join(".mullvad_rpc_address");
}
-fn read_rpc_address() -> io::Result<String> {
+fn read_rpc_address() -> io::Result<(String, String)> {
debug!(
"Trying to read RPC address at {}",
RPC_ADDRESS_FILE_PATH.to_string_lossy()
);
- let mut file = File::open(&*RPC_ADDRESS_FILE_PATH)?;
+ let file = File::open(&*RPC_ADDRESS_FILE_PATH)?;
if is_rpc_file_trusted(file.metadata()?) {
+ let mut buf_file = BufReader::new(file);
let mut address = String::new();
- file.read_to_string(&mut address)?;
- Ok(address)
+ buf_file.read_line(&mut address)?;
+ let mut shared_secret = String::new();
+ buf_file.read_line(&mut shared_secret)?;
+ Ok((address, shared_secret))
} else {
Err(io::Error::new(
io::ErrorKind::Other,
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index c427c252bb..e804dcace8 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -320,6 +320,7 @@ impl Daemon {
SetAccount(tx, account_token) => self.on_set_account(tx, account_token),
GetAccount(tx) => Ok(self.on_get_account(tx)),
SetCustomRelay(tx, relay_endpoint) => self.on_set_custom_relay(tx, relay_endpoint),
+ Shutdown => self.handle_trigger_shutdown_event(),
}
}
@@ -635,6 +636,7 @@ fn run() -> Result<()> {
daemon.run()?;
debug!("Mullvad daemon is quitting");
+ thread::sleep(Duration::from_millis(500));
Ok(())
}
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index e2fb6f33f7..829f843fca 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -91,6 +91,10 @@ build_rpc_trait! {
#[rpc(name = "get_location")]
fn get_location(&self) -> Result<Location, Error>;
+ /// Makes the daemon exit its main loop and quit.
+ #[rpc(meta, name = "shutdown")]
+ fn shutdown(&self, Self::Metadata) -> BoxFuture<(), Error>;
+
#[pubsub(name = "new_state")] {
/// Subscribes to the `new_state` event notifications.
#[rpc(name = "new_state_subscribe")]
@@ -131,6 +135,8 @@ pub enum TunnelCommand {
GetAccount(OneshotSender<Option<AccountToken>>),
/// Set a custom relay instead of the default list of relays
SetCustomRelay(OneshotSender<()>, Option<RelayEndpoint>),
+ /// Makes the daemon exit the main loop and quit.
+ Shutdown,
}
#[derive(Default)]
@@ -441,6 +447,12 @@ impl<T: From<TunnelCommand> + 'static + Send> ManagementInterfaceApi for Managem
})
}
+ fn shutdown(&self, meta: Self::Metadata) -> BoxFuture<(), Error> {
+ trace!("shutdown");
+ try_future!(self.check_auth(&meta));
+ self.send_command_to_daemon(TunnelCommand::Shutdown)
+ }
+
fn new_state_subscribe(
&self,
meta: Self::Metadata,
diff --git a/mullvad-daemon/src/rpc_info.rs b/mullvad-daemon/src/rpc_info.rs
index 7826b736a8..3bd42d9751 100644
--- a/mullvad-daemon/src/rpc_info.rs
+++ b/mullvad-daemon/src/rpc_info.rs
@@ -5,8 +5,8 @@ use std::path::{Path, PathBuf};
error_chain! {
errors {
WriteFailed(path: PathBuf) {
- description("Failed to write RCP address to file")
- display("Failed to write RPC address to {}", path.to_string_lossy())
+ description("Failed to write RCP connection info to file")
+ display("Failed to write RPC connection info to {}", path.to_string_lossy())
}
RemoveFailed(path: PathBuf) {
description("Failed to remove file")
@@ -17,18 +17,18 @@ error_chain! {
#[cfg(unix)]
lazy_static! {
- /// The path to the file where we write the RPC address
+ /// The path to the file where we write the RPC connection info
static ref RPC_ADDRESS_FILE_PATH: PathBuf = Path::new("/tmp").join(".mullvad_rpc_address");
}
#[cfg(not(unix))]
lazy_static! {
- /// The path to the file where we write the RPC address
+ /// The path to the file where we write the RPC connection info
static ref RPC_ADDRESS_FILE_PATH: PathBuf = ::std::env::temp_dir().join(".mullvad_rpc_address");
}
-/// Writes down the RPC address to some API to a file.
+/// Writes down the RPC connection info to some API to a file.
pub fn write(rpc_address: &str, shared_secret: &str) -> Result<()> {
open_file(RPC_ADDRESS_FILE_PATH.as_path())
.and_then(|mut file| {
@@ -37,7 +37,7 @@ pub fn write(rpc_address: &str, shared_secret: &str) -> Result<()> {
.chain_err(|| ErrorKind::WriteFailed(RPC_ADDRESS_FILE_PATH.to_owned()))?;
debug!(
- "Wrote RPC address to {}",
+ "Wrote RPC connection info to {}",
RPC_ADDRESS_FILE_PATH.to_string_lossy()
);
Ok(())