summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2019-04-12 12:25:17 +0200
committerLinus Färnstrand <linus@mullvad.net>2019-04-12 12:25:17 +0200
commit9ee8720d10217914ea15cd344ef2c3a4be71ca6b (patch)
tree9cb18883695bc01b1159bcf0638c50899e14b4a7
parentf720db702dfc5afae6210d2d0b42960702856c72 (diff)
parentcf3b0755b4fc526770b7f7c80bf5a0df85565774 (diff)
downloadmullvadvpn-9ee8720d10217914ea15cd344ef2c3a4be71ca6b.tar.xz
mullvadvpn-9ee8720d10217914ea15cd344ef2c3a4be71ca6b.zip
Merge branch 'eliminate-error-chain-daemon'
-rw-r--r--Cargo.lock1
-rw-r--r--mullvad-daemon/Cargo.toml1
-rw-r--r--mullvad-daemon/src/cli.rs9
-rw-r--r--mullvad-daemon/src/lib.rs188
-rw-r--r--mullvad-daemon/src/main.rs91
-rw-r--r--mullvad-daemon/src/management_interface.rs2
-rw-r--r--mullvad-daemon/src/system_service.rs45
7 files changed, 172 insertions, 165 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3cfe9cbc90..615b812eac 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1086,7 +1086,6 @@ dependencies = [
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"ipnetwork 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/mullvad-daemon/Cargo.toml b/mullvad-daemon/Cargo.toml
index 5d252c1217..b50b97d96a 100644
--- a/mullvad-daemon/Cargo.toml
+++ b/mullvad-daemon/Cargo.toml
@@ -16,7 +16,6 @@ edition = "2018"
[dependencies]
chrono = { version = "0.4", features = ["serde"] }
clap = "2.25"
-error-chain = "0.12"
err-derive = "0.1.5"
fern = { version = "0.5", features = ["colored"] }
futures = "0.1"
diff --git a/mullvad-daemon/src/cli.rs b/mullvad-daemon/src/cli.rs
index 722a176878..d39a80309e 100644
--- a/mullvad-daemon/src/cli.rs
+++ b/mullvad-daemon/src/cli.rs
@@ -11,7 +11,14 @@ pub struct Config {
pub register_service: bool,
}
-pub fn get_config() -> Config {
+pub fn get_config() -> &'static Config {
+ lazy_static::lazy_static! {
+ static ref CONFIG: Config = create_config();
+ }
+ &*CONFIG
+}
+
+pub fn create_config() -> Config {
let app = create_app();
let matches = app.get_matches();
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 8edd755c60..aab7f406f7 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -9,8 +9,6 @@
#![deny(rust_2018_idioms)]
#[macro_use]
-extern crate error_chain;
-#[macro_use]
extern crate serde;
@@ -41,7 +39,7 @@ use mullvad_types::{
states::TargetState,
version::{AppVersion, AppVersionInfo},
};
-use std::{mem, path::PathBuf, sync::mpsc, thread, time::Duration};
+use std::{io, mem, path::PathBuf, sync::mpsc, thread, time::Duration};
use talpid_core::{
mpsc::IntoSender,
tunnel_state_machine::{self, TunnelCommand, TunnelParametersGenerator},
@@ -52,30 +50,43 @@ use talpid_types::{
ErrorExt,
};
+pub type Result<T> = std::result::Result<T, Error>;
-error_chain! {
- errors {
- NoCacheDir {
- description("Unable to create cache directory")
- }
- DaemonIsAlreadyRunning {
- description("Another instance of the daemon is already running")
- }
- UnsupportedTunnel {
- description("Unsupported tunnel")
- }
- ManagementInterfaceError(msg: &'static str) {
- description("Error in the management interface")
- display("Management interface error: {}", msg)
- }
- NoKeyAvailable {
- description("No wireguard private key available")
- }
- }
- foreign_links {
- AccountHistory(account_history::Error);
- TunnelError(tunnel_state_machine::Error);
- }
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "Another instance of the daemon is already running")]
+ DaemonIsAlreadyRunning,
+
+ #[error(display = "Unable to initialize network event loop")]
+ InitIoEventLoop(#[error(cause)] io::Error),
+
+ #[error(display = "Unable to create RPC client")]
+ InitRpcClient(#[error(cause)] mullvad_rpc::HttpError),
+
+ #[error(display = "Unable to create am.i.mullvad client")]
+ InitHttpsClient(#[error(cause)] mullvad_rpc::rest::Error),
+
+ #[error(display = "Unable to load settings")]
+ LoadSettings(#[error(cause)] settings::Error),
+
+ #[error(display = "Unable to load account history with wireguard key cache")]
+ LoadAccountHistory(#[error(cause)] account_history::Error),
+
+ /// Error in the management interface
+ #[error(display = "Unable to start management interface server")]
+ StartManagementInterface(#[error(cause)] talpid_ipc::Error),
+
+ #[error(display = "Management interface server exited unexpectedly")]
+ ManagementInterfaceExited,
+
+ #[error(display = "No wireguard private key available")]
+ NoKeyAvailable,
+
+ #[error(display = "Account history problems")]
+ AccountHistory(#[error(cause)] account_history::Error),
+
+ #[error(display = "Tunnel state machine error")]
+ TunnelError(#[error(cause)] tunnel_state_machine::Error),
}
type SyncUnboundedSender<T> = ::futures::sink::Wait<UnboundedSender<T>>;
@@ -180,10 +191,9 @@ impl Daemon {
cache_dir: PathBuf,
version: String,
) -> Result<Self> {
- ensure!(
- !rpc_uniqueness_check::is_another_instance_running(),
- ErrorKind::DaemonIsAlreadyRunning
- );
+ if rpc_uniqueness_check::is_another_instance_running() {
+ return Err(Error::DaemonIsAlreadyRunning);
+ }
let ca_path = resource_dir.join(mullvad_paths::resources::API_CA_FILENAME);
let mut rpc_manager = mullvad_rpc::MullvadRpcFactory::with_cache_dir(&cache_dir, &ca_path);
@@ -196,9 +206,9 @@ impl Daemon {
let remote = core.remote();
(rpc, https_handle, remote)
})
- .chain_err(|| "Unable to initialize network event loop")?;
- let rpc_handle = rpc_handle.chain_err(|| "Unable to create RPC client")?;
- let https_handle = https_handle.chain_err(|| "Unable to create am.i.mullvad client")?;
+ .map_err(Error::InitIoEventLoop)?;
+ let rpc_handle = rpc_handle.map_err(Error::InitRpcClient)?;
+ let https_handle = https_handle.map_err(Error::InitHttpsClient)?;
let (internal_event_tx, internal_event_rx) = mpsc::channel();
@@ -215,9 +225,9 @@ impl Daemon {
&resource_dir,
&cache_dir,
);
- let settings = Settings::load().chain_err(|| "Unable to read settings")?;
- let account_history = account_history::AccountHistory::new(&cache_dir)
- .chain_err(|| "Unable to read wireguard key cache")?;
+ let settings = Settings::load().map_err(Error::LoadSettings)?;
+ let account_history =
+ account_history::AccountHistory::new(&cache_dir).map_err(Error::LoadAccountHistory)?;
let tunnel_parameters_generator = MullvadTunnelParametersGenerator {
tx: internal_event_tx.clone(),
@@ -230,7 +240,8 @@ impl Daemon {
resource_dir,
cache_dir.clone(),
IntoSender::from(internal_event_tx.clone()),
- )?;
+ )
+ .map_err(Error::TunnelError)?;
// Attempt to download a fresh relay list
relay_selector.update();
@@ -275,8 +286,8 @@ impl Daemon {
fn start_management_interface_server(
event_tx: IntoSender<ManagementCommand, InternalDaemonEvent>,
) -> Result<ManagementInterfaceServer> {
- let server = ManagementInterfaceServer::start(event_tx)
- .chain_err(|| ErrorKind::ManagementInterfaceError("Failed to start server"))?;
+ let server =
+ ManagementInterfaceServer::start(event_tx).map_err(Error::StartManagementInterface)?;
info!(
"Mullvad management interface listening on {}",
server.socket_path()
@@ -321,9 +332,7 @@ impl Daemon {
}
ManagementInterfaceEvent(event) => self.handle_management_interface_event(event),
ManagementInterfaceExited => {
- return Err(
- ErrorKind::ManagementInterfaceError("Server exited unexpectedly").into(),
- );
+ return Err(Error::ManagementInterfaceExited);
}
TriggerShutdown => self.handle_trigger_shutdown_event(),
}
@@ -358,35 +367,39 @@ impl Daemon {
tunnel_parameters_tx: &mpsc::Sender<TunnelParameters>,
retry_attempt: u32,
) {
- let result = self
- .settings
- .get_account_token()
- .ok_or_else(|| Error::from("No account token configured"))
- .map(|account_token| {
- match self.settings.get_relay_settings() {
- RelaySettings::CustomTunnelEndpoint(custom_relay) => {
- self.last_generated_relay = None;
- custom_relay
- .to_tunnel_parameters(self.settings.get_tunnel_options().clone())
- .chain_err(|| "Custom tunnel endpoint could not be resolved")
- }
- RelaySettings::Normal(constraints) => self
- .relay_selector
- .get_tunnel_endpoint(&constraints, retry_attempt)
- .chain_err(|| "No valid relay servers match the current settings")
- .and_then(|(relay, endpoint)| {
- self.last_generated_relay = Some(relay);
- self.create_tunnel_parameters(endpoint, account_token)
- }),
+ if let Some(account_token) = self.settings.get_account_token() {
+ if let Err(error_str) = match self.settings.get_relay_settings() {
+ RelaySettings::CustomTunnelEndpoint(custom_relay) => {
+ self.last_generated_relay = None;
+ custom_relay
+ .to_tunnel_parameters(self.settings.get_tunnel_options().clone())
+ .map_err(|e| {
+ e.display_chain_with_msg("Custom tunnel endpoint could not be resolved")
+ })
}
- .map(|tunnel_params| {
- tunnel_parameters_tx
- .send(tunnel_params)
- .map_err(|_| Error::from("Tunnel parameters receiver stopped listening"))
+ RelaySettings::Normal(constraints) => self
+ .relay_selector
+ .get_tunnel_endpoint(&constraints, retry_attempt)
+ .map_err(|e| {
+ e.display_chain_with_msg(
+ "No valid relay servers match the current settings",
+ )
+ })
+ .and_then(|(relay, endpoint)| {
+ self.last_generated_relay = Some(relay);
+ self.create_tunnel_parameters(endpoint, account_token)
+ .map_err(|e| e.display_chain())
+ }),
+ }
+ .and_then(|tunnel_params| {
+ tunnel_parameters_tx.send(tunnel_params).map_err(|e| {
+ e.display_chain_with_msg("Tunnel parameters receiver stopped listening")
})
- });
- if let Err(e) = result {
- error!("{}", e.display_chain());
+ }) {
+ error!("{}", error_str);
+ }
+ } else {
+ error!("No account token configured");
}
}
@@ -410,9 +423,10 @@ impl Daemon {
} => {
let wg_data = self
.account_history
- .get(&account_token)?
+ .get(&account_token)
+ .map_err(Error::AccountHistory)?
.and_then(|entry| entry.wireguard)
- .ok_or(ErrorKind::NoKeyAvailable)?;
+ .ok_or(Error::NoKeyAvailable)?;
let tunnel = wireguard::TunnelConfig {
private_key: wg_data.private_key,
addresses: vec![
@@ -592,7 +606,7 @@ impl Daemon {
fn on_set_account(&mut self, tx: oneshot::Sender<()>, account_token: Option<String>) {
let save_result = self.settings.set_account_token(account_token.clone());
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(account_changed) => {
Self::oneshot_send(tx, (), "set_account response");
if account_changed {
@@ -613,7 +627,7 @@ impl Daemon {
}
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
@@ -660,7 +674,7 @@ impl Daemon {
fn on_update_relay_settings(&mut self, tx: oneshot::Sender<()>, update: RelaySettingsUpdate) {
let save_result = self.settings.update_relay_settings(update);
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(settings_changed) => {
Self::oneshot_send(tx, (), "update_relay_settings response");
if settings_changed {
@@ -670,13 +684,13 @@ impl Daemon {
self.reconnect_tunnel();
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
fn on_set_allow_lan(&mut self, tx: oneshot::Sender<()>, allow_lan: bool) {
let save_result = self.settings.set_allow_lan(allow_lan);
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(settings_changed) => {
Self::oneshot_send(tx, (), "set_allow_lan response");
if settings_changed {
@@ -685,7 +699,7 @@ impl Daemon {
self.send_tunnel_command(TunnelCommand::AllowLan(allow_lan));
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
@@ -697,7 +711,7 @@ impl Daemon {
let save_result = self
.settings
.set_block_when_disconnected(block_when_disconnected);
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(settings_changed) => {
Self::oneshot_send(tx, (), "set_block_when_disconnected response");
if settings_changed {
@@ -708,13 +722,13 @@ impl Daemon {
));
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
fn on_set_auto_connect(&mut self, tx: oneshot::Sender<()>, auto_connect: bool) {
let save_result = self.settings.set_auto_connect(auto_connect);
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(settings_changed) => {
Self::oneshot_send(tx, (), "set auto-connect response");
if settings_changed {
@@ -722,13 +736,13 @@ impl Daemon {
.notify_settings(self.settings.clone());
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
fn on_set_openvpn_mssfix(&mut self, tx: oneshot::Sender<()>, mssfix_arg: Option<u16>) {
let save_result = self.settings.set_openvpn_mssfix(mssfix_arg);
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(settings_changed) => {
Self::oneshot_send(tx, (), "set_openvpn_mssfix response");
if settings_changed {
@@ -738,7 +752,7 @@ impl Daemon {
self.reconnect_tunnel();
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
@@ -795,7 +809,7 @@ impl Daemon {
fn on_set_enable_ipv6(&mut self, tx: oneshot::Sender<()>, enable_ipv6: bool) {
let save_result = self.settings.set_enable_ipv6(enable_ipv6);
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(settings_changed) => {
Self::oneshot_send(tx, (), "set_enable_ipv6 response");
if settings_changed {
@@ -805,13 +819,13 @@ impl Daemon {
self.reconnect_tunnel();
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
fn on_set_wireguard_mtu(&mut self, tx: oneshot::Sender<()>, mtu: Option<u16>) {
let save_result = self.settings.set_wireguard_mtu(mtu);
- match save_result.chain_err(|| "Unable to save settings") {
+ match save_result {
Ok(settings_changed) => {
Self::oneshot_send(tx, (), "set_wireguard_mtu response");
if settings_changed {
@@ -821,7 +835,7 @@ impl Daemon {
self.reconnect_tunnel();
}
}
- Err(e) => error!("{}", e.display_chain()),
+ Err(e) => error!("{}", e.display_chain_with_msg("Unable to save settings")),
}
}
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index bb9afb65ee..e9346405d9 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -8,14 +8,10 @@
#![deny(rust_2018_idioms)]
-#[macro_use]
-extern crate error_chain;
-
-
-use error_chain::ChainedError;
use log::{debug, error, info, warn};
use mullvad_daemon::Daemon;
-use std::{thread, time::Duration};
+use std::{path::PathBuf, thread, time::Duration};
+use talpid_types::ErrorExt;
mod cli;
mod logging;
@@ -26,44 +22,25 @@ mod version;
const DAEMON_LOG_FILENAME: &str = "daemon.log";
-error_chain! {
- errors {
- LogError(msg: &'static str) {
- description("Error setting up log")
- display("Error setting up log: {}", msg)
- }
- }
- links {
- DaemonError(mullvad_daemon::Error, mullvad_daemon::ErrorKind);
- }
-}
-
fn main() {
- let exit_code = match run() {
+ let config = cli::get_config();
+ let log_dir = init_logging(config).unwrap_or_else(|error| {
+ eprintln!("{}", error);
+ std::process::exit(1)
+ });
+ let exit_code = match run_platform(config, log_dir) {
Ok(_) => 0,
Err(error) => {
- if let ErrorKind::LogError(_) = error.kind() {
- eprintln!("{}", error.display_chain());
- } else {
- error!("{}", error.display_chain());
- }
+ error!("{}", error);
1
}
};
debug!("Process exiting with code {}", exit_code);
- ::std::process::exit(exit_code);
+ std::process::exit(exit_code);
}
-fn run() -> Result<()> {
- let config = cli::get_config();
- let log_dir = if config.log_to_file {
- Some(
- mullvad_paths::log_dir()
- .chain_err(|| ErrorKind::LogError("Unable to get log directory"))?,
- )
- } else {
- None
- };
+fn init_logging(config: &cli::Config) -> Result<Option<PathBuf>, String> {
+ let log_dir = get_log_dir(config)?;
let log_file = log_dir.as_ref().map(|dir| dir.join(DAEMON_LOG_FILENAME));
logging::init_logger(
@@ -71,65 +48,69 @@ fn run() -> Result<()> {
log_file.as_ref(),
config.log_stdout_timestamps,
)
- .chain_err(|| ErrorKind::LogError("Unable to initialize logger"))?;
+ .map_err(|e| e.display_chain_with_msg("Unable to initialize logger"))?;
log_panics::init();
log_version();
if let Some(ref log_dir) = log_dir {
info!("Logging to {}", log_dir.display());
}
+ Ok(log_dir)
+}
- run_platform(&config)
+fn get_log_dir(config: &cli::Config) -> Result<Option<PathBuf>, String> {
+ if config.log_to_file {
+ Ok(Some(mullvad_paths::log_dir().map_err(|e| {
+ e.display_chain_with_msg("Unable to get log directory")
+ })?))
+ } else {
+ Ok(None)
+ }
}
#[cfg(windows)]
-fn run_platform(config: &cli::Config) -> Result<()> {
+fn run_platform(config: &cli::Config, log_dir: Option<PathBuf>) -> Result<(), String> {
if config.run_as_service {
system_service::run()
} else {
if config.register_service {
- let install_result =
- system_service::install_service().chain_err(|| "Unable to install the service");
+ let install_result = system_service::install_service().map_err(|e| e.display_chain());
if install_result.is_ok() {
println!("Installed the service.");
}
install_result
} else {
- run_standalone(config)
+ run_standalone(log_dir)
}
}
}
#[cfg(not(windows))]
-fn run_platform(config: &cli::Config) -> Result<()> {
- run_standalone(config)
+fn run_platform(_config: &cli::Config, log_dir: Option<PathBuf>) -> Result<(), String> {
+ run_standalone(log_dir)
}
-fn run_standalone(config: &cli::Config) -> Result<()> {
+fn run_standalone(log_dir: Option<PathBuf>) -> Result<(), String> {
if !running_as_admin() {
warn!("Running daemon as a non-administrator user, clients might refuse to connect");
}
- let daemon = create_daemon(config)?;
+ let daemon = create_daemon(log_dir)?;
let shutdown_handle = daemon.shutdown_handle();
shutdown::set_shutdown_signal_handler(move || shutdown_handle.shutdown())
- .chain_err(|| "Unable to attach shutdown signal handler")?;
+ .map_err(|e| e.display_chain())?;
- daemon.run()?;
+ daemon.run().map_err(|e| e.display_chain())?;
info!("Mullvad daemon is quitting");
thread::sleep(Duration::from_millis(500));
Ok(())
}
-fn create_daemon(config: &cli::Config) -> Result<Daemon> {
- let log_dir = if config.log_to_file {
- Some(mullvad_paths::log_dir().chain_err(|| "Unable to get log directory")?)
- } else {
- None
- };
+fn create_daemon(log_dir: Option<PathBuf>) -> Result<Daemon, String> {
let resource_dir = mullvad_paths::get_resource_dir();
- let cache_dir = mullvad_paths::cache_dir().chain_err(|| "Unable to get cache dir")?;
+ let cache_dir = mullvad_paths::cache_dir()
+ .map_err(|e| e.display_chain_with_msg("Unable to get cache dir"))?;
Daemon::start(
log_dir,
@@ -137,7 +118,7 @@ fn create_daemon(config: &cli::Config) -> Result<Daemon> {
cache_dir,
version::PRODUCT_VERSION.to_owned(),
)
- .chain_err(|| "Unable to initialize daemon")
+ .map_err(|e| e.display_chain_with_msg("Unable to initialize daemon"))
}
fn log_version() {
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 24bf2df391..cb313ed653 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -1,4 +1,3 @@
-use error_chain::ChainedError;
use jsonrpc_core::{
futures::{
future,
@@ -30,6 +29,7 @@ use talpid_ipc;
use talpid_types::{
net::{openvpn, wireguard},
tunnel::TunnelStateTransition,
+ ErrorExt,
};
use uuid;
diff --git a/mullvad-daemon/src/system_service.rs b/mullvad-daemon/src/system_service.rs
index c4b98d88fc..61bbb84981 100644
--- a/mullvad-daemon/src/system_service.rs
+++ b/mullvad-daemon/src/system_service.rs
@@ -1,5 +1,5 @@
use crate::cli;
-use error_chain::ChainedError;
+use mullvad_daemon::DaemonShutdownHandle;
use std::{
env,
ffi::OsString,
@@ -10,6 +10,7 @@ use std::{
thread,
time::Duration,
};
+use talpid_types::ErrorExt;
use windows_service::{
service::{
ServiceAccess, ServiceControl, ServiceControlAccept, ServiceDependency,
@@ -21,19 +22,16 @@ use windows_service::{
service_manager::{ServiceManager, ServiceManagerAccess},
};
-use super::{Result, ResultExt};
-use mullvad_daemon::DaemonShutdownHandle;
-
static SERVICE_NAME: &'static str = "MullvadVPN";
static SERVICE_DISPLAY_NAME: &'static str = "Mullvad VPN Service";
static SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS;
-pub fn run() -> Result<()> {
+pub fn run() -> Result<(), String> {
// Start the service dispatcher.
// This will block current thread until the service stopped and spawn `service_main` on a
// background thread.
service_dispatcher::start(SERVICE_NAME, service_main)
- .chain_err(|| "Failed to start a service dispatcher")
+ .map_err(|e| e.display_chain_with_msg("Failed to start a service dispatcher"))
}
windows_service::define_windows_service!(service_main, handle_service_main);
@@ -42,11 +40,11 @@ pub fn handle_service_main(_arguments: Vec<OsString>) {
log::info!("Service started.");
match run_service() {
Ok(()) => log::info!("Service stopped."),
- Err(error) => log::error!("{}", error.display_chain()),
+ Err(error) => log::error!("{}", error),
};
}
-fn run_service() -> Result<()> {
+fn run_service() -> Result<(), String> {
let (event_tx, event_rx) = mpsc::channel();
// Register service event handler
@@ -65,14 +63,14 @@ fn run_service() -> Result<()> {
}
};
let status_handle = service_control_handler::register(SERVICE_NAME, event_handler)
- .chain_err(|| "Failed to register a service control handler")?;
+ .map_err(|e| e.display_chain_with_msg("Failed to register a service control handler"))?;
let mut persistent_service_status = PersistentServiceStatus::new(status_handle);
persistent_service_status
.set_pending_start(Duration::from_secs(1))
.unwrap();
- let config = cli::get_config();
- let result = crate::create_daemon(&config).and_then(|daemon| {
+ let log_dir = crate::get_log_dir(cli::get_config()).expect("Log dir should be available here");
+ let result = crate::create_daemon(log_dir).and_then(|daemon| {
let shutdown_handle = daemon.shutdown_handle();
// Register monitor that translates `ServiceControl` to Daemon events
@@ -80,7 +78,7 @@ fn run_service() -> Result<()> {
persistent_service_status.set_running().unwrap();
- Ok(daemon.run()?)
+ daemon.run().map_err(|e| e.display_chain())
});
let exit_code = match result {
@@ -216,18 +214,27 @@ fn accepted_controls_by_state(state: ServiceState) -> ServiceControlAccept {
}
}
-pub fn install_service() -> Result<()> {
+#[derive(err_derive::Error, Debug)]
+pub enum InstallError {
+ #[error(display = "Unable to connect to service manager")]
+ ConnectServiceManager(#[error(cause)] windows_service::Error),
+
+ #[error(display = "Unable to create a service")]
+ CreateService(#[error(cause)] windows_service::Error),
+}
+
+pub fn install_service() -> Result<(), InstallError> {
let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)
- .chain_err(|| "Unable to connect to service manager")?;
+ .map_err(InstallError::ConnectServiceManager)?;
service_manager
- .create_service(get_service_info()?, ServiceAccess::empty())
+ .create_service(get_service_info(), ServiceAccess::empty())
.map(|_| ())
- .chain_err(|| "Unable to create a service")
+ .map_err(InstallError::CreateService)
}
-fn get_service_info() -> Result<ServiceInfo> {
- Ok(ServiceInfo {
+fn get_service_info() -> ServiceInfo {
+ ServiceInfo {
name: OsString::from(SERVICE_NAME),
display_name: OsString::from(SERVICE_DISPLAY_NAME),
service_type: SERVICE_TYPE,
@@ -243,5 +250,5 @@ fn get_service_info() -> Result<ServiceInfo> {
],
account_name: None, // run as System
account_password: None,
- })
+ }
}