summaryrefslogtreecommitdiffhomepage
path: root/mullvad-cli/src
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2023-04-07 00:50:22 +0200
committerDavid Lönnhager <david.l@mullvad.net>2023-05-03 10:40:09 +0200
commit8117988bb826c1cb4e5f8345717a7368fc64c379 (patch)
tree2333ab8c1354833e893302856f1f0c38ecbae48b /mullvad-cli/src
parent5a8ce732572e83e8abbdef7afa38394730ed7ee7 (diff)
downloadmullvadvpn-8117988bb826c1cb4e5f8345717a7368fc64c379.tar.xz
mullvadvpn-8117988bb826c1cb4e5f8345717a7368fc64c379.zip
Replace error handling in mullvad-cli with anyhow
Diffstat (limited to 'mullvad-cli/src')
-rw-r--r--mullvad-cli/src/cmds/account.rs47
-rw-r--r--mullvad-cli/src/cmds/auto_connect.rs2
-rw-r--r--mullvad-cli/src/cmds/beta_program.rs4
-rw-r--r--mullvad-cli/src/cmds/bridge.rs3
-rw-r--r--mullvad-cli/src/cmds/dns.rs3
-rw-r--r--mullvad-cli/src/cmds/lan.rs2
-rw-r--r--mullvad-cli/src/cmds/lockdown.rs2
-rw-r--r--mullvad-cli/src/cmds/obfuscation.rs3
-rw-r--r--mullvad-cli/src/cmds/relay.rs11
-rw-r--r--mullvad-cli/src/cmds/reset.rs6
-rw-r--r--mullvad-cli/src/cmds/split_tunnel/linux.rs3
-rw-r--r--mullvad-cli/src/cmds/split_tunnel/windows.rs2
-rw-r--r--mullvad-cli/src/cmds/status.rs5
-rw-r--r--mullvad-cli/src/cmds/tunnel.rs3
-rw-r--r--mullvad-cli/src/cmds/tunnel_state.rs11
-rw-r--r--mullvad-cli/src/cmds/version.rs18
-rw-r--r--mullvad-cli/src/main.rs73
17 files changed, 59 insertions, 139 deletions
diff --git a/mullvad-cli/src/cmds/account.rs b/mullvad-cli/src/cmds/account.rs
index cf0d2e9df5..d46469484f 100644
--- a/mullvad-cli/src/cmds/account.rs
+++ b/mullvad-cli/src/cmds/account.rs
@@ -1,20 +1,12 @@
-use std::io::{self, Write};
-
+use anyhow::{anyhow, Result};
use clap::Subcommand;
use itertools::Itertools;
use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::{account::AccountToken, device::DeviceState};
-
-use crate::{Error, Result};
+use std::io::{self, Write};
const NOT_LOGGED_IN_MESSAGE: &str = "Not logged in on any account";
const REVOKED_MESSAGE: &str = "The current device has been revoked";
-const DEVICE_NOT_FOUND_ERROR: &str = "There is no such device";
-const INVALID_ACCOUNT_ERROR: &str = "The account does not exist";
-const TOO_MANY_DEVICES_ERROR: &str =
- "There are too many devices on this account. Revoke one to log in";
-const ALREADY_LOGGED_IN_ERROR: &str =
- "You are already logged in. Please log out before creating a new account";
#[derive(Subcommand, Debug)]
pub enum Account {
@@ -90,15 +82,13 @@ impl Account {
}
async fn create(rpc: &mut MullvadProxyClient) -> Result<()> {
- rpc.create_new_account().await.map_err(map_device_error)?;
+ rpc.create_new_account().await?;
println!("New account created!");
Self::get(rpc, false).await
}
async fn login(rpc: &mut MullvadProxyClient, token: AccountToken) -> Result<()> {
- rpc.login_account(token.clone())
- .await
- .map_err(map_device_error)?;
+ rpc.login_account(token.clone()).await?;
println!("Mullvad account \"{token}\" set");
Ok(())
}
@@ -112,7 +102,7 @@ impl Account {
async fn get(rpc: &mut MullvadProxyClient, verbose: bool) -> Result<()> {
let _ = rpc.update_device().await;
- let state = rpc.get_device().await.map_err(map_device_error)?;
+ let state = rpc.get_device().await?;
match state {
DeviceState::LoggedIn(device) => {
@@ -149,7 +139,7 @@ impl Account {
verbose: bool,
) -> Result<()> {
let token = account_else_current(rpc, account).await?;
- let mut device_list = rpc.list_devices(token).await.map_err(map_device_error)?;
+ let mut device_list = rpc.list_devices(token).await?;
println!("Devices on the account:");
device_list.sort_unstable_by_key(|dev| dev.created.timestamp());
@@ -181,21 +171,16 @@ impl Account {
) -> Result<()> {
let token = account_else_current(rpc, account).await?;
- let device_list = rpc
- .list_devices(token.clone())
- .await
- .map_err(map_device_error)?;
+ let device_list = rpc.list_devices(token.clone()).await?;
let device_id = device_list
.into_iter()
.find(|dev| {
dev.name.eq_ignore_ascii_case(&device) || dev.id.eq_ignore_ascii_case(&device)
})
.map(|dev| dev.id)
- .ok_or(Error::Other(DEVICE_NOT_FOUND_ERROR))?;
+ .ok_or(mullvad_management_interface::Error::DeviceNotFound)?;
- rpc.remove_device(token, device_id)
- .await
- .map_err(map_device_error)?;
+ rpc.remove_device(token, device_id).await?;
println!("Removed device");
Ok(())
}
@@ -216,18 +201,6 @@ impl Account {
}
}
-fn map_device_error(error: mullvad_management_interface::Error) -> Error {
- match &error {
- mullvad_management_interface::Error::TooManyDevices => Error::Other(TOO_MANY_DEVICES_ERROR),
- mullvad_management_interface::Error::InvalidAccount => Error::Other(INVALID_ACCOUNT_ERROR),
- mullvad_management_interface::Error::AlreadyLoggedIn => {
- Error::Other(ALREADY_LOGGED_IN_ERROR)
- }
- mullvad_management_interface::Error::DeviceNotFound => Error::Other(DEVICE_NOT_FOUND_ERROR),
- _other => Error::ManagementInterfaceError(error),
- }
-}
-
async fn account_else_current(
rpc: &mut MullvadProxyClient,
token: Option<String>,
@@ -238,7 +211,7 @@ async fn account_else_current(
let state = rpc.get_device().await?;
match state {
DeviceState::LoggedIn(account) => Ok(account.account_token),
- _ => Err(Error::Other("Log in or specify an account")),
+ _ => Err(anyhow!("Log in or specify an account")),
}
}
}
diff --git a/mullvad-cli/src/cmds/auto_connect.rs b/mullvad-cli/src/cmds/auto_connect.rs
index fda8c292b6..4da11dc68f 100644
--- a/mullvad-cli/src/cmds/auto_connect.rs
+++ b/mullvad-cli/src/cmds/auto_connect.rs
@@ -1,8 +1,8 @@
+use anyhow::Result;
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use super::on_off_parser;
-use crate::Result;
#[derive(Subcommand, Debug)]
pub enum AutoConnect {
diff --git a/mullvad-cli/src/cmds/beta_program.rs b/mullvad-cli/src/cmds/beta_program.rs
index 891599b733..df98efbf79 100644
--- a/mullvad-cli/src/cmds/beta_program.rs
+++ b/mullvad-cli/src/cmds/beta_program.rs
@@ -1,8 +1,8 @@
+use anyhow::{anyhow, Result};
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use super::on_off_parser;
-use crate::{Error, Result};
#[derive(Subcommand, Debug)]
pub enum BetaProgram {
@@ -25,7 +25,7 @@ impl BetaProgram {
async fn set(enable: bool) -> Result<()> {
if !enable && mullvad_version::VERSION.contains("beta") {
- return Err(Error::InvalidCommand(
+ return Err(anyhow!(
"The beta program must be enabled while running a beta version",
));
}
diff --git a/mullvad-cli/src/cmds/bridge.rs b/mullvad-cli/src/cmds/bridge.rs
index c189c16d61..1652a0cfb2 100644
--- a/mullvad-cli/src/cmds/bridge.rs
+++ b/mullvad-cli/src/cmds/bridge.rs
@@ -1,3 +1,4 @@
+use anyhow::Result;
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::{
@@ -10,8 +11,6 @@ use mullvad_types::{
use std::net::{IpAddr, SocketAddr};
use talpid_types::net::openvpn::{self, SHADOWSOCKS_CIPHERS};
-use crate::Result;
-
use super::relay_constraints::LocationArgs;
#[derive(Subcommand, Debug)]
diff --git a/mullvad-cli/src/cmds/dns.rs b/mullvad-cli/src/cmds/dns.rs
index 16611687c1..fd2b215936 100644
--- a/mullvad-cli/src/cmds/dns.rs
+++ b/mullvad-cli/src/cmds/dns.rs
@@ -1,10 +1,9 @@
+use anyhow::Result;
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::settings::{CustomDnsOptions, DefaultDnsOptions, DnsOptions, DnsState};
use std::net::IpAddr;
-use crate::Result;
-
#[derive(Subcommand, Debug)]
pub enum Dns {
/// Display the current DNS settings
diff --git a/mullvad-cli/src/cmds/lan.rs b/mullvad-cli/src/cmds/lan.rs
index ed3c16babe..21c49ca05c 100644
--- a/mullvad-cli/src/cmds/lan.rs
+++ b/mullvad-cli/src/cmds/lan.rs
@@ -1,8 +1,8 @@
+use anyhow::Result;
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use super::on_off_parser_custom;
-use crate::Result;
#[derive(Subcommand, Debug)]
pub enum Lan {
diff --git a/mullvad-cli/src/cmds/lockdown.rs b/mullvad-cli/src/cmds/lockdown.rs
index a57fe86a7f..12cac6d126 100644
--- a/mullvad-cli/src/cmds/lockdown.rs
+++ b/mullvad-cli/src/cmds/lockdown.rs
@@ -1,8 +1,8 @@
+use anyhow::Result;
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use super::on_off_parser;
-use crate::Result;
#[derive(Subcommand, Debug)]
pub enum LockdownMode {
diff --git a/mullvad-cli/src/cmds/obfuscation.rs b/mullvad-cli/src/cmds/obfuscation.rs
index 1b93245e32..b2aaaa1f6e 100644
--- a/mullvad-cli/src/cmds/obfuscation.rs
+++ b/mullvad-cli/src/cmds/obfuscation.rs
@@ -1,11 +1,10 @@
+use anyhow::Result;
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::relay_constraints::{
Constraint, ObfuscationSettings, SelectedObfuscation, Udp2TcpObfuscationSettings,
};
-use crate::Result;
-
#[derive(Subcommand, Debug)]
pub enum Obfuscation {
/// Get current obfuscation settings
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index 437b0977c2..acc99214d4 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -1,3 +1,4 @@
+use anyhow::{anyhow, Context, Result};
use clap::Subcommand;
use itertools::Itertools;
use mullvad_management_interface::MullvadProxyClient;
@@ -19,8 +20,6 @@ use talpid_types::net::{
all_of_the_internet, openvpn, wireguard, Endpoint, IpVersion, TransportProtocol, TunnelType,
};
-use crate::{Error, Result};
-
use super::{on_off_parser, relay_constraints::LocationArgs};
#[derive(Subcommand, Debug)]
@@ -369,8 +368,8 @@ impl Relay {
.await
.unwrap();
- let private_key = wireguard::PrivateKey::from_base64(&private_key_str)
- .map_err(|_| Error::InvalidCommand("invalid private key"))?;
+ let private_key =
+ wireguard::PrivateKey::from_base64(&private_key_str).context("Invalid private key")?;
Ok(CustomTunnelEndpoint {
host,
@@ -415,7 +414,7 @@ impl Relay {
None
};
- let location = find_relay().ok_or(Error::InvalidCommand("hostname not found"))?;
+ let location = find_relay().ok_or(anyhow!("Hostname not found"))?;
println!("Setting location constraint to {location}");
Self::update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate {
@@ -518,7 +517,7 @@ impl Relay {
.into_iter()
.any(|(first, last)| first <= specific_port && specific_port <= last);
if !is_valid_port {
- return Err(Error::CommandFailed("The specified port is invalid"));
+ return Err(anyhow!("The specified port is invalid"));
}
Constraint::Only(specific_port)
}
diff --git a/mullvad-cli/src/cmds/reset.rs b/mullvad-cli/src/cmds/reset.rs
index e1870e3d5c..a8c275a042 100644
--- a/mullvad-cli/src/cmds/reset.rs
+++ b/mullvad-cli/src/cmds/reset.rs
@@ -1,7 +1,7 @@
+use anyhow::Result;
+use mullvad_management_interface::MullvadProxyClient;
use std::io::stdin;
-use crate::{MullvadProxyClient, Result};
-
pub async fn handle() -> Result<()> {
if receive_confirmation().await {
let mut rpc = MullvadProxyClient::new().await?;
@@ -24,7 +24,7 @@ async fn receive_confirmation() -> bool {
match buf.trim() {
"Yes" => return true,
"No" | "no" | "" => return false,
- _ => println!("Unexpected response. Please enter \"Yes\" or \"No\""),
+ _ => eprintln!("Unexpected response. Please enter \"Yes\" or \"No\""),
}
})
.await
diff --git a/mullvad-cli/src/cmds/split_tunnel/linux.rs b/mullvad-cli/src/cmds/split_tunnel/linux.rs
index 11fb01492c..5a66d899ab 100644
--- a/mullvad-cli/src/cmds/split_tunnel/linux.rs
+++ b/mullvad-cli/src/cmds/split_tunnel/linux.rs
@@ -1,8 +1,7 @@
+use anyhow::Result;
use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
-use crate::Result;
-
/// Manage split tunneling. To launch applications outside the tunnel, use the program
/// 'mullvad-exclude' instead of this command
#[derive(Subcommand, Debug)]
diff --git a/mullvad-cli/src/cmds/split_tunnel/windows.rs b/mullvad-cli/src/cmds/split_tunnel/windows.rs
index 4ab6471357..3969880bee 100644
--- a/mullvad-cli/src/cmds/split_tunnel/windows.rs
+++ b/mullvad-cli/src/cmds/split_tunnel/windows.rs
@@ -1,3 +1,4 @@
+use anyhow::Result;
use std::{
ffi::OsStr,
path::{Path, PathBuf},
@@ -7,7 +8,6 @@ use clap::Subcommand;
use mullvad_management_interface::MullvadProxyClient;
use super::super::on_off_parser;
-use crate::Result;
/// Set options for applications to exclude from the tunnel.
#[derive(Subcommand, Debug)]
diff --git a/mullvad-cli/src/cmds/status.rs b/mullvad-cli/src/cmds/status.rs
index e7cb8d7452..8ddd195333 100644
--- a/mullvad-cli/src/cmds/status.rs
+++ b/mullvad-cli/src/cmds/status.rs
@@ -1,9 +1,10 @@
+use anyhow::Result;
use clap::{Args, Subcommand};
use futures::StreamExt;
use mullvad_management_interface::{client::DaemonEvent, MullvadProxyClient};
use mullvad_types::states::TunnelState;
-use crate::{format, Error, Result};
+use crate::format;
#[derive(Subcommand, Debug, PartialEq)]
pub enum Status {
@@ -105,7 +106,7 @@ async fn print_location(rpc: &mut MullvadProxyClient) -> Result<()> {
println!("Location data unavailable");
return Ok(());
}
- _ => return Err(Error::ManagementInterfaceError(error)),
+ _ => return Err(error.into()),
},
};
if let Some(ipv4) = location.ipv4 {
diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs
index 2104f48b3b..8387e053cf 100644
--- a/mullvad-cli/src/cmds/tunnel.rs
+++ b/mullvad-cli/src/cmds/tunnel.rs
@@ -1,6 +1,7 @@
use super::on_off_parser;
-use crate::{MullvadProxyClient, Result};
+use anyhow::Result;
use clap::Subcommand;
+use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::{
relay_constraints::Constraint,
wireguard::{QuantumResistantState, RotationInterval, DEFAULT_ROTATION_INTERVAL},
diff --git a/mullvad-cli/src/cmds/tunnel_state.rs b/mullvad-cli/src/cmds/tunnel_state.rs
index 7f5c3c321e..383b343ef4 100644
--- a/mullvad-cli/src/cmds/tunnel_state.rs
+++ b/mullvad-cli/src/cmds/tunnel_state.rs
@@ -1,6 +1,7 @@
-use crate::{format, Error, MullvadProxyClient, Result};
+use crate::format;
+use anyhow::{anyhow, Result};
use futures::{Stream, StreamExt};
-use mullvad_management_interface::client::DaemonEvent;
+use mullvad_management_interface::{client::DaemonEvent, MullvadProxyClient};
use mullvad_types::states::TunnelState;
pub async fn connect(wait: bool) -> Result<()> {
@@ -16,7 +17,7 @@ pub async fn connect(wait: bool) -> Result<()> {
if let Some(receiver) = listener {
wait_for_tunnel_state(receiver, |state| match state {
TunnelState::Connected { .. } => Ok(true),
- TunnelState::Error(_) => Err(Error::CommandFailed("connect")),
+ TunnelState::Error(_) => Err(anyhow!("Failed to connect")),
_ => Ok(false),
})
.await?;
@@ -57,7 +58,7 @@ pub async fn reconnect(wait: bool) -> Result<()> {
if let Some(receiver) = listener {
wait_for_tunnel_state(receiver, |state| match state {
TunnelState::Connected { .. } => Ok(true),
- TunnelState::Error(_) => Err(Error::CommandFailed("reconnect")),
+ TunnelState::Error(_) => Err(anyhow!("Failed to reconnect")),
_ => Ok(false),
})
.await?;
@@ -80,5 +81,5 @@ async fn wait_for_tunnel_state(
}
}
}
- Err(Error::StatusListenerFailed)
+ Err(anyhow!("Failed to wait for expected tunnel state"))
}
diff --git a/mullvad-cli/src/cmds/version.rs b/mullvad-cli/src/cmds/version.rs
index ea9ab387ac..9a0cce2f41 100644
--- a/mullvad-cli/src/cmds/version.rs
+++ b/mullvad-cli/src/cmds/version.rs
@@ -1,10 +1,17 @@
-use crate::{MullvadProxyClient, Result};
+use anyhow::{Context, Result};
+use mullvad_management_interface::MullvadProxyClient;
pub async fn print() -> Result<()> {
let mut rpc = MullvadProxyClient::new().await?;
- let current_version = rpc.get_current_version().await?;
+ let current_version = rpc
+ .get_current_version()
+ .await
+ .context("Failed to get current version")?;
println!("{:21}: {}", "Current version", current_version);
- let version_info = rpc.get_version_info().await?;
+ let version_info = rpc
+ .get_version_info()
+ .await
+ .context("Failed to get version info")?;
println!("{:21}: {}", "Is supported", version_info.supported);
if let Some(suggested_upgrade) = version_info.suggested_upgrade {
@@ -20,7 +27,10 @@ pub async fn print() -> Result<()> {
);
}
- let settings = rpc.get_settings().await?;
+ let settings = rpc
+ .get_settings()
+ .await
+ .context("Failed to obtain settings")?;
if settings.show_beta_releases {
println!("{:21}: {}", "Latest beta version", version_info.latest_beta);
};
diff --git a/mullvad-cli/src/main.rs b/mullvad-cli/src/main.rs
index 6c23b4de61..a36ec58a81 100644
--- a/mullvad-cli/src/main.rs
+++ b/mullvad-cli/src/main.rs
@@ -1,55 +1,16 @@
#![deny(rust_2018_idioms)]
+#[cfg(all(unix, not(target_os = "android")))]
+use anyhow::anyhow;
+use anyhow::Result;
use clap::Parser;
-use std::io;
-use talpid_types::ErrorExt;
-
-pub use mullvad_management_interface::{self, MullvadProxyClient};
mod cmds;
mod format;
-
use cmds::*;
pub const BIN_NAME: &str = env!("CARGO_BIN_NAME");
-pub type Result<T> = std::result::Result<T, Error>;
-
-#[derive(err_derive::Error, Debug)]
-pub enum Error {
- #[error(display = "Failed to connect to daemon")]
- DaemonNotRunning(#[error(source)] io::Error),
-
- #[error(display = "Management interface error")]
- ManagementInterfaceError(#[error(source)] mullvad_management_interface::Error),
-
- #[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)]
- InvalidCommand(&'static str),
-
- #[error(display = "Command failed: {}", _0)]
- CommandFailed(&'static str),
-
- #[error(display = "Failed to listen for status updates")]
- StatusListenerFailed,
-
- #[cfg(all(unix, not(target_os = "android")))]
- #[error(display = "Failed to generate shell completions")]
- CompletionsError(#[error(source, no_from)] io::Error),
-
- #[error(display = "{}", _0)]
- Other(&'static str),
-}
-
#[derive(Debug, Parser)]
#[command(author, version = mullvad_version::VERSION, about, long_about = None)]
#[command(propagate_version = true)]
@@ -154,29 +115,7 @@ enum Cli {
}
#[tokio::main]
-async fn main() {
- let exit_code = match run().await {
- Ok(_) => 0,
- Err(error) => {
- 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
- }
- };
- std::process::exit(exit_code);
-}
-
-async fn run() -> Result<()> {
+async fn main() -> Result<()> {
env_logger::init();
match Cli::parse() {
@@ -206,8 +145,8 @@ async fn run() -> Result<()> {
// FIXME: The shell completions include hidden commands (including "shell-completions")
println!("Generating shell completions to {}", dir.display());
clap_complete::generate_to(shell, &mut Cli::command(), BIN_NAME, dir)
- .map(|_| ())
- .map_err(Error::CompletionsError)
+ .map_err(|_| anyhow!("Failed to generate shell completions"))?;
+ Ok(())
}
}
}