From 906c2a2f9aa30ec6f8f5424ff7019c775af3e6a7 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sat, 13 Feb 2021 23:56:20 -0500 Subject: [PATCH] local server back --- client/index.js | 2 - lib/STP.js | 212 ------------------------------------------- lib/STP/index.js | 136 +++++++++++++++++++++++++++ lib/STP/packets.js | 38 ++++++++ lib/node.js | 11 +++ lib/upnp.js | 63 +++++++++++++ name-server/index.js | 8 -- package.json | 4 +- relay/index.js | 54 +++++++++-- 9 files changed, 297 insertions(+), 231 deletions(-) delete mode 100644 lib/STP.js create mode 100644 lib/STP/index.js create mode 100644 lib/STP/packets.js create mode 100644 lib/node.js create mode 100644 lib/upnp.js diff --git a/client/index.js b/client/index.js index 1b36a71..35c60d9 100644 --- a/client/index.js +++ b/client/index.js @@ -20,8 +20,6 @@ const identity = yargs.profile ? // title(identity.name.replace(/-/g, ' ')); // await profiles.create(); -// log.debug(await profiles.all()) -log.debug(await identity.name()); diff --git a/lib/STP.js b/lib/STP.js deleted file mode 100644 index f4ce3eb..0000000 --- a/lib/STP.js +++ /dev/null @@ -1,212 +0,0 @@ -const net = require('net'); -const EventEmitter = require('events'); -const NodeRSA = require('node-rsa'); -const log = require('signale').scope('stp'); -const natUpnp = require('nat-upnp'); -const client = natUpnp.createClient(); -client.map = function(port) { - return new Promise((res, rej) => { - this.portMapping({ - private: port, - public: port, - ttl: 10, - description: 'valnet' - }, (err) => { - if(err) rej(err); - res(); - }); - }); -} -client.unmap = function(port) { - return new Promise((res, rej) => { - this.portUnmapping({ - private: port, - public: port - }, (err) => { - if(err) rej(err); - res(); - }); - }); -} -client.mappings = function() { - return new Promise((res, rej) => { - this.getMappings((err, mappings) => { - if(err) rej(err); - res(mappings); - }); - }); -} -const { config } = require('./../package.json'); - - -module.exports.createServer = function(keys, port) { - const server = new Server(keys, port); - // server.on('connection'); - return server; - // return 5; -} - -module.exports.connect = function(identity, port, ip) { - const client = net.connect(port, ip); - return new STPSocket(client, identity); -} - -class Server extends EventEmitter { - tcpServer; - identity; - port; - - constructor(identity, port) { - super(); - this.identity = identity; - this.port = port; - - (async () => { - try { - log.debug('first upnp mapping attempt...'); - await client.map(this.port); - this.openServer(); - } catch (e) { - log.warn(`Could not open upnp port ${this.port}`); - log.warn('Check your router is configured to allow upnp.'); - log.warn('Valnet will continue to operate, but incomming') - log.warn('peer connections will not be possible.') - } - })(); - } - - openServer() { - log.success(`opened upnp port ${this.port}`); - this.tcpServer = net.createServer(this.tcpConnectClient.bind(this)); - this.tcpServer.listen(this.port); - } - - tcpConnectClient(tcpSocket) { - log.debug('incomming TCP connection! ' + tcpSocket.remoteAddress); - const socket = new STPSocket(tcpSocket, this.identity); - socket.on('ready', () => { - this.emit('connection', socket); - }) - } -} - -class STPSocket extends EventEmitter { - tcpSocket; - readyState = 0; - buffer = ''; - externalIdentity; - - get remoteAddress() { - return this.tcpSocket.remoteAddress; - } - - get remoteIdentity() { - return this.externalIdentity.exportKey('pkcs8-public-pem'); - } - - get open() { - return this.tcpSocket.readyState === 'open' - } - - constructor(tcpSocket, identity) { - super(); - this.tcpSocket = tcpSocket; - this.identity = identity; - if(this.open) this.handshake(); - else this.tcpSocket.on('connect', this.handshake.bind(this)); - - this.tcpSocket.on('data', this.data.bind(this)); - this.tcpSocket.on('error', (...args) => this.emit('error', ...args)); - this.tcpSocket.on('close', (...args) => this.emit('close', ...args)); - } - - data(evt) { - // log.debug(evt.toString()); - this.buffer += evt.toString(); - this.processBuffer(); - } - - processBuffer() { - const parts = this.buffer.split(/(\x02[^\x02\x03]*\x03)/g); - this.buffer = ''; - for(const message of parts) { - if(message.endsWith('\x03')) { - const obj = JSON.parse(message.substr(1, message.length - 2)); - this.processMessage(obj); - } else { - this.buffer += message; - } - } - } - - processMessage(obj) { - switch(obj.cmd) { - case 'KEY': { - if(this.readyState === 0) { - // log.debug('registering external key'); - this.externalIdentity = new NodeRSA(); - this.externalIdentity.importKey(obj.data.key, 'pkcs8-public-pem'); - this.tcpSocket.write(new AckPacket().toBuffer()); - this.readyState = 1; - } - break; - } - case 'ACK': { - if(this.readyState === 1) { - this.readyState = 2; - // log.debug('socket ready!'); - this.emit('ready'); - } - break; - } - } - } - - handshake() { - // log.debug('begin handshake on socket'); - const pk = this.identity.publicKey; - const packet = new KeyExchangePacket(pk); - const buffer = packet.toBuffer(); - this.tcpSocket.write(buffer); - } -} - -class STPPacket { - cmd = 'NOOP'; - data = {}; - meta = {}; - - toBuffer() { - return Buffer.from(`\x02${JSON.stringify({ - cmd: this.cmd, - data: this.data, - meta: this.meta - })}\x03`); - } -} - -class KeyExchangePacket extends STPPacket { - constructor(key, type = 'pkcs8-pem') { - super(); - this.cmd = 'KEY'; - this.data.key = key; - this.meta.type = type; - } -} - -class AckPacket extends STPPacket { - constructor() { - super(); - this.cmd = 'ACK'; - } -} - - -// client.getMappings(function(err, results) { -// }); - -// client.getMappings({ local: true }, function(err, results) { -// }); - -// client.externalIp(function(err, ip) { -// }); \ No newline at end of file diff --git a/lib/STP/index.js b/lib/STP/index.js new file mode 100644 index 0000000..077882d --- /dev/null +++ b/lib/STP/index.js @@ -0,0 +1,136 @@ +const net = require('net'); +const EventEmitter = require('events'); +const NodeRSA = require('node-rsa'); +const log = require('signale').scope('stp'); +const { + KeyExchangePacket, + AckPacket +} = require('./packets'); +const { rejects } = require('assert'); + +module.exports.createServer = function({identity = {}, port = 5000} = {}, cb = _ => _) { + const server = new Server(identity, port); + server.on('connection', connection => { + cb(connection); + }); + // return 5; +} + +module.exports.connect = function({ + identity, + port, + ip +}) { + return new STPSocket(net.connect(port, ip), identity); +} + +class Server extends EventEmitter { + tcpServer; + identity; + port; + + constructor(identity, port) { + super(); + this.identity = identity; + this.port = port; + this.openServer(); + } + + openServer() { + log.info(`opening STP server on ${this.port}`); + this.tcpServer = net.createServer(this.tcpConnectClient.bind(this)); + this.tcpServer.listen(this.port); + } + + tcpConnectClient(tcpSocket) { + const socket = new STPSocket(tcpSocket, this.identity); + socket.on('ready', () => { + this.emit('connection', socket); + }) + } +} + +class STPSocket extends EventEmitter { + tcpSocket; + readyState = 0; + buffer = ''; + externalKey; + identity; + + get loopback() { + return this.identity.publicKey === + this.externalKey.exportKey('pkcs8-public-pem'); + } + + get remoteAddress() { + return this.tcpSocket.remoteAddress; + } + + get remoteIdentity() { + return this.externalKey.exportKey('pkcs8-public-pem'); + } + + get open() { + return this.tcpSocket.readyState === 'open' + } + + constructor(tcpSocket, identity) { + super(); + this.tcpSocket = tcpSocket; + this.identity = identity; + if(this.open) this.handshake(); + else this.tcpSocket.on('connect', this.handshake.bind(this)); + + this.tcpSocket.on('data', this.data.bind(this)); + this.tcpSocket.on('error', (...args) => this.emit('error', ...args)); + this.tcpSocket.on('close', (...args) => this.emit('close', ...args)); + } + + data(evt) { + this.buffer += evt.toString(); + this.processBuffer(); + } + + processBuffer() { + const parts = this.buffer.split(/(\x02[^\x02\x03]*\x03)/g); + this.buffer = ''; + for(const message of parts) { + if(message.endsWith('\x03')) { + const obj = JSON.parse(message.substr(1, message.length - 2)); + this.processMessage(obj); + } else { + this.buffer += message; + } + } + } + + processMessage(obj) { + switch(obj.cmd) { + case 'KEY': { + if(this.readyState === 0) { + log.info('registering external key'); + this.externalKey = new NodeRSA(); + this.externalKey.importKey(obj.data.key, 'pkcs8-public-pem'); + this.tcpSocket.write(new AckPacket().toBuffer()); + this.readyState = 1; + } + break; + } + case 'ACK': { + if(this.readyState === 1) { + this.readyState = 2; + log.success('internal key acknowledged'); + this.emit('ready'); + } + break; + } + } + } + + handshake() { + const pk = this.identity.publicKey; + const packet = new KeyExchangePacket(pk); + const buffer = packet.toBuffer(); + this.tcpSocket.write(buffer); + } +} diff --git a/lib/STP/packets.js b/lib/STP/packets.js new file mode 100644 index 0000000..233ae89 --- /dev/null +++ b/lib/STP/packets.js @@ -0,0 +1,38 @@ + + +class STPPacket { + cmd = 'NOOP'; + data = {}; + meta = {}; + + toBuffer() { + return Buffer.from(`\x02${JSON.stringify({ + cmd: this.cmd, + data: this.data, + meta: this.meta + })}\x03`); + } +} + +class KeyExchangePacket extends STPPacket { + constructor(key, type = 'pkcs8-pem') { + super(); + this.cmd = 'KEY'; + this.data.key = key; + this.meta.type = type; + } +} + +function basicPacket(commandName) { + return class extends STPPacket { + constructor() { + super(); + this.cmd = commandName; + } + } +} + +module.exports.STPPacket = STPPacket; +module.exports.KeyExchangePacket = KeyExchangePacket; +module.exports.AckPacket = basicPacket('ACK') +module.exports.GetClientsPacket = basicPacket('NODES') diff --git a/lib/node.js b/lib/node.js new file mode 100644 index 0000000..8b76499 --- /dev/null +++ b/lib/node.js @@ -0,0 +1,11 @@ +const EventEmitter = require('events') + + +class Node extends EventEmitter { + constructor() { + + } +} + + +module.exports.Node = Node; \ No newline at end of file diff --git a/lib/upnp.js b/lib/upnp.js new file mode 100644 index 0000000..49ccfe3 --- /dev/null +++ b/lib/upnp.js @@ -0,0 +1,63 @@ +const natUpnp = require('nat-upnp'); +const client = natUpnp.createClient(); +module.exports.map = function(port) { + return new Promise((res, rej) => { + client.portMapping({ + private: port, + public: port, + ttl: 10, + description: 'valnet' + }, (err) => { + if(err) rej(err); + res(); + }); + }); +} +module.exports.mapIndefinite = function(port) { + return new Promise((res, rej) => { + client.portMapping({ + private: port, + public: port, + ttl: 0, + description: 'valnet' + }, (err) => { + if(err) rej(err); + res(); + }); + }); +} +module.exports.unmap = function(port) { + return new Promise((res, rej) => { + client.portUnmapping({ + private: port, + public: port + }, (err) => { + if(err) rej(err); + res(); + }); + }); +} +module.exports.mappings = function() { + return new Promise((res, rej) => { + client.getMappings((err, mappings) => { + if(err) rej(err); + res(mappings); + }); + }); +} + + +/* +(async () => { + try { + log.debug('first upnp mapping attempt...'); + await client.map(this.port); + this.openServer(); + } catch (e) { + log.warn(`Could not open upnp port ${this.port}`); + log.warn('Check your router is configured to allow upnp.'); + log.warn('Valnet will continue to operate, but incomming') + log.warn('peer connections will not be possible.') + } +})(); +*/ \ No newline at end of file diff --git a/name-server/index.js b/name-server/index.js index 4a1aeb6..a146745 100644 --- a/name-server/index.js +++ b/name-server/index.js @@ -23,13 +23,5 @@ const identity = new Identity('name-server', 'default'); -// async function connectClient (client) { -// log.info(`connected client ${client.remoteAddress}`); -// client.on('error', () => { -// log.debug('who cares') -// }) -// } - - })(); \ No newline at end of file diff --git a/package.json b/package.json index 343064b..a543204 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "license": "MIT", "config": { "ports": { - "ns": 5500, "relay": 5600, - "http": 5700 + "http": 5700, + "service": 5800 }, "addresses": { "relay": "valnet.xyz" diff --git a/relay/index.js b/relay/index.js index 6930109..f0e48c7 100644 --- a/relay/index.js +++ b/relay/index.js @@ -13,7 +13,22 @@ const clients = []; // const client = stp.connect(identity, config.ports.relay, '127.0.0.1'); // ==================================== [STP SERVER] -const server = stp.createServer(identity, config.ports.relay); +stp.createServer({ + identity: identity, + port: config.ports.relay +}, socket => { + log.debug('loopback ' + socket.loopback) + clients.push(socket); +}); + +const client = stp.connect({ + identity, + port: config.ports.relay, + ip: 'valnet.xyz' +}); +client.on('error', e => { + log.error(e) +}) // ==================================== [EXPRESS] const express = require('express'); @@ -21,20 +36,45 @@ const app = express(); app.get('/', (req, res) => { res.end(` - - ${clients.map(client => ` + +
- - + + + - `).join('')} + ${clients.map((client, index) => ` + + + + + + `).join('')}
${client.remoteAddress}
${client.remoteIdentity}
IdAddressloopback
${index}
${client.remoteAddress}
${client.loopback}
`); }); // app.post -app.listen(9999); +app.listen(8080);