2021-02-13 23:56:20 -05:00
|
|
|
const EventEmitter = require('events')
|
2021-04-01 01:04:17 -04:00
|
|
|
const stp = require('./STP');
|
|
|
|
|
const upnp = require('./upnp');
|
|
|
|
|
const md5 = require('md5');
|
|
|
|
|
const pkg = require('./../package.json');
|
|
|
|
|
const { config, write } = require('./config.js');
|
2021-04-01 15:06:22 -04:00
|
|
|
const log = require('signale').scope('NODE');
|
2021-04-01 15:40:09 -04:00
|
|
|
const bonjour = require('bonjour')();
|
2021-04-01 21:15:41 -04:00
|
|
|
const Gateway = require('./Gateway');
|
2021-02-13 23:56:20 -05:00
|
|
|
|
|
|
|
|
class Node extends EventEmitter {
|
2021-04-01 01:04:17 -04:00
|
|
|
clients = [];
|
|
|
|
|
hash = null;
|
|
|
|
|
name = null;
|
|
|
|
|
readyPromise = null;
|
2021-04-01 01:19:00 -04:00
|
|
|
port = null;
|
|
|
|
|
identity;
|
2021-04-01 15:06:22 -04:00
|
|
|
multicastAd = null;
|
|
|
|
|
multicastBrowser = null;
|
|
|
|
|
connected = false;
|
2021-04-02 10:06:40 -04:00
|
|
|
multicastDevices = [];
|
2021-04-01 01:04:17 -04:00
|
|
|
|
|
|
|
|
constructor(identity) {
|
|
|
|
|
super();
|
2021-04-01 01:19:00 -04:00
|
|
|
this.identity = identity;
|
2021-04-01 01:04:17 -04:00
|
|
|
this.hash = md5(identity.publicKey);
|
2021-04-01 15:06:22 -04:00
|
|
|
this.name = `valnet-node-${identity.name}`;
|
|
|
|
|
|
|
|
|
|
this.readyPromise = this.negotiatePort()
|
|
|
|
|
.then(this.startServer.bind(this))
|
|
|
|
|
.catch(this.serverStartupFailed.bind(this))
|
|
|
|
|
.then(this.connectNetwork.bind(this))
|
2021-04-01 01:22:48 -04:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 15:06:22 -04:00
|
|
|
async connectNetwork() {
|
2021-04-01 21:15:41 -04:00
|
|
|
const gateway = new Gateway(this.identity, config.endpoints);
|
2021-04-01 15:06:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async serverStartupFailed(error) {
|
|
|
|
|
log.warn('Failed to set up Valet server on node.')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async startServer() {
|
|
|
|
|
log.info('creating Valnet Node on port ' + this.port + '...');
|
2021-04-01 01:22:48 -04:00
|
|
|
|
|
|
|
|
stp.createServer({
|
|
|
|
|
identity: this.identity,
|
|
|
|
|
port: this.port
|
|
|
|
|
}, (connection) => {
|
2021-04-02 10:06:40 -04:00
|
|
|
log.info('incomming connection from ' + connection.remoteName);
|
2021-04-01 15:06:22 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
log.info('advertising node on multicast...')
|
2021-04-01 15:40:09 -04:00
|
|
|
this.multicastAd = bonjour.publish({
|
|
|
|
|
name: this.name,
|
2021-04-02 10:06:40 -04:00
|
|
|
type: 'stp',
|
|
|
|
|
port: this.port,
|
|
|
|
|
protocol: 'tcp'
|
2021-04-01 15:06:22 -04:00
|
|
|
});
|
|
|
|
|
|
2021-04-02 10:06:40 -04:00
|
|
|
this.multicastBrowser = bonjour.find({type: 'stp'});
|
2021-04-01 15:06:22 -04:00
|
|
|
|
2021-04-01 15:40:09 -04:00
|
|
|
this.multicastBrowser.on('up', this.serviceUp.bind(this));
|
|
|
|
|
this.multicastBrowser.on('down', this.serviceDown.bind(this));
|
2021-04-01 15:06:22 -04:00
|
|
|
|
|
|
|
|
// log.success('Node successfully registered!');
|
2021-04-01 01:04:17 -04:00
|
|
|
}
|
|
|
|
|
|
2021-04-02 19:35:29 -04:00
|
|
|
async serviceUp(device) {
|
|
|
|
|
this.multicastDevices.push(device);
|
2021-04-01 15:06:22 -04:00
|
|
|
}
|
2021-04-01 01:04:17 -04:00
|
|
|
|
2021-04-02 19:35:29 -04:00
|
|
|
async serviceDown(device) {
|
|
|
|
|
this.multicastDevices = this.multicastDevices.filter(testDevice => {
|
|
|
|
|
return testDevice.host !== device.host
|
|
|
|
|
|| testDevice.port !== device.port
|
|
|
|
|
})
|
2021-04-01 15:06:22 -04:00
|
|
|
}
|
2021-04-01 01:04:17 -04:00
|
|
|
|
2021-04-01 15:06:22 -04:00
|
|
|
async negotiatePort() {
|
|
|
|
|
const mappings = await upnp.mappings();
|
2021-04-01 01:24:54 -04:00
|
|
|
const matchingMappings = mappings.filter(mapping => {
|
2021-04-01 01:04:17 -04:00
|
|
|
return mapping.description === this.name
|
2021-04-01 01:24:54 -04:00
|
|
|
});
|
|
|
|
|
const alreadyMapped = matchingMappings.length > 0;
|
2021-04-01 15:06:22 -04:00
|
|
|
const takenPorts = mappings.map(mapping => mapping.public.port);
|
2021-04-01 01:04:17 -04:00
|
|
|
|
|
|
|
|
if(alreadyMapped) {
|
2021-04-01 01:24:54 -04:00
|
|
|
this.port = matchingMappings[0].public.port;
|
2021-04-01 15:06:22 -04:00
|
|
|
log.success(`upnp port ${this.port} already registered!`);
|
2021-04-01 01:04:17 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(let port = config.ports.relay; port <= config.ports.relayEnd; port ++) {
|
|
|
|
|
if(takenPorts.indexOf(port) === -1) {
|
2021-04-01 01:13:07 -04:00
|
|
|
await upnp.mapIndefinite(port, this.name);
|
2021-04-01 01:19:00 -04:00
|
|
|
this.port = port;
|
2021-04-01 15:06:22 -04:00
|
|
|
log.success(`registered upnp port ${this.port}`);
|
|
|
|
|
return;
|
2021-04-01 01:04:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// console.log(mappings, this.hash);
|
2021-02-13 23:56:20 -05:00
|
|
|
}
|
2021-03-20 10:36:40 -04:00
|
|
|
|
|
|
|
|
static get Node() {
|
|
|
|
|
return Node;
|
|
|
|
|
}
|
2021-04-01 01:04:17 -04:00
|
|
|
|
|
|
|
|
get ready() {
|
|
|
|
|
return this.readyPromise;
|
|
|
|
|
}
|
2021-02-13 23:56:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-03-20 10:36:40 -04:00
|
|
|
module.exports = Node;
|