--- /dev/null
+var _ = require('lodash'),
+ rehash = require('./rehash.js'),
+ config = require('../server/configuration.js'),
+ kiwiModules = require('../server/modules');
+
+
+
+var ControlInterface = module.exports = function(stream_in, stream_out, opts) {
+ stream_out = stream_out || stream_in;
+ this.stream_out = stream_out;
+ this.stream_in = stream_in;
+
+ opts = opts || {};
+ this.prompt = (typeof opts.prompt === 'string') ?
+ opts.prompt :
+ 'Kiwi > ';
+
+ this._custom_commands = {};
+
+ this._onData = this.onData.bind(this);
+ stream_in.on('data', this._onData);
+
+ this.displayPrompt();
+};
+
+
+
+ControlInterface.prototype.dispose = function() {
+ this.stream_in.removeListener('data', this._onData);
+ this.stream_in = null;
+ this.stream_out = null;
+};
+
+
+
+ControlInterface.prototype.write = function(data, append) {
+ if (typeof append === 'undefined') append = '\n';
+ try {
+ this.stream_out.write(data + append);
+ } catch(err){}
+};
+
+
+
+ControlInterface.prototype.displayPrompt = function(prompt) {
+ prompt = prompt || this.prompt;
+ this.write(prompt, '');
+};
+
+
+
+ControlInterface.prototype.onData = function(buffered) {
+ var data = buffered.toString().trim(),
+ data_parts = data.split(' '),
+ cmd = data_parts[0] || null;
+
+ if (typeof this._custom_commands[cmd] === 'function') {
+ this._custom_commands[cmd].call(this, data_parts.slice(1), data);
+
+ } else if (typeof commands[cmd] === 'function') {
+ commands[cmd].call(this, data_parts.slice(1), data);
+
+ } else {
+ this.write('Unrecognised command: ' + cmd);
+ }
+
+ this.displayPrompt();
+};
+
+
+
+ControlInterface.prototype.addCommand = function(command, fn) {
+ this._custom_commands[command] = fn;
+};
+
+
+
+var commands = {};
+commands.stats = function(args, raw) {
+ this.write('Connected clients: ' + _.size(global.clients.clients).toString());
+ this.write('Num. remote hosts: ' + _.size(global.clients.addresses).toString());
+};
+
+
+commands.reconfig = function(args, raw) {
+ if (config.loadConfig()) {
+ console.log('New config file loaded');
+ } else {
+ console.log("No new config file was loaded");
+ }
+};
+
+
+commands.rehash = function(args, raw) {
+ rehash.rehashAll();
+ console.log('Rehashed');
+};
+
+
+commands.jumpserver = function(args, raw) {
+ var num_clients = _.size(global.clients.clients),
+ packet = {}, args_idx;
+
+ if (num_clients === 0) {
+ console.log('No connected clients');
+ return;
+ }
+
+ // For each word in the line minus the last, add it to the packet
+ for(args_idx=0; args_idx<args.length-1; args_idx++){
+ packet[args[args_idx]] = true;
+ }
+
+ packet.kiwi_server = args[args_idx];
+
+ console.log('Broadcasting jumpserver to ' + num_clients.toString() + ' clients..');
+ global.clients.broadcastKiwiCommand('jumpserver', packet, function() {
+ console.log('Broadcast complete.');
+ });
+};
+
+
+commands.module = function(args, raw) {
+ switch(args[0]) {
+ case 'reload':
+ if (!args[1]) {
+ this.write('A module name must be specified');
+ return;
+ }
+
+ if (!kiwiModules.unload(args[1])) {
+ this.write('Module ' + (args[1] || '') + ' is not loaded');
+ return;
+ }
+
+ if (!kiwiModules.load(args[1])) {
+ this.write('Error loading module ' + (args[1] || ''));
+ }
+ this.write('Module ' + args[1] + ' reloaded');
+
+ break;
+
+ case 'list':
+ case 'ls':
+ default:
+ var module_names = [];
+ kiwiModules.getRegisteredModules().forEach(function(module) {
+ module_names.push(module.module_name);
+ });
+ this.write('Loaded modules: ' + module_names.join(', '));
+ }
+};
+
+
+commands.hello = function(args, raw) {
+ this.write('Hello, beautiful :)');
+};
util = require('util'),
WebListener = require('./weblistener.js'),
config = require('./configuration.js'),
- rehash = require('./rehash.js'),
modules = require('./modules.js'),
- Identd = require('./identd.js');
+ Identd = require('./identd.js'),
+ ControlInterface = require('./controlinterface.js');
/*
* Listen for runtime commands
*/
-
process.stdin.resume();
-process.stdin.on('data', function (buffered) {
- var data = buffered.toString().trim(),
- data_parts = data.split(' '),
- cmd = data_parts[0] || null;
-
- switch (cmd) {
- case 'stats':
- console.log('Connected clients: ' + _.size(global.clients.clients).toString());
- console.log('Num. remote hosts: ' + _.size(global.clients.addresses).toString());
- break;
-
- case 'reconfig':
- if (config.loadConfig()) {
- console.log('New config file loaded');
- } else {
- console.log("No new config file was loaded");
- }
-
- break;
-
-
- case 'rehash':
- (function () {
- rehash.rehashAll();
- console.log('Rehashed');
- })();
-
- break;
-
- case 'jumpserver':
- (function() {
- var num_clients = _.size(global.clients.clients),
- packet = {}, parts_idx;
-
- if (num_clients === 0) {
- console.log('No connected clients');
- return;
- }
-
- // For each word in the line minus the last, add it to the packet
- for(parts_idx=1; parts_idx<data_parts.length-1; parts_idx++){
- packet[data_parts[parts_idx]] = true;
- }
-
- packet.kiwi_server = data_parts[parts_idx];
-
- console.log('Broadcasting jumpserver to ' + num_clients.toString() + ' clients..');
- global.clients.broadcastKiwiCommand('jumpserver', packet, function() {
- console.log('Broadcast complete.');
- });
- })();
-
- break;
-
- default:
- console.log('Unrecognised command: ' + data);
- }
-});
+new ControlInterface(process.stdin, process.stdout, {prompt: ''});
* Listens on localhost:8888 by default\r
*/\r
\r
-var net = require('net'),\r
- kiwiModules = require('../server/modules'),\r
- rehash = require('../server/rehash.js'),\r
- config = require('../server/configuration.js'),\r
- _ = require('lodash');\r
+var net = require('net'),\r
+ kiwiModules = require('../server/modules'),\r
+ ControlInterface = require('../server/controlinterface.js'),\r
+ _ = require('lodash');\r
\r
var control_module = new kiwiModules.Module('Control');\r
\r
* The socket client\r
*/\r
function SocketClient (socket) {\r
+ var that = this;\r
+\r
this.socket = socket;\r
this.socket_closing = false;\r
\r
this.bindEvents();\r
\r
socket.write("\nHello, you are connected to the Kiwi server :)\n\n");\r
- this.displayPrompt();\r
+\r
+ this.control_interface = new ControlInterface(socket);\r
+ _.each(socket_commands, function(fn, command_name) {\r
+ console.log('adding command', command_name);\r
+ that.control_interface.addCommand(command_name, fn.bind(that));\r
+ });\r
}\r
\r
SocketClient.prototype.bindEvents = function() {\r
var that = this;\r
\r
- this.socket.on('data', function() { that.onData.apply(that, arguments); });\r
this.socket.on('close', function() { that.onClose.apply(that, arguments); });\r
};\r
-SocketClient.prototype.unbindEvents = function() {\r
- this.socket.removeAllListeners();\r
-};\r
-\r
-\r
-\r
-SocketClient.prototype.write = function(data, append) {\r
- if (typeof append === 'undefined') append = '\n';\r
- if (this.socket && !this.socket_closing)\r
- this.socket.write(data + append);\r
-};\r
-SocketClient.prototype.displayPrompt = function(prompt) {\r
- prompt = prompt || 'Kiwi > ';\r
- this.write(prompt, '');\r
-};\r
-\r
-\r
-\r
-SocketClient.prototype.onData = function(data) {\r
- data = data.toString().trim();\r
-\r
-\r
\r
- try {\r
- var data_split = data.split(' ');\r
\r
- if (typeof socket_commands[data_split[0]] === 'function') {\r
- socket_commands[data_split[0]].call(this, data_split.slice(1));\r
- } else {\r
- this.write('Unrecognised command: ' + data);\r
- }\r
-\r
- } catch (err) {\r
- console.log('[Control error] ' + err);\r
- this.write('An error occured. Check the Kiwi server log for more details');\r
- }\r
-\r
- this.displayPrompt();\r
+SocketClient.prototype.unbindEvents = function() {\r
+ this.socket.removeAllListeners();\r
};\r
\r
\r
SocketClient.prototype.onClose = function() {\r
+ this.control_interface.dispose();\r
+ this.control_interface = null;\r
+\r
this.unbindEvents();\r
this.socket = null;\r
+\r
console.log('Control connection from ' + this.remoteAddress + ' closed');\r
};\r
\r
* Each function is run in context of the SocketClient\r
*/\r
var socket_commands = {\r
- module: function(data) {\r
- switch(data[0]) {\r
- case 'reload':\r
- if (!data[1]) {\r
- this.write('A module name must be specified');\r
- return;\r
- }\r
-\r
- if (!kiwiModules.unload(data[1])) {\r
- this.write('Module ' + (data[1] || '') + ' is not loaded');\r
- return;\r
- }\r
-\r
- if (!kiwiModules.load(data[1])) {\r
- this.write('Error loading module ' + (data[1] || ''));\r
- }\r
- this.write('Module ' + data[1] + ' reloaded');\r
-\r
- break;\r
-\r
- case 'list':\r
- case 'ls':\r
- default:\r
- var module_names = [];\r
- kiwiModules.getRegisteredModules().forEach(function(module) {\r
- module_names.push(module.module_name);\r
- });\r
- this.write('Loaded modules: ' + module_names.join(', '));\r
- }\r
-\r
- },\r
-\r
- stats: function(data) {\r
- this.write('Connected clients: ' + _.size(global.clients.clients).toString());\r
- this.write('Num. remote hosts: ' + _.size(global.clients.addresses).toString());\r
- },\r
-\r
- rehash: function(data) {\r
- rehash.rehashAll();\r
- this.write('Rehashed');\r
- },\r
-\r
- reconfig: function(data) {\r
- if (config.loadConfig()) {\r
- this.write('New config file loaded');\r
- } else {\r
- this.write("No new config file was loaded");\r
- }\r
- },\r
-\r
quit: function(data) {\r
this.socket.destroy();\r
this.socket_closing = true;\r