+ Concept of PluginModule and inherited classes such as ServerModule, MenuModule, ...

* Client now tracks current menu module. Auto detach events, etc.
This commit is contained in:
Bryan Ashby 2015-03-18 23:08:23 -06:00
parent d3e35d286a
commit f7462bbbdd
11 changed files with 226 additions and 60 deletions

View File

@ -3,7 +3,7 @@
// ENiGMA½ // ENiGMA½
var conf = require('./config.js'); var conf = require('./config.js');
var modules = require('./modules.js'); var moduleUtil = require('./module_util.js');
var logger = require('./logger.js'); var logger = require('./logger.js');
var miscUtil = require('./misc_util.js'); var miscUtil = require('./misc_util.js');
var database = require('./database.js'); var database = require('./database.js');
@ -117,7 +117,7 @@ function startListening() {
return []; return [];
} }
modules.loadModulesForCategory('servers', function onServerModule(err, module) { moduleUtil.loadModulesForCategory('servers', function onServerModule(err, module) {
if(err) { if(err) {
logger.log.info(err); logger.log.info(err);
return; return;
@ -129,7 +129,8 @@ function startListening() {
return; return;
} }
var server = module.createServer(); var moduleInst = new module.getModule();
var server = moduleInst.createServer();
// :TODO: handle maxConnections, e.g. conf.maxConnections // :TODO: handle maxConnections, e.g. conf.maxConnections

View File

@ -2,12 +2,15 @@
'use strict'; 'use strict';
var stream = require('stream'); var stream = require('stream');
var term = require('./client_term.js');
var assert = require('assert'); var assert = require('assert');
var term = require('./client_term.js');
var miscUtil = require('./misc_util.js'); var miscUtil = require('./misc_util.js');
var ansi = require('./ansi_term.js'); var ansi = require('./ansi_term.js');
var logger = require('./logger.js'); var logger = require('./logger.js'); // :TODO: cleanup and just use Log.
var Log = require('./logger.js').log;
var user = require('./user.js'); var user = require('./user.js');
var moduleUtil = require('./module_util.js');
exports.Client = Client; exports.Client = Client;
@ -183,6 +186,33 @@ Client.prototype.address = function() {
return this.input.address(); return this.input.address();
}; };
Client.prototype.gotoMenuModule = function(name, cb) {
var self = this;
// Assign a default missing module handler callback if none was provided
cb = miscUtil.valueWithDefault(cb, self.defaultHandlerMissingMod());
if(self.currentMenuModule) {
self.currentMenuModule.leave();
}
moduleUtil.loadModule(name, 'mods', function onModuleLoaded(err, mod) {
if(err) {
cb(err);
} else {
try {
Log.debug({ moduleName : name }, 'Goto menu module');
var modInst = new mod.getModule();
modInst.enter(self);
self.currentMenuModule = modInst;
} catch(e) {
cb(e);
}
}
});
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Default error handlers // Default error handlers
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -43,7 +43,7 @@ module.exports = {
}, },
ssh : { ssh : {
port : 8889, port : 8889,
enabled : true, enabled : false,
rsaPrivateKey : paths.join(__dirname, './../misc/default_key.rsa'), rsaPrivateKey : paths.join(__dirname, './../misc/default_key.rsa'),
dsaPrivateKey : paths.join(__dirname, './../misc/default_key.dsa'), dsaPrivateKey : paths.join(__dirname, './../misc/default_key.dsa'),
} }

View File

@ -3,7 +3,7 @@
var ansi = require('./ansi_term.js'); var ansi = require('./ansi_term.js');
var artwork = require('./art.js'); var artwork = require('./art.js');
var modules = require('./modules.js'); var moduleUtil = require('./module_util.js');
var Log = require('./logger.js').log; var Log = require('./logger.js').log;
var Config = require('./config.js').config; var Config = require('./config.js').config;
var packageJson = require('../package.json'); var packageJson = require('../package.json');
@ -84,7 +84,8 @@ function connectEntry(client) {
setTimeout(function onTimeout() { setTimeout(function onTimeout() {
term.write(ansi.clearScreen()); term.write(ansi.clearScreen());
modules.goto(Config.entryMod, client); client.gotoMenuModule(Config.entryMod);
//moduleUtil.goto(Config.entryMod, client);
}, timeout); }, timeout);
}); });
}, 500); }, 500);

29
core/menu_module.js Normal file
View File

@ -0,0 +1,29 @@
/* jslint node: true */
'use strict';
var PluginModule = require('./plugin_module.js').PluginModule;
exports.MenuModule = MenuModule;
function MenuModule() {
PluginModule.call(this);
this.viewControllers = [];
}
require('util').inherits(MenuModule, PluginModule);
MenuModule.prototype.enter = function(client) {
};
MenuModule.prototype.leave = function() {
this.viewControllers.forEach(function onVC(vc) {
vc.detachClientEvents();
});
};
MenuModule.prototype.addViewController = function(vc) {
this.viewControllers.push(vc);
return vc; // allow var vc = this.addViewController(new ViewController(...));
};

View File

@ -3,16 +3,14 @@
var fs = require('fs'); var fs = require('fs');
var paths = require('path'); var paths = require('path');
var conf = require('./config.js'); var conf = require('./config.js');
var miscUtil = require('./misc_util.js'); var miscUtil = require('./misc_util.js');
var logger = require('./logger.js');
// exports // exports
exports.loadModule = loadModule; exports.loadModule = loadModule;
exports.loadModulesForCategory = loadModulesForCategory; exports.loadModulesForCategory = loadModulesForCategory;
exports.goto = goto;
function loadModule(name, category, cb) { function loadModule(name, category, cb) {
var config = conf.config; var config = conf.config;
var path = config.paths[category]; var path = config.paths[category];
@ -32,12 +30,17 @@ function loadModule(name, category, cb) {
try { try {
var mod = require(paths.join(path, name + '.js')); var mod = require(paths.join(path, name + '.js'));
if(!mod.moduleInfo) { if(!mod.moduleInfo) {
cb(new Error('module is missing \'moduleInfo\' section')); cb(new Error('module is missing \'moduleInfo\' section'));
return; return;
} }
if(!mod.getModule || typeof mod.getModule !== 'function') {
cb(new Error('Invalid or missing missing \'getModule\' method'));
return;
}
mod.runtime = { mod.runtime = {
config : config config : config
}; };
@ -46,7 +49,7 @@ function loadModule(name, category, cb) {
} catch(e) { } catch(e) {
cb(e); cb(e);
} }
}; }
function loadModulesForCategory(category, cb) { function loadModulesForCategory(category, cb) {
var path = conf.config.paths[category]; var path = conf.config.paths[category];
@ -63,23 +66,4 @@ function loadModulesForCategory(category, cb) {
loadModule(paths.basename(file, '.js'), category, cb); loadModule(paths.basename(file, '.js'), category, cb);
}); });
}); });
}; }
function goto(name, client, cb) {
// Assign a default missing module handler callback if none was provided
cb = miscUtil.valueWithDefault(cb, client.defaultHandlerMissingMod());
loadModule(name, 'mods', function onMod(err, mod) {
if(err) {
cb(err);
} else {
try {
logger.log.debug({ moduleName : name }, 'Goto module');
mod.entryPoint(client);
} catch (e) {
cb(e);
}
}
});
};

7
core/plugin_module.js Normal file
View File

@ -0,0 +1,7 @@
/* jslint node: true */
'use strict';
exports.PluginModule = PluginModule;
function PluginModule() {
}

19
core/server_module.js Normal file
View File

@ -0,0 +1,19 @@
/* jslint node: true */
'use strict';
var PluginModule = require('./plugin_module.js').PluginModule;
exports.ServerModule = ServerModule;
function ServerModule() {
PluginModule.call(this);
this.viewControllers = [];
}
require('util').inherits(ServerModule, PluginModule);
ServerModule.prototype.createServer = function() {
console.log('ServerModule createServer')
return null;
};

View File

@ -25,7 +25,7 @@ function SSHClient(input, output) {
this.input.on('authentication', function onAuthentication(ctx) { this.input.on('authentication', function onAuthentication(ctx) {
console.log('auth: ' + ctx.method); console.log('auth: ' + ctx.method);
if('password' == ctx.method) { if('password' === ctx.method) {
// :TODO: Log attempts // :TODO: Log attempts
user.authenticate(ctx.username, ctx.password, self, function onAuthResult(isAuth) { user.authenticate(ctx.username, ctx.password, self, function onAuthResult(isAuth) {
if(isAuth) { if(isAuth) {
@ -34,9 +34,19 @@ function SSHClient(input, output) {
ctx.reject(); ctx.reject();
} }
}); });
} else if('publickey' == ctx.method) { } else if('publickey' === ctx.method) {
console.log('pub key path'); console.log('pub key path');
} else if('keyboard-interactive' === ctx.method) {
ctx.reject(['password']);
// :TODO: support this. Allow users to generate a key for use or w/e // :TODO: support this. Allow users to generate a key for use or w/e
/*} else if('keyboard-interactive' === ctx.method) {
console.log(ctx.submethods); // :TODO: proper logging; handle known types, etc.
ctx.prompt([ { prompt : 'Password: ', echo : false } ], function onPromptResponses(err, responses) {
console.log(err);
console.log(responses);
});*/
} else { } else {
ctx.reject(); ctx.reject();
} }
@ -44,10 +54,10 @@ function SSHClient(input, output) {
this.input.on('ready', function onReady() { this.input.on('ready', function onReady() {
console.log('Client authenticated'); console.log('Client authenticated');
});
this.input.on('session', function onSession(accept, reject) { self.input.on('session', function onSession(accept, reject) {
var session = accept();
});
}); });
this.input.on('end', function onEnd() { this.input.on('end', function onEnd() {
@ -66,7 +76,8 @@ function createServer() {
}; };
var server = ssh2.Server(serverConf); var server = ssh2.Server(serverConf);
server.on('connection', function onConnection(conn) { server.on('connection', function onConnection(conn, info) {
console.log(info); // :TODO: Proper logging
var client = new SSHClient(conn, conn); var client = new SSHClient(conn, conn);
this.emit('client', client); this.emit('client', client);
}); });

View File

@ -2,14 +2,16 @@
'use strict'; 'use strict';
// ENiGMA½ // ENiGMA½
var baseClient = require('../client.js'); var baseClient = require('../client.js');
var logger = require('../logger.js'); var logger = require('../logger.js');
var ServerModule = require('../server_module.js').ServerModule;
var net = require('net'); var net = require('net');
var buffers = require('buffers'); var buffers = require('buffers');
var binary = require('binary'); var binary = require('binary');
var stream = require('stream'); var stream = require('stream');
var assert = require('assert'); var assert = require('assert');
var util = require('util');
//var debug = require('debug')('telnet'); //var debug = require('debug')('telnet');
@ -19,7 +21,8 @@ exports.moduleInfo = {
author : 'NuSkooler' author : 'NuSkooler'
}; };
exports.createServer = createServer; exports.getModule = TelnetServerModule;
// //
// Telnet Protocol Resources // Telnet Protocol Resources
@ -469,7 +472,7 @@ function TelnetClient(input, output) {
}); });
} }
require('util').inherits(TelnetClient, baseClient.Client); util.inherits(TelnetClient, baseClient.Client);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Telnet Command/Option handling // Telnet Command/Option handling
@ -716,7 +719,7 @@ Object.keys(OPTIONS).forEach(function(name) {
}); });
}); });
/*
function createServer() { function createServer() {
var server = net.createServer(function onConnection(sock) { var server = net.createServer(function onConnection(sock) {
var self = this; var self = this;
@ -729,3 +732,27 @@ function createServer() {
return server; return server;
} }
*/
function TelnetServerModule() {
console.log('TelnetServerModule')
ServerModule.call(this);
}
util.inherits(TelnetServerModule, ServerModule);
TelnetServerModule.prototype.createServer = function() {
console.log('TelnetServerModule createServer')
TelnetServerModule.super_.prototype.createServer.call(this);
var server = net.createServer(function onConnection(sock) {
var self = this;
var client = new TelnetClient(sock, sock);
client.banner();
self.emit('client', client);
});
return server;
};

View File

@ -1,18 +1,18 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var ansi = require('../core/ansi_term.js'); var ansi = require('../core/ansi_term.js');
var art = require('../core/art.js'); var art = require('../core/art.js');
var user = require('../core/user.js'); var user = require('../core/user.js');
var theme = require('../core/theme.js'); var theme = require('../core/theme.js');
var modules = require('../core/modules.js'); var MenuModule = require('../core/menu_module.js').MenuModule;
//var view = require('../core/view.js'); //var view = require('../core/view.js');
var textView = require('../core/text_view.js'); var textView = require('../core/text_view.js');
var editTextView = require('../core/edit_text_view.js'); var editTextView = require('../core/edit_text_view.js');
var ViewController = require('../core/view_controller.js').ViewController; var ViewController = require('../core/view_controller.js').ViewController;
var async = require('async'); //var async = require('async');
exports.moduleInfo = { exports.moduleInfo = {
name : 'Matrix', name : 'Matrix',
@ -20,8 +20,63 @@ exports.moduleInfo = {
author : 'NuSkooler', author : 'NuSkooler',
}; };
exports.entryPoint = entryPoint; //exports.entryPoint = entryPoint;
exports.getModule = MatrixModule;
function MatrixModule() {
MenuModule.call(this);
}
require('util').inherits(MatrixModule, MenuModule);
MatrixModule.prototype.enter = function(client) {
MatrixModule.super_.prototype.enter.call(this);
var self = this;
client.term.write(ansi.resetScreen());
//client.term.write('\x1b[?33h');
theme.displayThemeArt('MATRIX', client, function onMatrix(err, mciMap) {
console.log(mciMap);
if(mciMap.ET1 && mciMap.ET2 && mciMap.BN1 && mciMap.BN2 && mciMap.BN3) {
//
// Form via EditTextViews and ButtonViews
// * ET1 - userName
// * ET2 - password
// * BN1 - Login
// * BN2 - New
// * BN3 - Bye!
//
} else if(mciMap.VM1) {
//
// Menu via VerticalMenuView
//
// * VM1 - menu with the following items:
// 0 - Login
// 1 - New
// 2 - Bye!
//
//var vc = new ViewController(client);
var vc = self.addViewController(new ViewController(client));
vc.on('submit', function onSubmit(form) {
console.log(form);
});
vc.loadFromMCIMap(mciMap);
vc.setViewOrder();
// :TODO: Localize
vc.getView(1).setItems(['Login', 'New User', 'Goodbye!']);
vc.getView(1).submit = true;
vc.switchFocus(1);
}
});
};
/*
function entryPoint(client) { function entryPoint(client) {
client.term.write(ansi.resetScreen()); client.term.write(ansi.resetScreen());
@ -50,17 +105,19 @@ function entryPoint(client) {
var vc = new ViewController(client); var vc = new ViewController(client);
vc.on('submit', function onSubmit(form) { vc.on('submit', function onSubmit(form) {
console.log(form);
}); });
vc.loadFromMCIMap(mciMap); vc.loadFromMCIMap(mciMap);
vc.setViewOrder(); vc.setViewOrder();
// :TODO: Localize // :TODO: Localize
vc.getView(1).setItems(['Login', 'New User', 'Goodbye!']); vc.getView(1).setItems(['Login', 'New User', 'Goodbye!']);
vc.getView(1).submit = true;
vc.switchFocus(1); vc.switchFocus(1);
} }
}); });
} }
*/
/* /*
function entryPoint(client) { function entryPoint(client) {