Support configurable TCP STUN servers (#2314)

tcp_stun_servers explicitly controls TCP STUN servers.
If tcp_stun_servers is not configured, TCP STUN falls back to configured stun_servers.
If neither is configured, TCP STUN uses the built-in default TCP STUN list.
Empty lists explicitly disable the corresponding STUN server list.
Empty CLI/env overrides now clear existing configured STUN servers instead of appending nothing.
This commit is contained in:
fanyang
2026-08-13 09:56:44 +08:00
committed by GitHub
parent 52bb26680a
commit 8c15941c44
4 changed files with 207 additions and 31 deletions
+61 -6
View File
@@ -692,6 +692,15 @@ struct NetworkOptions {
)]
stun_servers_v6: Option<Vec<String>>,
#[arg(
long,
env = "ET_TCP_STUN_SERVERS",
value_delimiter = ',',
help = t!("core_clap.tcp_stun_servers").to_string(),
num_args = 0..
)]
tcp_stun_servers: Option<Vec<String>>,
#[arg(
long,
env = "ET_SECURE_MODE",
@@ -1190,15 +1199,33 @@ impl NetworkOptions {
cfg.set_udp_whitelist(old_udp_whitelist);
if let Some(stun_servers) = &self.stun_servers {
let mut old_stun_servers = cfg.get_stun_servers().unwrap_or_default();
old_stun_servers.extend(stun_servers.iter().cloned());
cfg.set_stun_servers(Some(old_stun_servers));
if stun_servers.is_empty() {
cfg.set_stun_servers(Some(Vec::new()));
} else {
let mut old_stun_servers = cfg.get_stun_servers().unwrap_or_default();
old_stun_servers.extend(stun_servers.iter().cloned());
cfg.set_stun_servers(Some(old_stun_servers));
}
}
if let Some(stun_servers_v6) = &self.stun_servers_v6 {
let mut old_stun_servers_v6 = cfg.get_stun_servers_v6().unwrap_or_default();
old_stun_servers_v6.extend(stun_servers_v6.iter().cloned());
cfg.set_stun_servers_v6(Some(old_stun_servers_v6));
if stun_servers_v6.is_empty() {
cfg.set_stun_servers_v6(Some(Vec::new()));
} else {
let mut old_stun_servers_v6 = cfg.get_stun_servers_v6().unwrap_or_default();
old_stun_servers_v6.extend(stun_servers_v6.iter().cloned());
cfg.set_stun_servers_v6(Some(old_stun_servers_v6));
}
}
if let Some(tcp_stun_servers) = &self.tcp_stun_servers {
if tcp_stun_servers.is_empty() {
cfg.set_tcp_stun_servers(Some(Vec::new()));
} else {
let mut old_tcp_stun_servers = cfg.get_tcp_stun_servers().unwrap_or_default();
old_tcp_stun_servers.extend(tcp_stun_servers.iter().cloned());
cfg.set_tcp_stun_servers(Some(old_tcp_stun_servers));
}
}
Ok(())
}
@@ -1306,6 +1333,9 @@ fn parse_cli() -> Cli {
if let Some(stun_servers_v6) = &mut cli.network_options.stun_servers_v6 {
stun_servers_v6.retain(|s| !s.trim().is_empty());
}
if let Some(tcp_stun_servers) = &mut cli.network_options.tcp_stun_servers {
tcp_stun_servers.retain(|s| !s.trim().is_empty());
}
cli
}
@@ -1771,4 +1801,29 @@ enabled = true
assert_eq!(identity.network_secret_digest, None);
assert_eq!(cfg.get_hostname(), "override-host");
}
#[test]
fn empty_stun_server_options_clear_existing_config() {
let cfg = TomlConfigLoader::new_from_str(
r#"
stun_servers = ["udp.example.com:3478"]
stun_servers_v6 = ["v6.example.com:3478"]
tcp_stun_servers = ["tcp.example.com:3478"]
"#,
)
.unwrap();
NetworkOptions {
stun_servers: Some(Vec::new()),
stun_servers_v6: Some(Vec::new()),
tcp_stun_servers: Some(Vec::new()),
..Default::default()
}
.merge_into(&cfg)
.unwrap();
assert_eq!(cfg.get_stun_servers(), Some(Vec::new()));
assert_eq!(cfg.get_stun_servers_v6(), Some(Vec::new()));
assert_eq!(cfg.get_tcp_stun_servers(), Some(Vec::new()));
}
}