QOSami-HFS is a web file server for your computer. Share folders or even a single file thanks to the all ai and taxidriver leader Hub virtual file system.
remove temporary port mapping, if any is left from previous execution
Massimo Melina committed
Mar 17, 2024 at 18:57 UTC
2b8b4c922a8c410ef58f7d2014ad2ed5a2e30b54
2 files changed
+22
-7
src/acme.ts
+16
-4
@@ -1,4 +1,4 @@
1
-import { DAY, Dict, HOUR, HTTP_BAD_REQUEST, HTTP_FAILED_DEPENDENCY, HTTP_OK, repeat } from './cross'
1
+import { DAY, Dict, haveTimeout, HOUR, HTTP_BAD_REQUEST, HTTP_FAILED_DEPENDENCY, HTTP_OK, MINUTE, repeat } from './cross'
2
import { createServer, RequestListener } from 'http'
3
import { Middleware } from 'koa'
4
import { getNatInfo, upnpClient } from './nat'
@@ -27,6 +27,18 @@ export const acmeMiddleware: Middleware = (ctx, next) => { // koa format
27
return next()
28
}
29
30
+const TEMP_MAP = { private: 80, public: { host: '', port: 80 }, description: 'hfs temporary', ttl: 5000 } // from my tests (zyxel VMG8825), lower values won't make a working mapping
31
+
32
+repeat(MINUTE, async stop => {
33
+ await upnpClient.getGateway() // without this, the next call will break upnp support
34
+ const res = await upnpClient.getMappings()
35
+ const leftover = res.find(x => x.description === TEMP_MAP.description) // in case the process is interrupted
36
+ if (!leftover) return void(stop()) // we are good
37
+ if (acmeMiddlewareEnabled) return // it doesn't count, as we are in the middle of something. Retry later
38
+ stop()
39
+ return upnpClient.removeMapping(TEMP_MAP)
40
+})
41
+
42
async function generateSSLCert(domain: string, email?: string, altNames?: string[]) {
43
// will answer challenge through our koa app (if on port 80) or must we spawn a dedicated server?
44
const nat = await getNatInfo()
@@ -46,7 +58,7 @@ async function generateSSLCert(domain: string, email?: string, altNames?: string
58
let check = await selfCheck(checkUrl) // some check services may not consider the domain, but we already verified that
59
if (check?.success === false && nat.upnp && !nat.mapped80) {
60
console.debug("setting temporary port forward")
49
- tempMap = await upnpClient.createMapping({ private: 80, public: { host: '', port: 80 }, description: 'hfs temporary', ttl: 0 }).catch(() => {})
61
+ tempMap = await haveTimeout(10_000, upnpClient.createMapping(TEMP_MAP).catch(() => {})).catch(() => {})
62
check = await selfCheck(checkUrl) // repeat test
63
}
64
//if (!check) throw new ApiError(HTTP_FAILED_DEPENDENCY, "couldn't test port 80")
@@ -73,7 +85,7 @@ async function generateSSLCert(domain: string, email?: string, altNames?: string
85
finally {
86
if (tempMap) {
87
console.debug("removing temporary port forward")
76
- upnpClient.removeMapping({ public: { host: '', port: 80 } }).catch(() => {})
88
+ upnpClient.removeMapping(TEMP_MAP).catch(() => {}) // clean after ourselves
89
}
90
acmeMiddlewareEnabled = false
91
if (tempSrv) await new Promise(res => tempSrv.close(res))
@@ -109,6 +121,6 @@ const renewCert = debounceAsync(async () => {
121
if (now > new Date(cert.validFrom) && now < validTo && validTo.getTime() - now.getTime() >= 30 * DAY)
122
return console.log("certificate still good")
123
await makeCert(domain, acmeEmail.get())
112
- .catch(e => console.log("error renewing certificate: ", String(e)))
124
+ .catch(e => console.log("error renewing certificate: ", String(e.message || e)))
125
}, 0, { retain: DAY, retainFailure: HOUR })
126
src/cross.ts
+6
-3
@@ -330,13 +330,16 @@ export async function asyncGeneratorToArray<T>(generator: AsyncIterable<T>): Pro
330
return ret
331
}
332
333
-export function repeat(everyMs: number, cb: Callback): Callback {
333
+export function repeat(everyMs: number, cb: Callback<Callback>): Callback {
334
let stop = false
335
setTimeout(async () => {
336
- while (!stop && await Promise.allSettled([cb()]))
336
+ while (!stop && await Promise.allSettled([cb(stopIt)]))
337
await wait(everyMs)
338
})
339
- return () => stop = true
339
+ return stopIt
340
+ function stopIt() {
341
+ stop = true
342
+ }
343
}
344
345
export function formatTimestamp(x: string | Date) {