From f40b645c0530b3b870c22c556546f20b933ca627 Mon Sep 17 00:00:00 2001 From: Alexey <247128645+axkurcom@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:28:06 +0300 Subject: [PATCH] Defaults in-place --- src/config/defaults.rs | 50 +++++++++++++++++++++++++++++++++++++++--- src/config/load.rs | 49 +++++++++++++++++++++++++++++++++++++++++ src/config/types.rs | 43 ++++++++++++++++-------------------- 3 files changed, 115 insertions(+), 27 deletions(-) diff --git a/src/config/defaults.rs b/src/config/defaults.rs index 2ce7bac..51abe65 100644 --- a/src/config/defaults.rs +++ b/src/config/defaults.rs @@ -3,6 +3,15 @@ use ipnetwork::IpNetwork; use serde::Deserialize; // Helper defaults kept private to the config module. +const DEFAULT_NETWORK_IPV6: Option = Some(false); +const DEFAULT_STUN_TCP_FALLBACK: bool = true; +const DEFAULT_MIDDLE_PROXY_WARM_STANDBY: usize = 16; +const DEFAULT_ME_RECONNECT_MAX_CONCURRENT_PER_DC: u32 = 8; +const DEFAULT_ME_RECONNECT_FAST_RETRY_COUNT: u32 = 12; +const DEFAULT_LISTEN_ADDR_IPV6: &str = "::"; +const DEFAULT_ACCESS_USER: &str = "default"; +const DEFAULT_ACCESS_SECRET: &str = "00000000000000000000000000000000"; + pub(crate) fn default_true() -> bool { true } @@ -77,6 +86,14 @@ pub(crate) fn default_prefer_4() -> u8 { 4 } +pub(crate) fn default_network_ipv6() -> Option { + DEFAULT_NETWORK_IPV6 +} + +pub(crate) fn default_stun_tcp_fallback() -> bool { + DEFAULT_STUN_TCP_FALLBACK +} + pub(crate) fn default_unknown_dc_log_path() -> Option { Some("unknown-dc.txt".to_string()) } @@ -85,6 +102,10 @@ pub(crate) fn default_pool_size() -> usize { 8 } +pub(crate) fn default_middle_proxy_warm_standby() -> usize { + DEFAULT_MIDDLE_PROXY_WARM_STANDBY +} + pub(crate) fn default_keepalive_interval() -> u64 { 25 } @@ -109,6 +130,14 @@ pub(crate) fn default_reconnect_backoff_cap_ms() -> u64 { 30_000 } +pub(crate) fn default_me_reconnect_max_concurrent_per_dc() -> u32 { + DEFAULT_ME_RECONNECT_MAX_CONCURRENT_PER_DC +} + +pub(crate) fn default_me_reconnect_fast_retry_count() -> u32 { + DEFAULT_ME_RECONNECT_FAST_RETRY_COUNT +} + pub(crate) fn default_crypto_pending_buffer() -> usize { 256 * 1024 } @@ -191,7 +220,11 @@ pub(crate) fn default_proxy_config_reload_secs() -> u64 { } pub(crate) fn default_update_every_secs() -> u64 { - 30 * 60 + 5 * 60 +} + +pub(crate) fn default_update_every() -> Option { + Some(default_update_every_secs()) } pub(crate) fn default_me_reinit_every_secs() -> u64 { @@ -199,11 +232,11 @@ pub(crate) fn default_me_reinit_every_secs() -> u64 { } pub(crate) fn default_me_hardswap_warmup_delay_min_ms() -> u64 { - 2000 + 1000 } pub(crate) fn default_me_hardswap_warmup_delay_max_ms() -> u64 { - 3500 + 2000 } pub(crate) fn default_me_hardswap_warmup_extra_passes() -> u8 { @@ -266,6 +299,17 @@ pub(crate) fn default_degradation_min_unavailable_dc_groups() -> u8 { 2 } +pub(crate) fn default_listen_addr_ipv6() -> String { + DEFAULT_LISTEN_ADDR_IPV6.to_string() +} + +pub(crate) fn default_access_users() -> HashMap { + HashMap::from([( + DEFAULT_ACCESS_USER.to_string(), + DEFAULT_ACCESS_SECRET.to_string(), + )]) +} + // Custom deserializer helpers #[derive(Deserialize)] diff --git a/src/config/load.rs b/src/config/load.rs index aab553f..be6759e 100644 --- a/src/config/load.rs +++ b/src/config/load.rs @@ -427,6 +427,55 @@ impl ProxyConfig { mod tests { use super::*; + #[test] + fn serde_defaults_remain_unchanged_for_present_sections() { + let toml = r#" + [network] + [general] + [server] + [access] + "#; + let cfg: ProxyConfig = toml::from_str(toml).unwrap(); + + assert_eq!(cfg.network.ipv6, None); + assert!(!cfg.network.stun_tcp_fallback); + assert_eq!(cfg.general.middle_proxy_warm_standby, 0); + assert_eq!(cfg.general.me_reconnect_max_concurrent_per_dc, 0); + assert_eq!(cfg.general.me_reconnect_fast_retry_count, 0); + assert_eq!(cfg.general.update_every, None); + assert_eq!(cfg.server.listen_addr_ipv4, None); + assert_eq!(cfg.server.listen_addr_ipv6, None); + assert!(cfg.access.users.is_empty()); + } + + #[test] + fn impl_defaults_are_sourced_from_default_helpers() { + let network = NetworkConfig::default(); + assert_eq!(network.ipv6, default_network_ipv6()); + assert_eq!(network.stun_tcp_fallback, default_stun_tcp_fallback()); + + let general = GeneralConfig::default(); + assert_eq!( + general.middle_proxy_warm_standby, + default_middle_proxy_warm_standby() + ); + assert_eq!( + general.me_reconnect_max_concurrent_per_dc, + default_me_reconnect_max_concurrent_per_dc() + ); + assert_eq!( + general.me_reconnect_fast_retry_count, + default_me_reconnect_fast_retry_count() + ); + assert_eq!(general.update_every, default_update_every()); + + let server = ServerConfig::default(); + assert_eq!(server.listen_addr_ipv6, Some(default_listen_addr_ipv6())); + + let access = AccessConfig::default(); + assert_eq!(access.users, default_access_users()); + } + #[test] fn dc_overrides_allow_string_and_array() { let toml = r#" diff --git a/src/config/types.rs b/src/config/types.rs index cfa8d31..ad22c93 100644 --- a/src/config/types.rs +++ b/src/config/types.rs @@ -76,7 +76,7 @@ impl Default for ProxyModes { Self { classic: false, secure: false, - tls: true, + tls: default_true(), } } } @@ -117,12 +117,12 @@ pub struct NetworkConfig { impl Default for NetworkConfig { fn default() -> Self { Self { - ipv4: true, - ipv6: Some(false), - prefer: 4, + ipv4: default_true(), + ipv6: default_network_ipv6(), + prefer: default_prefer_4(), multipath: false, stun_servers: default_stun_servers(), - stun_tcp_fallback: true, + stun_tcp_fallback: default_stun_tcp_fallback(), http_ip_detect_urls: default_http_ip_detect_urls(), cache_public_ip_path: default_cache_public_ip_path(), } @@ -370,27 +370,27 @@ impl Default for GeneralConfig { Self { modes: ProxyModes::default(), prefer_ipv6: false, - fast_mode: true, + fast_mode: default_true(), use_middle_proxy: false, ad_tag: None, proxy_secret_path: None, middle_proxy_nat_ip: None, - middle_proxy_nat_probe: false, + middle_proxy_nat_probe: true, middle_proxy_nat_stun: None, middle_proxy_nat_stun_servers: Vec::new(), middle_proxy_pool_size: default_pool_size(), - middle_proxy_warm_standby: 16, - me_keepalive_enabled: true, + middle_proxy_warm_standby: default_middle_proxy_warm_standby(), + me_keepalive_enabled: default_true(), me_keepalive_interval_secs: default_keepalive_interval(), me_keepalive_jitter_secs: default_keepalive_jitter(), - me_keepalive_payload_random: true, - me_warmup_stagger_enabled: true, + me_keepalive_payload_random: default_true(), + me_warmup_stagger_enabled: default_true(), me_warmup_step_delay_ms: default_warmup_step_delay_ms(), me_warmup_step_jitter_ms: default_warmup_step_jitter_ms(), - me_reconnect_max_concurrent_per_dc: 8, + me_reconnect_max_concurrent_per_dc: default_me_reconnect_max_concurrent_per_dc(), me_reconnect_backoff_base_ms: default_reconnect_backoff_base_ms(), me_reconnect_backoff_cap_ms: default_reconnect_backoff_cap_ms(), - me_reconnect_fast_retry_count: 8, + me_reconnect_fast_retry_count: default_me_reconnect_fast_retry_count(), stun_iface_mismatch_ignore: false, unknown_dc_log_path: default_unknown_dc_log_path(), log_level: LogLevel::Normal, @@ -399,13 +399,13 @@ impl Default for GeneralConfig { crypto_pending_buffer: default_crypto_pending_buffer(), max_client_frame: default_max_client_frame(), desync_all_full: default_desync_all_full(), - beobachten: false, + beobachten: true, beobachten_minutes: default_beobachten_minutes(), beobachten_flush_secs: default_beobachten_flush_secs(), beobachten_file: default_beobachten_file(), hardswap: default_hardswap(), fast_mode_min_tls_record: default_fast_mode_min_tls_record(), - update_every: Some(default_update_every_secs()), + update_every: default_update_every(), me_reinit_every_secs: default_me_reinit_every_secs(), me_hardswap_warmup_delay_min_ms: default_me_hardswap_warmup_delay_min_ms(), me_hardswap_warmup_delay_max_ms: default_me_hardswap_warmup_delay_max_ms(), @@ -423,7 +423,7 @@ impl Default for GeneralConfig { proxy_config_auto_reload_secs: default_proxy_config_reload_secs(), ntp_check: default_ntp_check(), ntp_servers: default_ntp_servers(), - auto_degradation_enabled: true, + auto_degradation_enabled: default_true(), degradation_min_unavailable_dc_groups: default_degradation_min_unavailable_dc_groups(), } } @@ -510,7 +510,7 @@ impl Default for ServerConfig { Self { port: default_port(), listen_addr_ipv4: Some(default_listen_addr()), - listen_addr_ipv6: Some("::".to_string()), + listen_addr_ipv6: Some(default_listen_addr_ipv6()), listen_unix_sock: None, listen_unix_sock_perm: None, listen_tcp: None, @@ -618,7 +618,7 @@ impl Default for AntiCensorshipConfig { Self { tls_domain: default_tls_domain(), tls_domains: Vec::new(), - mask: true, + mask: default_true(), mask_host: None, mask_port: default_mask_port(), mask_unix_sock: None, @@ -663,13 +663,8 @@ pub struct AccessConfig { impl Default for AccessConfig { fn default() -> Self { - let mut users = HashMap::new(); - users.insert( - "default".to_string(), - "00000000000000000000000000000000".to_string(), - ); Self { - users, + users: default_access_users(), user_max_tcp_conns: HashMap::new(), user_expirations: HashMap::new(), user_data_quota: HashMap::new(),