fix(web): preserve managed config and status compatibility (#2389)

Fix web/frontend compat bugs in managed config & runtime status

- Preserve [[peer]].peer_public_key when TOML configs round-trip
  through the web/managed NetworkConfig path
- Keep old peer_urls clients working while adding structured peer
  metadata for new clients
- Make frontend protobuf JSON normalization preserve omitted-field
  semantics instead of turning missing data into misleading defaults
- Harden runtime status rendering against omitted or string-encoded
  backend fields
- Expose peer-route feature flags in the web status UI
This commit is contained in:
KKRainbow
2026-06-29 12:40:04 +08:00
committed by GitHub
parent 15e5d89f70
commit 4e61612944
18 changed files with 665 additions and 164 deletions
+11 -14
View File
@@ -163,14 +163,10 @@ async function registerVpnServiceListener() {
)
}
function getRoutesForVpn(routes: Route[], node_config: NetworkTypes.NetworkConfig): string[] {
if (!routes) {
return []
}
function getRoutesForVpn(routes: Route[] | undefined, node_config: NetworkTypes.NetworkConfig): string[] {
const ret = []
for (const r of routes) {
for (let cidr of r.proxy_cidrs) {
for (const r of routes ?? []) {
for (let cidr of r.proxy_cidrs ?? []) {
if (!cidr.includes('/')) {
cidr += '/32'
}
@@ -178,9 +174,9 @@ function getRoutesForVpn(routes: Route[], node_config: NetworkTypes.NetworkConfi
}
}
node_config.routes.forEach(r => {
ret.push(r)
})
for (const route of node_config.routes ?? []) {
ret.push(route)
}
if (node_config.enable_magic_dns) {
ret.push('100.100.100.101/32')
@@ -215,14 +211,15 @@ export async function onNetworkInstanceChange(instanceId: string) {
console.log('vpn service skipped because no_tun is enabled', instanceId)
return
}
const curNetworkInfo = (await collectNetworkInfo(instanceId)).info.map[instanceId]
const curNetworkInfo = (await collectNetworkInfo(instanceId))?.info?.map?.[instanceId]
if (!curNetworkInfo || curNetworkInfo?.error_msg?.length) {
console.warn('vpn service skipped because network info is unavailable', instanceId, curNetworkInfo?.error_msg)
await doStopVpn()
return
}
const virtual_ip = Utils.ipv4ToString(curNetworkInfo?.my_node_info?.virtual_ipv4.address)
const virtualIpv4 = curNetworkInfo.my_node_info?.virtual_ipv4
const virtual_ip = virtualIpv4?.address?.addr ? Utils.ipv4ToString(virtualIpv4.address) : undefined
if (config.dhcp && (!virtual_ip || !virtual_ip.length)) {
console.log('DHCP enabled but no IP yet, will retry in', DHCP_POLLING_INTERVAL, 'ms')
@@ -237,7 +234,7 @@ export async function onNetworkInstanceChange(instanceId: string) {
return
}
let network_length = curNetworkInfo?.my_node_info?.virtual_ipv4.network_length
let network_length = virtualIpv4?.network_length
if (!network_length) {
network_length = 24
}
@@ -290,7 +287,7 @@ async function isNoTunEnabled(instanceId: string | undefined) {
async function findRunningTunInstanceId() {
const instanceIds = await listNetworkInstanceIds()
const runningIds = instanceIds.running_inst_ids.map(Utils.UuidToStr)
const runningIds = (instanceIds.running_inst_ids ?? []).map(Utils.UuidToStr)
console.log('vpn service sync running instances', JSON.stringify(runningIds))
for (const instanceId of runningIds) {
+2 -2
View File
@@ -9,7 +9,7 @@ export class GUIRemoteClient implements Api.RemoteClient {
await backend.runNetworkInstance(config, save);
}
async get_network_info(inst_id: string): Promise<NetworkTypes.NetworkInstanceRunningInfo | undefined> {
return backend.collectNetworkInfo(inst_id).then(infos => infos.info.map[inst_id]);
return backend.collectNetworkInfo(inst_id).then(infos => infos.info?.map?.[inst_id]);
}
async list_network_instance_ids(): Promise<Api.ListNetworkInstanceIdResponse> {
return backend.listNetworkInstanceIds();
@@ -44,4 +44,4 @@ export class GUIRemoteClient implements Api.RemoteClient {
return await backend.getNetworkMetas(instance_ids);
}
}
}