diff --git a/app/modules/ws2p/lib/ws2p-upnp.ts b/app/modules/upnp-provider.ts similarity index 80% rename from app/modules/ws2p/lib/ws2p-upnp.ts rename to app/modules/upnp-provider.ts index 3b2140de831767046f687f7f9a5284bc1dea192e..cc7a396f936131eccce7fd49a2dcc1a549ca97c1 100644 --- a/app/modules/ws2p/lib/ws2p-upnp.ts +++ b/app/modules/upnp-provider.ts @@ -11,9 +11,6 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -import {WS2PConstants} from "./constants" -import {ConfDTO} from "../../../lib/dto/ConfDTO" - const upnp = require('nat-upnp'); export interface UPnPBinding { @@ -22,13 +19,20 @@ export interface UPnPBinding { port:number } -export class WS2PUpnp { +export class UpnpProvider { private currentConfig:UPnPBinding|null private interval:NodeJS.Timer|null private client = upnp.createClient() - constructor(private logger:any, private conf:ConfDTO) {} + constructor( + private portStart: number, + private portEnd: number, + private identifier: string, + private upnpInterval = 300, + private ttl = 600, + private logger?:any, + ) {} async checkUPnPisAvailable() { try { @@ -52,9 +56,7 @@ export class WS2PUpnp { } getUpnpDescription() { - const uuid = (this.conf.ws2p && this.conf.ws2p.uuid) || "no-uuid-yet" - const suffix = this.conf.pair.pub.substr(0, 6) + ":" + uuid - return 'duniter:ws2p:' + suffix + return 'duniter:' + this.identifier } /** @@ -66,17 +68,17 @@ export class WS2PUpnp { if (!this.currentConfig) { this.currentConfig = await this.getAvailablePort(this.client) } - this.logger.trace('WS2P: mapping external port %s to local %s using UPnP...', this.currentConfig.port, [this.currentConfig.host, this.currentConfig.port].join(':')) + this.logger && this.logger.trace('WS2P: mapping external port %s to local %s using UPnP...', this.currentConfig.port, [this.currentConfig.host, this.currentConfig.port].join(':')) const client = upnp.createClient() client.portMapping({ 'public': this.currentConfig.port, 'private': this.currentConfig.port, - 'ttl': WS2PConstants.WS2P_UPNP_TTL, + 'ttl': this.ttl, 'description': this.getUpnpDescription() }, (err:any) => { client.close() if (err) { - this.logger.warn(err) + this.logger && this.logger.warn(err) return reject(err) } resolve(this.currentConfig) @@ -89,7 +91,7 @@ export class WS2PUpnp { const available = await this.checkUPnPisAvailable() if (available) { // Update UPnP IGD every INTERVAL seconds - this.interval = setInterval(() => this.openPort(), 1000 * WS2PConstants.WS2P_UPNP_INTERVAL) + this.interval = setInterval(() => this.openPort(), 1000 * this.upnpInterval) const { host, port } = await this.openPort() return { host, port, available } } @@ -121,8 +123,8 @@ export class WS2PUpnp { } private async getAvailablePort(client:any) { - const localIP = await WS2PUpnp.getLocalIP(client) - const remoteIP = await WS2PUpnp.getRemoteIP(client) + const localIP = await UpnpProvider.getLocalIP(client) + const remoteIP = await UpnpProvider.getRemoteIP(client) const mappings:{ private: { host:string @@ -131,15 +133,15 @@ export class WS2PUpnp { port:number } description:string - }[] = await WS2PUpnp.getUPnPMappings(client) + }[] = await UpnpProvider.getUPnPMappings(client) const thisDesc = this.getUpnpDescription() const externalPortsUsed = mappings.filter((m) => m.description !== thisDesc).map((m) => m.public.port) - let availablePort = WS2PConstants.WS2P_PORTS_START + let availablePort = this.portStart while (externalPortsUsed.indexOf(availablePort) !== -1 - && availablePort <= WS2PConstants.WS2P_PORTS_END) { + && availablePort <= this.portEnd) { availablePort++ } - if (availablePort > WS2PConstants.WS2P_PORTS_END) { + if (availablePort > this.portEnd) { throw "No port available for UPnP" } return { diff --git a/app/modules/ws2p/index.ts b/app/modules/ws2p/index.ts index 6eac3d27dd2230be304eaf521d796e7bb790014d..8deb5523c8d8127f66765245dfad7e68dc014ba9 100644 --- a/app/modules/ws2p/index.ts +++ b/app/modules/ws2p/index.ts @@ -16,9 +16,9 @@ import {ConfDTO, WS2PConfDTO} from "../../lib/dto/ConfDTO" import {Server} from "../../../server" import * as stream from 'stream'; import {WS2PCluster} from "./lib/WS2PCluster" -import {WS2PUpnp} from "./lib/ws2p-upnp" import {CommonConstants} from "../../lib/common-libs/constants" import {NewLogger} from "../../lib/logger" +import {UpnpProvider} from "../upnp-provider" const constants = require("../../lib/constants"); const logger = NewLogger() @@ -196,7 +196,7 @@ export class WS2PAPI extends stream.Transform { // Public http interface private cluster:WS2PCluster - private upnpAPI:WS2PUpnp|null + private upnpAPI:UpnpProvider|null constructor( private server:Server, @@ -235,7 +235,15 @@ export class WS2PAPI extends stream.Transform { this.upnpAPI.stopRegular(); } try { - this.upnpAPI = new WS2PUpnp(logger, this.conf) + const uuid = (this.conf.ws2p && this.conf.ws2p.uuid) || "no-uuid-yet" + const suffix = this.conf.pair.pub.substr(0, 6) + ":" + uuid + this.upnpAPI = new UpnpProvider( + WS2PConstants.WS2P_PORTS_START, + WS2PConstants.WS2P_PORTS_END, + ':ws2p:' + suffix, + WS2PConstants.WS2P_UPNP_INTERVAL, + WS2PConstants.WS2P_UPNP_TTL, + logger) const { host, port, available } = await this.upnpAPI.startRegular() if (available) { // Defaults UPnP to true if not defined and available