* Servers now use async listen()

This commit is contained in:
Bryan Ashby 2018-12-27 02:46:16 -07:00
parent 9d1815682d
commit 3864d957c9
7 changed files with 100 additions and 66 deletions

View File

@ -2,11 +2,10 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
const logger = require('./logger.js'); const logger = require('./logger.js');
const { ErrorReasons } = require('./enig_error.js');
// deps // deps
const async = require('async'); const async = require('async');
const listeningServers = {}; // packageName -> info const listeningServers = {}; // packageName -> info
@ -34,15 +33,22 @@ function startListening(cb) {
const moduleInst = new module.getModule(); const moduleInst = new module.getModule();
try { try {
moduleInst.createServer(err => { moduleInst.createServer(err => {
if(!moduleInst.listen()) { if(err) {
throw new Error('Failed listening'); return nextModule(err);
} }
listeningServers[module.moduleInfo.packageName] = { moduleInst.listen( err => {
instance : moduleInst, if(err) {
info : module.moduleInfo, return nextModule(err);
}; }
return nextModule(err);
listeningServers[module.moduleInfo.packageName] = {
instance : moduleInst,
info : module.moduleInfo,
};
return nextModule(null);
});
}); });
} catch(e) { } catch(e) {
logger.log.error(e, 'Exception caught creating server!'); logger.log.error(e, 'Exception caught creating server!');

View File

@ -5,6 +5,7 @@
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const { ServerModule } = require('../../server_module.js'); const { ServerModule } = require('../../server_module.js');
const Config = require('../../config.js').get; const Config = require('../../config.js').get;
const { Errors } = require('../../enig_error.js');
const { const {
splitTextAtTerms, splitTextAtTerms,
isAnsi, isAnsi,
@ -100,19 +101,19 @@ exports.getModule = class GopherModule extends ServerModule {
return cb(null); return cb(null);
} }
listen() { listen(cb) {
if(!this.enabled) { if(!this.enabled) {
return true; // nothing to do, but not an error return cb(null);
} }
const config = Config(); const config = Config();
const port = parseInt(config.contentServers.gopher.port); const port = parseInt(config.contentServers.gopher.port);
if(isNaN(port)) { if(isNaN(port)) {
this.log.warn( { port : config.contentServers.gopher.port, server : ModuleInfo.name }, 'Invalid port' ); this.log.warn( { port : config.contentServers.gopher.port, server : ModuleInfo.name }, 'Invalid port' );
return false; return cb(Errors.Invalid(`Invalid port: ${config.contentServers.gopher.port}`));
} }
return this.server.listen(port); return this.server.listen(port, cb);
} }
get enabled() { get enabled() {

View File

@ -918,21 +918,26 @@ exports.getModule = class NNTPServerModule extends ServerModule {
}); });
} }
listen() { listen(cb) {
const config = Config(); const config = Config();
[ 'nntp', 'nntps' ].forEach( service => { forEachSeries([ 'nntp', 'nntps' ], (service, nextService) => {
const server = this[`${service}Server`]; const server = this[`${service}Server`];
if(server) { if(server) {
const port = config.contentServers.nntp[service].port; const port = config.contentServers.nntp[service].port;
server.listen(this.listenURI(port, service)) server.listen(this.listenURI(port, service))
.catch(e => { .catch(e => {
Log.warn( { error : e.message, port }, `${service.toUpperCase()} failed to listen`); Log.warn( { error : e.message, port }, `${service.toUpperCase()} failed to listen`);
return nextService(null); // try next anyway
}).then( () => {
return nextService(null);
}); });
} else {
return nextService(null);
} }
},
err => {
return cb(err);
}); });
// :TODO: listen() needs to be async. I always should have been...
return true;
} }
listenURI(port, service = 'nntp') { listenURI(port, service = 'nntp') {

View File

@ -5,6 +5,7 @@
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const ServerModule = require('../../server_module.js').ServerModule; const ServerModule = require('../../server_module.js').ServerModule;
const Config = require('../../config.js').get; const Config = require('../../config.js').get;
const { Errors } = require('../../enig_error.js');
// deps // deps
const http = require('http'); const http = require('http');
@ -13,6 +14,7 @@ const _ = require('lodash');
const fs = require('graceful-fs'); const fs = require('graceful-fs');
const paths = require('path'); const paths = require('path');
const mimeTypes = require('mime-types'); const mimeTypes = require('mime-types');
const forEachSeries = require('async/forEachSeries');
const ModuleInfo = exports.moduleInfo = { const ModuleInfo = exports.moduleInfo = {
name : 'Web', name : 'Web',
@ -125,23 +127,27 @@ exports.getModule = class WebServerModule extends ServerModule {
return cb(null); return cb(null);
} }
listen() { listen(cb) {
let ok = true;
const config = Config(); const config = Config();
[ 'http', 'https' ].forEach(service => { forEachSeries([ 'http', 'https' ], (service, nextService) => {
const name = `${service}Server`; const name = `${service}Server`;
if(this[name]) { if(this[name]) {
const port = parseInt(config.contentServers.web[service].port); const port = parseInt(config.contentServers.web[service].port);
if(isNaN(port)) { if(isNaN(port)) {
ok = false; Log.warn( { port : config.contentServers.web[service].port, server : ModuleInfo.name }, `Invalid port (${service})` );
return Log.warn( { port : config.contentServers.web[service].port, server : ModuleInfo.name }, `Invalid port (${service})` ); return nextService(Errors.Invalid(`Invalid port: ${config.contentServers.web[service].port}`));
} }
return this[name].listen(port);
}
});
return ok; this[name].listen(port, err => {
return nextService(err);
});
} else {
return nextService(null);
}
},
err => {
return cb(err);
});
} }
addRoute(route) { addRoute(route) {

View File

@ -322,20 +322,23 @@ exports.getModule = class SSHServerModule extends LoginServerModule {
return cb(null); return cb(null);
} }
listen() { listen(cb) {
const config = Config(); const config = Config();
if(true != config.loginServers.ssh.enabled) { if(true != config.loginServers.ssh.enabled) {
return true; // no server, but not an error return cb(null);
} }
const port = parseInt(config.loginServers.ssh.port); const port = parseInt(config.loginServers.ssh.port);
if(isNaN(port)) { if(isNaN(port)) {
Log.error( { server : ModuleInfo.name, port : config.loginServers.ssh.port }, 'Cannot load server (invalid port)' ); Log.error( { server : ModuleInfo.name, port : config.loginServers.ssh.port }, 'Cannot load server (invalid port)' );
return false; return cb(Errors.Invalid(`Invalid port: ${config.loginServers.ssh.port}`));
} }
this.server.listen(port); this.server.listen(port, err => {
Log.info( { server : ModuleInfo.name, port : port }, 'Listening for connections' ); if(!err) {
return true; Log.info( { server : ModuleInfo.name, port : port }, 'Listening for connections' );
}
return cb(err);
});
} }
}; };

View File

@ -8,6 +8,7 @@ const LoginServerModule = require('../../login_server_module.js');
const Config = require('../../config.js').get; const Config = require('../../config.js').get;
const EnigAssert = require('../../enigma_assert.js'); const EnigAssert = require('../../enigma_assert.js');
const { stringFromNullTermBuffer } = require('../../string_util.js'); const { stringFromNullTermBuffer } = require('../../string_util.js');
const { Errors } = require('../../enig_error.js');
// deps // deps
const net = require('net'); const net = require('net');
@ -880,16 +881,19 @@ exports.getModule = class TelnetServerModule extends LoginServerModule {
return cb(null); return cb(null);
} }
listen() { listen(cb) {
const config = Config(); const config = Config();
const port = parseInt(config.loginServers.telnet.port); const port = parseInt(config.loginServers.telnet.port);
if(isNaN(port)) { if(isNaN(port)) {
Log.error( { server : ModuleInfo.name, port : config.loginServers.telnet.port }, 'Cannot load server (invalid port)' ); Log.error( { server : ModuleInfo.name, port : config.loginServers.telnet.port }, 'Cannot load server (invalid port)' );
return false; return cb(Errors.Invalid(`Invalid port: ${config.loginServers.telnet.port}`));
} }
this.server.listen(port); this.server.listen(port, err => {
Log.info( { server : ModuleInfo.name, port : port }, 'Listening for connections' ); if(!err) {
return true; Log.info( { server : ModuleInfo.name, port : port }, 'Listening for connections' );
}
return cb(err);
});
} }
}; };

View File

@ -6,6 +6,7 @@ const Config = require('../../config.js').get;
const TelnetClient = require('./telnet.js').TelnetClient; const TelnetClient = require('./telnet.js').TelnetClient;
const Log = require('../../logger.js').log; const Log = require('../../logger.js').log;
const LoginServerModule = require('../../login_server_module.js'); const LoginServerModule = require('../../login_server_module.js');
const { Errors } = require('../../enig_error.js');
// deps // deps
const _ = require('lodash'); const _ = require('lodash');
@ -14,6 +15,7 @@ const http = require('http');
const https = require('https'); const https = require('https');
const fs = require('graceful-fs'); const fs = require('graceful-fs');
const Writable = require('stream'); const Writable = require('stream');
const forEachSeries = require('async/forEachSeries');
const ModuleInfo = exports.moduleInfo = { const ModuleInfo = exports.moduleInfo = {
name : 'WebSocket', name : 'WebSocket',
@ -165,31 +167,7 @@ exports.getModule = class WebSocketLoginServer extends LoginServerModule {
return cb(null); return cb(null);
} }
listen() { listen(cb) {
WSS_SERVER_TYPES.forEach(serverType => {
const server = this[serverType];
if(!server) {
return;
}
const serverName = `${ModuleInfo.name} (${serverType})`;
const port = parseInt(_.get(Config(), [ 'loginServers', 'webSocket', 'secure' === serverType ? 'wss' : 'ws', 'port' ] ));
if(isNaN(port)) {
Log.error( { server : serverName, port : port }, 'Cannot load server (invalid port)' );
return;
}
server.httpServer.listen(port);
server.wsServer.on('connection', (ws, req) => {
const webSocketClient = new WebSocketClient(ws, req, serverType);
this.handleNewClient(webSocketClient, webSocketClient.socketBridge, ModuleInfo);
});
Log.info( { server : serverName, port : port }, 'Listening for connections' );
});
// //
// Send pings every 30s // Send pings every 30s
// //
@ -215,7 +193,38 @@ exports.getModule = class WebSocketLoginServer extends LoginServerModule {
}); });
}, 30000); }, 30000);
return true; forEachSeries(WSS_SERVER_TYPES, (serverType, nextServerType) => {
const server = this[serverType];
if(!server) {
return nextServerType(null);
}
const serverName = `${ModuleInfo.name} (${serverType})`;
const confPort = _.get(Config(), [ 'loginServers', 'webSocket', 'secure' === serverType ? 'wss' : 'ws', '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, err => {
if(err) {
return nextServerType(err);
}
server.wsServer.on('connection', (ws, req) => {
const webSocketClient = new WebSocketClient(ws, req, serverType);
this.handleNewClient(webSocketClient, webSocketClient.socketBridge, ModuleInfo);
});
Log.info( { server : serverName, port : port }, 'Listening for connections' );
return nextServerType(null);
});
},
err => {
cb(err);
});
} }
webSocketConnection(conn) { webSocketConnection(conn) {