diff options
| author | David Lönnhager <david.l@mullvad.net> | 2023-04-07 00:50:22 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2023-05-03 10:40:09 +0200 |
| commit | 8117988bb826c1cb4e5f8345717a7368fc64c379 (patch) | |
| tree | 2333ab8c1354833e893302856f1f0c38ecbae48b /mullvad-cli/src | |
| parent | 5a8ce732572e83e8abbdef7afa38394730ed7ee7 (diff) | |
| download | mullvadvpn-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.rs | 47 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/auto_connect.rs | 2 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/beta_program.rs | 4 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/bridge.rs | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/dns.rs | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/lan.rs | 2 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/lockdown.rs | 2 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/obfuscation.rs | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/relay.rs | 11 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/reset.rs | 6 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/split_tunnel/linux.rs | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/split_tunnel/windows.rs | 2 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/status.rs | 5 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/tunnel.rs | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/tunnel_state.rs | 11 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/version.rs | 18 | ||||
| -rw-r--r-- | mullvad-cli/src/main.rs | 73 |
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(()) } } } |
