summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-01-28 13:28:44 +0100
committerDavid Lönnhager <david.l@mullvad.net>2021-01-28 13:28:44 +0100
commite0b5655614cf2b65cffd136b22106e547b15fb7c (patch)
tree64c9fde6bc58b6ee2294c6e49e5b288f8dcc5ba4
parent115099777c1ca93048cf46ef5cfbb253475bc573 (diff)
parentb0e5a1ec09dae40501c6ef4450852436020b86f8 (diff)
downloadmullvadvpn-e0b5655614cf2b65cffd136b22106e547b15fb7c.tar.xz
mullvadvpn-e0b5655614cf2b65cffd136b22106e547b15fb7c.zip
Merge branch 'improve-ipc-errors'
-rw-r--r--mullvad-cli/src/cmds/account.rs5
-rw-r--r--mullvad-cli/src/cmds/bridge.rs8
-rw-r--r--mullvad-cli/src/cmds/relay.rs10
-rw-r--r--mullvad-cli/src/cmds/reset.rs13
-rw-r--r--mullvad-cli/src/cmds/status.rs2
-rw-r--r--mullvad-cli/src/cmds/tunnel.rs8
-rw-r--r--mullvad-cli/src/cmds/version.rs14
-rw-r--r--mullvad-cli/src/main.rs25
-rw-r--r--mullvad-cli/src/state.rs4
-rw-r--r--mullvad-daemon/src/lib.rs410
-rw-r--r--mullvad-daemon/src/management_interface.rs277
-rw-r--r--mullvad-jni/src/daemon_interface.rs62
12 files changed, 540 insertions, 298 deletions
diff --git a/mullvad-cli/src/cmds/account.rs b/mullvad-cli/src/cmds/account.rs
index f68e2a12eb..0dba7600ce 100644
--- a/mullvad-cli/src/cmds/account.rs
+++ b/mullvad-cli/src/cmds/account.rs
@@ -91,7 +91,8 @@ impl Account {
println!("Mullvad account: {}", settings.account_token);
let expiry = rpc
.get_account_data(settings.account_token)
- .await?
+ .await
+ .map_err(|error| Error::RpcFailedExt("Failed to fetch account data", error))?
.into_inner();
println!(
"Expires at : {}",
@@ -132,7 +133,7 @@ impl Account {
Code::NotFound | Code::ResourceExhausted => {
eprintln!("Failed to submit voucher: {}", err.message());
}
- _ => return Err(Error::GrpcClientError(err)),
+ _ => return Err(Error::RpcFailed(err)),
}
std::process::exit(1);
}
diff --git a/mullvad-cli/src/cmds/bridge.rs b/mullvad-cli/src/cmds/bridge.rs
index 4bb85b4060..9a674069a8 100644
--- a/mullvad-cli/src/cmds/bridge.rs
+++ b/mullvad-cli/src/cmds/bridge.rs
@@ -1,4 +1,4 @@
-use crate::{location, new_rpc_client, Command, Result};
+use crate::{location, new_rpc_client, Command, Error, Result};
use clap::value_t;
use mullvad_management_interface::types::{
@@ -404,7 +404,11 @@ impl Bridge {
async fn list_bridge_relays() -> Result<()> {
let mut rpc = new_rpc_client().await?;
- let mut locations = rpc.get_relay_locations(()).await?.into_inner();
+ let mut locations = rpc
+ .get_relay_locations(())
+ .await
+ .map_err(|error| Error::RpcFailedExt("Failed to obtain relay locations", error))?
+ .into_inner();
let mut countries = Vec::new();
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index ab1ea41fe1..e8783e04f3 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -193,7 +193,9 @@ impl Command for Relay {
impl Relay {
async fn update_constraints(&self, update: RelaySettingsUpdate) -> Result<()> {
let mut rpc = new_rpc_client().await?;
- rpc.update_relay_settings(update).await?;
+ rpc.update_relay_settings(update)
+ .await
+ .map_err(|error| Error::RpcFailedExt("Failed to update relay settings", error))?;
println!("Relay constraints updated");
Ok(())
}
@@ -680,7 +682,11 @@ impl Relay {
async fn get_filtered_relays() -> Result<Vec<RelayListCountry>> {
let mut rpc = new_rpc_client().await?;
- let mut locations = rpc.get_relay_locations(()).await?.into_inner();
+ let mut locations = rpc
+ .get_relay_locations(())
+ .await
+ .map_err(|error| Error::RpcFailedExt("Failed to obtain relay locations", error))?
+ .into_inner();
let mut countries = Vec::new();
diff --git a/mullvad-cli/src/cmds/reset.rs b/mullvad-cli/src/cmds/reset.rs
index bb10a3f0fe..1be34a0ab0 100644
--- a/mullvad-cli/src/cmds/reset.rs
+++ b/mullvad-cli/src/cmds/reset.rs
@@ -1,4 +1,4 @@
-use crate::{new_rpc_client, Command, Result};
+use crate::{new_rpc_client, Command, Error, Result};
use std::io::stdin;
pub struct Reset;
@@ -15,12 +15,11 @@ impl Command for Reset {
async fn run(&self, _: &clap::ArgMatches<'_>) -> Result<()> {
let mut rpc = new_rpc_client().await?;
if Self::receive_confirmation() {
- if rpc.factory_reset(()).await.is_err() {
- eprintln!("FAILED TO PERFORM FACTORY RESET");
- } else {
- #[cfg(target_os = "linux")]
- println!("If you're running systemd, to remove all logs, you must use journalctl");
- }
+ rpc.factory_reset(())
+ .await
+ .map_err(|error| Error::RpcFailedExt("FAILED TO PERFORM FACTORY RESET", error))?;
+ #[cfg(target_os = "linux")]
+ println!("If you're running systemd, to remove all logs, you must use journalctl");
}
Ok(())
}
diff --git a/mullvad-cli/src/cmds/status.rs b/mullvad-cli/src/cmds/status.rs
index 76a4ed2e67..f4e943cb3c 100644
--- a/mullvad-cli/src/cmds/status.rs
+++ b/mullvad-cli/src/cmds/status.rs
@@ -97,7 +97,7 @@ async fn print_location(rpc: &mut ManagementServiceClient) -> Result<()> {
println!("Location data unavailable");
return Ok(());
} else {
- return Err(Error::GrpcClientError(status));
+ return Err(Error::RpcFailed(status));
}
}
};
diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs
index 53a329af13..4af0864ddf 100644
--- a/mullvad-cli/src/cmds/tunnel.rs
+++ b/mullvad-cli/src/cmds/tunnel.rs
@@ -187,7 +187,7 @@ impl Tunnel {
if status.code() == mullvad_management_interface::Code::NotFound {
None
} else {
- return Err(Error::GrpcClientError(status));
+ return Err(Error::RpcFailedExt("Failed to obtain key", status));
}
}
};
@@ -202,7 +202,11 @@ impl Tunnel {
return Ok(());
}
- let is_valid = rpc.verify_wireguard_key(()).await?.into_inner();
+ let is_valid = rpc
+ .verify_wireguard_key(())
+ .await
+ .map_err(|error| Error::RpcFailedExt("Failed to verify key", error))?
+ .into_inner();
println!("Key is valid for use with current account: {}", is_valid);
Ok(())
}
diff --git a/mullvad-cli/src/cmds/version.rs b/mullvad-cli/src/cmds/version.rs
index 06855212bf..08944f921b 100644
--- a/mullvad-cli/src/cmds/version.rs
+++ b/mullvad-cli/src/cmds/version.rs
@@ -1,4 +1,4 @@
-use crate::{new_rpc_client, Command, Result};
+use crate::{new_rpc_client, Command, Error, Result};
pub struct Version;
@@ -15,9 +15,17 @@ impl Command for Version {
async fn run(&self, _: &clap::ArgMatches<'_>) -> Result<()> {
let mut rpc = new_rpc_client().await?;
- let current_version = rpc.get_current_version(()).await?.into_inner();
+ let current_version = rpc
+ .get_current_version(())
+ .await
+ .map_err(|error| Error::RpcFailedExt("Failed to obtain current version", error))?
+ .into_inner();
println!("Current version: {}", current_version);
- let version_info = rpc.get_version_info(()).await?.into_inner();
+ let version_info = rpc
+ .get_version_info(())
+ .await
+ .map_err(|error| Error::RpcFailedExt("Failed to obtain version info", error))?
+ .into_inner();
println!("\tIs supported: {}", version_info.supported);
if !version_info.suggested_upgrade.is_empty() {
diff --git a/mullvad-cli/src/main.rs b/mullvad-cli/src/main.rs
index 7f93e17222..20dfae5fc9 100644
--- a/mullvad-cli/src/main.rs
+++ b/mullvad-cli/src/main.rs
@@ -25,8 +25,14 @@ pub enum Error {
#[error(display = "Management interface error")]
ManagementInterfaceError(#[error(source)] mullvad_management_interface::Error),
- #[error(display = "Failed to communicate with mullvad-daemon over RPC")]
- GrpcClientError(#[error(source)] mullvad_management_interface::Status),
+ #[error(display = "RPC failed")]
+ RpcFailed(#[error(source)] mullvad_management_interface::Status),
+
+ #[error(display = "RPC failed: {}", _0)]
+ RpcFailedExt(
+ &'static str,
+ #[error(source)] mullvad_management_interface::Status,
+ ),
/// The given command is not correct in some way
#[error(display = "Invalid command: {}", _0)]
@@ -44,7 +50,20 @@ async fn main() {
let exit_code = match run().await {
Ok(_) => 0,
Err(error) => {
- eprintln!("{}", error.display_chain());
+ match &error {
+ Error::RpcFailed(status) => {
+ eprintln!("{}: {:?}: {}", error, status.code(), status.message())
+ }
+ Error::RpcFailedExt(_message, status) => {
+ eprintln!(
+ "{}\nCaused by: {:?}: {}",
+ error,
+ status.code(),
+ status.message()
+ )
+ }
+ error => eprintln!("{}", error.display_chain()),
+ }
1
}
};
diff --git a/mullvad-cli/src/state.rs b/mullvad-cli/src/state.rs
index 9890218545..4cf826214f 100644
--- a/mullvad-cli/src/state.rs
+++ b/mullvad-cli/src/state.rs
@@ -23,7 +23,7 @@ pub fn state_listen(mut rpc: ManagementServiceClient) -> Receiver<Result<TunnelS
_ => continue,
},
Ok(None) => break,
- Err(status) => Err(Error::GrpcClientError(status)),
+ Err(status) => Err(Error::RpcFailed(status)),
};
if let Err(_) = sender.send(forward).await {
@@ -32,7 +32,7 @@ pub fn state_listen(mut rpc: ManagementServiceClient) -> Receiver<Result<TunnelS
}
}
Err(status) => {
- let _ = sender.send(Err(Error::GrpcClientError(status))).await;
+ let _ = sender.send(Err(Error::RpcFailed(status))).await;
}
}
});
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 42f067a4f3..691e96cd5b 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -82,6 +82,8 @@ const FIRST_KEY_PUSH_TIMEOUT: Duration = Duration::from_secs(5);
/// Delay between generating a new WireGuard key and reconnecting
const WG_RECONNECT_DELAY: Duration = Duration::from_secs(30);
+pub type ResponseTx<T, E> = oneshot::Sender<Result<T, E>>;
+
#[derive(err_derive::Error, Debug)]
#[error(no_from)]
pub enum Error {
@@ -94,6 +96,9 @@ pub enum Error {
#[error(display = "Unable to create RPC client")]
InitRpcFactory(#[error(source)] mullvad_rpc::Error),
+ #[error(display = "REST request failed")]
+ RestError(#[error(source)] mullvad_rpc::rest::Error),
+
#[error(display = "Unable to load account history with wireguard key cache")]
LoadAccountHistory(#[error(source)] account_history::Error),
@@ -107,9 +112,30 @@ pub enum Error {
#[error(display = "No bridge available")]
NoBridgeAvailable,
- #[error(display = "Account history problems")]
+ #[error(display = "No account token is set")]
+ NoAccountToken,
+
+ #[error(display = "No account history available for the token")]
+ NoAccountTokenHistory,
+
+ #[error(display = "Settings error")]
+ SettingsError(#[error(source)] settings::Error),
+
+ #[error(display = "Account history error")]
AccountHistory(#[error(source)] account_history::Error),
+ #[error(display = "Failed to clear cache directory")]
+ ClearCacheError,
+
+ #[error(display = "Failed to clear logs directory")]
+ ClearLogsError,
+
+ #[error(display = "Failed to clear account history")]
+ ClearAccountHistoryError(#[error(source)] account_history::Error),
+
+ #[error(display = "Failed to clear settings")]
+ ClearSettingsError(#[error(source)] settings::Error),
+
#[error(display = "Tunnel state machine error")]
TunnelError(#[error(source)] tunnel_state_machine::Error),
@@ -151,83 +177,80 @@ pub enum DaemonCommand {
GetState(oneshot::Sender<TunnelState>),
/// Get the current geographical location.
GetCurrentLocation(oneshot::Sender<Option<GeoIpLocation>>),
- CreateNewAccount(oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>),
+ CreateNewAccount(ResponseTx<String, Error>),
/// Request the metadata for an account.
GetAccountData(
- oneshot::Sender<Result<AccountData, mullvad_rpc::rest::Error>>,
+ ResponseTx<AccountData, mullvad_rpc::rest::Error>,
AccountToken,
),
/// Request www auth token for an account
- GetWwwAuthToken(oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>),
+ GetWwwAuthToken(ResponseTx<String, Error>),
/// Submit voucher to add time to the current account. Returns time added in seconds
- SubmitVoucher(
- oneshot::Sender<Result<VoucherSubmission, mullvad_rpc::rest::Error>>,
- String,
- ),
+ SubmitVoucher(ResponseTx<VoucherSubmission, Error>, String),
/// Request account history
GetAccountHistory(oneshot::Sender<Vec<AccountToken>>),
/// Request account history
- RemoveAccountFromHistory(oneshot::Sender<()>, AccountToken),
+ RemoveAccountFromHistory(ResponseTx<(), Error>, AccountToken),
/// Clear account history
- ClearAccountHistory(oneshot::Sender<()>),
+ ClearAccountHistory(ResponseTx<(), Error>),
/// Get the list of countries and cities where there are relays.
GetRelayLocations(oneshot::Sender<RelayList>),
/// Trigger an asynchronous relay list update. This returns before the relay list is actually
/// updated.
UpdateRelayLocations,
/// Set which account token to use for subsequent connection attempts.
- SetAccount(oneshot::Sender<()>, Option<AccountToken>),
+ SetAccount(ResponseTx<(), settings::Error>, Option<AccountToken>),
/// Place constraints on the type of tunnel and relay
- UpdateRelaySettings(oneshot::Sender<()>, RelaySettingsUpdate),
+ UpdateRelaySettings(ResponseTx<(), settings::Error>, RelaySettingsUpdate),
/// Set the allow LAN setting.
- SetAllowLan(oneshot::Sender<()>, bool),
+ SetAllowLan(ResponseTx<(), settings::Error>, bool),
/// Set the beta program setting.
- SetShowBetaReleases(oneshot::Sender<()>, bool),
+ SetShowBetaReleases(ResponseTx<(), settings::Error>, bool),
/// Set the block_when_disconnected setting.
- SetBlockWhenDisconnected(oneshot::Sender<()>, bool),
+ SetBlockWhenDisconnected(ResponseTx<(), settings::Error>, bool),
/// Set the auto-connect setting.
- SetAutoConnect(oneshot::Sender<()>, bool),
+ SetAutoConnect(ResponseTx<(), settings::Error>, bool),
/// Set the mssfix argument for OpenVPN
- SetOpenVpnMssfix(oneshot::Sender<()>, Option<u16>),
+ SetOpenVpnMssfix(ResponseTx<(), settings::Error>, Option<u16>),
/// Set proxy details for OpenVPN
- SetBridgeSettings(oneshot::Sender<Result<(), settings::Error>>, BridgeSettings),
+ SetBridgeSettings(ResponseTx<(), settings::Error>, BridgeSettings),
/// Set proxy state
- SetBridgeState(oneshot::Sender<Result<(), settings::Error>>, BridgeState),
+ SetBridgeState(ResponseTx<(), settings::Error>, BridgeState),
/// Set if IPv6 should be enabled in the tunnel
- SetEnableIpv6(oneshot::Sender<()>, bool),
+ SetEnableIpv6(ResponseTx<(), settings::Error>, bool),
/// Set custom DNS servers to use instead of passing requests to the gateway
- SetDnsOptions(oneshot::Sender<()>, DnsOptions),
+ SetDnsOptions(ResponseTx<(), settings::Error>, DnsOptions),
/// Set MTU for wireguard tunnels
- SetWireguardMtu(oneshot::Sender<()>, Option<u16>),
+ SetWireguardMtu(ResponseTx<(), settings::Error>, Option<u16>),
/// Set automatic key rotation interval for wireguard tunnels
- SetWireguardRotationInterval(oneshot::Sender<()>, Option<u32>),
+ SetWireguardRotationInterval(ResponseTx<(), settings::Error>, Option<u32>),
/// Get the daemon settings
GetSettings(oneshot::Sender<Settings>),
/// Generate new wireguard key
- GenerateWireguardKey(oneshot::Sender<wireguard::KeygenEvent>),
+ GenerateWireguardKey(ResponseTx<wireguard::KeygenEvent, Error>),
/// Return a public key of the currently set wireguard private key, if there is one
- GetWireguardKey(oneshot::Sender<Option<wireguard::PublicKey>>),
+ GetWireguardKey(ResponseTx<Option<wireguard::PublicKey>, Error>),
/// Verify if the currently set wireguard key is valid.
- VerifyWireguardKey(oneshot::Sender<bool>),
+ VerifyWireguardKey(ResponseTx<bool, Error>),
/// Get information about the currently running and latest app versions
GetVersionInfo(oneshot::Sender<Option<AppVersionInfo>>),
/// Get current version of the app
GetCurrentVersion(oneshot::Sender<AppVersion>),
/// Remove settings and clear the cache
#[cfg(not(target_os = "android"))]
- FactoryReset(oneshot::Sender<()>),
+ FactoryReset(ResponseTx<(), Error>),
/// Request list of processes excluded from the tunnel
#[cfg(target_os = "linux")]
- GetSplitTunnelProcesses(oneshot::Sender<Vec<i32>>),
+ GetSplitTunnelProcesses(ResponseTx<Vec<i32>, split_tunnel::Error>),
/// Exclude traffic of a process (PID) from the tunnel
#[cfg(target_os = "linux")]
- AddSplitTunnelProcess(oneshot::Sender<()>, i32),
+ AddSplitTunnelProcess(ResponseTx<(), split_tunnel::Error>, i32),
/// Remove process (PID) from list of processes excluded from the tunnel
#[cfg(target_os = "linux")]
- RemoveSplitTunnelProcess(oneshot::Sender<()>, i32),
+ RemoveSplitTunnelProcess(ResponseTx<(), split_tunnel::Error>, i32),
/// Clear list of processes excluded from the tunnel
#[cfg(target_os = "linux")]
- ClearSplitTunnelProcesses(oneshot::Sender<()>),
+ ClearSplitTunnelProcesses(ResponseTx<(), split_tunnel::Error>),
/// Makes the daemon exit the main loop and quit.
Shutdown,
/// Saves the target tunnel state and enters a blocking state. The state is restored
@@ -258,10 +281,7 @@ pub(crate) enum InternalDaemonEvent {
),
),
/// New Account created
- NewAccountEvent(
- AccountToken,
- oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>,
- ),
+ NewAccountEvent(AccountToken, oneshot::Sender<Result<String, Error>>),
/// The background job fetching new `AppVersionInfo`s got a new info object.
NewAppVersionInfo(AppVersionInfo),
}
@@ -1220,7 +1240,7 @@ where
async fn handle_new_account_event(
&mut self,
new_token: AccountToken,
- tx: oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>,
+ tx: ResponseTx<String, Error>,
) {
match self.set_account(Some(new_token.clone())).await {
Ok(_) => {
@@ -1228,7 +1248,11 @@ where
let _ = tx.send(Ok(new_token));
}
Err(err) => {
- log::error!("Failed to save new account - {}", err);
+ log::error!(
+ "{}",
+ err.display_chain_with_msg("Failed to save new account")
+ );
+ let _ = tx.send(Err(Error::SettingsError(err)));
}
};
}
@@ -1333,10 +1357,7 @@ where
})
}
- async fn on_create_new_account(
- &mut self,
- tx: oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>,
- ) {
+ async fn on_create_new_account(&mut self, tx: ResponseTx<String, Error>) {
let daemon_tx = self.tx.clone();
let future = self.accounts_proxy.create_account();
@@ -1346,7 +1367,7 @@ where
let _ = daemon_tx.send(InternalDaemonEvent::NewAccountEvent(account_token, tx));
}
Err(err) => {
- let _ = tx.send(Err(err));
+ let _ = tx.send(Err(Error::RestError(err)));
}
}
});
@@ -1354,7 +1375,7 @@ where
async fn on_get_account_data(
&mut self,
- tx: oneshot::Sender<Result<AccountData, mullvad_rpc::rest::Error>>,
+ tx: ResponseTx<AccountData, mullvad_rpc::rest::Error>,
account_token: AccountToken,
) {
let expiry_fut = self.accounts_proxy.get_expiry(account_token);
@@ -1365,30 +1386,43 @@ where
tokio::spawn(rpc_call);
}
- async fn on_get_www_auth_token(
- &mut self,
- tx: oneshot::Sender<Result<String, mullvad_rpc::rest::Error>>,
- ) {
+ async fn on_get_www_auth_token(&mut self, tx: ResponseTx<String, Error>) {
if let Some(account_token) = self.settings.get_account_token() {
let future = self.accounts_proxy.get_www_auth_token(account_token);
let rpc_call = async {
- Self::oneshot_send(tx, future.await, "get_www_auth_token response");
+ Self::oneshot_send(
+ tx,
+ future.await.map_err(Error::RestError),
+ "get_www_auth_token response",
+ );
};
tokio::spawn(rpc_call);
+ } else {
+ Self::oneshot_send(
+ tx,
+ Err(Error::NoAccountToken),
+ "get_www_auth_token response",
+ );
}
}
async fn on_submit_voucher(
&mut self,
- tx: oneshot::Sender<Result<VoucherSubmission, mullvad_rpc::rest::Error>>,
+ tx: ResponseTx<VoucherSubmission, Error>,
voucher: String,
) {
if let Some(account_token) = self.settings.get_account_token() {
let future = self.accounts_proxy.submit_voucher(account_token, voucher);
let rpc_call = async {
- Self::oneshot_send(tx, future.await, "submit_voucher response");
+ Self::oneshot_send(
+ tx,
+ future.await.map_err(Error::RestError),
+ "submit_voucher response",
+ );
};
tokio::spawn(rpc_call);
+ } else {
+ Self::oneshot_send(tx, Err(Error::NoAccountToken), "submit_voucher response");
}
}
@@ -1400,7 +1434,11 @@ where
self.relay_selector.update().await;
}
- async fn on_set_account(&mut self, tx: oneshot::Sender<()>, account_token: Option<String>) {
+ async fn on_set_account(
+ &mut self,
+ tx: ResponseTx<(), settings::Error>,
+ account_token: Option<String>,
+ ) {
match self.set_account(account_token.clone()).await {
Ok(account_changed) => {
if account_changed {
@@ -1415,10 +1453,11 @@ where
}
};
}
- Self::oneshot_send(tx, (), "set_account response");
+ Self::oneshot_send(tx, Ok(()), "set_account response");
}
- Err(e) => {
- log::error!("Failed to set account - {}", e);
+ Err(error) => {
+ log::error!("{}", error.display_chain_with_msg("Failed to set account"));
+ Self::oneshot_send(tx, Err(error), "set_account response");
}
}
}
@@ -1454,29 +1493,34 @@ where
async fn on_remove_account_from_history(
&mut self,
- tx: oneshot::Sender<()>,
+ tx: ResponseTx<(), Error>,
account_token: AccountToken,
) {
- if self
+ let result = self
.account_history
.remove_account(&account_token)
.await
- .is_ok()
- {
- Self::oneshot_send(tx, (), "remove_account_from_history response");
- }
+ .map_err(Error::AccountHistory);
+ Self::oneshot_send(tx, result, "remove_account_from_history response");
}
- async fn on_clear_account_history(&mut self, tx: oneshot::Sender<()>) {
+ async fn on_clear_account_history(&mut self, tx: ResponseTx<(), Error>) {
match self.account_history.clear().await {
Ok(_) => {
self.set_target_state(TargetState::Unsecured);
- Self::oneshot_send(tx, (), "clear_account_history response");
+ Self::oneshot_send(tx, Ok(()), "clear_account_history response");
+ }
+ Err(err) => {
+ log::error!(
+ "{}",
+ err.display_chain_with_msg("Failed to clear account history")
+ );
+ Self::oneshot_send(
+ tx,
+ Err(Error::AccountHistory(err)),
+ "clear_account_history response",
+ );
}
- Err(err) => log::error!(
- "{}",
- err.display_chain_with_msg("Failed to clear account history")
- ),
}
}
@@ -1503,18 +1547,18 @@ where
}
#[cfg(not(target_os = "android"))]
- async fn on_factory_reset(&mut self, tx: oneshot::Sender<()>) {
- let mut failed = false;
+ async fn on_factory_reset(&mut self, tx: ResponseTx<(), Error>) {
+ let mut last_error = Ok(());
if let Err(e) = self.settings.reset() {
log::error!("Failed to reset settings - {}", e);
- failed = true;
+ last_error = Err(Error::ClearSettingsError(e));
}
if let Err(e) = self.account_history.clear().await {
log::error!("Failed to clear account history - {}", e);
- failed = true;
+ last_error = Err(Error::ClearAccountHistoryError(e));
}
// Shut the daemon down.
@@ -1526,7 +1570,7 @@ where
"{}",
e.display_chain_with_msg("Failed to clear cache directory")
);
- failed = true;
+ last_error = Err(Error::ClearCacheError);
}
if let Err(e) = Self::clear_log_directory() {
@@ -1534,51 +1578,61 @@ where
"{}",
e.display_chain_with_msg("Failed to clear log directory")
);
- failed = true;
- }
- if !failed {
- Self::oneshot_send(tx, (), "factory_reset response");
+ last_error = Err(Error::ClearLogsError);
}
+ Self::oneshot_send(tx, last_error, "factory_reset response");
}));
}
#[cfg(target_os = "linux")]
- fn on_get_split_tunnel_processes(&mut self, tx: oneshot::Sender<Vec<i32>>) {
- match self.exclude_pids.list() {
- Ok(pids) => Self::oneshot_send(tx, pids, "get_split_tunnel_processes response"),
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to obtain PIDs")),
- }
+ fn on_get_split_tunnel_processes(&mut self, tx: ResponseTx<Vec<i32>, split_tunnel::Error>) {
+ let result = self.exclude_pids.list().map_err(|error| {
+ error!("{}", error.display_chain_with_msg("Unable to obtain PIDs"));
+ error
+ });
+ Self::oneshot_send(tx, result, "get_split_tunnel_processes response");
}
#[cfg(target_os = "linux")]
- fn on_add_split_tunnel_process(&mut self, tx: oneshot::Sender<()>, pid: i32) {
- match self.exclude_pids.add(pid) {
- Ok(()) => Self::oneshot_send(tx, (), "add_split_tunnel_process response"),
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to add PID")),
- }
+ fn on_add_split_tunnel_process(&mut self, tx: ResponseTx<(), split_tunnel::Error>, pid: i32) {
+ let result = self.exclude_pids.add(pid).map_err(|error| {
+ error!("{}", error.display_chain_with_msg("Unable to add PID"));
+ error
+ });
+ Self::oneshot_send(tx, result, "add_split_tunnel_process response");
}
#[cfg(target_os = "linux")]
- fn on_remove_split_tunnel_process(&mut self, tx: oneshot::Sender<()>, pid: i32) {
- match self.exclude_pids.remove(pid) {
- Ok(()) => Self::oneshot_send(tx, (), "remove_split_tunnel_process response"),
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to remove PID")),
- }
+ fn on_remove_split_tunnel_process(
+ &mut self,
+ tx: ResponseTx<(), split_tunnel::Error>,
+ pid: i32,
+ ) {
+ let result = self.exclude_pids.remove(pid).map_err(|error| {
+ error!("{}", error.display_chain_with_msg("Unable to remove PID"));
+ error
+ });
+ Self::oneshot_send(tx, result, "remove_split_tunnel_process response");
}
#[cfg(target_os = "linux")]
- fn on_clear_split_tunnel_processes(&mut self, tx: oneshot::Sender<()>) {
- match self.exclude_pids.clear() {
- Ok(()) => Self::oneshot_send(tx, (), "clear_split_tunnel_processes response"),
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to clear PIDs")),
- }
+ fn on_clear_split_tunnel_processes(&mut self, tx: ResponseTx<(), split_tunnel::Error>) {
+ let result = self.exclude_pids.clear().map_err(|error| {
+ error!("{}", error.display_chain_with_msg("Unable to clear PIDs"));
+ error
+ });
+ Self::oneshot_send(tx, result, "clear_split_tunnel_processes response");
}
- fn on_update_relay_settings(&mut self, tx: oneshot::Sender<()>, update: RelaySettingsUpdate) {
+ fn on_update_relay_settings(
+ &mut self,
+ tx: ResponseTx<(), settings::Error>,
+ update: RelaySettingsUpdate,
+ ) {
let save_result = self.settings.update_relay_settings(update);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "update_relay_settings response");
+ Self::oneshot_send(tx, Ok(()), "update_relay_settings response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
@@ -1586,30 +1640,40 @@ where
self.reconnect_tunnel();
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "update_relay_settings response");
+ }
}
}
- fn on_set_allow_lan(&mut self, tx: oneshot::Sender<()>, allow_lan: bool) {
+ fn on_set_allow_lan(&mut self, tx: ResponseTx<(), settings::Error>, allow_lan: bool) {
let save_result = self.settings.set_allow_lan(allow_lan);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_allow_lan response");
+ Self::oneshot_send(tx, Ok(()), "set_allow_lan response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
self.send_tunnel_command(TunnelCommand::AllowLan(allow_lan));
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_allow_lan response");
+ }
}
}
- async fn on_set_show_beta_releases(&mut self, tx: oneshot::Sender<()>, enabled: bool) {
+ async fn on_set_show_beta_releases(
+ &mut self,
+ tx: ResponseTx<(), settings::Error>,
+ enabled: bool,
+ ) {
let save_result = self.settings.set_show_beta_releases(enabled);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_show_beta_releases response");
+ Self::oneshot_send(tx, Ok(()), "set_show_beta_releases response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
@@ -1617,13 +1681,16 @@ where
handle.set_show_beta_releases(enabled).await;
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_show_beta_releases response");
+ }
}
}
fn on_set_block_when_disconnected(
&mut self,
- tx: oneshot::Sender<()>,
+ tx: ResponseTx<(), settings::Error>,
block_when_disconnected: bool,
) {
let save_result = self
@@ -1631,7 +1698,7 @@ where
.set_block_when_disconnected(block_when_disconnected);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_block_when_disconnected response");
+ Self::oneshot_send(tx, Ok(()), "set_block_when_disconnected response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
@@ -1640,29 +1707,39 @@ where
));
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_block_when_disconnected response");
+ }
}
}
- fn on_set_auto_connect(&mut self, tx: oneshot::Sender<()>, auto_connect: bool) {
+ fn on_set_auto_connect(&mut self, tx: ResponseTx<(), settings::Error>, auto_connect: bool) {
let save_result = self.settings.set_auto_connect(auto_connect);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set auto-connect response");
+ Self::oneshot_send(tx, Ok(()), "set auto-connect response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set auto-connect response");
+ }
}
}
- fn on_set_openvpn_mssfix(&mut self, tx: oneshot::Sender<()>, mssfix_arg: Option<u16>) {
+ fn on_set_openvpn_mssfix(
+ &mut self,
+ tx: ResponseTx<(), settings::Error>,
+ mssfix_arg: Option<u16>,
+ ) {
let save_result = self.settings.set_openvpn_mssfix(mssfix_arg);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_openvpn_mssfix response");
+ Self::oneshot_send(tx, Ok(()), "set_openvpn_mssfix response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
@@ -1674,13 +1751,16 @@ where
}
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_openvpn_mssfix response");
+ }
}
}
fn on_set_bridge_settings(
&mut self,
- tx: oneshot::Sender<Result<(), settings::Error>>,
+ tx: ResponseTx<(), settings::Error>,
new_settings: BridgeSettings,
) {
match self.settings.set_bridge_settings(new_settings) {
@@ -1705,7 +1785,7 @@ where
fn on_set_bridge_state(
&mut self,
- tx: oneshot::Sender<Result<(), settings::Error>>,
+ tx: ResponseTx<(), settings::Error>,
bridge_state: BridgeState,
) {
let result = match self.settings.set_bridge_state(bridge_state) {
@@ -1730,11 +1810,11 @@ where
}
- fn on_set_enable_ipv6(&mut self, tx: oneshot::Sender<()>, enable_ipv6: bool) {
+ fn on_set_enable_ipv6(&mut self, tx: ResponseTx<(), settings::Error>, enable_ipv6: bool) {
let save_result = self.settings.set_enable_ipv6(enable_ipv6);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_enable_ipv6 response");
+ Self::oneshot_send(tx, Ok(()), "set_enable_ipv6 response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
@@ -1742,15 +1822,18 @@ where
self.reconnect_tunnel();
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_enable_ipv6 response");
+ }
}
}
- fn on_set_dns_options(&mut self, tx: oneshot::Sender<()>, dns_options: DnsOptions) {
+ fn on_set_dns_options(&mut self, tx: ResponseTx<(), settings::Error>, dns_options: DnsOptions) {
let save_result = self.settings.set_dns_options(dns_options.clone());
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_dns_options response");
+ Self::oneshot_send(tx, Ok(()), "set_dns_options response");
if settings_changed {
let settings = self.settings.to_settings();
let resolvers =
@@ -1759,15 +1842,18 @@ where
self.send_tunnel_command(TunnelCommand::CustomDns(resolvers));
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_dns_options response");
+ }
}
}
- fn on_set_wireguard_mtu(&mut self, tx: oneshot::Sender<()>, mtu: Option<u16>) {
+ fn on_set_wireguard_mtu(&mut self, tx: ResponseTx<(), settings::Error>, mtu: Option<u16>) {
let save_result = self.settings.set_wireguard_mtu(mtu);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_wireguard_mtu response");
+ Self::oneshot_send(tx, Ok(()), "set_wireguard_mtu response");
if settings_changed {
self.event_listener
.notify_settings(self.settings.to_settings());
@@ -1779,26 +1865,32 @@ where
}
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_wireguard_mtu response");
+ }
}
}
async fn on_set_wireguard_rotation_interval(
&mut self,
- tx: oneshot::Sender<()>,
+ tx: ResponseTx<(), settings::Error>,
interval: Option<u32>,
) {
let save_result = self.settings.set_wireguard_rotation_interval(interval);
match save_result {
Ok(settings_changed) => {
- Self::oneshot_send(tx, (), "set_wireguard_rotation_interval response");
+ Self::oneshot_send(tx, Ok(()), "set_wireguard_rotation_interval response");
if settings_changed {
self.ensure_key_rotation().await;
self.event_listener
.notify_settings(self.settings.to_settings());
}
}
- Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
+ Err(e) => {
+ error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_wireguard_rotation_interval response");
+ }
}
}
@@ -1822,28 +1914,29 @@ where
}
}
- async fn on_generate_wireguard_key(&mut self, tx: oneshot::Sender<KeygenEvent>) {
+ async fn on_generate_wireguard_key(&mut self, tx: ResponseTx<KeygenEvent, Error>) {
match self.on_generate_wireguard_key_inner().await {
Ok(key_event) => {
- Self::oneshot_send(tx, key_event, "generate_wireguard_key response");
+ Self::oneshot_send(tx, Ok(key_event), "generate_wireguard_key");
}
Err(e) => {
log::error!("Failed to generate new wireguard key - {}", e);
+ Self::oneshot_send(tx, Err(e), "generate_wireguard_key");
}
}
}
- async fn on_generate_wireguard_key_inner(&mut self) -> Result<KeygenEvent, String> {
+ async fn on_generate_wireguard_key_inner(&mut self) -> Result<KeygenEvent, Error> {
let account_token = self
.settings
.get_account_token()
- .ok_or_else(|| "No account token set".to_owned())?;
+ .ok_or(Error::NoAccountToken)?;
let mut account_entry = self
.account_history
.get(&account_token)
.await
- .map_err(|e| format!("Failed to read account entry from history: {}", e))
+ .map_err(Error::AccountHistory)
.map(|data| {
data.unwrap_or_else(|| {
log::error!("Account token set in settings but not in account history");
@@ -1874,9 +1967,7 @@ where
self.account_history
.insert(account_entry)
.await
- .map_err(|e| {
- format!("Failed to add new wireguard key to account data: {}", e)
- })?;
+ .map_err(Error::AccountHistory)?;
if let Some(TunnelType::Wireguard) = self.get_target_tunnel_type() {
self.reconnect_tunnel();
}
@@ -1899,29 +1990,33 @@ where
Ok(keygen_event)
}
Err(wireguard::Error::TooManyKeys) => Ok(KeygenEvent::TooManyKeys),
- Err(e) => Err(format!(
- "Failed to generate new key - {}",
- e.display_chain_with_msg("Failed to generate new wireguard key:")
- )),
+ Err(wireguard::Error::RestError(error)) => Err(Error::RestError(error)),
}
}
- async fn on_get_wireguard_key(&mut self, tx: oneshot::Sender<Option<wireguard::PublicKey>>) {
+ async fn on_get_wireguard_key(&mut self, tx: ResponseTx<Option<wireguard::PublicKey>, Error>) {
let token = self.settings.get_account_token();
- if let Some(token) = token {
+ let result = if let Some(token) = token {
let entry = self.account_history.get(&token).await;
- if let Ok(Some(entry)) = entry {
- let key = entry.wireguard.map(|wg| wg.get_public_key());
- Self::oneshot_send(tx, key, "get_wireguard_key response");
+ match entry {
+ Ok(Some(entry)) => {
+ let key = entry.wireguard.map(|wg| wg.get_public_key());
+ Ok(key)
+ }
+ Ok(None) => Err(Error::NoAccountTokenHistory),
+ Err(error) => Err(Error::AccountHistory(error)),
}
- }
+ } else {
+ Err(Error::NoAccountToken)
+ };
+ Self::oneshot_send(tx, result, "get_wireguard_key response");
}
- async fn on_verify_wireguard_key(&mut self, tx: oneshot::Sender<bool>) {
+ async fn on_verify_wireguard_key(&mut self, tx: ResponseTx<bool, Error>) {
let account = match self.settings.get_account_token() {
Some(account) => account,
None => {
- Self::oneshot_send(tx, false, "verify_wireguard_key response");
+ Self::oneshot_send(tx, Ok(false), "verify_wireguard_key response");
return;
}
};
@@ -1935,11 +2030,16 @@ where
let public_key = match key {
Ok(Some(public_key)) => public_key,
Ok(None) => {
- Self::oneshot_send(tx, false, "verify_wireguard_key response");
+ Self::oneshot_send(tx, Ok(false), "verify_wireguard_key response");
return;
}
Err(e) => {
log::error!("Failed to read key data: {}", e);
+ Self::oneshot_send(
+ tx,
+ Err(Error::AccountHistory(e)),
+ "verify_wireguard_key response",
+ );
return;
}
};
@@ -1949,14 +2049,12 @@ where
.verify_wireguard_key(account, public_key);
tokio::spawn(async move {
- match verification_rpc.await {
- Ok(is_valid) => {
- Self::oneshot_send(tx, is_valid, "verify_wireguard_key response");
- }
- Err(err) => {
- log::error!("Failed to verify wireguard key - {}", err);
- }
- }
+ let result = match verification_rpc.await {
+ Ok(is_valid) => Ok(is_valid),
+ Err(wireguard::Error::RestError(error)) => Err(Error::RestError(error)),
+ Err(wireguard::Error::TooManyKeys) => return,
+ };
+ Self::oneshot_send(tx, result, "verify_wireguard_key response");
});
}
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index ccde44ba8f..7faa0eee14 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -1,4 +1,4 @@
-use crate::{DaemonCommand, DaemonCommandSender, EventListener};
+use crate::{account_history, settings, DaemonCommand, DaemonCommandSender, EventListener};
use futures::channel::oneshot;
use mullvad_management_interface::{
types::{self, daemon_event, management_service_server::ManagementService},
@@ -67,7 +67,7 @@ impl ManagementService for ManagementServiceImpl {
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetTargetState(tx, TargetState::Secured))?;
- let connect_issued = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let connect_issued = self.wait_for_result(rx).await?;
Ok(Response::new(connect_issued))
}
@@ -76,7 +76,7 @@ impl ManagementService for ManagementServiceImpl {
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetTargetState(tx, TargetState::Unsecured))?;
- let disconnect_issued = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let disconnect_issued = self.wait_for_result(rx).await?;
Ok(Response::new(disconnect_issued))
}
@@ -84,7 +84,7 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("reconnect_tunnel");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::Reconnect(tx))?;
- let reconnect_issued = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let reconnect_issued = self.wait_for_result(rx).await?;
Ok(Response::new(reconnect_issued))
}
@@ -92,7 +92,7 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("get_tunnel_state");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetState(tx))?;
- let state = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let state = self.wait_for_result(rx).await?;
Ok(Response::new(convert_state(state)))
}
@@ -126,13 +126,14 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("factory_reset");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::FactoryReset(tx))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_daemon_error)
}
#[cfg(target_os = "android")]
{
- Response::new(())
+ Ok(Response::new(()))
}
}
@@ -140,9 +141,8 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("get_current_version");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetCurrentVersion(tx))?;
- rx.await
- .map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ let version = self.wait_for_result(rx).await?;
+ Ok(Response::new(version))
}
async fn get_version_info(&self, _: Request<()>) -> ServiceResult<types::AppVersionInfo> {
@@ -150,8 +150,8 @@ impl ManagementService for ManagementServiceImpl {
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetVersionInfo(tx))?;
- let version_info = rx.await.map_err(|_| Status::internal("internal error"))?;
- version_info
+ self.wait_for_result(rx)
+ .await?
.ok_or(Status::not_found("no version cache"))
.map(|version_info| convert_version_info(&version_info))
.map(Response::new)
@@ -176,9 +176,10 @@ impl ManagementService for ManagementServiceImpl {
let message = DaemonCommand::UpdateRelaySettings(tx, constraints_update);
self.send_command_to_daemon(message)?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn get_relay_locations(
@@ -189,7 +190,7 @@ impl ManagementService for ManagementServiceImpl {
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetRelayLocations(tx))?;
- let locations = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let locations = self.wait_for_result(rx).await?;
let (mut stream_tx, stream_rx) =
tokio::sync::mpsc::channel(cmp::max(1, locations.countries.len()));
@@ -215,7 +216,7 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("get_current_location");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetCurrentLocation(tx))?;
- let result = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let result = self.wait_for_result(rx).await?;
match result {
Some(geoip) => Ok(Response::new(convert_geoip_location(geoip))),
None => Err(Status::not_found("no location was found")),
@@ -295,10 +296,10 @@ impl ManagementService for ManagementServiceImpl {
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetBridgeSettings(tx, settings))?;
- let settings_result = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let settings_result = self.wait_for_result(rx).await?;
settings_result
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn set_bridge_state(&self, request: Request<types::BridgeState>) -> ServiceResult<()> {
@@ -314,10 +315,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("set_bridge_state({:?})", bridge_state);
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetBridgeState(tx, bridge_state))?;
- let settings_result = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let settings_result = self.wait_for_result(rx).await?;
settings_result
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
// Settings
@@ -327,9 +328,9 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("get_settings");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetSettings(tx))?;
- rx.await
+ self.wait_for_result(rx)
+ .await
.map(|settings| Response::new(convert_settings(&settings)))
- .map_err(|_| Status::internal("internal error"))
}
async fn set_allow_lan(&self, request: Request<bool>) -> ServiceResult<()> {
@@ -337,9 +338,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("set_allow_lan({})", allow_lan);
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetAllowLan(tx, allow_lan))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn set_show_beta_releases(&self, request: Request<bool>) -> ServiceResult<()> {
@@ -347,9 +349,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("set_show_beta_releases({})", enabled);
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetShowBetaReleases(tx, enabled))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn set_block_when_disconnected(&self, request: Request<bool>) -> ServiceResult<()> {
@@ -360,9 +363,10 @@ impl ManagementService for ManagementServiceImpl {
tx,
block_when_disconnected,
))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn set_auto_connect(&self, request: Request<bool>) -> ServiceResult<()> {
@@ -370,9 +374,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("set_auto_connect({})", auto_connect);
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetAutoConnect(tx, auto_connect))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn set_openvpn_mssfix(&self, request: Request<u32>) -> ServiceResult<()> {
@@ -385,9 +390,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("set_openvpn_mssfix({:?})", mssfix);
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetOpenVpnMssfix(tx, mssfix))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn set_wireguard_mtu(&self, request: Request<u32>) -> ServiceResult<()> {
@@ -396,9 +402,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("set_wireguard_mtu({:?})", mtu);
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetWireguardMtu(tx, mtu))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn set_enable_ipv6(&self, request: Request<bool>) -> ServiceResult<()> {
@@ -406,9 +413,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("set_enable_ipv6({})", enable_ipv6);
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetEnableIpv6(tx, enable_ipv6))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
#[cfg(not(target_os = "android"))]
@@ -438,9 +446,10 @@ impl ManagementService for ManagementServiceImpl {
addresses: servers_ip,
},
))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
#[cfg(target_os = "android")]
async fn set_dns_options(&self, _: Request<types::DnsOptions>) -> ServiceResult<()> {
@@ -453,11 +462,10 @@ impl ManagementService for ManagementServiceImpl {
async fn create_new_account(&self, _: Request<()>) -> ServiceResult<String> {
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::CreateNewAccount(tx))?;
- let result = rx.await.map_err(|_| Status::internal("internal error"))?;
- match result {
- Ok(account_token) => Ok(Response::new(account_token)),
- Err(_) => Err(Status::internal("internal error")),
- }
+ self.wait_for_result(rx)
+ .await?
+ .map(Response::new)
+ .map_err(map_daemon_error)
}
async fn set_account(&self, request: Request<AccountToken>) -> ServiceResult<()> {
@@ -470,9 +478,10 @@ impl ManagementService for ManagementServiceImpl {
};
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetAccount(tx, account_token))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_settings_error)
}
async fn get_account_data(
@@ -483,7 +492,7 @@ impl ManagementService for ManagementServiceImpl {
let account_token = request.into_inner();
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetAccountData(tx, account_token))?;
- let result = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let result = self.wait_for_result(rx).await?;
result
.map(|account_data| {
Response::new(types::AccountData {
@@ -498,7 +507,7 @@ impl ManagementService for ManagementServiceImpl {
"Unable to get account data from API: {}",
error.display_chain()
);
- map_rest_account_error(error)
+ map_rest_error(error)
})
}
@@ -507,8 +516,8 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("get_account_history");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetAccountHistory(tx))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
+ self.wait_for_result(rx)
+ .await
.map(|history| Response::new(types::AccountHistory { token: history }))
}
@@ -520,34 +529,34 @@ impl ManagementService for ManagementServiceImpl {
let account_token = request.into_inner();
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::RemoveAccountFromHistory(tx, account_token))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_daemon_error)
}
async fn clear_account_history(&self, _: Request<()>) -> ServiceResult<()> {
log::debug!("clear_account_history");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::ClearAccountHistory(tx))?;
- rx.await
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(map_daemon_error)
}
async fn get_www_auth_token(&self, _: Request<()>) -> ServiceResult<String> {
log::debug!("get_www_auth_token");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetWwwAuthToken(tx))?;
- let result = rx.await.map_err(|_| Status::internal("internal error"))?;
- result
- .map(Response::new)
- .map_err(|error: mullvad_rpc::rest::Error| {
- log::error!(
- "Unable to get account data from API: {}",
- error.display_chain()
- );
- map_rest_account_error(error)
- })
+ let result = self.wait_for_result(rx).await?;
+ result.map(Response::new).map_err(|error| {
+ log::error!(
+ "Unable to get account data from API: {}",
+ error.display_chain()
+ );
+ map_daemon_error(error)
+ })
}
async fn submit_voucher(
@@ -558,7 +567,7 @@ impl ManagementService for ManagementServiceImpl {
let voucher = request.into_inner();
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SubmitVoucher(tx, voucher))?;
- let result = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let result = self.wait_for_result(rx).await?;
result
.map(|submission| {
Response::new(types::VoucherSubmission {
@@ -569,19 +578,9 @@ impl ManagementService for ManagementServiceImpl {
}),
})
})
- .map_err(|e| match e {
- RestError::ApiError(StatusCode::BAD_REQUEST, message) => match &message.as_str() {
- &mullvad_rpc::INVALID_VOUCHER => {
- Status::new(Code::NotFound, INVALID_VOUCHER_MESSAGE)
- }
-
- &mullvad_rpc::VOUCHER_USED => {
- Status::new(Code::ResourceExhausted, USED_VOUCHER_MESSAGE)
- }
-
- _ => Status::internal("internal error"),
- },
- _ => Status::internal("internal error"),
+ .map_err(|error| match error {
+ crate::Error::RestError(error) => map_rest_voucher_error(error),
+ error => map_daemon_error(error),
})
}
@@ -597,18 +596,20 @@ impl ManagementService for ManagementServiceImpl {
tx,
Some(interval),
))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
+ .map_err(map_settings_error)
}
async fn reset_wireguard_rotation_interval(&self, _: Request<()>) -> ServiceResult<()> {
log::debug!("reset_wireguard_rotation_interval");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::SetWireguardRotationInterval(tx, None))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
+ .map_err(map_settings_error)
}
async fn generate_wireguard_key(&self, _: Request<()>) -> ServiceResult<types::KeygenEvent> {
@@ -617,20 +618,20 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("generate_wireguard_key");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GenerateWireguardKey(tx))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
+ self.wait_for_result(rx)
+ .await?
.map(|event| Response::new(convert_wireguard_key_event(&event)))
+ .map_err(map_daemon_error)
}
async fn get_wireguard_key(&self, _: Request<()>) -> ServiceResult<types::PublicKey> {
log::debug!("get_wireguard_key");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetWireguardKey(tx))?;
- let response = rx.await.map_err(|_| Status::internal("internal error"));
- match response {
- Ok(Some(key)) => Ok(Response::new(convert_public_key(&key))),
- Ok(None) => Err(Status::not_found("no WireGuard key was found")),
- Err(e) => Err(e),
+ let key = self.wait_for_result(rx).await?.map_err(map_daemon_error)?;
+ match key {
+ Some(key) => Ok(Response::new(convert_public_key(&key))),
+ None => Err(Status::not_found("no WireGuard key was found")),
}
}
@@ -638,9 +639,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("verify_wireguard_key");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::VerifyWireguardKey(tx))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
+ self.wait_for_result(rx)
+ .await?
.map(Response::new)
+ .map_err(map_daemon_error)
}
// Split tunneling
@@ -655,7 +657,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("get_split_tunnel_processes");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::GetSplitTunnelProcesses(tx))?;
- let pids = rx.await.map_err(|_| Status::internal("internal error"))?;
+ let pids = self
+ .wait_for_result(rx)
+ .await?
+ .map_err(|error| Status::failed_precondition(error.to_string()))?;
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
tokio::spawn(async move {
@@ -679,9 +684,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("add_split_tunnel_process");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::AddSplitTunnelProcess(tx, pid))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
- .map(Response::new)
+ self.wait_for_result(rx)
+ .await?
+ .map_err(|error| Status::failed_precondition(error.to_string()))?;
+ Ok(Response::new(()))
}
#[cfg(not(target_os = "linux"))]
async fn add_split_tunnel_process(&self, _: Request<i32>) -> ServiceResult<()> {
@@ -694,9 +700,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("remove_split_tunnel_process");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::RemoveSplitTunnelProcess(tx, pid))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
- .map(Response::new)
+ self.wait_for_result(rx)
+ .await?
+ .map_err(|error| Status::failed_precondition(error.to_string()))?;
+ Ok(Response::new(()))
}
#[cfg(not(target_os = "linux"))]
async fn remove_split_tunnel_process(&self, _: Request<i32>) -> ServiceResult<()> {
@@ -709,9 +716,10 @@ impl ManagementService for ManagementServiceImpl {
log::debug!("clear_split_tunnel_processes");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::ClearSplitTunnelProcesses(tx))?;
- rx.await
- .map_err(|_| Status::internal("internal error"))
- .map(Response::new)
+ self.wait_for_result(rx)
+ .await?
+ .map_err(|error| Status::failed_precondition(error.to_string()))?;
+ Ok(Response::new(()))
}
#[cfg(not(target_os = "linux"))]
{
@@ -725,7 +733,11 @@ impl ManagementServiceImpl {
fn send_command_to_daemon(&self, command: DaemonCommand) -> Result<(), Status> {
self.daemon_tx
.send(command)
- .map_err(|_| Status::internal("internal error"))
+ .map_err(|_| Status::internal("the daemon channel receiver has been dropped"))
+ }
+
+ async fn wait_for_result<T>(&self, rx: oneshot::Receiver<T>) -> Result<T, Status> {
+ rx.await.map_err(|_| Status::internal("sender was dropped"))
}
}
@@ -1618,14 +1630,69 @@ impl Drop for ManagementInterfaceEventBroadcaster {
}
}
-// Converts a REST API error for an account into a tonic status.
-fn map_rest_account_error(error: RestError) -> Status {
+/// Converts [`mullvad_daemon::Error`] into a tonic status.
+fn map_daemon_error(error: crate::Error) -> Status {
+ use crate::Error as DaemonError;
+
+ match error {
+ DaemonError::RestError(error) => map_rest_error(error),
+ DaemonError::SettingsError(error) => map_settings_error(error),
+ DaemonError::AccountHistory(error) => map_account_history_error(error),
+ DaemonError::NoAccountToken | DaemonError::NoAccountTokenHistory => {
+ Status::unauthenticated(error.to_string())
+ }
+ error => Status::unknown(error.to_string()),
+ }
+}
+
+/// Converts a REST API voucher error into a tonic status.
+fn map_rest_voucher_error(error: RestError) -> Status {
+ match error {
+ RestError::ApiError(StatusCode::BAD_REQUEST, message) => match &message.as_str() {
+ &mullvad_rpc::INVALID_VOUCHER => Status::new(Code::NotFound, INVALID_VOUCHER_MESSAGE),
+
+ &mullvad_rpc::VOUCHER_USED => {
+ Status::new(Code::ResourceExhausted, USED_VOUCHER_MESSAGE)
+ }
+
+ error => Status::unknown(format!("Voucher error: {}", error)),
+ },
+ error => map_rest_error(error),
+ }
+}
+
+/// Converts a REST API error into a tonic status.
+fn map_rest_error(error: RestError) -> Status {
match error {
RestError::ApiError(status, message)
if status == StatusCode::UNAUTHORIZED || status == StatusCode::FORBIDDEN =>
{
Status::new(Code::Unauthenticated, message)
}
- _ => Status::internal("internal error"),
+ RestError::TimeoutError(_elapsed) => Status::deadline_exceeded("API request timed out"),
+ RestError::HyperError(_) => Status::unavailable("Cannot reach the API"),
+ error => Status::unknown(format!("REST error: {}", error)),
+ }
+}
+
+/// Converts an instance of [`mullvad_daemon::settings::Error`] into a tonic status.
+fn map_settings_error(error: settings::Error) -> Status {
+ match error {
+ settings::Error::DeleteError(..) | settings::Error::WriteError(..) => {
+ Status::new(Code::FailedPrecondition, error.to_string())
+ }
+ settings::Error::SerializeError(..) => Status::new(Code::Internal, error.to_string()),
+ }
+}
+
+/// Converts an instance of [`mullvad_daemon::account_history::Error`] into a tonic status.
+fn map_account_history_error(error: account_history::Error) -> Status {
+ match error {
+ account_history::Error::Read(..) | account_history::Error::Write(..) => {
+ Status::new(Code::FailedPrecondition, error.to_string())
+ }
+ account_history::Error::Serialize(..) | account_history::Error::WriteCancelled(..) => {
+ Status::new(Code::Internal, error.to_string())
+ }
}
}
diff --git a/mullvad-jni/src/daemon_interface.rs b/mullvad-jni/src/daemon_interface.rs
index 4b54ca4c58..777cee99c2 100644
--- a/mullvad-jni/src/daemon_interface.rs
+++ b/mullvad-jni/src/daemon_interface.rs
@@ -12,6 +12,7 @@ use mullvad_types::{
};
#[derive(Debug, err_derive::Error)]
+#[error(no_from)]
pub enum Error {
#[error(display = "Can't send command to daemon because it is not running")]
NoDaemon(#[error(source)] mullvad_daemon::Error),
@@ -24,6 +25,21 @@ pub enum Error {
#[error(display = "Error performing RPC with the remote API")]
RpcError(#[error(source)] mullvad_rpc::rest::Error),
+
+ #[error(display = "Failed to update settings")]
+ SettingsError,
+
+ #[error(display = "Daemon returned an error")]
+ OtherError(#[error(source)] mullvad_daemon::Error),
+}
+
+impl From<mullvad_daemon::Error> for Error {
+ fn from(error: mullvad_daemon::Error) -> Error {
+ match error {
+ mullvad_daemon::Error::RestError(error) => Error::RpcError(error),
+ error => Error::OtherError(error),
+ }
+ }
}
type Result<T> = std::result::Result<T, Error>;
@@ -52,7 +68,7 @@ impl DaemonInterface {
block_on(rx)
.map_err(|_| Error::NoResponse)?
- .map_err(Error::RpcError)
+ .map_err(Error::from)
}
pub fn disconnect(&self) -> Result<()> {
@@ -68,7 +84,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::GenerateWireguardKey(tx))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(Error::from)
}
pub fn get_account_data(&self, account_token: String) -> Result<AccountData> {
@@ -96,7 +114,7 @@ impl DaemonInterface {
block_on(rx)
.map_err(|_| Error::NoResponse)?
- .map_err(Error::RpcError)
+ .map_err(Error::from)
}
pub fn get_current_location(&self) -> Result<Option<GeoIpLocation>> {
@@ -162,7 +180,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::RemoveAccountFromHistory(tx, account_token))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(Error::from)
}
pub fn get_wireguard_key(&self) -> Result<Option<wireguard::PublicKey>> {
@@ -170,14 +190,18 @@ impl DaemonInterface {
self.send_command(DaemonCommand::GetWireguardKey(tx))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(Error::from)
}
pub fn verify_wireguard_key(&self) -> Result<bool> {
let (tx, rx) = oneshot::channel();
self.send_command(DaemonCommand::VerifyWireguardKey(tx))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(Error::from)
}
pub fn set_account(&self, account_token: Option<String>) -> Result<()> {
@@ -185,7 +209,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::SetAccount(tx, account_token))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(|_| Error::SettingsError)
}
pub fn set_allow_lan(&self, allow_lan: bool) -> Result<()> {
@@ -193,7 +219,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::SetAllowLan(tx, allow_lan))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(|_| Error::SettingsError)
}
pub fn set_auto_connect(&self, auto_connect: bool) -> Result<()> {
@@ -201,7 +229,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::SetAutoConnect(tx, auto_connect))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(|_| Error::SettingsError)
}
pub fn set_dns_options(&self, dns_options: DnsOptions) -> Result<()> {
@@ -209,7 +239,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::SetDnsOptions(tx, dns_options))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(|_| Error::SettingsError)
}
pub fn set_wireguard_mtu(&self, wireguard_mtu: Option<u16>) -> Result<()> {
@@ -217,7 +249,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::SetWireguardMtu(tx, wireguard_mtu))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(|_| Error::SettingsError)
}
pub fn shutdown(&self) -> Result<()> {
@@ -231,7 +265,7 @@ impl DaemonInterface {
block_on(rx)
.map_err(|_| Error::NoResponse)?
- .map_err(Error::RpcError)
+ .map_err(Error::from)
}
pub fn update_relay_settings(&self, update: RelaySettingsUpdate) -> Result<()> {
@@ -239,7 +273,9 @@ impl DaemonInterface {
self.send_command(DaemonCommand::UpdateRelaySettings(tx, update))?;
- block_on(rx).map_err(|_| Error::NoResponse)
+ block_on(rx)
+ .map_err(|_| Error::NoResponse)?
+ .map_err(|_| Error::SettingsError)
}
fn send_command(&self, command: DaemonCommand) -> Result<()> {