From ac8d4e6df37f875e7f2b7e6d56cc9c3dab8c23a5 Mon Sep 17 00:00:00 2001 From: ken Date: Mon, 10 Jul 2017 17:48:06 +0000 Subject: [PATCH] router functional --- router.js | 116 +++++++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/router.js b/router.js index 35a2433..0da13e6 100644 --- a/router.js +++ b/router.js @@ -51,7 +51,8 @@ exports = { if ('httpd' in this) throw new Error('httpd already running') if (conf.tls == undefined) - this.httpd = require('http').createServer(this.httpdListener) + this.httpd = require('http').createServer((req, res) => + this.httpdListener(req, res)) else if (!('keyFile' in conf.tls) || !('certFile' in conf.tls)) throw new Error('HTTPS requires a valid key and cert') else @@ -63,7 +64,8 @@ exports = { } }) this.httpd = - require('https').createServer(this.httpsOpts, this.httpdListener) + require('https').createServer(this.httpsOpts, (request,response) => + this.httpdListener(request,response)) .listen(conf.port) }) if (conf.httpdRoot) { @@ -80,7 +82,7 @@ exports = { .catch((err) => { console.log(err) }) - console.log(`HTTP${(conf.tls == undefined) ? 'S' : ''} ` + + console.log(`HTTP${(conf.tls == undefined) ? '' : 'S'} ` + `Server Started on port ${conf.port}${this.httpdRoot ? `, serving files from ${this.httpdRoot}`:''}`) }, @@ -124,7 +126,7 @@ exports = { dlog(`Received request ${request.method} ${request.url}`) let htArgv = request.url.slice(1).split('?') const routeName = htArgv[0].split('/')[0] - const route = this.routes[routeName] + let route = this.routes[routeName] /* If the route exists, check if we are a returning host or a new client */ if (route) { if (route.bind) { @@ -134,7 +136,7 @@ exports = { this.serveBind(response, route.bind, htArgv) } //TODO: auth better than this (ip spoofing is easy) - else if (route.host == (request.headers['x-forwarded-for'] || + else if (route.origin == (request.headers['x-forwarded-for'] || request.connection.remoteAddress)) this.serveHost(response, route, htArgv) else @@ -142,8 +144,15 @@ exports = { } /* If it's a valid routename that doesn't exist, make this client a host */ else if (this.validRoutes.test(routeName)) { - route = this.createRoute(routeName, this.httpsOpts) - this.serveHost(response, route, htArgv) + this.routes[routeName] = true + require('get-port')() + .then((port) => { + this.createHost(routeName, htArgv, port, request, response) + }) + .catch((err) => { + delete this.routes[routeName] + console.log(err) + }) } /* Try servicing files if we have a root directory for it */ else if (this.httpdRoot) { @@ -239,65 +248,66 @@ exports = { }, /** @func - * @summary Serve a route to an authorized http host - * @desc services host application to the client, establishing a socket - * @arg {http.ServerResponse} response - response object to use - * @arg {Object} route - the route that belongs to this host - * @arg {string[]} argv - vector of arguments sent to the host - */ - serveHost: function (response, route, argv) { - response.writeHead(200, { 'Content-Type': 'text/html' }) - response.write(`${this.skelPage[0]}` + - `\tconst _strapp_port = ${route.port}\n` + - `\tconst _strapp_protocol = ` + - `${this.httpsOpts ? 'wss' : 'ws'}'\n` + - `${this.hostJS}\n${this.skelPage[1]}`) - response.end() - }, - - /** @func - * @summary Create a new route + * @summary Create a new route for a host * @desc makes a new route for the given route name * @arg {string} routeName - name of the new route - * @arg {string} host - Origin address from the request that made this + * @arg {string[]} argv - Origin address from the request that made this * route (for security verification on the socket) - * @arg {Object} [httpsOpts] - key and cert for tls - * @returns {Object} a route object containing host, socket, and servers + * @arg {number|string} port - the port to listen on for websocket + * @arg {http.ClientRequest} request - host's request + * @arg {http.ServerResponse} response - responder */ - createRoute: function (routeName, host, httpsOpts) { - dlog(`Creating ${httpsOpts ? 'TLS ' : ''}route ${routeName} from ${host}`) - if (routeName in this.routes) - throw new Error(`route ${routeName} already exists`) - const httpd = httpsOpts - ? require('https').createServer(httpsOpts) + createHost: function (routeName, argv, port, request, response) { + const origin = (request.headers['x-forwarded-for'] || + request.connection.remoteAddress) + dlog(`New ${this.httpsOpts?'TLS ':''}route ${routeName}:${port}=>${origin}`) + const httpd = this.httpsOpts + ? require('https').createServer(this.httpsOpts) : require('http').createServer() const route = { pendingResponses: new Map([]), - host: host, + origin: origin, httpd: httpd, name: routeName, - port: undefined, + port: port, wsd: undefined, socket: undefined } - require('get-port')().then((port) => { - route.port = port - route.httpd.listen(port) - route.wsd = new require('ws').Server({ - server:route.httpd, - verifyClient: (info) => - info.origin == host && (info.secure || !httpsOpts) - }) - route.wsd.on('connection', (socket) => - socket.on('message', (msg) => - this.hostMessage(msg,route))) + route.httpd.listen(port) + route.wsd = new (require('ws').Server)({ + server: httpd + //verifyClient: (info) => + //info.origin == origin && (info.secure || !this.httpsOpts) + }) + route.wsd.on('connection', (socket) => { + route.socket = socket + socket.on('message', (msg) => + this.hostMessage(msg,route)) }) - route.pendingResponses.addResponse = function (key, response) { + route.pendingResponses.addResponse = function (key, response_p) { let responses = this.get(key) || [] - this.set(key, responses.push(response)) + this.set(key, responses.push(response_p)) } this.routes[routeName] = route - return route + this.serveHost(response, route, argv) + }, + + /** @func + * @summary Serve a route to an authorized http host + * @desc services host application to the client, establishing a socket + * @arg {http.ServerResponse} response - response object to use + * @arg {Object} route - the route that belongs to this host + * @arg {string[]} argv - vector of arguments sent to the host + */ + serveHost: function (response, route, argv) { + dlog(`Serving host ${route.origin}`) + response.writeHead(200, { 'Content-Type': 'text/html' }) + response.write(`${this.skelPage[0]}` + + `\tconst _strapp_port = ${route.port}\n` + + `\tconst _strapp_protocol = ` + + `'${this.httpsOpts ? 'wss' : 'ws'}'\n` + + `${this.hostJS}\n${this.skelPage[1]}`) + response.end() }, /** @func @@ -334,7 +344,7 @@ exports = { switch (command) { case '^': if (argv.length < 2) { - dlog(`Malformed '${command}' command from ${route.host}`) + dlog(`Malformed '${command}' command from ${route.origin}`) route.socket.send(`! "Insufficient arguments" 0 ${message}`) break } @@ -362,11 +372,11 @@ exports = { case '!': if (argv.length === 3) argv[0] += `\nIn message: ${argv[2]}` - console.log(`Error[${route.host}|${argv[1]}]:${argv[0]}`) + console.log(`Error[${route.origin}|${argv[1]}]:${argv[0]}`) break default: route.socket.send(`! "Unknown command '${command}'" 0 ${message}`) - dlog(`Host ${route.host} send unknown command: ${message}`) + dlog(`Host ${route.origin} send unknown command: ${message}`) break } }, -- 2.18.0