First pass formatting with Prettier
* Added .prettierrc.json * Added .prettierignore * Formatted
This commit is contained in:
@@ -2,32 +2,32 @@
|
||||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
const Config = require('../../config.js').get;
|
||||
const TelnetClient = require('./telnet.js').TelnetClient;
|
||||
const Log = require('../../logger.js').log;
|
||||
const Config = require('../../config.js').get;
|
||||
const TelnetClient = require('./telnet.js').TelnetClient;
|
||||
const Log = require('../../logger.js').log;
|
||||
const LoginServerModule = require('../../login_server_module.js');
|
||||
const { Errors } = require('../../enig_error.js');
|
||||
const { Errors } = require('../../enig_error.js');
|
||||
|
||||
// deps
|
||||
const _ = require('lodash');
|
||||
const WebSocketServer = require('ws').Server;
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const fs = require('graceful-fs');
|
||||
const _ = require('lodash');
|
||||
const WebSocketServer = require('ws').Server;
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const fs = require('graceful-fs');
|
||||
const { Duplex } = require('stream');
|
||||
const forEachSeries = require('async/forEachSeries');
|
||||
const forEachSeries = require('async/forEachSeries');
|
||||
|
||||
const ModuleInfo = exports.moduleInfo = {
|
||||
name : 'WebSocket',
|
||||
desc : 'WebSocket Server',
|
||||
author : 'NuSkooler',
|
||||
packageName : 'codes.l33t.enigma.websocket.server',
|
||||
};
|
||||
const ModuleInfo = (exports.moduleInfo = {
|
||||
name: 'WebSocket',
|
||||
desc: 'WebSocket Server',
|
||||
author: 'NuSkooler',
|
||||
packageName: 'codes.l33t.enigma.websocket.server',
|
||||
});
|
||||
|
||||
class WebSocketClient extends TelnetClient {
|
||||
constructor(ws, req, serverType) {
|
||||
// allow WebSocket to act like a Duplex (socket)
|
||||
const wsDuplex = new class WebSocketDuplex extends Duplex {
|
||||
const wsDuplex = new (class WebSocketDuplex extends Duplex {
|
||||
constructor(ws) {
|
||||
super();
|
||||
this.ws = ws;
|
||||
@@ -42,17 +42,23 @@ class WebSocketClient extends TelnetClient {
|
||||
|
||||
// Support X-Forwarded-For and X-Real-IP headers for proxied connections
|
||||
this.resolvedRemoteAddress =
|
||||
(this.client.proxied && (httpRequest.headers['x-forwarded-for'] || httpRequest.headers['x-real-ip'])) ||
|
||||
(this.client.proxied &&
|
||||
(httpRequest.headers['x-forwarded-for'] ||
|
||||
httpRequest.headers['x-real-ip'])) ||
|
||||
httpRequest.connection.remoteAddress;
|
||||
}
|
||||
|
||||
get remoteAddress() {
|
||||
return this.resolvedRemoteAddress;
|
||||
return this.resolvedRemoteAddress;
|
||||
}
|
||||
|
||||
_write(data, encoding, cb) {
|
||||
cb = cb || ( () => { /* eat it up */} ); // handle data writes after close
|
||||
return this.ws.send(data, { binary : true }, cb);
|
||||
cb =
|
||||
cb ||
|
||||
(() => {
|
||||
/* eat it up */
|
||||
}); // handle data writes after close
|
||||
return this.ws.send(data, { binary: true }, cb);
|
||||
}
|
||||
|
||||
_read() {
|
||||
@@ -62,7 +68,7 @@ class WebSocketClient extends TelnetClient {
|
||||
_data(data) {
|
||||
this.push(data);
|
||||
}
|
||||
}(ws);
|
||||
})(ws);
|
||||
|
||||
super(wsDuplex);
|
||||
wsDuplex.setClient(this, req);
|
||||
@@ -85,16 +91,19 @@ class WebSocketClient extends TelnetClient {
|
||||
ws.isConnectionAlive = true;
|
||||
});
|
||||
|
||||
Log.trace( { headers : req.headers }, 'WebSocket connection headers' );
|
||||
Log.trace({ headers: req.headers }, 'WebSocket connection headers');
|
||||
|
||||
//
|
||||
// If the config allows it, look for 'x-forwarded-proto' as "https"
|
||||
// to override |isSecure|
|
||||
//
|
||||
if(true === _.get(Config(), 'loginServers.webSocket.proxied') &&
|
||||
'https' === req.headers['x-forwarded-proto'])
|
||||
{
|
||||
Log.debug(`Assuming secure connection due to X-Forwarded-Proto of "${req.headers['x-forwarded-proto']}"`);
|
||||
if (
|
||||
true === _.get(Config(), 'loginServers.webSocket.proxied') &&
|
||||
'https' === req.headers['x-forwarded-proto']
|
||||
) {
|
||||
Log.debug(
|
||||
`Assuming secure connection due to X-Forwarded-Proto of "${req.headers['x-forwarded-proto']}"`
|
||||
);
|
||||
this.proxied = true;
|
||||
} else {
|
||||
this.proxied = false;
|
||||
@@ -105,11 +114,11 @@ class WebSocketClient extends TelnetClient {
|
||||
}
|
||||
|
||||
get isSecure() {
|
||||
return ('secure' === this.serverType || true === this.proxied) ? true : false;
|
||||
return 'secure' === this.serverType || true === this.proxied ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
const WSS_SERVER_TYPES = [ 'insecure', 'secure' ];
|
||||
const WSS_SERVER_TYPES = ['insecure', 'secure'];
|
||||
|
||||
exports.getModule = class WebSocketLoginServer extends LoginServerModule {
|
||||
constructor() {
|
||||
@@ -123,35 +132,39 @@ exports.getModule = class WebSocketLoginServer extends LoginServerModule {
|
||||
// * secure (tls) websocket (wss://)
|
||||
//
|
||||
const config = _.get(Config(), 'loginServers.webSocket');
|
||||
if(!_.isObject(config)) {
|
||||
if (!_.isObject(config)) {
|
||||
return cb(null);
|
||||
}
|
||||
|
||||
const wsPort = _.get(config, 'ws.port');
|
||||
const wssPort = _.get(config, 'wss.port');
|
||||
const wsPort = _.get(config, 'ws.port');
|
||||
const wssPort = _.get(config, 'wss.port');
|
||||
|
||||
if(true === _.get(config, 'ws.enabled') && _.isNumber(wsPort)) {
|
||||
const httpServer = http.createServer( (req, resp) => {
|
||||
if (true === _.get(config, 'ws.enabled') && _.isNumber(wsPort)) {
|
||||
const httpServer = http.createServer((req, resp) => {
|
||||
// dummy handler
|
||||
resp.writeHead(200);
|
||||
return resp.end('ENiGMA½ BBS WebSocket Server!');
|
||||
});
|
||||
|
||||
this.insecure = {
|
||||
httpServer : httpServer,
|
||||
wsServer : new WebSocketServer( { server : httpServer } ),
|
||||
httpServer: httpServer,
|
||||
wsServer: new WebSocketServer({ server: httpServer }),
|
||||
};
|
||||
}
|
||||
|
||||
if(_.isObject(config, 'wss') && true === _.get(config, 'wss.enabled') && _.isNumber(wssPort)) {
|
||||
if (
|
||||
_.isObject(config, 'wss') &&
|
||||
true === _.get(config, 'wss.enabled') &&
|
||||
_.isNumber(wssPort)
|
||||
) {
|
||||
const httpServer = https.createServer({
|
||||
key : fs.readFileSync(config.wss.keyPem),
|
||||
cert : fs.readFileSync(config.wss.certPem),
|
||||
key: fs.readFileSync(config.wss.keyPem),
|
||||
cert: fs.readFileSync(config.wss.certPem),
|
||||
});
|
||||
|
||||
this.secure = {
|
||||
httpServer : httpServer,
|
||||
wsServer : new WebSocketServer( { server : httpServer } ),
|
||||
httpServer: httpServer,
|
||||
wsServer: new WebSocketServer({ server: httpServer }),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -162,21 +175,24 @@ exports.getModule = class WebSocketLoginServer extends LoginServerModule {
|
||||
//
|
||||
// Send pings every 30s
|
||||
//
|
||||
setInterval( () => {
|
||||
setInterval(() => {
|
||||
WSS_SERVER_TYPES.forEach(serverType => {
|
||||
if(this[serverType]) {
|
||||
if (this[serverType]) {
|
||||
this[serverType].wsServer.clients.forEach(ws => {
|
||||
if(false === ws.isConnectionAlive) {
|
||||
Log.debug('WebSocket connection seems inactive. Terminating.');
|
||||
if (false === ws.isConnectionAlive) {
|
||||
Log.debug(
|
||||
'WebSocket connection seems inactive. Terminating.'
|
||||
);
|
||||
return ws.terminate();
|
||||
}
|
||||
|
||||
ws.isConnectionAlive = false; // pong will reset this
|
||||
ws.isConnectionAlive = false; // pong will reset this
|
||||
|
||||
Log.trace('Ping to remote WebSocket client');
|
||||
try {
|
||||
ws.ping('', false); // false=don't mask
|
||||
} catch(e) { // don't barf on closing state
|
||||
ws.ping('', false); // false=don't mask
|
||||
} catch (e) {
|
||||
// don't barf on closing state
|
||||
/* nothing */
|
||||
}
|
||||
});
|
||||
@@ -184,38 +200,55 @@ exports.getModule = class WebSocketLoginServer extends LoginServerModule {
|
||||
});
|
||||
}, 30000);
|
||||
|
||||
forEachSeries(WSS_SERVER_TYPES, (serverType, nextServerType) => {
|
||||
const server = this[serverType];
|
||||
if(!server) {
|
||||
return nextServerType(null);
|
||||
}
|
||||
|
||||
const serverName = `${ModuleInfo.name} (${serverType})`;
|
||||
const conf = _.get(Config(), [ 'loginServers', 'webSocket', 'secure' === serverType ? 'wss' : 'ws' ] );
|
||||
const confPort = conf.port;
|
||||
const port = parseInt(confPort);
|
||||
|
||||
if(isNaN(port)) {
|
||||
Log.error( { server : serverName, port : confPort }, 'Cannot load server (invalid port)' );
|
||||
return nextServerType(Errors.Invalid(`Invalid port: ${confPort}`));
|
||||
}
|
||||
|
||||
server.httpServer.listen(port, conf.address, err => {
|
||||
if(err) {
|
||||
return nextServerType(err);
|
||||
forEachSeries(
|
||||
WSS_SERVER_TYPES,
|
||||
(serverType, nextServerType) => {
|
||||
const server = this[serverType];
|
||||
if (!server) {
|
||||
return nextServerType(null);
|
||||
}
|
||||
|
||||
server.wsServer.on('connection', (ws, req) => {
|
||||
const webSocketClient = new WebSocketClient(ws, req, serverType);
|
||||
this.handleNewClient(webSocketClient, webSocketClient.socket, ModuleInfo);
|
||||
});
|
||||
const serverName = `${ModuleInfo.name} (${serverType})`;
|
||||
const conf = _.get(Config(), [
|
||||
'loginServers',
|
||||
'webSocket',
|
||||
'secure' === serverType ? 'wss' : 'ws',
|
||||
]);
|
||||
const confPort = conf.port;
|
||||
const port = parseInt(confPort);
|
||||
|
||||
Log.info( { server : serverName, port : port }, 'Listening for connections' );
|
||||
return nextServerType(null);
|
||||
});
|
||||
},
|
||||
err => {
|
||||
cb(err);
|
||||
});
|
||||
if (isNaN(port)) {
|
||||
Log.error(
|
||||
{ server: serverName, port: confPort },
|
||||
'Cannot load server (invalid port)'
|
||||
);
|
||||
return nextServerType(Errors.Invalid(`Invalid port: ${confPort}`));
|
||||
}
|
||||
|
||||
server.httpServer.listen(port, conf.address, err => {
|
||||
if (err) {
|
||||
return nextServerType(err);
|
||||
}
|
||||
|
||||
server.wsServer.on('connection', (ws, req) => {
|
||||
const webSocketClient = new WebSocketClient(ws, req, serverType);
|
||||
this.handleNewClient(
|
||||
webSocketClient,
|
||||
webSocketClient.socket,
|
||||
ModuleInfo
|
||||
);
|
||||
});
|
||||
|
||||
Log.info(
|
||||
{ server: serverName, port: port },
|
||||
'Listening for connections'
|
||||
);
|
||||
return nextServerType(null);
|
||||
});
|
||||
},
|
||||
err => {
|
||||
cb(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user