Skip to content
Snippets Groups Projects
Commit 0066df94 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[enh] Generalizing WS2PUpnp to UpnpProvider

parent f2818a68
Branches
Tags
No related merge requests found
...@@ -11,9 +11,6 @@ ...@@ -11,9 +11,6 @@
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details. // GNU Affero General Public License for more details.
import {WS2PConstants} from "./constants"
import {ConfDTO} from "../../../lib/dto/ConfDTO"
const upnp = require('nat-upnp'); const upnp = require('nat-upnp');
export interface UPnPBinding { export interface UPnPBinding {
...@@ -22,13 +19,20 @@ export interface UPnPBinding { ...@@ -22,13 +19,20 @@ export interface UPnPBinding {
port:number port:number
} }
export class WS2PUpnp { export class UpnpProvider {
private currentConfig:UPnPBinding|null private currentConfig:UPnPBinding|null
private interval:NodeJS.Timer|null private interval:NodeJS.Timer|null
private client = upnp.createClient() 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() { async checkUPnPisAvailable() {
try { try {
...@@ -52,9 +56,7 @@ export class WS2PUpnp { ...@@ -52,9 +56,7 @@ export class WS2PUpnp {
} }
getUpnpDescription() { getUpnpDescription() {
const uuid = (this.conf.ws2p && this.conf.ws2p.uuid) || "no-uuid-yet" return 'duniter:' + this.identifier
const suffix = this.conf.pair.pub.substr(0, 6) + ":" + uuid
return 'duniter:ws2p:' + suffix
} }
/** /**
...@@ -66,17 +68,17 @@ export class WS2PUpnp { ...@@ -66,17 +68,17 @@ export class WS2PUpnp {
if (!this.currentConfig) { if (!this.currentConfig) {
this.currentConfig = await this.getAvailablePort(this.client) 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() const client = upnp.createClient()
client.portMapping({ client.portMapping({
'public': this.currentConfig.port, 'public': this.currentConfig.port,
'private': this.currentConfig.port, 'private': this.currentConfig.port,
'ttl': WS2PConstants.WS2P_UPNP_TTL, 'ttl': this.ttl,
'description': this.getUpnpDescription() 'description': this.getUpnpDescription()
}, (err:any) => { }, (err:any) => {
client.close() client.close()
if (err) { if (err) {
this.logger.warn(err) this.logger && this.logger.warn(err)
return reject(err) return reject(err)
} }
resolve(this.currentConfig) resolve(this.currentConfig)
...@@ -89,7 +91,7 @@ export class WS2PUpnp { ...@@ -89,7 +91,7 @@ export class WS2PUpnp {
const available = await this.checkUPnPisAvailable() const available = await this.checkUPnPisAvailable()
if (available) { if (available) {
// Update UPnP IGD every INTERVAL seconds // 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() const { host, port } = await this.openPort()
return { host, port, available } return { host, port, available }
} }
...@@ -121,8 +123,8 @@ export class WS2PUpnp { ...@@ -121,8 +123,8 @@ export class WS2PUpnp {
} }
private async getAvailablePort(client:any) { private async getAvailablePort(client:any) {
const localIP = await WS2PUpnp.getLocalIP(client) const localIP = await UpnpProvider.getLocalIP(client)
const remoteIP = await WS2PUpnp.getRemoteIP(client) const remoteIP = await UpnpProvider.getRemoteIP(client)
const mappings:{ const mappings:{
private: { private: {
host:string host:string
...@@ -131,15 +133,15 @@ export class WS2PUpnp { ...@@ -131,15 +133,15 @@ export class WS2PUpnp {
port:number port:number
} }
description:string description:string
}[] = await WS2PUpnp.getUPnPMappings(client) }[] = await UpnpProvider.getUPnPMappings(client)
const thisDesc = this.getUpnpDescription() const thisDesc = this.getUpnpDescription()
const externalPortsUsed = mappings.filter((m) => m.description !== thisDesc).map((m) => m.public.port) 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 while (externalPortsUsed.indexOf(availablePort) !== -1
&& availablePort <= WS2PConstants.WS2P_PORTS_END) { && availablePort <= this.portEnd) {
availablePort++ availablePort++
} }
if (availablePort > WS2PConstants.WS2P_PORTS_END) { if (availablePort > this.portEnd) {
throw "No port available for UPnP" throw "No port available for UPnP"
} }
return { return {
......
...@@ -16,9 +16,9 @@ import {ConfDTO, WS2PConfDTO} from "../../lib/dto/ConfDTO" ...@@ -16,9 +16,9 @@ import {ConfDTO, WS2PConfDTO} from "../../lib/dto/ConfDTO"
import {Server} from "../../../server" import {Server} from "../../../server"
import * as stream from 'stream'; import * as stream from 'stream';
import {WS2PCluster} from "./lib/WS2PCluster" import {WS2PCluster} from "./lib/WS2PCluster"
import {WS2PUpnp} from "./lib/ws2p-upnp"
import {CommonConstants} from "../../lib/common-libs/constants" import {CommonConstants} from "../../lib/common-libs/constants"
import {NewLogger} from "../../lib/logger" import {NewLogger} from "../../lib/logger"
import {UpnpProvider} from "../upnp-provider"
const constants = require("../../lib/constants"); const constants = require("../../lib/constants");
const logger = NewLogger() const logger = NewLogger()
...@@ -196,7 +196,7 @@ export class WS2PAPI extends stream.Transform { ...@@ -196,7 +196,7 @@ export class WS2PAPI extends stream.Transform {
// Public http interface // Public http interface
private cluster:WS2PCluster private cluster:WS2PCluster
private upnpAPI:WS2PUpnp|null private upnpAPI:UpnpProvider|null
constructor( constructor(
private server:Server, private server:Server,
...@@ -235,7 +235,15 @@ export class WS2PAPI extends stream.Transform { ...@@ -235,7 +235,15 @@ export class WS2PAPI extends stream.Transform {
this.upnpAPI.stopRegular(); this.upnpAPI.stopRegular();
} }
try { 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() const { host, port, available } = await this.upnpAPI.startRegular()
if (available) { if (available) {
// Defaults UPnP to true if not defined and available // Defaults UPnP to true if not defined and available
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment