diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2018-03-27 15:58:22 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2018-03-27 15:58:22 +0200 |
| commit | 5a1d8547668e0d3bbf857822b59d23f8015fc1fe (patch) | |
| tree | 13002d37f83ffd62dbe471e6dcf402de6162e6f2 | |
| parent | 5d24fd701facb66e94a43ad78fd564df188db9d4 (diff) | |
| parent | 5061978a720dda7b32054fb0165ba5b784a2eb1a (diff) | |
| download | mullvadvpn-5a1d8547668e0d3bbf857822b59d23f8015fc1fe.tar.xz mullvadvpn-5a1d8547668e0d3bbf857822b59d23f8015fc1fe.zip | |
Merge branch 'feature-version-status'
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/mod.rs | 3 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/version.rs | 29 | ||||
| -rw-r--r-- | mullvad-daemon/src/cli.rs | 7 | ||||
| -rw-r--r-- | mullvad-daemon/src/main.rs | 38 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 40 | ||||
| -rw-r--r-- | mullvad-daemon/src/version.rs | 9 | ||||
| -rw-r--r-- | mullvad-rpc/src/lib.rs | 6 | ||||
| -rw-r--r-- | mullvad-types/src/lib.rs | 1 | ||||
| -rw-r--r-- | mullvad-types/src/version.rs | 16 |
10 files changed, 143 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 4908520313..3b46c2937d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Warn if daemon is running as a non-root user. - Include the last two OpenVPN logs in problem reports instead of only the last. - Prevent two instances of the daemon to run at the same time. +- Daemon now fetches latest app versions and verifies whether the current + version is supported. +- Add `version` subcommand in the CLI to show information about current versions. ### Fixed - Fix a bug in account input field that advanced the cursor to the end regardless its prior diff --git a/mullvad-cli/src/cmds/mod.rs b/mullvad-cli/src/cmds/mod.rs index 4450d9d34f..6de212b7fb 100644 --- a/mullvad-cli/src/cmds/mod.rs +++ b/mullvad-cli/src/cmds/mod.rs @@ -25,6 +25,8 @@ pub use self::lan::Lan; mod tunnel; pub use self::tunnel::Tunnel; +mod version; +pub use self::version::Version; /// Returns a map of all available subcommands with their name as key. pub fn get_commands() -> HashMap<&'static str, Box<Command>> { @@ -37,6 +39,7 @@ pub fn get_commands() -> HashMap<&'static str, Box<Command>> { Box::new(Relay), Box::new(Lan), Box::new(Tunnel), + Box::new(Version), ]; let mut map = HashMap::new(); for cmd in commands { diff --git a/mullvad-cli/src/cmds/version.rs b/mullvad-cli/src/cmds/version.rs new file mode 100644 index 0000000000..bf754c386a --- /dev/null +++ b/mullvad-cli/src/cmds/version.rs @@ -0,0 +1,29 @@ +use clap; +use {Command, Result}; + +use mullvad_types::version; +use rpc; + +pub struct Version; + +impl Command for Version { + fn name(&self) -> &'static str { + "version" + } + + fn clap_subcommand(&self) -> clap::App<'static, 'static> { + clap::SubCommand::with_name(self.name()) + .about("Shows current version, and the currently supported versions") + } + + fn run(&self, _: &clap::ArgMatches) -> Result<()> { + let current_version: String = rpc::call("get_current_version", &[] as &[u8; 0])?; + println!("Current version: {}", current_version); + let version_info: version::AppVersionInfo = rpc::call("get_version_info", &[] as &[u8; 0])?; + println!("Supported: {}", version_info.current_is_supported); + println!("Latest releases:"); + println!("\tlatest stable: {}", version_info.latest.latest_stable); + println!("\tlatest: {}", version_info.latest.latest); + Ok(()) + } +} diff --git a/mullvad-daemon/src/cli.rs b/mullvad-daemon/src/cli.rs index 4c0779bf97..8867e42ca2 100644 --- a/mullvad-daemon/src/cli.rs +++ b/mullvad-daemon/src/cli.rs @@ -3,6 +3,8 @@ use log; use std::path::PathBuf; +use version; + pub struct Config { pub log_level: log::LevelFilter, pub log_file: Option<PathBuf>, @@ -36,10 +38,7 @@ pub fn get_config() -> Config { fn create_app() -> App<'static, 'static> { App::new(crate_name!()) - .version(include_str!(concat!( - env!("OUT_DIR"), - "/git-commit-desc.txt" - ))) + .version(version::current()) .author(crate_authors!()) .about(crate_description!()) .arg( diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs index c998672897..b1d5b641b9 100644 --- a/mullvad-daemon/src/main.rs +++ b/mullvad-daemon/src/main.rs @@ -51,7 +51,7 @@ mod rpc_address_file; mod rpc_uniqueness_check; mod settings; mod shutdown; - +mod version; use app_dirs::AppInfo; use error_chain::ChainedError; @@ -59,13 +59,14 @@ use futures::Future; use jsonrpc_core::futures::sync::oneshot::Sender as OneshotSender; use management_interface::{BoxFuture, ManagementInterfaceServer, TunnelCommand}; -use mullvad_rpc::{AccountsProxy, HttpHandle}; +use mullvad_rpc::{AccountsProxy, AppVersionProxy, HttpHandle}; use mullvad_types::account::{AccountData, AccountToken}; use mullvad_types::location::GeoIpLocation; use mullvad_types::relay_constraints::{RelaySettings, RelaySettingsUpdate}; use mullvad_types::relay_list::{Relay, RelayList}; use mullvad_types::states::{DaemonState, SecurityState, TargetState}; +use mullvad_types::version::{AppVersion, AppVersionInfo}; use std::env; use std::io; @@ -194,6 +195,7 @@ struct Daemon { management_interface_broadcaster: management_interface::EventBroadcaster, settings: settings::Settings, accounts_proxy: AccountsProxy<HttpHandle>, + version_proxy: AppVersionProxy<HttpHandle>, http_handle: mullvad_rpc::rest::RequestSender, tokio_remote: tokio_core::reactor::Remote, relay_selector: relays::RelaySelector, @@ -247,7 +249,8 @@ impl Daemon { tx, management_interface_broadcaster, settings: settings::Settings::load().chain_err(|| "Unable to read settings")?, - accounts_proxy: AccountsProxy::new(rpc_handle), + accounts_proxy: AccountsProxy::new(rpc_handle.clone()), + version_proxy: AppVersionProxy::new(rpc_handle), http_handle, tokio_remote, relay_selector, @@ -397,6 +400,8 @@ impl Daemon { SetOpenVpnMssfix(tx, mssfix_arg) => self.on_set_openvpn_mssfix(tx, mssfix_arg), GetTunnelOptions(tx) => self.on_get_tunnel_options(tx), GetRelaySettings(tx) => Ok(self.on_get_relay_settings(tx)), + GetVersionInfo(tx) => Ok(self.on_get_version_info(tx)), + GetCurrentVersion(tx) => Ok(self.on_get_current_version(tx)), Shutdown => self.handle_trigger_shutdown_event(), } } @@ -480,6 +485,29 @@ impl Daemon { Ok(()) } + fn on_get_version_info( + &mut self, + tx: OneshotSender<BoxFuture<AppVersionInfo, mullvad_rpc::Error>>, + ) { + let current_version = version::current().to_owned(); + let fut = self.version_proxy + .latest_app_version() + .join( + self.version_proxy + .is_app_version_supported(¤t_version), + ) + .map(|(latest_versions, is_supported)| AppVersionInfo { + current_is_supported: is_supported, + latest: latest_versions, + }); + Self::oneshot_send(tx, Box::new(fut), "get_version_info response"); + } + + fn on_get_current_version(&mut self, tx: OneshotSender<AppVersion>) { + let current_version = version::current().to_owned(); + Self::oneshot_send(tx, current_version, "get_current_version response"); + } + fn on_get_account(&self, tx: OneshotSender<Option<String>>) { Self::oneshot_send(tx, self.settings.get_account_token(), "current account") } @@ -843,8 +871,8 @@ fn log_version() { info!( "Starting {} - {} {}", env!("CARGO_PKG_NAME"), - include_str!(concat!(env!("OUT_DIR"), "/git-commit-desc.txt")), - include_str!(concat!(env!("OUT_DIR"), "/git-commit-date.txt")) + version::current(), + version::commit_date(), ) } diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index 6d44528e56..234bfd3d59 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -14,6 +14,7 @@ use mullvad_types::location::GeoIpLocation; use mullvad_types::relay_constraints::{RelaySettings, RelaySettingsUpdate}; use mullvad_types::relay_list::RelayList; use mullvad_types::states::{DaemonState, TargetState}; +use mullvad_types::version; use serde; @@ -124,6 +125,14 @@ build_rpc_trait! { #[rpc(meta, name = "get_tunnel_options")] fn get_tunnel_options(&self, Self::Metadata) -> BoxFuture<TunnelOptions, Error>; + /// Retreive version of the app + #[rpc(meta, name = "get_current_version")] + fn get_current_version(&self, Self::Metadata) -> BoxFuture<String, Error>; + + /// Retrieve information about the currently running and latest versions of the app + #[rpc(meta, name = "get_version_info")] + fn get_version_info(&self, Self::Metadata) -> BoxFuture<version::AppVersionInfo, Error>; + #[pubsub(name = "new_state")] { /// Subscribes to the `new_state` event notifications. #[rpc(name = "new_state_subscribe")] @@ -178,6 +187,10 @@ pub enum TunnelCommand { SetOpenVpnMssfix(OneshotSender<()>, Option<u16>), /// Get the mssfix argument for OpenVPN GetTunnelOptions(OneshotSender<TunnelOptions>), + /// Get information about the currently running and latest app versions + GetVersionInfo(OneshotSender<BoxFuture<version::AppVersionInfo, mullvad_rpc::Error>>), + /// Get current version of the app + GetCurrentVersion(OneshotSender<version::AppVersion>), /// Makes the daemon exit the main loop and quit. Shutdown, } @@ -591,6 +604,33 @@ impl<T: From<TunnelCommand> + 'static + Send> ManagementInterfaceApi for Managem Box::new(future) } + fn get_current_version(&self, meta: Self::Metadata) -> BoxFuture<String, Error> { + try_future!(self.check_auth(&meta)); + let (tx, rx) = sync::oneshot::channel(); + let future = self.send_command_to_daemon(TunnelCommand::GetCurrentVersion(tx)) + .and_then(|_| rx.map_err(|_| Error::internal_error())); + + Box::new(future) + } + + fn get_version_info(&self, meta: Self::Metadata) -> BoxFuture<version::AppVersionInfo, Error> { + try_future!(self.check_auth(&meta)); + let (tx, rx) = sync::oneshot::channel(); + let future = self.send_command_to_daemon(TunnelCommand::GetVersionInfo(tx)) + .and_then(|_| rx.map_err(|_| Error::internal_error())) + .and_then(|version_future| { + version_future.map_err(|error| { + error!( + "Unable to get version data from master: {}", + error.display_chain() + ); + Self::map_rpc_error(error) + }) + }); + + Box::new(future) + } + fn new_state_subscribe( &self, meta: Self::Metadata, diff --git a/mullvad-daemon/src/version.rs b/mullvad-daemon/src/version.rs new file mode 100644 index 0000000000..2252406e5f --- /dev/null +++ b/mullvad-daemon/src/version.rs @@ -0,0 +1,9 @@ +/// Returns a string that identifies the current version of the application +pub fn current() -> &'static str { + include_str!(concat!(env!("OUT_DIR"), "/git-commit-desc.txt")) +} + +/// Current description returns the current build date +pub fn commit_date() -> &'static str { + include_str!(concat!(env!("OUT_DIR"), "/git-commit-date.txt")) +} diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs index ad20b1a0a3..38327aa148 100644 --- a/mullvad-rpc/src/lib.rs +++ b/mullvad-rpc/src/lib.rs @@ -33,6 +33,7 @@ pub use jsonrpc_client_http::{Error as HttpError, HttpHandle}; use mullvad_types::account::AccountToken; use mullvad_types::relay_list::RelayList; +use mullvad_types::version; use std::collections::HashMap; @@ -77,3 +78,8 @@ impl ProblemReportProxy<HttpHandle> { jsonrpc_client!(pub struct RelayListProxy { pub fn relay_list(&mut self) -> RpcRequest<RelayList>; }); + +jsonrpc_client!(pub struct AppVersionProxy { + pub fn latest_app_version(&mut self) -> RpcRequest<version::LatestReleases>; + pub fn is_app_version_supported(&mut self, version: &version::AppVersion) -> RpcRequest<bool>; +}); diff --git a/mullvad-types/src/lib.rs b/mullvad-types/src/lib.rs index cd3a3bcb97..6cae36372d 100644 --- a/mullvad-types/src/lib.rs +++ b/mullvad-types/src/lib.rs @@ -24,6 +24,7 @@ pub mod location; pub mod relay_constraints; pub mod relay_list; pub mod states; +pub mod version; mod custom_tunnel; pub use custom_tunnel::*; diff --git a/mullvad-types/src/version.rs b/mullvad-types/src/version.rs new file mode 100644 index 0000000000..6efa47806e --- /dev/null +++ b/mullvad-types/src/version.rs @@ -0,0 +1,16 @@ +/// AppVersionInfo represents the current stable and the current latest release versions of the +/// Mullvad VPN app. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AppVersionInfo { + pub current_is_supported: bool, + pub latest: LatestReleases, +} + +/// LatestReleases represent the latest released versions of the Mullvad VPN app. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LatestReleases { + pub latest_stable: AppVersion, + pub latest: AppVersion, +} + +pub type AppVersion = String; |
