fix: admin/internet: unresponsive upnp caused timeout error
Massimo Melina committed
Sep 19, 2023 at 10:46 UTC
b9d171b21bd0b8b4575a0d1db53317d157263139
3 files changed
+7
-4
shared/api.ts
-1
@@ -9,7 +9,6 @@ export const API_URL = '/~/api/'
9
const timeoutByApi: Dict = {
10
loginSrp1: 90, // support antibrute
11
update: 600, // download can be lengthy
12
- get_nat: 10,
12
get_status: 20, // can be lengthy on slow machines because of the find-process-on-busy-port feature
13
}
14
src/api.net.ts
+3
-3
@@ -13,7 +13,7 @@ import { cert, getCertObject, getIps, getServerStatus, privateKey } from './list
13
import { getProjectInfo } from './github'
14
import { httpString } from './util-http'
15
import { exec } from 'child_process'
16
-import { apiAssertTypes, debounceAsync, HOUR, MINUTE, objSameKeys, onlyTruthy, repeat } from './misc'
16
+import { apiAssertTypes, debounceAsync, haveTimeout, HOUR, MINUTE, objSameKeys, onlyTruthy, repeat } from './misc'
17
import acme from 'acme-client'
18
import fs from 'fs/promises'
19
import { Dict } from './misc'
@@ -37,7 +37,7 @@ const getNatInfo = debounceAsync(async () => {
37
const gettingIp = getPublicIp() // don't wait, do it in parallel
38
const res = await client.getGateway().catch(() => null)
39
const status = await getServerStatus()
40
- const mappings = res && await client.getMappings().catch(() => null)
40
+ const mappings = res && await haveTimeout(5_000, client.getMappings()).catch(() => null)
41
console.debug('mappings found', mappings)
42
const gatewayIp = res ? new URL(res.gateway.description).hostname : await findGateway().catch(() => null)
43
const localIp = res?.address || (await getIps())[0]
@@ -130,7 +130,7 @@ async function generateSSLCert(domain: string, email?: string) {
130
let check = await checkPort(domain, 80) // some check services may not consider the domain, but we already verified that
131
if (check && !check.success && upnp && externalPort !== 80) { // consider a short-lived mapping
132
// @ts-ignore
133
- await client.createMapping({ private: 80, public: { host: '', port: 80 }, description: 'hfs challenge', ttl: 0 }).catch(() => {})
133
+ await client.createMapping({ private: 80, public: { host: '', port: 80 }, description: 'hfs temporary', ttl: 30 }).catch(() => {})
134
check = await checkPort(domain, 80) // repeat test
135
}
136
if (!check)
src/cross.ts
+4
@@ -34,6 +34,10 @@ export function wait<T=undefined>(ms: number, val?: T): Promise<T | undefined> {
34
return new Promise(res=> setTimeout(res,ms,val))
35
}
36
37
+export function haveTimeout<T>(ms: number, job: Promise<T>, error?: any) {
38
+ return Promise.race([job, wait(ms).then(() => { throw error })])
39
+}
40
+
41
export function objSameKeys<S extends object,VR=any>(src: S, newValue:(value:Truthy<S[keyof S]>, key:keyof S)=>VR) {
42
return Object.fromEntries(Object.entries(src).map(([k,v]) => [k, newValue(v,k as keyof S)])) as { [K in keyof S]:VR }
43
}