@samitouri / QOSami-HFS / commits / 2b8b4c92
Fork 0

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) {