diff --git a/nym-vpn-app/src-tauri/Cargo.lock b/nym-vpn-app/src-tauri/Cargo.lock index 88079883ba..254b7a0738 100644 --- a/nym-vpn-app/src-tauri/Cargo.lock +++ b/nym-vpn-app/src-tauri/Cargo.lock @@ -2995,21 +2995,21 @@ dependencies = [ [[package]] name = "nym-config" version = "0.1.0" -source = "git+https://github.com/nymtech/nym?rev=b7baff1#b7baff1a79d19ff8729531b1b8b10510b68cd8ca" +source = "git+https://github.com/nymtech/nym?rev=fabd48b#fabd48b7ea564df952abe058db93025a80a27f36" dependencies = [ "dirs", "handlebars", "log", "nym-network-defaults", "serde", - "toml 0.7.8", + "toml 0.8.19", "url", ] [[package]] name = "nym-network-defaults" version = "0.1.0" -source = "git+https://github.com/nymtech/nym?rev=b7baff1#b7baff1a79d19ff8729531b1b8b10510b68cd8ca" +source = "git+https://github.com/nymtech/nym?rev=fabd48b#fabd48b7ea564df952abe058db93025a80a27f36" dependencies = [ "dotenvy", "log", diff --git a/nym-vpn-app/src-tauri/src/cli.rs b/nym-vpn-app/src-tauri/src/cli.rs index c726f0ef88..bdab484998 100644 --- a/nym-vpn-app/src-tauri/src/cli.rs +++ b/nym-vpn-app/src-tauri/src/cli.rs @@ -10,11 +10,6 @@ use tracing::{error, info}; pub type ManagedCli = Arc; -// generate `crate::build_info` function that returns the data -// collected during build time -// see https://github.com/danielschemmel/build-info -build_info::build_info!(fn build_info); - #[derive(Parser, Serialize, Deserialize, Debug, Clone)] #[command(author, version, about, long_about = None)] pub struct Cli { @@ -123,7 +118,7 @@ pub fn db_command(db: &Db, command: &DbCommands) -> Result<()> { } pub fn print_build_info(package_info: &PackageInfo) { - let info = build_info(); + let info = crate::build_info(); print!( r"app name: {} diff --git a/nym-vpn-app/src-tauri/src/db.rs b/nym-vpn-app/src-tauri/src/db.rs index c6987451b5..9e991a2d80 100644 --- a/nym-vpn-app/src-tauri/src/db.rs +++ b/nym-vpn-app/src-tauri/src/db.rs @@ -113,9 +113,9 @@ impl Db { } })?; if db.was_recovered() { - info!("sled db recovered"); + info!("using existing db at {}", &path.display()); } else { - info!("new sled db created"); + info!("new db created at {}", &path.display()); } Ok(Self { db, path }) } diff --git a/nym-vpn-app/src-tauri/src/grpc/client.rs b/nym-vpn-app/src-tauri/src/grpc/client.rs index fdb0b29d97..fff8c6f572 100644 --- a/nym-vpn-app/src-tauri/src/grpc/client.rs +++ b/nym-vpn-app/src-tauri/src/grpc/client.rs @@ -1,3 +1,4 @@ +use std::env::consts::{ARCH, OS}; use std::path::PathBuf; use anyhow::{anyhow, Result}; @@ -7,11 +8,11 @@ use nym_vpn_proto::{ nym_vpnd_client::NymVpndClient, ConnectRequest, ConnectionStatus, DisconnectRequest, Dns, Empty, EntryNode, ExitNode, GatewayType, HealthCheckRequest, ImportUserCredentialRequest, ImportUserCredentialResponse, InfoRequest, InfoResponse, ListCountriesRequest, Location, - StatusRequest, StatusResponse, + StatusRequest, StatusResponse, UserAgent, }; use parity_tokio_ipc::Endpoint as IpcEndpoint; use serde::{Deserialize, Serialize}; -use tauri::{AppHandle, Manager}; +use tauri::{AppHandle, Manager, PackageInfo}; use thiserror::Error; use time::OffsetDateTime; use tokio::sync::mpsc; @@ -59,13 +60,31 @@ pub enum VpndError { } #[derive(Debug, Default, Clone)] -pub struct GrpcClient(Transport); +pub struct GrpcClient { + transport: Transport, + user_agent: UserAgent, +} impl GrpcClient { #[instrument(skip_all)] - pub fn new(config: &AppConfig, cli: &Cli) -> Self { - let client = GrpcClient(Transport::from((config, cli))); - match &client.0 { + pub fn new(config: &AppConfig, cli: &Cli, pkg: &PackageInfo) -> Self { + let git_commit = crate::build_info() + .version_control + .as_ref() + .and_then(|vc| vc.git()) + .map(|g| g.commit_short_id.clone()) + .unwrap_or_default(); + + let client = GrpcClient { + transport: Transport::from((config, cli)), + user_agent: UserAgent { + application: pkg.name.clone(), + version: pkg.version.to_string(), + platform: format!("{}; {}; {}", OS, tauri_plugin_os::version(), ARCH), + git_commit, + }, + }; + match &client.transport { Transport::Http(endpoint) => { info!("using grpc HTTP transport: {}", endpoint); } @@ -79,7 +98,7 @@ impl GrpcClient { /// Get the Vpnd service client #[instrument(skip_all)] pub async fn vpnd(&self) -> Result, VpndError> { - match &self.0 { + match &self.transport { Transport::Http(endpoint) => { NymVpndClient::connect(endpoint.clone()).await.map_err(|e| { warn!("failed to connect to the daemon: {}", e); @@ -99,7 +118,7 @@ impl GrpcClient { /// Get the Health service client #[instrument(skip_all)] pub async fn health(&self) -> Result, VpndError> { - match &self.0 { + match &self.transport { Transport::Http(endpoint) => { HealthClient::connect(endpoint.clone()).await.map_err(|e| { warn!("failed to connect to the daemon: {}", e); @@ -152,6 +171,25 @@ impl GrpcClient { Ok(response.into_inner()) } + /// Update `user_agent` with the daemon info + // TODO this is dirty, this logic shouldn't be handled in the client side + #[instrument(skip_all)] + pub async fn update_agent(&mut self) -> Result<(), VpndError> { + let mut vpnd = self.vpnd().await?; + + let request = Request::new(InfoRequest {}); + let response = vpnd.info(request).await.map_err(|e| { + error!("grpc info: {}", e); + VpndError::GrpcError(e) + })?; + let d_info = response.get_ref(); + self.user_agent.version = format!("{} ({})", self.user_agent.version, d_info.version); + self.user_agent.git_commit = + format!("{} ({})", self.user_agent.git_commit, d_info.git_commit); + info!("updated user agent: {:?}", self.user_agent); + Ok(()) + } + /// Get VPN status #[instrument(skip_all)] pub async fn vpn_status(&self) -> Result { @@ -306,7 +344,7 @@ impl GrpcClient { disable_background_cover_traffic: false, enable_credentials_mode: false, dns, - user_agent: None, + user_agent: Some(self.user_agent.clone()), min_mixnode_performance: None, min_gateway_mixnet_performance: None, min_gateway_vpn_performance: None, @@ -363,7 +401,7 @@ impl GrpcClient { let request = Request::new(ListCountriesRequest { kind: gw_type as i32, - user_agent: None, + user_agent: Some(self.user_agent.clone()), min_mixnet_performance: None, min_vpn_performance: None, }); diff --git a/nym-vpn-app/src-tauri/src/main.rs b/nym-vpn-app/src-tauri/src/main.rs index e61ac05c28..bc1c38bae3 100644 --- a/nym-vpn-app/src-tauri/src/main.rs +++ b/nym-vpn-app/src-tauri/src/main.rs @@ -59,6 +59,9 @@ const APP_CONFIG_FILE: &str = "config.toml"; const ENV_APP_NOSPLASH: &str = "APP_NOSPLASH"; const VPND_RETRY_INTERVAL: Duration = Duration::from_secs(2); +// build time pkg data +build_info::build_info!(fn build_info); + #[tokio::main] async fn main() -> Result<()> { dotenvy::dotenv().ok(); @@ -135,7 +138,8 @@ async fn main() -> Result<()> { let app_state = AppState::new(&db, &app_config, &cli); - let grpc = GrpcClient::new(&app_config, &cli); + let mut grpc = GrpcClient::new(&app_config, &cli, context.package_info()); + grpc.update_agent().await.ok(); info!("Starting tauri app"); tauri::Builder::default() @@ -184,11 +188,12 @@ async fn main() -> Result<()> { }); let handle = app.handle().clone(); - let c_grpc = grpc.clone(); + let mut c_grpc = grpc.clone(); tokio::spawn(async move { info!("starting vpn status spy"); loop { if c_grpc.refresh_vpn_status(&handle).await.is_ok() { + c_grpc.update_agent().await.ok(); c_grpc.watch_vpn_state(&handle).await.ok(); } sleep(VPND_RETRY_INTERVAL).await;