diff --git a/nym-vpn-core/crates/nym-vpn-lib-types/src/lib.rs b/nym-vpn-core/crates/nym-vpn-lib-types/src/lib.rs index a4c4db51d3..0df1ef2a00 100644 --- a/nym-vpn-core/crates/nym-vpn-lib-types/src/lib.rs +++ b/nym-vpn-core/crates/nym-vpn-lib-types/src/lib.rs @@ -78,7 +78,7 @@ pub use rpc_requests::{ AccountBalanceResponse, AccountCommandResponse, Coin, DecentralisedObtainTicketbooksRequest, ListGatewaysOptions, StoreAccountRequest, }; -pub use service::{TargetState, VpnServiceConfig, VpnServiceInfo}; +pub use service::{MixnetTrafficConfig, TargetState, VpnServiceConfig, VpnServiceInfo}; pub use socks5::{HttpRpcSettings, Socks5Settings, Socks5State, Socks5Status}; pub use tunnel_event::{ BandwidthEvent, ConnectionEvent, ConnectionStatisticsEvent, MixnetEvent, SphinxPacketRates, diff --git a/nym-vpn-core/crates/nym-vpn-lib-types/src/service.rs b/nym-vpn-core/crates/nym-vpn-lib-types/src/service.rs index b263502b67..27b5771ff0 100644 --- a/nym-vpn-core/crates/nym-vpn-lib-types/src/service.rs +++ b/nym-vpn-core/crates/nym-vpn-lib-types/src/service.rs @@ -10,6 +10,32 @@ use time::OffsetDateTime; use ts_rs::TS; use crate::{EntryPoint, ExitPoint, NetworkStatisticsConfig, NymNetworkDetails, NymVpnNetwork}; +#[cfg_attr(feature = "uniffi-bindings", derive(uniffi::Record))] +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct MixnetTrafficConfig { + pub poisson_parameter: Option, + pub average_packet_delay: Option, + pub message_sending_average_delay: Option, + + pub disable_poisson_rate: bool, + pub disable_background_cover_traffic: bool, + + pub min_mixnode_performance: Option, + pub min_gateway_mixnet_performance: Option, +} +impl Default for MixnetTrafficConfig { + fn default() -> Self { + Self { + poisson_parameter: None, + average_packet_delay: None, + message_sending_average_delay: None, + disable_poisson_rate: false, + disable_background_cover_traffic: false, + min_mixnode_performance: None, + min_gateway_mixnet_performance: None, + } + } +} #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "uniffi-bindings", derive(uniffi::Record))] @@ -21,6 +47,7 @@ use crate::{EntryPoint, ExitPoint, NetworkStatisticsConfig, NymNetworkDetails, N )] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "typescript-bindings", serde(rename_all = "camelCase"))] + pub struct VpnServiceConfig { pub entry_point: EntryPoint, pub exit_point: ExitPoint, @@ -29,15 +56,12 @@ pub struct VpnServiceConfig { pub enable_two_hop: bool, pub enable_bridges: bool, pub netstack: bool, - pub disable_poisson_rate: bool, - pub disable_background_cover_traffic: bool, - pub min_mixnode_performance: Option, - pub min_gateway_mixnet_performance: Option, pub min_gateway_vpn_performance: Option, pub residential_exit: bool, pub enable_custom_dns: bool, pub custom_dns: Vec, pub network_stats: NetworkStatisticsConfig, + pub mixnet_traffic: MixnetTrafficConfig, } impl fmt::Display for VpnServiceConfig { @@ -55,15 +79,18 @@ impl fmt::Display for VpnServiceConfig { writeln!( f, "disable_poisson_rate: {}, disable_background_cover_traffic: {}", - self.disable_poisson_rate, self.disable_background_cover_traffic + self.mixnet_traffic.disable_poisson_rate, + self.mixnet_traffic.disable_background_cover_traffic )?; writeln!( f, "min_mixnode_performance: {}, min_gateway_mixnet_performance: {}, min_gateway_vpn_performance: {}", - self.min_mixnode_performance + self.mixnet_traffic + .min_mixnode_performance .map(|p| p.to_string()) .unwrap_or_else(|| "".to_string()), - self.min_gateway_mixnet_performance + self.mixnet_traffic + .min_gateway_mixnet_performance .map(|p| p.to_string()) .unwrap_or_else(|| "".to_string()), self.min_gateway_vpn_performance @@ -82,10 +109,27 @@ impl fmt::Display for VpnServiceConfig { .join(", ") )?; writeln!(f, "networks stats config: {}", self.network_stats)?; + writeln!( + f, + "poisson_parameter: {:?}", + self.mixnet_traffic.poisson_parameter + )?; + writeln!( + f, + "average_packet_delay: {} ms, message_sending_average_delay: {} ms", + self.mixnet_traffic + .average_packet_delay + .map(|v| format!("{v}")) + .unwrap_or_else(|| "".to_string()), + self.mixnet_traffic + .message_sending_average_delay + .map(|v| format!("{v}")) + .unwrap_or_else(|| "".to_string()) + )?; + Ok(()) } } - impl Default for VpnServiceConfig { fn default() -> Self { Self { @@ -96,15 +140,12 @@ impl Default for VpnServiceConfig { enable_two_hop: true, enable_bridges: false, netstack: false, - disable_poisson_rate: false, - disable_background_cover_traffic: false, - min_mixnode_performance: None, - min_gateway_mixnet_performance: None, min_gateway_vpn_performance: None, residential_exit: false, enable_custom_dns: false, custom_dns: vec![], network_stats: Default::default(), + mixnet_traffic: MixnetTrafficConfig::default(), } } } diff --git a/nym-vpn-core/crates/nym-vpn-lib/src/tunnel_state_machine/mod.rs b/nym-vpn-core/crates/nym-vpn-lib/src/tunnel_state_machine/mod.rs index 9546069112..2ee197f534 100644 --- a/nym-vpn-core/crates/nym-vpn-lib/src/tunnel_state_machine/mod.rs +++ b/nym-vpn-core/crates/nym-vpn-lib/src/tunnel_state_machine/mod.rs @@ -737,7 +737,6 @@ impl TunnelStateMachine { &mut self.shared_state, ) .await; - match next_state { NextTunnelState::NewState((new_state_handler, new_state)) => { self.current_state_handler = new_state_handler; diff --git a/nym-vpn-core/crates/nym-vpn-proto/proto/nym_vpn_service.proto b/nym-vpn-core/crates/nym-vpn-proto/proto/nym_vpn_service.proto index d1c5c113c5..3cfea134b1 100644 --- a/nym-vpn-core/crates/nym-vpn-proto/proto/nym_vpn_service.proto +++ b/nym-vpn-core/crates/nym-vpn-proto/proto/nym_vpn_service.proto @@ -245,6 +245,18 @@ message Threshold { uint32 min_performance = 1; } +message MixnetTrafficConfig { + optional uint32 poisson_parameter = 1; + optional uint32 average_packet_delay = 2; + optional uint32 message_sending_average_delay = 3; + + bool disable_poisson_rate = 4; + bool disable_background_cover_traffic = 5; + + optional uint32 min_mixnode_performance = 6; + optional uint32 min_gateway_mixnet_performance = 7; +} + message VpnServiceConfig { EntryNode entry_point = 1; ExitNode exit_point = 2; @@ -254,14 +266,14 @@ message VpnServiceConfig { bool enable_bridges = 21; bool residential_exit = 15; bool netstack = 13; - bool disable_poisson_rate = 6; - bool disable_background_cover_traffic = 7; - optional uint32 min_mixnode_performance = 8; - optional uint32 min_gateway_mixnet_performance = 9; - optional uint32 min_gateway_vpn_performance = 10; + bool enable_custom_dns = 17; IpAddrList custom_dns = 16; + optional uint32 min_gateway_vpn_performance = 10; + NetworkStatsConfig network_stats = 18; + + MixnetTrafficConfig mixnet_traffic = 25; } message NetworkStatsConfig { @@ -843,10 +855,22 @@ message NetworkStatisticsIdentity { string id = 2; } +message SetMessageSendingAverageDelayRequest { + uint32 delay_ms = 1; +} +message SetDisablePoissonRateRequest { + bool disable = 1; +} +message SetPoissonParameterRequest { + uint32 poisson_parameter = 1; +} +message SetAveragePacketDelayRequest { + uint32 delay_ms = 1; +} + service NymVpnService { // Get info regarding the nym-vpnd in general, like version etc. rpc Info (google.protobuf.Empty) returns (InfoResponse) {} - // Get the VPN service configuration rpc GetConfig (google.protobuf.Empty) returns (GetConfigResponse) {} @@ -861,6 +885,10 @@ service NymVpnService { rpc SetResidentialExit (google.protobuf.BoolValue) returns (google.protobuf.Empty) {} rpc SetEnableCustomDns (google.protobuf.BoolValue) returns (google.protobuf.Empty) {} rpc SetCustomDns (IpAddrList) returns (google.protobuf.Empty) {} + rpc SetPoissonParameter (SetPoissonParameterRequest) returns (google.protobuf.Empty); + rpc SetDisablePoissonRate (SetDisablePoissonRateRequest) returns (google.protobuf.Empty); + rpc SetAveragePacketDelay(SetAveragePacketDelayRequest) returns (google.protobuf.Empty); + rpc SetMessageSendingAverageDelay(SetMessageSendingAverageDelayRequest) returns (google.protobuf.Empty); // Set the network. This requires a restart to take effect rpc SetNetwork (google.protobuf.StringValue) returns (google.protobuf.Empty) {} diff --git a/nym-vpn-core/crates/nym-vpn-proto/src/conversions/service.rs b/nym-vpn-core/crates/nym-vpn-proto/src/conversions/service.rs index dfe107ef5a..ee68a9bafb 100644 --- a/nym-vpn-core/crates/nym-vpn-proto/src/conversions/service.rs +++ b/nym-vpn-core/crates/nym-vpn-proto/src/conversions/service.rs @@ -32,6 +32,20 @@ impl TryFrom for nym_vpn_lib_types::VpnServiceConfig { ))? .into(); + let mt = value.mixnet_traffic.ok_or(ConversionError::NoValueSet( + "VpnServiceConfig.mixnet_traffic", + ))?; + + let mixnet_traffic = nym_vpn_lib_types::MixnetTrafficConfig { + poisson_parameter: mt.poisson_parameter, + average_packet_delay: mt.average_packet_delay, + message_sending_average_delay: mt.message_sending_average_delay, + disable_poisson_rate: mt.disable_poisson_rate, + disable_background_cover_traffic: mt.disable_background_cover_traffic, + min_mixnode_performance: mt.min_mixnode_performance.map(|u| u as u8), + min_gateway_mixnet_performance: mt.min_gateway_mixnet_performance.map(|u| u as u8), + }; + let config = nym_vpn_lib_types::VpnServiceConfig { entry_point, exit_point, @@ -40,15 +54,14 @@ impl TryFrom for nym_vpn_lib_types::VpnServiceConfig { enable_two_hop: value.enable_two_hop, enable_bridges: value.enable_bridges, netstack: value.netstack, - disable_poisson_rate: value.disable_poisson_rate, - disable_background_cover_traffic: value.disable_background_cover_traffic, - min_mixnode_performance: value.min_mixnode_performance.map(|u| u as u8), - min_gateway_mixnet_performance: value.min_gateway_mixnet_performance.map(|u| u as u8), - min_gateway_vpn_performance: value.min_gateway_vpn_performance.map(|u| u as u8), + residential_exit: value.residential_exit, enable_custom_dns: value.enable_custom_dns, custom_dns, network_stats, + + min_gateway_vpn_performance: value.min_gateway_vpn_performance.map(|u| u as u8), + mixnet_traffic, }; Ok(config) } @@ -59,7 +72,21 @@ impl From for proto::VpnServiceConfig { let entry_point = Some(proto::EntryNode::from(value.entry_point)); let exit_point = Some(proto::ExitNode::from(value.exit_point)); let custom_dns = Some(proto::IpAddrList::from(value.custom_dns)); - + let mixnet_traffic = Some(proto::MixnetTrafficConfig { + poisson_parameter: value.mixnet_traffic.poisson_parameter, + average_packet_delay: value.mixnet_traffic.average_packet_delay, + message_sending_average_delay: value.mixnet_traffic.message_sending_average_delay, + disable_poisson_rate: value.mixnet_traffic.disable_poisson_rate, + disable_background_cover_traffic: value.mixnet_traffic.disable_background_cover_traffic, + min_mixnode_performance: value + .mixnet_traffic + .min_mixnode_performance + .map(|u| u as u32), + min_gateway_mixnet_performance: value + .mixnet_traffic + .min_gateway_mixnet_performance + .map(|u| u as u32), + }); proto::VpnServiceConfig { entry_point, exit_point, @@ -68,15 +95,15 @@ impl From for proto::VpnServiceConfig { enable_two_hop: value.enable_two_hop, enable_bridges: value.enable_bridges, netstack: value.netstack, - disable_poisson_rate: value.disable_poisson_rate, - disable_background_cover_traffic: value.disable_background_cover_traffic, - min_mixnode_performance: value.min_mixnode_performance.map(|u| u as u32), - min_gateway_mixnet_performance: value.min_gateway_mixnet_performance.map(|u| u as u32), - min_gateway_vpn_performance: value.min_gateway_vpn_performance.map(|u| u as u32), residential_exit: value.residential_exit, enable_custom_dns: value.enable_custom_dns, custom_dns, + network_stats: Some(proto::NetworkStatsConfig::from(value.network_stats)), + + min_gateway_vpn_performance: value.min_gateway_vpn_performance.map(|u| u as u32), + + mixnet_traffic, } } } diff --git a/nym-vpn-core/crates/nym-vpn-proto/src/rpc_client.rs b/nym-vpn-core/crates/nym-vpn-proto/src/rpc_client.rs index efa422250a..dc185aed72 100644 --- a/nym-vpn-core/crates/nym-vpn-proto/src/rpc_client.rs +++ b/nym-vpn-core/crates/nym-vpn-proto/src/rpc_client.rs @@ -77,7 +77,51 @@ impl RpcClient { Ok(()) } + pub async fn set_poisson_parameter(&mut self, value: u32) -> Result<()> { + let request = proto::SetPoissonParameterRequest { + poisson_parameter: value, + }; + + self.0 + .set_poisson_parameter(request) + .await + .map_err(Error::Rpc)?; + Ok(()) + } + /// Sets the average per-mixnode packet delay (in milliseconds) + pub async fn set_average_packet_delay(&mut self, delay_ms: u32) -> Result<()> { + let request = proto::SetAveragePacketDelayRequest { delay_ms }; + + self.0 + .set_average_packet_delay(request) + .await + .map_err(Error::Rpc)? + .into_inner(); + + Ok(()) + } + /// Sets the average real traffic message-sending delay (in milliseconds) + pub async fn set_message_sending_average_delay(&mut self, delay_ms: u32) -> Result<()> { + let request = proto::SetMessageSendingAverageDelayRequest { delay_ms }; + + self.0 + .set_message_sending_average_delay(request) + .await + .map_err(Error::Rpc)? + .into_inner(); + + Ok(()) + } + pub async fn set_disable_poisson_rate(&mut self, disable: bool) -> Result<()> { + let request = proto::SetDisablePoissonRateRequest { disable }; + self.0 + .set_disable_poisson_rate(request) + .await + .map_err(Error::Rpc)? + .into_inner(); + Ok(()) + } pub async fn set_disable_ipv6(&mut self, disable_ipv6: bool) -> Result<()> { self.0 .set_disable_ipv6(disable_ipv6) diff --git a/nym-vpn-core/crates/nym-vpnc/src/commands/tunnel.rs b/nym-vpn-core/crates/nym-vpnc/src/commands/tunnel.rs index fa7bac2252..bf0794a403 100644 --- a/nym-vpn-core/crates/nym-vpnc/src/commands/tunnel.rs +++ b/nym-vpn-core/crates/nym-vpnc/src/commands/tunnel.rs @@ -6,6 +6,7 @@ use anyhow::Result; use nym_vpn_proto::rpc_client::RpcClient; use crate::{boolean_option::BooleanOption, display_helpers::display_on_off}; +use clap::builder::ValueParser; #[derive(Debug, Clone, clap::Subcommand)] pub enum Command { @@ -35,6 +36,55 @@ pub struct SetParams { /// Enable Circumvention Transport (CT) wrapping for the connection to the entry gateway in two hop wireguard mode. #[arg(long, alias = "ct", value_parser = clap::value_parser!(BooleanOption))] circumvention_transports: Option, + /// Set the average delay for a loop cover packet (milliseconds) + #[arg( + long, + value_name = "MILLISECONDS", + value_parser = ValueParser::from(|s: &str| -> Result { + let val: u32 = s.parse().map_err(|_| format!("Invalid integer: {}", s))?; + if !(0..=200).contains(&val) { + return Err(format!("Value must be between 0 and 200 (got {val})")); + } + Ok(val) + }) + )] + pub loop_cover_stream_average_delay: Option, + + /// Set average packet delay at each mixnode (milliseconds) + #[arg( + long, + value_name = "MILLISECONDS", + value_parser = ValueParser::from(|s: &str| -> Result { + let val: u32 = s.parse().map_err(|_| format!("Invalid integer: {}", s))?; + if !(0..=200).contains(&val) { + return Err(format!("Packet delay must be between 0 and 200 (got {val})")); + } + Ok(val) + }) + )] + pub average_packet_delay: Option, + + /// Set average real message sending delay (milliseconds) + #[arg( + long, + value_name = "MILLISECONDS", + value_parser = ValueParser::from(|s: &str| -> Result { + let val: u32 = s.parse().map_err(|_| format!("Invalid integer: {}", s))?; + if !(5..=50).contains(&val) { + return Err(format!( + "Message sending delay must be between 5 and 50 (got {val})" + )); + } + Ok(val) + }) + )] + pub message_sending_delay: Option, + #[arg( + long, + help = "Disable Poisson process rate limiting for real traffic", + value_parser = BooleanOption::custom_parser("on","off") + )] + pub disable_real_traffic_poisson_rate: Option, } impl Command { @@ -57,6 +107,10 @@ impl Command { netstack, ipv6, circumvention_transports, + loop_cover_stream_average_delay, + average_packet_delay, + message_sending_delay, + disable_real_traffic_poisson_rate, }) => { if let Some(two_hop) = two_hop { rpc_client.set_enable_two_hop(*two_hop).await?; @@ -73,7 +127,21 @@ impl Command { if let Some(enable_ct) = circumvention_transports { rpc_client.set_enable_bridges(*enable_ct).await?; } + if let Some(poisson) = loop_cover_stream_average_delay { + rpc_client.set_poisson_parameter(poisson).await?; + } + if let Some(delay_ms) = average_packet_delay { + rpc_client.set_average_packet_delay(delay_ms).await?; + } + if let Some(delay_ms) = message_sending_delay { + rpc_client + .set_message_sending_average_delay(delay_ms) + .await?; + } + if let Some(disable) = disable_real_traffic_poisson_rate { + rpc_client.set_disable_poisson_rate(*disable).await?; + } Ok(()) } } diff --git a/nym-vpn-core/crates/nym-vpnd/src/command_interface.rs b/nym-vpn-core/crates/nym-vpnd/src/command_interface.rs index 4b35eacf49..62f65fae89 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/command_interface.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/command_interface.rs @@ -129,7 +129,69 @@ impl NymVpnService for CommandInterface { Ok(tonic::Response::new(())) } + async fn set_poisson_parameter( + &self, + request: tonic::Request, + ) -> Result> { + let value = request.into_inner().poisson_parameter; + tracing::debug!("Received set_poisson_parameter RPC with value: {}", value); + + let _ = self + .send_and_wait(VpnServiceCommand::SetPoissonParameter, value) + .await + .map_err(|e| { + tonic::Status::internal(format!("Failed to set Poisson parameter: {e}")) + })?; + Ok(tonic::Response::new(())) + } + async fn set_average_packet_delay( + &self, + request: tonic::Request, + ) -> Result> { + let delay_ms = request.into_inner().delay_ms; + tracing::debug!("Received SetAveragePacketDelay: {} ms", delay_ms); + + let _ = self + .send_and_wait(VpnServiceCommand::SetAveragePacketDelay, delay_ms) + .await + .map_err(|e| { + tonic::Status::internal(format!("Failed to set average packet delay: {e}")) + })?; + + Ok(tonic::Response::new(())) + } + async fn set_disable_poisson_rate( + &self, + request: tonic::Request, + ) -> Result> { + let disable_poisson_rate = request.into_inner().disable; + + self.send_and_wait( + VpnServiceCommand::SetDisablePoissonRate, + disable_poisson_rate, + ) + .await + .map_err(|e| tonic::Status::internal(format!("Failed to set disable Poisson rate: {e}")))?; + + Ok(tonic::Response::new(())) + } + async fn set_message_sending_average_delay( + &self, + request: tonic::Request, + ) -> Result> { + let delay_ms = request.into_inner().delay_ms; + tracing::debug!("Received SetMessageSendingAverageDelay: {} ms", delay_ms); + + let _ = self + .send_and_wait(VpnServiceCommand::SetMessageSendingAverageDelay, delay_ms) + .await + .map_err(|e| { + tonic::Status::internal(format!("Failed to set message sending average delay: {e}")) + })?; + + Ok(tonic::Response::new(())) + } async fn set_enable_two_hop( &self, request: tonic::Request, diff --git a/nym-vpn-core/crates/nym-vpnd/src/main.rs b/nym-vpn-core/crates/nym-vpnd/src/main.rs index 356a2e521d..143b68f2ed 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/main.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/main.rs @@ -109,7 +109,6 @@ async fn run_vpn_service(args: CliArgs) -> anyhow::Result<()> { #[cfg(not(windows))] run_standalone(run_parameters, remove_log_file_signal, shutdown_token).await?; - let _worker_guard = if let Some(setup) = logging_setup { if setup.log_file_remover_join_handle.await.is_err() { tracing::error!("Failed to join on file logging handle"); @@ -204,7 +203,6 @@ impl VpnServiceHandle { if let Err(e) = self.vpn_service_handle.await { tracing::error!("Failed to join on vpn service: {}", e); } - self.command_shutdown_token.cancel(); if let Err(e) = self.command_handle.await { diff --git a/nym-vpn-core/crates/nym-vpnd/src/service/config/config_manager.rs b/nym-vpn-core/crates/nym-vpnd/src/service/config/config_manager.rs index d5746ba5cf..b1f4c7bfbb 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/service/config/config_manager.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/service/config/config_manager.rs @@ -162,24 +162,43 @@ impl VpnServiceConfigManager { #[allow(unused)] pub async fn set_disable_poisson_rate(&mut self, disable_poisson_rate: bool) { - if self.config.disable_poisson_rate != disable_poisson_rate { - self.config.disable_poisson_rate = disable_poisson_rate; + if self.config.mixnet_traffic.disable_poisson_rate != disable_poisson_rate { + self.config.mixnet_traffic.disable_poisson_rate = disable_poisson_rate; self.save_config_and_send_event().await; } } #[allow(unused)] pub async fn set_disable_background_cover_traffic(&mut self, disable: bool) { - if self.config.disable_background_cover_traffic != disable { - self.config.disable_background_cover_traffic = disable; + if self.config.mixnet_traffic.disable_background_cover_traffic != disable { + self.config.mixnet_traffic.disable_background_cover_traffic = disable; self.save_config_and_send_event().await; } } + #[allow(unused)] + pub async fn set_poisson_parameter(&mut self, poisson: u32) { + self.config.mixnet_traffic.poisson_parameter = Some(poisson); + self.save_config_and_send_event().await; + } + + #[allow(unused)] + pub async fn set_message_sending_average_delay(&mut self, message_sending_delay: Option) { + self.config.mixnet_traffic.message_sending_average_delay = message_sending_delay; + self.save_config_and_send_event().await; + } + + #[allow(unused)] + pub async fn set_average_packet_delay(&mut self, average_delay: Option) { + self.config.mixnet_traffic.average_packet_delay = average_delay; + self.save_config_and_send_event().await; + } + #[allow(unused)] pub async fn set_min_mixnode_performance(&mut self, min_mixnode_performance: Option) { - if self.config.min_mixnode_performance != min_mixnode_performance { - self.config.min_mixnode_performance = min_mixnode_performance.map(|u| u.min(100)); + if self.config.mixnet_traffic.min_mixnode_performance != min_mixnode_performance { + self.config.mixnet_traffic.min_mixnode_performance = + min_mixnode_performance.map(|u| u.min(100)); self.save_config_and_send_event().await; } } @@ -189,8 +208,10 @@ impl VpnServiceConfigManager { &mut self, min_gateway_mixnet_performance: Option, ) { - if self.config.min_gateway_mixnet_performance != min_gateway_mixnet_performance { - self.config.min_gateway_mixnet_performance = + if self.config.mixnet_traffic.min_gateway_mixnet_performance + != min_gateway_mixnet_performance + { + self.config.mixnet_traffic.min_gateway_mixnet_performance = min_gateway_mixnet_performance.map(|u| u.min(100)); self.save_config_and_send_event().await; } @@ -321,23 +342,31 @@ impl VpnServiceConfigManager { tracing::info!("Using config: {:?}", self.config); let gateway_options = GatewayPerformanceOptions { - mixnet_min_performance: self.config.min_gateway_mixnet_performance, + mixnet_min_performance: self.config.mixnet_traffic.min_gateway_mixnet_performance, vpn_min_performance: self.config.min_gateway_vpn_performance, }; let mixnet_client_config = MixnetClientConfig { - disable_poisson_rate: self.config.disable_poisson_rate, - disable_background_cover_traffic: self.config.disable_background_cover_traffic, + disable_poisson_rate: self.config.mixnet_traffic.disable_poisson_rate, + disable_background_cover_traffic: self + .config + .mixnet_traffic + .disable_background_cover_traffic, min_mixnode_performance: Some( self.config + .mixnet_traffic .min_mixnode_performance .unwrap_or(DEFAULT_MIN_MIXNODE_PERFORMANCE), ), min_gateway_performance: Some( self.config + .mixnet_traffic .min_gateway_mixnet_performance .unwrap_or(DEFAULT_MIN_GATEWAY_PERFORMANCE), ), + poisson_rate: self.config.mixnet_traffic.poisson_parameter, + average_packet_delay: self.config.mixnet_traffic.average_packet_delay, + message_sending_average_delay: self.config.mixnet_traffic.message_sending_average_delay, }; let tunnel_type = if self.config.enable_two_hop { diff --git a/nym-vpn-core/crates/nym-vpnd/src/service/config/mod.rs b/nym-vpn-core/crates/nym-vpnd/src/service/config/mod.rs index 7468c29ffa..e35ee4ac12 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/service/config/mod.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/service/config/mod.rs @@ -164,10 +164,10 @@ impl TryFrom<&nym_vpn_lib_types::VpnServiceConfig> for VpnServiceConfigExt { enable_two_hop: value.enable_two_hop, enable_bridges: value.enable_bridges, netstack: value.netstack, - disable_poisson_rate: value.disable_poisson_rate, - disable_background_cover_traffic: value.disable_background_cover_traffic, - min_mixnode_performance: value.min_mixnode_performance, - min_gateway_mixnet_performance: value.min_gateway_mixnet_performance, + disable_poisson_rate: value.mixnet_traffic.disable_poisson_rate, + disable_background_cover_traffic: value.mixnet_traffic.disable_background_cover_traffic, + min_mixnode_performance: value.mixnet_traffic.min_mixnode_performance, + min_gateway_mixnet_performance: value.mixnet_traffic.min_gateway_mixnet_performance, min_gateway_vpn_performance: value.min_gateway_vpn_performance, residential_exit: value.residential_exit, enable_custom_dns: value.enable_custom_dns, diff --git a/nym-vpn-core/crates/nym-vpnd/src/service/config/v2.rs b/nym-vpn-core/crates/nym-vpnd/src/service/config/v2.rs index 3a113e5f3f..90410cbe2e 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/service/config/v2.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/service/config/v2.rs @@ -47,24 +47,38 @@ impl TryFrom for nym_vpn_lib_types::VpnServiceConfig { } None => vec![], }; + let mixnet_traffic = nym_vpn_lib_types::MixnetTrafficConfig { + poisson_parameter: None, + average_packet_delay: None, + message_sending_average_delay: None, + + disable_poisson_rate: value.disable_poisson_rate, + disable_background_cover_traffic: value.disable_background_cover_traffic, + + min_mixnode_performance: value.min_mixnode_performance, + min_gateway_mixnet_performance: value.min_gateway_mixnet_performance, + }; let config = nym_vpn_lib_types::VpnServiceConfig { entry_point: nym_vpn_lib_types::EntryPoint::try_from(value.entry_point)?, exit_point: nym_vpn_lib_types::ExitPoint::try_from(value.exit_point)?, + allow_lan: value.allow_lan, disable_ipv6: value.disable_ipv6, enable_two_hop: value.enable_two_hop, enable_bridges: value.enable_bridges, netstack: value.netstack, - disable_poisson_rate: value.disable_poisson_rate, - disable_background_cover_traffic: value.disable_background_cover_traffic, - min_mixnode_performance: value.min_mixnode_performance, - min_gateway_mixnet_performance: value.min_gateway_mixnet_performance, - min_gateway_vpn_performance: value.min_gateway_vpn_performance, + residential_exit: value.residential_exit, + enable_custom_dns: !custom_dns.is_empty(), custom_dns, + + mixnet_traffic, + network_stats: Default::default(), + + min_gateway_vpn_performance: value.min_gateway_vpn_performance, }; Ok(config) } diff --git a/nym-vpn-core/crates/nym-vpnd/src/service/config/v3.rs b/nym-vpn-core/crates/nym-vpnd/src/service/config/v3.rs index d042035662..ceb95588f1 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/service/config/v3.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/service/config/v3.rs @@ -50,25 +50,40 @@ impl TryFrom for nym_vpn_lib_types::VpnServiceConfig { }) .collect::>()?, }; + let mixnet_traffic = nym_vpn_lib_types::MixnetTrafficConfig { + poisson_parameter: None, + average_packet_delay: None, + message_sending_average_delay: None, + + disable_poisson_rate: value.disable_poisson_rate, + disable_background_cover_traffic: value.disable_background_cover_traffic, + + min_mixnode_performance: value.min_mixnode_performance, + min_gateway_mixnet_performance: value.min_gateway_mixnet_performance, + }; let config = nym_vpn_lib_types::VpnServiceConfig { entry_point: nym_vpn_lib_types::EntryPoint::try_from(value.entry_point)?, exit_point: nym_vpn_lib_types::ExitPoint::try_from(value.exit_point)?, + allow_lan: value.allow_lan, disable_ipv6: value.disable_ipv6, enable_two_hop: value.enable_two_hop, enable_bridges: value.enable_bridges, netstack: value.netstack, - disable_poisson_rate: value.disable_poisson_rate, - disable_background_cover_traffic: value.disable_background_cover_traffic, - min_mixnode_performance: value.min_mixnode_performance, - min_gateway_mixnet_performance: value.min_gateway_mixnet_performance, - min_gateway_vpn_performance: value.min_gateway_vpn_performance, + residential_exit: value.residential_exit, + + mixnet_traffic, + + min_gateway_vpn_performance: value.min_gateway_vpn_performance, + enable_custom_dns: !custom_dns.is_empty(), custom_dns, + network_stats: Default::default(), }; + Ok(config) } } diff --git a/nym-vpn-core/crates/nym-vpnd/src/service/config/v4.rs b/nym-vpn-core/crates/nym-vpnd/src/service/config/v4.rs index 6aebaba6a6..db8d5b2361 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/service/config/v4.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/service/config/v4.rs @@ -51,24 +51,39 @@ impl TryFrom for nym_vpn_lib_types::VpnServiceConfig { }) .collect::>()?; + let mixnet_traffic = nym_vpn_lib_types::MixnetTrafficConfig { + poisson_parameter: None, + average_packet_delay: None, + message_sending_average_delay: None, + + disable_poisson_rate: value.disable_poisson_rate, + disable_background_cover_traffic: value.disable_background_cover_traffic, + + min_mixnode_performance: value.min_mixnode_performance, + min_gateway_mixnet_performance: value.min_gateway_mixnet_performance, + }; let config = nym_vpn_lib_types::VpnServiceConfig { entry_point: nym_vpn_lib_types::EntryPoint::try_from(value.entry_point)?, exit_point: nym_vpn_lib_types::ExitPoint::try_from(value.exit_point)?, + allow_lan: value.allow_lan, disable_ipv6: value.disable_ipv6, enable_two_hop: value.enable_two_hop, enable_bridges: value.enable_bridges, netstack: value.netstack, - disable_poisson_rate: value.disable_poisson_rate, - disable_background_cover_traffic: value.disable_background_cover_traffic, - min_mixnode_performance: value.min_mixnode_performance, - min_gateway_mixnet_performance: value.min_gateway_mixnet_performance, - min_gateway_vpn_performance: value.min_gateway_vpn_performance, + residential_exit: value.residential_exit, + + mixnet_traffic, + + min_gateway_vpn_performance: value.min_gateway_vpn_performance, + enable_custom_dns: value.enable_custom_dns, custom_dns, + network_stats: nym_vpn_lib_types::NetworkStatisticsConfig::from(value.network_stats), }; + Ok(config) } } diff --git a/nym-vpn-core/crates/nym-vpnd/src/service/vpn_service.rs b/nym-vpn-core/crates/nym-vpnd/src/service/vpn_service.rs index 56f199904c..6ae35da24a 100644 --- a/nym-vpn-core/crates/nym-vpnd/src/service/vpn_service.rs +++ b/nym-vpn-core/crates/nym-vpnd/src/service/vpn_service.rs @@ -150,6 +150,10 @@ pub enum VpnServiceCommand { oneshot::Sender>, (), ), + SetPoissonParameter(oneshot::Sender<()>, u32), + SetAveragePacketDelay(oneshot::Sender<()>, u32), + SetMessageSendingAverageDelay(oneshot::Sender<()>, u32), + SetDisablePoissonRate(oneshot::Sender<()>, bool), } pub struct NymVpnServiceParameters { @@ -927,6 +931,24 @@ impl NymVpnService { let result = self.handle_get_socks5_status().await; let _ = tx.send(result); } + VpnServiceCommand::SetPoissonParameter(tx, value) => { + self.handle_set_poisson_parameter(value).await; + let _ = tx.send(()); + } + VpnServiceCommand::SetAveragePacketDelay(resp, delay_ms) => { + self.handle_set_average_packet_delay(delay_ms).await; + let _ = resp.send(()); + } + + VpnServiceCommand::SetMessageSendingAverageDelay(resp, delay_ms) => { + self.handle_set_message_sending_average_delay(delay_ms) + .await; + let _ = resp.send(()); + } + VpnServiceCommand::SetDisablePoissonRate(tx, disable) => { + self.handle_set_disable_poisson_rate(disable).await; + let _ = tx.send(()); + } } } @@ -973,6 +995,38 @@ impl NymVpnService { self.config_manager.set_netstack(netstack).await; self.update_tunnel_settings_with_throttle(); } + async fn handle_set_poisson_parameter(&mut self, value: u32) { + // Update the Poisson parameter inside the configuration manager + self.config_manager.set_poisson_parameter(value).await; + + // Update tunnel settings with throttle + self.update_tunnel_settings_with_throttle(); + } + async fn handle_set_disable_poisson_rate(&mut self, disable: bool) { + // Update the disable_poisson_rate flag in the configuration manager + self.config_manager.set_disable_poisson_rate(disable).await; + + // Update tunnel settings accordingly + self.update_tunnel_settings_with_throttle(); + } + pub async fn handle_set_message_sending_average_delay(&mut self, delay_ms: u32) { + // Update config + self.config_manager + .set_message_sending_average_delay(Some(delay_ms)) + .await; + + // Update tunnel settings (with throttle) + self.update_tunnel_settings_with_throttle(); + } + pub async fn handle_set_average_packet_delay(&mut self, delay_ms: u32) { + // Update config + self.config_manager + .set_average_packet_delay(Some(delay_ms)) + .await; + + // Update tunnel settings (with throttle) + self.update_tunnel_settings_with_throttle(); + } async fn handle_set_allow_lan(&mut self, allow_lan: bool) { self.config_manager.set_allow_lan(allow_lan).await;