From f6358143791c7bab9bb016572ce89608de4215c6 Mon Sep 17 00:00:00 2001 From: Andrej Mihajlov Date: Thu, 31 Oct 2024 13:26:17 +0100 Subject: [PATCH] Delete nym-vpn-cli --- nym-vpn-core/Cargo.lock | 34 -- nym-vpn-core/Cargo.toml | 1 - nym-vpn-core/Makefile | 5 +- nym-vpn-core/crates/nym-vpn-cli/Cargo.toml | 59 ---- nym-vpn-core/crates/nym-vpn-cli/README.md | 111 ------- nym-vpn-core/crates/nym-vpn-cli/build.rs | 14 - .../crates/nym-vpn-cli/src/commands.rs | 178 ----------- nym-vpn-core/crates/nym-vpn-cli/src/error.rs | 28 -- nym-vpn-core/crates/nym-vpn-cli/src/main.rs | 295 ------------------ .../nym-vpn-cli/src/shutdown_handler.rs | 52 --- 10 files changed, 1 insertion(+), 776 deletions(-) delete mode 100644 nym-vpn-core/crates/nym-vpn-cli/Cargo.toml delete mode 100644 nym-vpn-core/crates/nym-vpn-cli/README.md delete mode 100644 nym-vpn-core/crates/nym-vpn-cli/build.rs delete mode 100644 nym-vpn-core/crates/nym-vpn-cli/src/commands.rs delete mode 100644 nym-vpn-core/crates/nym-vpn-cli/src/error.rs delete mode 100644 nym-vpn-core/crates/nym-vpn-cli/src/main.rs delete mode 100644 nym-vpn-core/crates/nym-vpn-cli/src/shutdown_handler.rs diff --git a/nym-vpn-core/Cargo.lock b/nym-vpn-core/Cargo.lock index 766dd4cc35..b7cb92c289 100644 --- a/nym-vpn-core/Cargo.lock +++ b/nym-vpn-core/Cargo.lock @@ -2531,15 +2531,6 @@ dependencies = [ "serde", ] -[[package]] -name = "is_elevated" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5299060ff5db63e788015dcb9525ad9b84f4fd9717ed2cbdeba5018cbf42f9b5" -dependencies = [ - "winapi", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -4474,31 +4465,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "nym-vpn-cli" -version = "1.0.0-dev" -dependencies = [ - "anyhow", - "bs58", - "clap", - "dirs", - "futures", - "ipnetwork", - "is_elevated", - "nix 0.29.0", - "nym-bin-common", - "nym-vpn-api-client", - "nym-vpn-lib", - "nym-vpn-store", - "thiserror", - "time", - "tokio", - "tokio-util", - "tracing", - "tracing-subscriber", - "vergen", -] - [[package]] name = "nym-vpn-lib" version = "1.0.0-dev" diff --git a/nym-vpn-core/Cargo.toml b/nym-vpn-core/Cargo.toml index a5069f7f01..65a6ea65c8 100644 --- a/nym-vpn-core/Cargo.toml +++ b/nym-vpn-core/Cargo.toml @@ -13,7 +13,6 @@ members = [ "crates/nym-routing", "crates/nym-vpn-account-controller", "crates/nym-vpn-api-client", - "crates/nym-vpn-cli", "crates/nym-vpn-lib", "crates/nym-vpn-network-config", "crates/nym-vpn-proto", diff --git a/nym-vpn-core/Makefile b/nym-vpn-core/Makefile index 952b0cadd6..f24c48bc9b 100644 --- a/nym-vpn-core/Makefile +++ b/nym-vpn-core/Makefile @@ -21,7 +21,7 @@ build-release: ## Build the Rust workspace in release mode build-mac: ## Build the Rust workspace suitable for running the daemon RUSTFLAGS="-C link-arg=-all_load -C link-arg=-ObjC -C link-arg=-sectcreate -C link-arg=__TEXT -C link-arg=__info_plist -C link-arg=$(CURDIR)/../nym-vpn-apple/Daemon/Info.plist -C link-arg=-sectcreate -C link-arg=__TEXT -C link-arg=__launchd_plist -C link-arg=$(CURDIR)/nym-vpn-apple/Daemon/Launchd.plist" cargo build --release -deb: build-deb-vpn-cli build-deb-vpnd build-deb-vpnc ## Build debian packages +deb: build-deb-vpnd build-deb-vpnc ## Build debian packages # Linting targets clippy: ## Run clippy @@ -34,9 +34,6 @@ fmt-check: ## Check rustfmt cargo fmt --all --check # Debian package builds -build-deb-vpn-cli: - cargo deb -p nym-vpn-cli - build-deb-vpnd: cargo deb -p nym-vpnd diff --git a/nym-vpn-core/crates/nym-vpn-cli/Cargo.toml b/nym-vpn-core/crates/nym-vpn-cli/Cargo.toml deleted file mode 100644 index 32be3628f8..0000000000 --- a/nym-vpn-core/crates/nym-vpn-cli/Cargo.toml +++ /dev/null @@ -1,59 +0,0 @@ -[package] -name = "nym-vpn-cli" -description = "Standalone NymVPN commandline client" -version.workspace = true -authors.workspace = true -repository.workspace = true -homepage.workspace = true -documentation.workspace = true -edition.workspace = true -license.workspace = true - -[dependencies] -anyhow.workspace = true -bs58.workspace = true -clap = { workspace = true, features = ["cargo", "derive"] } -dirs.workspace = true -futures.workspace = true -ipnetwork.workspace = true -thiserror.workspace = true -time.workspace = true -tokio = { workspace = true, features = ["process", "rt-multi-thread", "fs", "sync"] } -tokio-util.workspace = true -tracing-subscriber.workspace = true -tracing.workspace = true - -nym-vpn-api-client = { path = "../nym-vpn-api-client" } -nym-vpn-lib = { path = "../nym-vpn-lib" } -nym-vpn-store = { path = "../nym-vpn-store" } - -nym-bin-common.workspace = true - -[target.'cfg(unix)'.dependencies] -nix = { workspace = true, features = ["user"] } - -[target.'cfg(windows)'.dependencies] -is_elevated = "0.1.2" - -[build-dependencies] -vergen = { workspace = true, default-features = false, features = [ - "build", - "git", - "gitcl", - "rustc", - "cargo", -] } - -[features] -metrics-server = ["nym-vpn-lib/metrics-server"] - -# Debian -[package.metadata.deb] -name = "nym-vpn-cli" -extended-description = '''NymVPN is a vpn service that uses the Nym mixnet. - -This package contains the nym-vpn-cli binary, that connects in the terminal and runs in the foreground - -It's primarily used for testing and not aimed and end-users''' -maintainer-scripts = "debian" -systemd-units = { enable = false } diff --git a/nym-vpn-core/crates/nym-vpn-cli/README.md b/nym-vpn-core/crates/nym-vpn-cli/README.md deleted file mode 100644 index b17ea72366..0000000000 --- a/nym-vpn-core/crates/nym-vpn-cli/README.md +++ /dev/null @@ -1,111 +0,0 @@ -# Nym VPN CLI - -A commandline VPN client that uses the [Nym mixnet](https://nymtech.net). - -By default it will do 5-hops (incl entry and exit gateways). - -``` - ┌─►mix──┐ mix mix - │ │ - entry │ │ exit -client ───► gateway ──┘ mix │ mix ┌─►mix ───► gateway ───► internet - │ │ - │ │ - mix └─►mix──┘ mix -``` - -It can optionally do the first connection to the entry gateway using wireguard, and it uses Mullvad libraries for wrapping wireguard-go and to setup local routing rules to route all traffic to the TUN virtual network device. - -## How to build - -### Prerequisites - -- Go toolchain -- Rust toolchain -- Some C-libraries - - libmnl-dev - - libnftnl-dev - -### The simple way - -```sh -$ make -``` - -in the root directory should if all things went well, produce a binary `bin/nym-vpn-cli` - -### The manual way - -#### Step 1. - -Build the wireguard-go static library: - -```sh -$ ./wireguard/build-wireguard-go.sh -``` - -This should create a local `build` directory with a static library `libwg.a` that wraps the wireguard-go implementation in a FFI. - -```sh -$ ls build/lib/x86_64-unknown-linux-gnu/ -libwg.a libwg.h -``` - -#### Step 2. - -Next, build the Rust CLI using cargo: - -```sh -cargo build --release -``` - -## How to run - -The binary needs root permissions to setup the TUN virtual network device. - -### Case 1: connect to the entry gateway using a websocket connection. - -```sh -$ sudo ./target/release/nym-vpn-cli --entry-gateway --exit-router -``` - -### Case 2: using WireGuard for the connection between the client and the entry gateway. - -```sh -$ sudo ./target/release/nym-vpn-cli --entry-gateway --exit-router --enable-wireguard --private-key -``` - -The full set of flags are: - -``` -$ ./target/release/nym-vpn-cli --help -Usage: nym-vpn-cli [OPTIONS] --entry-gateway --exit-router - -Options: - -c, --config-env-file - Path pointing to an env file describing the network - --mixnet-client-path - Path to the data directory of a previously initialised mixnet client, where the keys reside - --entry-gateway - Mixnet public ID of the entry gateway - --exit-router - Mixnet recipient address - --enable-wireguard - Enable the wireguard traffic between the client and the entry gateway - --private-key - Associated private key - --ip - The IP address of the TUN device - --mtu - The MTU of the TUN device - --disable-routing - Disable routing all traffic through the VPN TUN device - --enable-two-hop - Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway - --enable-poisson-rate - Enable Poission process rate limiting of outbound traffic - -h, --help - Print help - -V, --version - Print version -``` diff --git a/nym-vpn-core/crates/nym-vpn-cli/build.rs b/nym-vpn-core/crates/nym-vpn-cli/build.rs deleted file mode 100644 index 256966312c..0000000000 --- a/nym-vpn-core/crates/nym-vpn-cli/build.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: GPL-3.0-only - -use vergen::EmitBuilder; - -fn main() { - EmitBuilder::builder() - .all_build() - .all_git() - .all_rustc() - .all_cargo() - .emit() - .expect("failed to extract build metadata"); -} diff --git a/nym-vpn-core/crates/nym-vpn-cli/src/commands.rs b/nym-vpn-core/crates/nym-vpn-cli/src/commands.rs deleted file mode 100644 index aa3f3418cd..0000000000 --- a/nym-vpn-core/crates/nym-vpn-cli/src/commands.rs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: GPL-3.0-only - -use std::{ - net::{IpAddr, Ipv4Addr, Ipv6Addr}, - path::PathBuf, - str::FromStr, - sync::OnceLock, -}; - -use clap::{Args, Parser, Subcommand}; -use ipnetwork::{Ipv4Network, Ipv6Network}; - -const TUN_IP4_SUBNET: &str = "10.0.0.0/16"; -const TUN_IP6_SUBNET: &str = "2001:db8:a160::0/112"; - -// Helper for passing LONG_VERSION to clap -fn pretty_build_info_static() -> &'static str { - static PRETTY_BUILD_INFORMATION: OnceLock = OnceLock::new(); - PRETTY_BUILD_INFORMATION.get_or_init(|| nym_bin_common::bin_info_local_vergen!().pretty_print()) -} - -#[derive(Parser)] -#[clap(author = "Nymtech", version, about, long_version = pretty_build_info_static())] -pub(crate) struct CliArgs { - /// Path pointing to an env file describing the network. - #[arg(short, long, value_parser = check_path)] - pub(crate) config_env_file: Option, - - /// Path to the data directory of the mixnet client. - #[arg(long)] - pub(crate) data_path: Option, - - #[command(subcommand)] - pub(crate) command: Commands, -} - -#[derive(Subcommand)] -pub(crate) enum Commands { - /// Run the client - Run(RunArgs), - - /// Store the account - StoreAccount(StoreAccountArgs), -} - -#[derive(Args)] -pub(crate) struct RunArgs { - #[command(flatten)] - pub(crate) entry: CliEntry, - - #[command(flatten)] - pub(crate) exit: CliExit, - - /// Enable the wireguard mode. - #[arg(long, default_value_t = false)] - pub(crate) wireguard_mode: bool, - - /// The IPv4 address of the nym TUN device that wraps IP packets in sphinx packets. - #[arg(long, alias = "ipv4", value_parser = validate_ipv4, requires = "nym_ipv6")] - pub(crate) nym_ipv4: Option, - - /// The IPv6 address of the nym TUN device that wraps IP packets in sphinx packets. - #[arg(long, alias = "ipv6", value_parser = validate_ipv6, requires = "nym_ipv4")] - pub(crate) nym_ipv6: Option, - - /// The MTU of the nym TUN device that wraps IP packets in sphinx packets. - #[arg(long, alias = "mtu")] - pub(crate) nym_mtu: Option, - - /// The DNS server to use - #[arg(long)] - pub(crate) dns: Option, - - /// Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN - /// device will be created, but to route traffic through it you will need to do it manually, - /// e.g. ping -Itun0. - #[arg(long)] - pub(crate) disable_routing: bool, - - /// Disable the Poisson process rate limiting of outbound traffic. - #[arg(long, hide = true)] - pub(crate) disable_poisson_rate: bool, - - /// Disable constant rate background loop cover traffic. - #[arg(long, hide = true)] - pub(crate) disable_background_cover_traffic: bool, - - /// Enable credentials mode. - #[arg(long)] - pub(crate) enable_credentials_mode: bool, - - /// Set the minimum performance level for mixnodes. - #[arg(long, value_parser = clap::value_parser!(u8).range(0..=100), hide = true)] - pub(crate) min_mixnode_performance: Option, - - // Set the minimum performance level for gateways. - #[arg(long, value_parser = clap::value_parser!(u8).range(0..=100))] - pub(crate) min_gateway_mixnet_performance: Option, - - // Set the minimum performance level for VPN gateways. - #[arg(long, value_parser = clap::value_parser!(u8).range(0..=100))] - pub(crate) min_gateway_vpn_performance: Option, -} - -#[derive(Args)] -#[group(multiple = false)] -pub(crate) struct CliEntry { - /// Mixnet public ID of the entry gateway. - #[arg(long, alias = "entry-id")] - pub(crate) entry_gateway_id: Option, - - /// Auto-select entry gateway by country ISO. - #[arg(long, alias = "entry-country")] - pub(crate) entry_gateway_country: Option, - - /// Auto-select entry gateway by latency - #[arg(long, alias = "entry-fastest")] - pub(crate) entry_gateway_low_latency: bool, -} - -#[derive(Args)] -#[group(multiple = false)] -pub(crate) struct CliExit { - /// Mixnet recipient address. - #[arg(long, alias = "exit-address")] - pub(crate) exit_router_address: Option, - - /// Mixnet public ID of the exit gateway. - #[arg(long, alias = "exit-id")] - pub(crate) exit_gateway_id: Option, - - /// Auto-select exit gateway by country ISO. - #[arg(long, alias = "exit-country")] - pub(crate) exit_gateway_country: Option, -} - -#[derive(Args)] -pub(crate) struct StoreAccountArgs { - /// Recovery phrase for the account. - #[arg(long)] - pub(crate) mnemonic: String, -} - -fn validate_ipv4(ip: &str) -> Result { - let ip = Ipv4Addr::from_str(ip).map_err(|err| err.to_string())?; - let network = Ipv4Network::from_str(TUN_IP4_SUBNET).unwrap(); - if !network.contains(ip) { - return Err(format!("IPv4 address must be in the range {}", network)); - } - if ip == Ipv4Addr::new(10, 0, 0, 1) { - return Err("IPv4 address cannot be 10.0.0.1".to_string()); - } - Ok(ip) -} - -fn validate_ipv6(ip: &str) -> Result { - let ip = Ipv6Addr::from_str(ip).map_err(|err| err.to_string())?; - let network = Ipv6Network::from_str(TUN_IP6_SUBNET).unwrap(); - if !network.contains(ip) { - return Err(format!("IPv6 address must be in the range {}", network)); - } - if ip == Ipv6Addr::from_str("2001:db8:a160::1").unwrap() { - return Err("IPv6 address cannot be 2001:db8:a160::1".to_string()); - } - Ok(ip) -} - -fn check_path(path: &str) -> Result { - let path = PathBuf::from(path); - if !path.exists() { - return Err(format!("Path {:?} does not exist", path)); - } - if !path.is_file() { - return Err(format!("Path {:?} is not a file", path)); - } - Ok(path) -} diff --git a/nym-vpn-core/crates/nym-vpn-cli/src/error.rs b/nym-vpn-core/crates/nym-vpn-cli/src/error.rs deleted file mode 100644 index 417b8b6a0f..0000000000 --- a/nym-vpn-core/crates/nym-vpn-cli/src/error.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: GPL-3.0-only - -#[derive(thiserror::Error, Debug)] -pub(crate) enum Error { - #[error(transparent)] - VpnLib(#[from] nym_vpn_lib::Error), - - #[error("identity not formatted correctly")] - NodeIdentityFormatting, - - #[error("recipient is not formatted correctly")] - RecipientFormatting, - - #[cfg(unix)] - #[error("sudo/root privileges required, try rerunning with sudo: `sudo -E {binary_name} run`")] - RootPrivilegesRequired { binary_name: String }, - - #[cfg(windows)] - #[error("administrator privileges required, try rerunning with administrator privileges: `runas /user:Administrator {binary_name} run`")] - AdminPrivilegesRequired { binary_name: String }, - - #[error("failed to setup gateway minimum performance threshold: {0}")] - FailedToSetupGatewayPerformanceThresholds(#[source] nym_vpn_api_client::VpnApiClientError), -} - -// Result type based on our error type -pub(crate) type Result = std::result::Result; diff --git a/nym-vpn-core/crates/nym-vpn-cli/src/main.rs b/nym-vpn-core/crates/nym-vpn-cli/src/main.rs deleted file mode 100644 index 83a4ccda8c..0000000000 --- a/nym-vpn-core/crates/nym-vpn-cli/src/main.rs +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: GPL-3.0-only - -mod commands; -mod error; -mod shutdown_handler; - -use std::path::PathBuf; - -use anyhow::Context; -use clap::Parser; -use tokio::sync::mpsc; -use tokio_util::sync::CancellationToken; - -use nym_vpn_api_client::types::GatewayMinPerformance; -use nym_vpn_lib::{ - gateway_directory::{Config as GatewayConfig, EntryPoint, ExitPoint}, - nym_config::defaults::{setup_env, var_names}, - tunnel_state_machine::{ - DnsOptions, GatewayPerformanceOptions, MixnetTunnelOptions, NymConfig, TunnelCommand, - TunnelEvent, TunnelSettings, TunnelStateMachine, TunnelType, - }, - IpPair, MixnetClientConfig, NodeIdentity, Recipient, -}; -use nym_vpn_store::mnemonic::MnemonicStorage as _; - -use commands::{CliArgs, Commands}; -use error::{Error, Result}; - -const CONFIG_DIRECTORY_NAME: &str = "nym-vpn-cli"; - -#[tokio::main(flavor = "multi_thread")] -async fn main() -> anyhow::Result<()> { - let args = commands::CliArgs::parse(); - setup_logging(&args); - tracing::debug!("{:?}", nym_bin_common::bin_info_local_vergen!()); - setup_env(args.config_env_file.as_ref()); - - check_root_privileges(&args)?; - - let data_path = args.data_path.or(mixnet_data_path()); - - match args.command { - Commands::Run(args) => run_vpn(args, data_path).await, - Commands::StoreAccount(args) => store_account(args, data_path).await, - } -} - -pub(crate) fn setup_logging(args: &CliArgs) { - let mut filter = tracing_subscriber::EnvFilter::builder() - .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into()) - .from_env() - .unwrap() - .add_directive("hyper::proto=info".parse().unwrap()) - .add_directive("netlink_proto=info".parse().unwrap()); - if let Commands::Run(run_args) = &args.command { - if run_args.wireguard_mode { - filter = filter - .add_directive("nym_client_core=warn".parse().unwrap()) - .add_directive("nym_gateway_client=warn".parse().unwrap()); - } - } - - tracing_subscriber::fmt() - .with_env_filter(filter) - .compact() - .init(); -} - -fn parse_entry_point(args: &commands::RunArgs) -> Result { - if let Some(ref entry_gateway_id) = args.entry.entry_gateway_id { - Ok(EntryPoint::Gateway { - identity: NodeIdentity::from_base58_string(entry_gateway_id.clone()) - .map_err(|_| Error::NodeIdentityFormatting)?, - }) - } else if let Some(ref entry_gateway_country) = args.entry.entry_gateway_country { - Ok(EntryPoint::Location { - location: entry_gateway_country.clone(), - }) - } else if args.entry.entry_gateway_low_latency { - Ok(EntryPoint::RandomLowLatency) - } else { - Ok(EntryPoint::Random) - } -} - -fn parse_exit_point(args: &commands::RunArgs) -> Result { - if let Some(ref exit_router_address) = args.exit.exit_router_address { - Ok(ExitPoint::Address { - address: Recipient::try_from_base58_string(exit_router_address.clone()) - .map_err(|_| Error::RecipientFormatting)?, - }) - } else if let Some(ref exit_router_id) = args.exit.exit_gateway_id { - Ok(ExitPoint::Gateway { - identity: NodeIdentity::from_base58_string(exit_router_id.clone()) - .map_err(|_| Error::NodeIdentityFormatting)?, - }) - } else if let Some(ref exit_gateway_country) = args.exit.exit_gateway_country { - Ok(ExitPoint::Location { - location: exit_gateway_country.clone(), - }) - } else { - Ok(ExitPoint::Random) - } -} - -#[allow(unreachable_code)] -fn check_root_privileges(args: &commands::CliArgs) -> Result<()> { - let needs_root = match &args.command { - Commands::Run(run_args) => !run_args.disable_routing, - Commands::StoreAccount(_) => true, - }; - - if !needs_root { - tracing::debug!("Root privileges not required for this command"); - return Ok(()); - } - - #[cfg(unix)] - return unix_has_root("nym-vpn-cli"); - - #[cfg(windows)] - return win_has_admin("nym-vpn-cli"); - - // Assume we're all good on unknown platforms - tracing::debug!("Platform not supported for root privilege check"); - Ok(()) -} - -#[cfg(unix)] -pub(crate) fn unix_has_root(binary_name: &str) -> Result<()> { - if nix::unistd::geteuid().is_root() { - tracing::debug!("Root privileges acquired"); - Ok(()) - } else { - Err(Error::RootPrivilegesRequired { - binary_name: binary_name.to_string(), - }) - } -} - -#[cfg(windows)] -pub(crate) fn win_has_admin(binary_name: &str) -> Result<()> { - if is_elevated::is_elevated() { - tracing::debug!("Admin privileges acquired"); - Ok(()) - } else { - Err(Error::AdminPrivilegesRequired { - binary_name: binary_name.to_string(), - }) - } -} - -async fn run_vpn(args: commands::RunArgs, data_path: Option) -> anyhow::Result<()> { - // Setup gateway directory configuration - let min_gateway_performance = GatewayMinPerformance::from_percentage_values( - args.min_gateway_mixnet_performance.map(u64::from), - args.min_gateway_vpn_performance.map(u64::from), - ) - .map_err(Error::FailedToSetupGatewayPerformanceThresholds)?; - - let gateway_config = - GatewayConfig::new_from_env().with_min_gateway_performance(min_gateway_performance); - - tracing::info!("nym-api: {}", gateway_config.api_url()); - tracing::info!( - "nym-vpn-api: {}", - gateway_config - .nym_vpn_api_url() - .map(|url| url.to_string()) - .unwrap_or("unavailable".to_string()) - ); - - let entry_point = parse_entry_point(&args)?; - let exit_point = parse_exit_point(&args)?; - let nym_ips = if let (Some(ipv4), Some(ipv6)) = (args.nym_ipv4, args.nym_ipv6) { - Some(IpPair::new(ipv4, ipv6)) - } else { - None - }; - - let (command_tx, command_rx) = mpsc::unbounded_channel(); - let (event_tx, mut event_rx) = mpsc::unbounded_channel(); - let shutdown_token = CancellationToken::new(); - - let dns = args - .dns - .map(|ip| DnsOptions::Custom(vec![ip])) - .unwrap_or_default(); - - let tunnel_type = if args.wireguard_mode { - TunnelType::Wireguard - } else { - TunnelType::Mixnet - }; - - let mixnet_client_config = MixnetClientConfig { - disable_poisson_rate: args.wireguard_mode || args.disable_poisson_rate, - disable_background_cover_traffic: args.wireguard_mode - || args.disable_background_cover_traffic, - min_mixnode_performance: args.min_mixnode_performance, - min_gateway_performance: args.min_gateway_mixnet_performance, - }; - - let mixnet_tunnel_options = MixnetTunnelOptions { - interface_addrs: nym_ips, - mtu: args.nym_mtu, - }; - - let nym_config = NymConfig { - data_path, - gateway_config, - }; - - let tunnel_settings = TunnelSettings { - tunnel_type, - enable_credentials_mode: args.enable_credentials_mode, - mixnet_client_config: Some(mixnet_client_config), - gateway_performance_options: GatewayPerformanceOptions::default(), - mixnet_tunnel_options, - entry_point: Box::new(entry_point), - exit_point: Box::new(exit_point), - dns, - }; - - let state_machine_handle = TunnelStateMachine::spawn( - command_rx, - event_tx, - nym_config, - tunnel_settings, - shutdown_token.child_token(), - ) - .await - .with_context(|| "Failed to start a tunnel state machine")?; - - let mut shutdown_join_set = shutdown_handler::install(shutdown_token.clone()); - - command_tx - .send(TunnelCommand::Connect) - .with_context(|| "Failed to send a connect command.")?; - - loop { - tokio::select! { - Some(event) = event_rx.recv() => { - match event { - TunnelEvent::NewState(new_state) => { - tracing::info!("New state: {}", new_state); - } - TunnelEvent::MixnetState(event) => { - tracing::info!("Mixnet event: {}", event); - } - } - } - _ = shutdown_token.cancelled() => { - tracing::info!("Cancellation received. Breaking event loop."); - break; - } - else => { - tracing::info!("Event receiver is closed. Breaking event loop."); - break; - } - } - } - - tracing::info!("Waiting for state machine to shutdown"); - if let Err(e) = state_machine_handle.await { - tracing::warn!("Failed to join on state machine handle: {}", e); - } - - tracing::info!("Aborting signal handlers."); - shutdown_join_set.shutdown().await; - - tracing::info!("Goodbye."); - Ok(()) -} - -async fn store_account( - args: commands::StoreAccountArgs, - data_path: Option, -) -> anyhow::Result<()> { - let path = data_path.context("Data path not set")?; - let mnemonic = nym_vpn_store::mnemonic::Mnemonic::parse(&args.mnemonic) - .context("Failed to parse mnemonic")?; - let storage = nym_vpn_lib::storage::VpnClientOnDiskStorage::new(path); - storage - .store_mnemonic(mnemonic) - .await - .context("Failed to store mnemonic") -} - -fn mixnet_data_path() -> Option { - let network_name = - std::env::var(var_names::NETWORK_NAME).expect("NETWORK_NAME env var not set"); - dirs::data_dir().map(|dir| dir.join(CONFIG_DIRECTORY_NAME).join(network_name)) -} diff --git a/nym-vpn-core/crates/nym-vpn-cli/src/shutdown_handler.rs b/nym-vpn-core/crates/nym-vpn-cli/src/shutdown_handler.rs deleted file mode 100644 index 58adde1301..0000000000 --- a/nym-vpn-core/crates/nym-vpn-cli/src/shutdown_handler.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::io; - -use tokio::task::JoinSet; -use tokio_util::sync::CancellationToken; - -pub fn install(shutdown_token: CancellationToken) -> JoinSet<()> { - let mut join_set = JoinSet::new(); - - let ctrlc_shutdown_token = shutdown_token.clone(); - join_set.spawn(async move { - if let Err(e) = set_ctrlc_handler(ctrlc_shutdown_token).await { - tracing::error!("Failed to set the ctrl-c handler: {}", e); - } - }); - - #[cfg(unix)] - join_set.spawn(async move { - if let Err(e) = set_termination_handler(shutdown_token).await { - tracing::error!("Failed to set the termination handler: {}", e); - } - }); - - join_set -} - -async fn set_ctrlc_handler(shutdown_token: CancellationToken) -> io::Result<()> { - tokio::signal::ctrl_c().await?; - tracing::info!("Received Ctrl-C signal."); - shutdown_token.cancel(); - Ok(()) -} - -#[cfg(unix)] -async fn set_termination_handler(shutdown_token: CancellationToken) -> io::Result<()> { - use tokio::signal::unix::{signal, SignalKind}; - - let mut sigterm = signal(SignalKind::terminate())?; - let mut sigquit = signal(SignalKind::quit())?; - - tokio::select! { - _ = sigterm.recv() => { - tracing::info!("Received SIGTERM signal."); - }, - _ = sigquit.recv() => { - tracing::info!("Received SIGQUIT signal."); - } - } - - shutdown_token.cancel(); - - Ok(()) -}