@samitouri / QOSami-HFS / commits / b9d171b2

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 }