Events system, first pass
This commit is contained in:
parent
d6f5429ce8
commit
002b0e941e
25
core/bbs.js
25
core/bbs.js
|
@ -11,6 +11,7 @@ const logger = require('./logger.js');
|
|||
const database = require('./database.js');
|
||||
const clientConns = require('./client_connections.js');
|
||||
const resolvePath = require('./misc_util.js').resolvePath;
|
||||
const events = require('./events.js');
|
||||
|
||||
// deps
|
||||
const async = require('async');
|
||||
|
@ -27,7 +28,7 @@ exports.main = main;
|
|||
const initServices = {};
|
||||
|
||||
const ENIGMA_COPYRIGHT = 'ENiGMA½ Copyright (c) 2014-2017 Bryan Ashby';
|
||||
const HELP =
|
||||
const HELP =
|
||||
`${ENIGMA_COPYRIGHT}
|
||||
usage: main.js <args>
|
||||
|
||||
|
@ -60,7 +61,7 @@ function main() {
|
|||
conf.init(resolvePath(configPath), function configInit(err) {
|
||||
|
||||
//
|
||||
// If the user supplied a path and we can't read/parse it
|
||||
// If the user supplied a path and we can't read/parse it
|
||||
// then it's a fatal error
|
||||
//
|
||||
if(err) {
|
||||
|
@ -84,15 +85,17 @@ function main() {
|
|||
}
|
||||
return callback(err);
|
||||
});
|
||||
},
|
||||
}
|
||||
],
|
||||
function complete(err) {
|
||||
events.registerModules();
|
||||
|
||||
// note this is escaped:
|
||||
fs.readFile(paths.join(__dirname, '../misc/startup_banner.asc'), 'utf8', (err, banner) => {
|
||||
console.info(ENIGMA_COPYRIGHT);
|
||||
if(!err) {
|
||||
if(!err) {
|
||||
console.info(banner);
|
||||
}
|
||||
}
|
||||
console.info('System started!');
|
||||
});
|
||||
|
||||
|
@ -140,7 +143,7 @@ function shutdownSystem() {
|
|||
},
|
||||
function stopMsgNetwork(callback) {
|
||||
require('./msg_network.js').shutdown(callback);
|
||||
}
|
||||
}
|
||||
],
|
||||
() => {
|
||||
console.info('Goodbye!');
|
||||
|
@ -173,9 +176,9 @@ function initialize(cb) {
|
|||
process.on('SIGINT', shutdownSystem);
|
||||
|
||||
require('later').date.localTime(); // use local times for later.js/scheduling
|
||||
|
||||
|
||||
return callback(null);
|
||||
},
|
||||
},
|
||||
function initDatabases(callback) {
|
||||
return database.initializeDatabases(callback);
|
||||
},
|
||||
|
@ -195,7 +198,7 @@ function initialize(cb) {
|
|||
// * Makes this accessible for MCI codes, easy non-blocking access, etc.
|
||||
// * We do this every time as the op is free to change this information just
|
||||
// like any other user
|
||||
//
|
||||
//
|
||||
const User = require('./user.js');
|
||||
|
||||
async.waterfall(
|
||||
|
@ -223,7 +226,7 @@ function initialize(cb) {
|
|||
opProps.username = opUserName;
|
||||
|
||||
_.each(opProps, (v, k) => {
|
||||
StatLog.setNonPeristentSystemStat(`sysop_${k}`, v);
|
||||
StatLog.setNonPeristentSystemStat(`sysop_${k}`, v);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -235,7 +238,7 @@ function initialize(cb) {
|
|||
return require('./predefined_mci.js').init(callback);
|
||||
},
|
||||
function readyMessageNetworkSupport(callback) {
|
||||
return require('./msg_network.js').startup(callback);
|
||||
return require('./msg_network.js').startup(callback);
|
||||
},
|
||||
function listenConnections(callback) {
|
||||
return require('./listening_server.js').startup(callback);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// ENiGMA½
|
||||
const ansi = require('./ansi_term.js');
|
||||
const events = require('./events.js');
|
||||
|
||||
// deps
|
||||
const async = require('async');
|
||||
|
@ -82,7 +83,7 @@ function ansiQueryTermSizeIfNeeded(client, cb) {
|
|||
//
|
||||
if(h < 10 || w < 10) {
|
||||
client.log.warn(
|
||||
{ height : h, width : w },
|
||||
{ height : h, width : w },
|
||||
'Ignoring ANSI CPR screen size query response due to very small values');
|
||||
return done(new Error('Term size <= 10 considered invalid'));
|
||||
}
|
||||
|
@ -91,11 +92,11 @@ function ansiQueryTermSizeIfNeeded(client, cb) {
|
|||
client.term.termWidth = w;
|
||||
|
||||
client.log.debug(
|
||||
{
|
||||
termWidth : client.term.termWidth,
|
||||
termHeight : client.term.termHeight,
|
||||
source : 'ANSI CPR'
|
||||
},
|
||||
{
|
||||
termWidth : client.term.termWidth,
|
||||
termHeight : client.term.termHeight,
|
||||
source : 'ANSI CPR'
|
||||
},
|
||||
'Window size updated'
|
||||
);
|
||||
|
||||
|
@ -109,7 +110,7 @@ function ansiQueryTermSizeIfNeeded(client, cb) {
|
|||
return done(new Error('No term size established by CPR within timeout'));
|
||||
}, 2000);
|
||||
|
||||
// Start the process: Query for CPR
|
||||
// Start the process: Query for CPR
|
||||
client.term.rawWrite(ansi.queryScreenSize());
|
||||
}
|
||||
|
||||
|
@ -123,7 +124,7 @@ function displayBanner(term) {
|
|||
// note: intentional formatting:
|
||||
term.pipeWrite(`
|
||||
|06Connected to |02EN|10i|02GMA|10½ |06BBS version |12|VN
|
||||
|06Copyright (c) 2014-2017 Bryan Ashby |14- |12http://l33t.codes/
|
||||
|06Copyright (c) 2014-2017 Bryan Ashby |14- |12http://l33t.codes/
|
||||
|06Updates & source |14- |12https://github.com/NuSkooler/enigma-bbs/
|
||||
|00`
|
||||
);
|
||||
|
@ -153,11 +154,11 @@ function connectEntry(client, nextMenu) {
|
|||
if(0 === term.termHeight || 0 === term.termWidth) {
|
||||
//
|
||||
// We still don't have something good for term height/width.
|
||||
// Default to DOS size 80x25.
|
||||
// Default to DOS size 80x25.
|
||||
//
|
||||
// :TODO: Netrunner is currenting hitting this and it feels wrong. Why is NAWS/ENV/CPR all failing???
|
||||
// :TODO: Netrunner is currenting hitting this and it feels wrong. Why is NAWS/ENV/CPR all failing???
|
||||
client.log.warn( { reason : err.message }, 'Failed to negotiate term size; Defaulting to 80x25!');
|
||||
|
||||
|
||||
term.termHeight = 25;
|
||||
term.termWidth = 80;
|
||||
}
|
||||
|
@ -165,8 +166,8 @@ function connectEntry(client, nextMenu) {
|
|||
|
||||
return callback(null);
|
||||
});
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
() => {
|
||||
prepareTerminal(term);
|
||||
|
||||
|
@ -175,6 +176,9 @@ function connectEntry(client, nextMenu) {
|
|||
//
|
||||
displayBanner(term);
|
||||
|
||||
// fire event
|
||||
events.emit('codes.l33t.enigma.system.connect', {'client': client});
|
||||
|
||||
setTimeout( () => {
|
||||
return client.menuStack.goto(nextMenu);
|
||||
}, 500);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* jslint node: true */
|
||||
'use strict';
|
||||
|
||||
const Config = require('./config.js');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const events = require('events');
|
||||
const logger = require('./logger.js');
|
||||
|
||||
var eventEmitter = new events.EventEmitter();
|
||||
|
||||
var self = module.exports = {
|
||||
emit: function(eventName, args) {
|
||||
logger.log.debug("Emit "+eventName);
|
||||
eventEmitter.emit(eventName, args);
|
||||
},
|
||||
on: function(eventName, listener) {
|
||||
logger.log.debug("Register listener for "+eventName);
|
||||
eventEmitter.on(eventName, listener);
|
||||
},
|
||||
remove: function(eventName, listener) {
|
||||
logger.log.debug("Remove listener for "+eventName);
|
||||
eventEmitter.removeListener(eventName, listener);
|
||||
},
|
||||
registerModules: function() {
|
||||
var mods = fs.readdirSync(Config.config.paths.mods);
|
||||
|
||||
mods.forEach(function(item) {
|
||||
var modPath = Config.config.paths.mods+item;
|
||||
if (item.substr(item.length-3) != '.js') {
|
||||
modPath += path.sep+item+'.js';
|
||||
}
|
||||
if (fs.existsSync(modPath)) {
|
||||
var module = require(modPath);
|
||||
|
||||
if (module.registerEvents !== undefined) {
|
||||
logger.log.debug(modPath+" calling registerEvents function");
|
||||
module.registerEvents();
|
||||
} else {
|
||||
logger.log.debug(modPath+" has no registerEvents function");
|
||||
}
|
||||
} else {
|
||||
logger.log.debug(modPath+" - file not found");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,4 +4,4 @@
|
|||
exports.PluginModule = PluginModule;
|
||||
|
||||
function PluginModule(options) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,9 +25,11 @@ const ModuleInfo = exports.moduleInfo = {
|
|||
function WebSocketClient(ws, req, serverType) {
|
||||
|
||||
Object.defineProperty(this, 'isSecure', {
|
||||
get : () => ('secure' === serverType || true === this.secureProxyConnection) ? true : false,
|
||||
get : () => ('secure' === serverType || true === this.proxied) ? true : false,
|
||||
});
|
||||
|
||||
const self = this;
|
||||
|
||||
//
|
||||
// This bridge makes accessible various calls that client sub classes
|
||||
// want to access on I/O socket
|
||||
|
@ -39,7 +41,7 @@ function WebSocketClient(ws, req, serverType) {
|
|||
}
|
||||
|
||||
end() {
|
||||
return ws.terminate();
|
||||
return ws.terminate();
|
||||
}
|
||||
|
||||
write(data, cb) {
|
||||
|
@ -47,7 +49,8 @@ function WebSocketClient(ws, req, serverType) {
|
|||
}
|
||||
|
||||
get remoteAddress() {
|
||||
return req.connection.remoteAddress;
|
||||
// Support X-Forwarded-For and X-Real-IP headers for proxied connections
|
||||
return (self.proxied && (req.headers['x-forwarded-for'] || req.headers['x-real-ip'])) || req.connection.remoteAddress;
|
||||
}
|
||||
}(ws);
|
||||
|
||||
|
@ -56,7 +59,8 @@ function WebSocketClient(ws, req, serverType) {
|
|||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
this.end();
|
||||
// we'll remove client connection which will in turn end() via our SocketBridge above
|
||||
return this.emit('end');
|
||||
});
|
||||
|
||||
//
|
||||
|
@ -75,11 +79,13 @@ function WebSocketClient(ws, req, serverType) {
|
|||
// If the config allows it, look for 'x-forwarded-proto' as "https"
|
||||
// to override |isSecure|
|
||||
//
|
||||
if(true === _.get(Config, 'loginServers.webSocket.secureProxy') &&
|
||||
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.secureProxyConnection = true;
|
||||
Log.debug(`Assuming secure connection due to X-Forwarded-Proto of "${req.headers['x-forwarded-proto']}"`);
|
||||
this.proxied = true;
|
||||
} else {
|
||||
this.proxied = false;
|
||||
}
|
||||
|
||||
// start handshake process
|
||||
|
|
Loading…
Reference in New Issue