hyperMC-Web-Relay/non-worker-server.js

142 lines
5.5 KiB
JavaScript

const fs = require('fs');
const http = require('http');
const httpProxy = require('http-proxy');
const HyperDHTServer = require('hyperdht');
const libNet = require('hyper-cmd-lib-net');
const goodbye = require('graceful-goodbye');
const libKeys = require('hyper-cmd-lib-keys');
const b32 = require("hi-base32");
const net = require("net");
const pump = require("pump");
let invalid = false;
let mod = 0;
const tunnels = {};
const agent = new http.Agent({ maxSockets: Number.MAX_VALUE });
const content = fs.readFileSync('404.txt', 'utf8');
const DEBUG = 0; // Set DEBUG to 1 to enable debug mode
// Enabling DEBUG mode will slow down the code, please only enable this if you need
// Information about connections coming in because you need to validate connection hashes.
const startServer = async () => {
console.log("Creating HyperDHT server...");
const dhtServer = new HyperDHTServer();
await dhtServer.ready();
console.log("HyperDHT server created and ready.");
const proxy = httpProxy.createProxyServer({
ws: true,
agent: agent,
timeout: 360000
});
const server = http.createServer(async function (req, res) {
try {
console.log("Incoming HTTP request...");
const split = req.headers.host.split('.');
if (DEBUG === 1) console.log("Request Headers Host Split: ", split);
const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase()));
if (DEBUG === 1) {
console.log("Public Key Buffer: ", publicKey);
console.log("Length: " + publicKey.length);
}
if (!(publicKey.length >= 32)) {
console.log("Invalid Connection!")
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end(content);
invalid = true
} else {
invalid = false
}
if (invalid == true) return
if (!tunnels[publicKey]) {
console.log("No tunnel found for public key, creating new tunnel...");
const port = 1337 + ((mod++) % 1000);
const server = net.createServer(function (servsock) {
console.log('Incoming Connection, Connecting to:', publicKey.toString('hex'));
if (DEBUG === 1) console.log("Public Key Length: ", publicKey.toString('hex').length);
const socket = dhtServer.connect(publicKey);
const local = servsock;
let open = { local: true, remote: true };
local.on('data', (d) => {
if (DEBUG === 1) console.log("Local Data: ", d);
socket.write(d);
});
socket.on('data', (d) => {
if (DEBUG === 1) console.log("Socket Data: ", d);
local.write(d);
});
const remoteend = (type) => {
if (DEBUG === 1) console.log('Local Connection Ended, Ending Remote Connection');
if (open.remote) socket.end();
open.remote = false;
};
const localend = (type) => {
if (DEBUG === 1) console.log('Remote Connection Ended, Ending Local Connection');
if (open.local) local.end();
open.local = false;
};
local.on('error', remoteend);
local.on('finish', remoteend);
local.on('end', remoteend);
socket.on('finish', localend);
socket.on('error', localend);
socket.on('end', localend);
});
server.listen(port, "127.0.0.1");
tunnels[publicKey] = port;
console.log("New tunnel created. Public Key:", publicKey, "Port:", port);
proxy.web(req, res, {
target: 'http://127.0.0.1:' + port
}, function (e) {
console.log("Proxy Web Error: ", e);
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end(content);
});
return;
} else {
console.log('Tunnel exists for public key:', publicKey);
proxy.web(req, res, {
target: 'http://127.0.0.1:' + tunnels[publicKey]
}, function (e) {
console.log("Proxy Web Error: ", e);
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end(content);
});
}
} catch (e) {
console.error("Error Occurred: ", e);
}
});
server.on('upgrade', function (req, socket, head) {
console.log('Upgrade Request');
const split = req.headers.host.split('.');
const publicKey = Buffer.from(b32.decode.asBytes(split[0].toUpperCase()));
proxy.ws(req, socket, {
target: 'http://127.0.0.1:' + tunnels[publicKey]
}, function (e) {
console.error("Proxy WS Error: ", e);
socket.end();
});
});
server.listen(8081);
console.log("HTTP server listening on port 8081");
process.on('SIGINT', function () {
console.log("Shutting down...");
server.close();
dhtServer.destroy();
console.log("Shutdown complete.");
process.exit();
});
};
startServer().catch(console.error);