diff --git a/lib/core/services/server_connection_manager.dart b/lib/core/services/server_connection_manager.dart index 06eae7bb..6d10e1d4 100644 --- a/lib/core/services/server_connection_manager.dart +++ b/lib/core/services/server_connection_manager.dart @@ -422,9 +422,27 @@ class ServerConnectionManager { }); if (Platform.isAndroid) { + // 主动获取网络状态,确保能拿到子网代理路由 + List proxyCidrs = []; + try { + final netStatus = await getNetworkStatus(); + ServiceManager().connectionState.netStatus.value = netStatus; + for (final node in netStatus.nodes) { + for (final cidr in node.proxyCidrs) { + if (isValidCIDR(cidr) && !proxyCidrs.contains(cidr)) { + proxyCidrs.add(cidr); + } + } + } + } catch (_) { + // 如果获取失败,回退到从 state 中读取 + proxyCidrs = _extractProxyCidrs(); + } + await VpnManager.instance.start( ipv4Addr: ServiceManager().networkConfigState.ipv4.value, mtu: ServiceManager().networkConfigState.mtu.value, + proxyCidrs: proxyCidrs, ); if (ServiceManager().appSettingsState.enableConnectionNotification.value) { @@ -500,6 +518,22 @@ class ServerConnectionManager { } } + /// 从网络状态中提取子网代理路由 + List _extractProxyCidrs() { + final netStatus = ServiceManager().connectionState.netStatus.value; + if (netStatus == null) return []; + + final cidrs = []; + for (final node in netStatus.nodes) { + for (final cidr in node.proxyCidrs) { + if (isValidCIDR(cidr) && !cidrs.contains(cidr)) { + cidrs.add(cidr); + } + } + } + return cidrs; + } + /// 提取IPv4地址 String _extractIpv4Address(Map data) { final virtualIpv4 = data['my_node_info']?['virtual_ipv4']; diff --git a/lib/core/services/vpn_manager.dart b/lib/core/services/vpn_manager.dart index 90823f3f..4c29d3c6 100644 --- a/lib/core/services/vpn_manager.dart +++ b/lib/core/services/vpn_manager.dart @@ -36,6 +36,7 @@ class VpnManager { required String ipv4Addr, int mtu = 1300, List disallowedApplications = const ['com.kevin.astral'], + List proxyCidrs = const [], }) async { final plugin = _plugin; if (plugin == null) return; @@ -48,10 +49,13 @@ class VpnManager { } // 获取有效的VPN路由 - final routes = + final customRoutes = ServiceManager().vpnState.customVpn.value .where((route) => isValidCIDR(route)) .toList(); + + // 合并自定义路由和子网代理路由 + final routes = [...customRoutes, ...proxyCidrs.where((route) => isValidCIDR(route))]; await plugin.startVpn( ipv4Addr: finalIpv4, diff --git a/lib/src/rust/api/simple.dart b/lib/src/rust/api/simple.dart index f80f328e..0c464f21 100644 --- a/lib/src/rust/api/simple.dart +++ b/lib/src/rust/api/simple.dart @@ -291,6 +291,7 @@ class KVNodeInfo { final BigInt txBytes; final String version; final int cost; + final List proxyCidrs; const KVNodeInfo({ required this.peerId, @@ -307,6 +308,7 @@ class KVNodeInfo { required this.txBytes, required this.version, required this.cost, + this.proxyCidrs = const [], }); @override @@ -324,7 +326,8 @@ class KVNodeInfo { rxBytes.hashCode ^ txBytes.hashCode ^ version.hashCode ^ - cost.hashCode; + cost.hashCode ^ + proxyCidrs.hashCode; @override bool operator ==(Object other) => @@ -344,7 +347,8 @@ class KVNodeInfo { rxBytes == other.rxBytes && txBytes == other.txBytes && version == other.version && - cost == other.cost; + cost == other.cost && + proxyCidrs == other.proxyCidrs; } class NodeHopStats { diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 0aef48db..f112ab74 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -2898,8 +2898,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { KVNodeInfo dco_decode_kv_node_info(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 14) - throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); + if (arr.length != 15) + throw Exception('unexpected arr length: expect 15 but see ${arr.length}'); return KVNodeInfo( peerId: dco_decode_u_32(arr[0]), hostname: dco_decode_String(arr[1]), @@ -2915,6 +2915,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { txBytes: dco_decode_u_64(arr[11]), version: dco_decode_String(arr[12]), cost: dco_decode_i_32(arr[13]), + proxyCidrs: dco_decode_list_String(arr[14]), ); } @@ -3572,6 +3573,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_txBytes = sse_decode_u_64(deserializer); var var_version = sse_decode_String(deserializer); var var_cost = sse_decode_i_32(deserializer); + var var_proxyCidrs = sse_decode_list_String(deserializer); return KVNodeInfo( peerId: var_peerId, hostname: var_hostname, @@ -3587,6 +3589,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { txBytes: var_txBytes, version: var_version, cost: var_cost, + proxyCidrs: var_proxyCidrs, ); } @@ -4306,6 +4309,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(self.txBytes, serializer); sse_encode_String(self.version, serializer); sse_encode_i_32(self.cost, serializer); + sse_encode_list_String(self.proxyCidrs, serializer); } @protected diff --git a/rust/src/api/p2p.rs b/rust/src/api/p2p.rs index 9ff3967f..27e21395 100644 --- a/rust/src/api/p2p.rs +++ b/rust/src/api/p2p.rs @@ -726,6 +726,7 @@ pub async fn get_network_status(instance_id: String) -> KVNetworkStatus { .to_string(), rx_bytes: pair.get_rx_bytes().unwrap_or_default(), tx_bytes: pair.get_tx_bytes().unwrap_or_default(), + proxy_cidrs: route.proxy_cidrs.clone(), }; if let Some(peer) = &pair.peer { diff --git a/rust/src/api/simple.rs b/rust/src/api/simple.rs index fe7c7cc9..abc5063f 100644 --- a/rust/src/api/simple.rs +++ b/rust/src/api/simple.rs @@ -274,6 +274,7 @@ pub struct KVNodeInfo { pub version: String, pub cost: i32, + pub proxy_cidrs: Vec, } // 定义节点网络状态结构体 pub struct KVNetworkStatus { @@ -928,6 +929,7 @@ pub async fn get_network_status() -> KVNetworkStatus { .to_string(), rx_bytes: pair.get_rx_bytes().unwrap_or_default(), tx_bytes: pair.get_tx_bytes().unwrap_or_default(), + proxy_cidrs: route.proxy_cidrs.clone(), }; // 收集连接统计信息 diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index bfffcbd2..c0ec428f 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -2918,6 +2918,7 @@ impl SseDecode for crate::api::simple::KVNodeInfo { let mut var_txBytes = ::sse_decode(deserializer); let mut var_version = ::sse_decode(deserializer); let mut var_cost = ::sse_decode(deserializer); + let mut var_proxyCidrs = >::sse_decode(deserializer); return crate::api::simple::KVNodeInfo { peer_id: var_peerId, hostname: var_hostname, @@ -2933,6 +2934,7 @@ impl SseDecode for crate::api::simple::KVNodeInfo { tx_bytes: var_txBytes, version: var_version, cost: var_cost, + proxy_cidrs: var_proxyCidrs, }; } } @@ -3729,6 +3731,7 @@ impl flutter_rust_bridge::IntoDart for crate::api::simple::KVNodeInfo { self.tx_bytes.into_into_dart().into_dart(), self.version.into_into_dart().into_dart(), self.cost.into_into_dart().into_dart(), + self.proxy_cidrs.into_into_dart().into_dart(), ] .into_dart() } @@ -4159,6 +4162,7 @@ impl SseEncode for crate::api::simple::KVNodeInfo { ::sse_encode(self.tx_bytes, serializer); ::sse_encode(self.version, serializer); ::sse_encode(self.cost, serializer); + >::sse_encode(self.proxy_cidrs, serializer); } }