Defaults in-place

This commit is contained in:
Alexey 2026-02-25 17:28:06 +03:00
parent a66d5d56bb
commit f40b645c05
No known key found for this signature in database
3 changed files with 115 additions and 27 deletions

View File

@ -3,6 +3,15 @@ use ipnetwork::IpNetwork;
use serde::Deserialize; use serde::Deserialize;
// Helper defaults kept private to the config module. // Helper defaults kept private to the config module.
const DEFAULT_NETWORK_IPV6: Option<bool> = 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 { pub(crate) fn default_true() -> bool {
true true
} }
@ -77,6 +86,14 @@ pub(crate) fn default_prefer_4() -> u8 {
4 4
} }
pub(crate) fn default_network_ipv6() -> Option<bool> {
DEFAULT_NETWORK_IPV6
}
pub(crate) fn default_stun_tcp_fallback() -> bool {
DEFAULT_STUN_TCP_FALLBACK
}
pub(crate) fn default_unknown_dc_log_path() -> Option<String> { pub(crate) fn default_unknown_dc_log_path() -> Option<String> {
Some("unknown-dc.txt".to_string()) Some("unknown-dc.txt".to_string())
} }
@ -85,6 +102,10 @@ pub(crate) fn default_pool_size() -> usize {
8 8
} }
pub(crate) fn default_middle_proxy_warm_standby() -> usize {
DEFAULT_MIDDLE_PROXY_WARM_STANDBY
}
pub(crate) fn default_keepalive_interval() -> u64 { pub(crate) fn default_keepalive_interval() -> u64 {
25 25
} }
@ -109,6 +130,14 @@ pub(crate) fn default_reconnect_backoff_cap_ms() -> u64 {
30_000 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 { pub(crate) fn default_crypto_pending_buffer() -> usize {
256 * 1024 256 * 1024
} }
@ -191,7 +220,11 @@ pub(crate) fn default_proxy_config_reload_secs() -> u64 {
} }
pub(crate) fn default_update_every_secs() -> u64 { pub(crate) fn default_update_every_secs() -> u64 {
30 * 60 5 * 60
}
pub(crate) fn default_update_every() -> Option<u64> {
Some(default_update_every_secs())
} }
pub(crate) fn default_me_reinit_every_secs() -> u64 { 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 { pub(crate) fn default_me_hardswap_warmup_delay_min_ms() -> u64 {
2000 1000
} }
pub(crate) fn default_me_hardswap_warmup_delay_max_ms() -> u64 { pub(crate) fn default_me_hardswap_warmup_delay_max_ms() -> u64 {
3500 2000
} }
pub(crate) fn default_me_hardswap_warmup_extra_passes() -> u8 { 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 2
} }
pub(crate) fn default_listen_addr_ipv6() -> String {
DEFAULT_LISTEN_ADDR_IPV6.to_string()
}
pub(crate) fn default_access_users() -> HashMap<String, String> {
HashMap::from([(
DEFAULT_ACCESS_USER.to_string(),
DEFAULT_ACCESS_SECRET.to_string(),
)])
}
// Custom deserializer helpers // Custom deserializer helpers
#[derive(Deserialize)] #[derive(Deserialize)]

View File

@ -427,6 +427,55 @@ impl ProxyConfig {
mod tests { mod tests {
use super::*; 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] #[test]
fn dc_overrides_allow_string_and_array() { fn dc_overrides_allow_string_and_array() {
let toml = r#" let toml = r#"

View File

@ -76,7 +76,7 @@ impl Default for ProxyModes {
Self { Self {
classic: false, classic: false,
secure: false, secure: false,
tls: true, tls: default_true(),
} }
} }
} }
@ -117,12 +117,12 @@ pub struct NetworkConfig {
impl Default for NetworkConfig { impl Default for NetworkConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
ipv4: true, ipv4: default_true(),
ipv6: Some(false), ipv6: default_network_ipv6(),
prefer: 4, prefer: default_prefer_4(),
multipath: false, multipath: false,
stun_servers: default_stun_servers(), 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(), http_ip_detect_urls: default_http_ip_detect_urls(),
cache_public_ip_path: default_cache_public_ip_path(), cache_public_ip_path: default_cache_public_ip_path(),
} }
@ -370,27 +370,27 @@ impl Default for GeneralConfig {
Self { Self {
modes: ProxyModes::default(), modes: ProxyModes::default(),
prefer_ipv6: false, prefer_ipv6: false,
fast_mode: true, fast_mode: default_true(),
use_middle_proxy: false, use_middle_proxy: false,
ad_tag: None, ad_tag: None,
proxy_secret_path: None, proxy_secret_path: None,
middle_proxy_nat_ip: 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: None,
middle_proxy_nat_stun_servers: Vec::new(), middle_proxy_nat_stun_servers: Vec::new(),
middle_proxy_pool_size: default_pool_size(), middle_proxy_pool_size: default_pool_size(),
middle_proxy_warm_standby: 16, middle_proxy_warm_standby: default_middle_proxy_warm_standby(),
me_keepalive_enabled: true, me_keepalive_enabled: default_true(),
me_keepalive_interval_secs: default_keepalive_interval(), me_keepalive_interval_secs: default_keepalive_interval(),
me_keepalive_jitter_secs: default_keepalive_jitter(), me_keepalive_jitter_secs: default_keepalive_jitter(),
me_keepalive_payload_random: true, me_keepalive_payload_random: default_true(),
me_warmup_stagger_enabled: true, me_warmup_stagger_enabled: default_true(),
me_warmup_step_delay_ms: default_warmup_step_delay_ms(), me_warmup_step_delay_ms: default_warmup_step_delay_ms(),
me_warmup_step_jitter_ms: default_warmup_step_jitter_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_base_ms: default_reconnect_backoff_base_ms(),
me_reconnect_backoff_cap_ms: default_reconnect_backoff_cap_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, stun_iface_mismatch_ignore: false,
unknown_dc_log_path: default_unknown_dc_log_path(), unknown_dc_log_path: default_unknown_dc_log_path(),
log_level: LogLevel::Normal, log_level: LogLevel::Normal,
@ -399,13 +399,13 @@ impl Default for GeneralConfig {
crypto_pending_buffer: default_crypto_pending_buffer(), crypto_pending_buffer: default_crypto_pending_buffer(),
max_client_frame: default_max_client_frame(), max_client_frame: default_max_client_frame(),
desync_all_full: default_desync_all_full(), desync_all_full: default_desync_all_full(),
beobachten: false, beobachten: true,
beobachten_minutes: default_beobachten_minutes(), beobachten_minutes: default_beobachten_minutes(),
beobachten_flush_secs: default_beobachten_flush_secs(), beobachten_flush_secs: default_beobachten_flush_secs(),
beobachten_file: default_beobachten_file(), beobachten_file: default_beobachten_file(),
hardswap: default_hardswap(), hardswap: default_hardswap(),
fast_mode_min_tls_record: default_fast_mode_min_tls_record(), 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_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_min_ms: default_me_hardswap_warmup_delay_min_ms(),
me_hardswap_warmup_delay_max_ms: default_me_hardswap_warmup_delay_max_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(), proxy_config_auto_reload_secs: default_proxy_config_reload_secs(),
ntp_check: default_ntp_check(), ntp_check: default_ntp_check(),
ntp_servers: default_ntp_servers(), 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(), degradation_min_unavailable_dc_groups: default_degradation_min_unavailable_dc_groups(),
} }
} }
@ -510,7 +510,7 @@ impl Default for ServerConfig {
Self { Self {
port: default_port(), port: default_port(),
listen_addr_ipv4: Some(default_listen_addr()), 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: None,
listen_unix_sock_perm: None, listen_unix_sock_perm: None,
listen_tcp: None, listen_tcp: None,
@ -618,7 +618,7 @@ impl Default for AntiCensorshipConfig {
Self { Self {
tls_domain: default_tls_domain(), tls_domain: default_tls_domain(),
tls_domains: Vec::new(), tls_domains: Vec::new(),
mask: true, mask: default_true(),
mask_host: None, mask_host: None,
mask_port: default_mask_port(), mask_port: default_mask_port(),
mask_unix_sock: None, mask_unix_sock: None,
@ -663,13 +663,8 @@ pub struct AccessConfig {
impl Default for AccessConfig { impl Default for AccessConfig {
fn default() -> Self { fn default() -> Self {
let mut users = HashMap::new();
users.insert(
"default".to_string(),
"00000000000000000000000000000000".to_string(),
);
Self { Self {
users, users: default_access_users(),
user_max_tcp_conns: HashMap::new(), user_max_tcp_conns: HashMap::new(),
user_expirations: HashMap::new(), user_expirations: HashMap::new(),
user_data_quota: HashMap::new(), user_data_quota: HashMap::new(),