diff --git a/easytier/src/instance/instance.rs b/easytier/src/instance/instance.rs index dbb762cc..baa23fed 100644 --- a/easytier/src/instance/instance.rs +++ b/easytier/src/instance/instance.rs @@ -271,6 +271,9 @@ impl InstanceConfigPatcher { self.patch_connector(patch.connectors).await?; let global_ctx = weak_upgrade(&self.global_ctx)?; + let provider_reconcile_was_running = global_ctx.config.get_ipv6_public_addr_provider() + && global_ctx.config.get_ipv6_public_addr_prefix().is_none(); + let mut provider_config_changed = false; if let Some(hostname) = patch.hostname { global_ctx.set_hostname(hostname.clone()); global_ctx.config.set_hostname(Some(hostname)); @@ -285,9 +288,38 @@ impl InstanceConfigPatcher { global_ctx.set_ipv6(Some(ipv6.into())); global_ctx.config.set_ipv6(Some(ipv6.into())); } + if let Some(enabled) = patch.ipv6_public_addr_provider { + global_ctx.config.set_ipv6_public_addr_provider(enabled); + provider_config_changed = true; + } + if let Some(enabled) = patch.ipv6_public_addr_auto { + global_ctx.config.set_ipv6_public_addr_auto(enabled); + } + if let Some(prefix) = patch.ipv6_public_addr_prefix { + let prefix = prefix.trim(); + let parsed = if prefix.is_empty() { + None + } else { + Some(prefix.parse().with_context(|| { + format!("failed to parse ipv6 public address prefix: {prefix}") + })?) + }; + global_ctx.config.set_ipv6_public_addr_prefix(parsed); + provider_config_changed = true; + } global_ctx.issue_event(GlobalCtxEvent::ConfigPatched(patch_for_event)); + if provider_config_changed { + reconcile_public_ipv6_provider_runtime(&global_ctx).await; + + let provider_reconcile_should_run = global_ctx.config.get_ipv6_public_addr_provider() + && global_ctx.config.get_ipv6_public_addr_prefix().is_none(); + if !provider_reconcile_was_running && provider_reconcile_should_run { + run_public_ipv6_provider_reconcile_task(&global_ctx); + } + } + Ok(()) } diff --git a/easytier/src/launcher.rs b/easytier/src/launcher.rs index 290960fb..82d5b02b 100644 --- a/easytier/src/launcher.rs +++ b/easytier/src/launcher.rs @@ -881,8 +881,13 @@ impl NetworkConfig { result.network_length = Some(ipv4.network_length() as i32); } - result.ipv6_public_addr_provider = Some(config.get_ipv6_public_addr_provider()); - result.ipv6_public_addr_auto = Some(config.get_ipv6_public_addr_auto()); + if config.get_ipv6_public_addr_provider() != default_config.get_ipv6_public_addr_provider() + { + result.ipv6_public_addr_provider = Some(config.get_ipv6_public_addr_provider()); + } + if config.get_ipv6_public_addr_auto() != default_config.get_ipv6_public_addr_auto() { + result.ipv6_public_addr_auto = Some(config.get_ipv6_public_addr_auto()); + } result.ipv6_public_addr_prefix = config .get_ipv6_public_addr_prefix() .map(|prefix| prefix.to_string()); diff --git a/easytier/src/proto/api_config.proto b/easytier/src/proto/api_config.proto index 568f4855..131b8eb3 100644 --- a/easytier/src/proto/api_config.proto +++ b/easytier/src/proto/api_config.proto @@ -24,6 +24,9 @@ message InstanceConfigPatch { repeated ExitNodePatch exit_nodes = 8; repeated UrlPatch mapped_listeners = 9; repeated UrlPatch connectors = 10; + optional bool ipv6_public_addr_provider = 11; + optional bool ipv6_public_addr_auto = 12; + optional string ipv6_public_addr_prefix = 13; } message PortForwardPatch { diff --git a/easytier/src/tests/three_node.rs b/easytier/src/tests/three_node.rs index a1f6d7ae..4c2b15f9 100644 --- a/easytier/src/tests/three_node.rs +++ b/easytier/src/tests/three_node.rs @@ -3646,6 +3646,46 @@ pub async fn config_patch_test() { }, ); + // 测试1.1:修改公网 IPv6 provider 相关配置 + let public_prefix = "2001:db8:100::/64"; + let patch = InstanceConfigPatch { + ipv6_public_addr_provider: Some(true), + ipv6_public_addr_auto: Some(true), + ipv6_public_addr_prefix: Some(public_prefix.to_string()), + ..Default::default() + }; + insts[1] + .get_config_patcher() + .apply_patch(patch) + .await + .unwrap(); + assert!( + insts[1] + .get_global_ctx() + .config + .get_ipv6_public_addr_provider() + ); + assert!(insts[1].get_global_ctx().config.get_ipv6_public_addr_auto()); + assert_eq!( + insts[1] + .get_global_ctx() + .config + .get_ipv6_public_addr_prefix(), + Some(public_prefix.parse().unwrap()) + ); + assert!( + insts[1] + .get_global_ctx() + .get_feature_flags() + .ipv6_public_addr_provider + ); + assert_eq!( + insts[1] + .get_global_ctx() + .get_advertised_ipv6_public_addr_prefix(), + Some(public_prefix.parse().unwrap()) + ); + // 测试2: 端口转发 let patch = InstanceConfigPatch { port_forwards: vec![PortForwardPatch {