fix: admin/internet: server ip is sometimes wrong #437

Massimo Melina committed Feb 6, 2024 at 17:50 UTC d73a4b5204cbfafe09e30e62460b4f871fe0dcf0
3 files changed +12 -4
admin/src/InternetPage.ts
+1 -1
@@ -262,7 +262,7 @@ export default function InternetPage() {
262 function networkBox() {
263 if (nat.error) return nat.element
264 if (!data) return h(CircularProgress)
265 - const direct = data?.publicIps.includes(data?.localIp)
265 + const direct = data?.publicIps.includes(data?.localIp!)
266 return h(Flex, { justifyContent: 'space-around' },
267 h(Device, { name: "Server", icon: direct ? Storage : HomeWorkTwoTone, color: localColor, ip: data?.localIp,
268 below: port && h(Box, { fontSize: 'smaller' }, "port ", port),
src/cross.ts
+7
@@ -433,6 +433,13 @@ export function replace(s: string, symbols: Dict<string | Callback<string>>, del
433 return s
434 }
435
436 +export function inCommon<T extends string | unknown[]>(a: T, b: T) {
437 + let i = 0
438 + const n = a.length
439 + while (i < n && a[i] === b[i]) i++
440 + return i
441 +}
442 +
443 export function shortenAgent(agent: string) {
444 return _.findKey(BROWSERS, re => re.test(agent))
445 || /^[^/(]+ ?/.exec(agent)?.[0]
src/nat.ts
+4 -3
@@ -1,10 +1,10 @@
1 import { proxy } from 'valtio'
2 import { Client } from 'nat-upnp-ts'
3 import { debounceAsync } from './debounceAsync'
4 -import { haveTimeout, HOUR, MINUTE, promiseBestEffort, repeat, wantArray } from './cross'
4 +import { haveTimeout, HOUR, inCommon, MINUTE, promiseBestEffort, repeat, wantArray } from './cross'
5 import { getProjectInfo } from './github'
6 import _ from 'lodash'
7 -import { httpString } from './util-http'
7 +import { httpString } from './util-http'
8 import { Resolver } from 'dns/promises'
9 import { isIP } from 'net'
10 import { getIps, getServerStatus } from './listen'
@@ -67,7 +67,8 @@ export const getNatInfo = debounceAsync(async () => {
67 const mappings = res && await haveTimeout(5_000, upnpClient.getMappings()).catch(() => null)
68 console.debug('mappings found', mappings?.map(x => x.description))
69 const gatewayIp = res ? new URL(res.gateway.description).hostname : await findGateway().catch(() => undefined)
70 - const localIp = res?.address || (await getIps())[0]
70 + const localIps = await getIps(false)
71 + const localIp = res?.address || gatewayIp ? _.maxBy(localIps, x => inCommon(x, gatewayIp!)) : localIps[0]
72 const internalPort = status?.https?.listening && status.https.port || status?.http?.listening && status.http.port || undefined
73 const mapped = _.find(mappings, x => x.private.host === localIp && x.private.port === internalPort)
74 const externalPort = mapped?.public.port