Various cleanup WIP

This commit is contained in:
Bryan Ashby 2016-07-17 22:16:15 -06:00
parent b7274a16d4
commit e19b725aa8
1 changed files with 120 additions and 132 deletions

View File

@ -54,7 +54,7 @@ exports.getModule = TelnetServerModule;
*/ */
var COMMANDS = { const COMMANDS = {
SE : 240, // End of Sub-Negotation Parameters SE : 240, // End of Sub-Negotation Parameters
NOP : 241, // No Operation NOP : 241, // No Operation
DM : 242, // Data Mark DM : 242, // Data Mark
@ -77,7 +77,7 @@ var COMMANDS = {
// Resources: // Resources:
// * http://www.faqs.org/rfcs/rfc1572.html // * http://www.faqs.org/rfcs/rfc1572.html
// //
var SB_COMMANDS = { const SB_COMMANDS = {
IS : 0, IS : 0,
SEND : 1, SEND : 1,
INFO : 2, INFO : 2,
@ -89,7 +89,7 @@ var SB_COMMANDS = {
// Resources // Resources
// * http://mars.netanya.ac.il/~unesco/cdrom/booklet/HTML/NETWORKING/node300.html // * http://mars.netanya.ac.il/~unesco/cdrom/booklet/HTML/NETWORKING/node300.html
// //
var OPTIONS = { const OPTIONS = {
TRANSMIT_BINARY : 0, // http://tools.ietf.org/html/rfc856 TRANSMIT_BINARY : 0, // http://tools.ietf.org/html/rfc856
ECHO : 1, // http://tools.ietf.org/html/rfc857 ECHO : 1, // http://tools.ietf.org/html/rfc857
// RECONNECTION : 2 // RECONNECTION : 2
@ -148,7 +148,7 @@ var OPTIONS = {
}; };
// Commands used within NEW_ENVIRONMENT[_DEP] // Commands used within NEW_ENVIRONMENT[_DEP]
var NEW_ENVIRONMENT_COMMANDS = { const NEW_ENVIRONMENT_COMMANDS = {
VAR : 0, VAR : 0,
VALUE : 1, VALUE : 1,
ESC : 2, ESC : 2,
@ -156,8 +156,6 @@ var NEW_ENVIRONMENT_COMMANDS = {
}; };
const IAC_BUF = new Buffer([ COMMANDS.IAC ]); const IAC_BUF = new Buffer([ COMMANDS.IAC ]);
//var SB_BUF = new Buffer([ COMMANDS.SB ]);
//var SE_BUF = new Buffer([ COMMANDS.SE ]);
const IAC_SE_BUF = new Buffer([ COMMANDS.IAC, COMMANDS.SE ]); const IAC_SE_BUF = new Buffer([ COMMANDS.IAC, COMMANDS.SE ]);
const COMMAND_NAMES = Object.keys(COMMANDS).reduce(function(names, name) { const COMMAND_NAMES = Object.keys(COMMANDS).reduce(function(names, name) {
@ -179,12 +177,12 @@ const COMMAND_IMPLS = {};
// :TODO: See TooTallNate's telnet.js: Handle COMMAND_IMPL for IAC in binary mode // :TODO: See TooTallNate's telnet.js: Handle COMMAND_IMPL for IAC in binary mode
// Create option names such as 'transmit binary' -> OPTIONS.TRANSMIT_BINARY // Create option names such as 'transmit binary' -> OPTIONS.TRANSMIT_BINARY
var OPTION_NAMES = Object.keys(OPTIONS).reduce(function(names, name) { const OPTION_NAMES = Object.keys(OPTIONS).reduce(function(names, name) {
names[OPTIONS[name]] = name.toLowerCase().replace(/_/g, ' '); names[OPTIONS[name]] = name.toLowerCase().replace(/_/g, ' ');
return names; return names;
}, {}); }, {});
var OPTION_IMPLS = {}; const OPTION_IMPLS = {};
// :TODO: fill in the rest... // :TODO: fill in the rest...
OPTION_IMPLS.NO_ARGS = OPTION_IMPLS.NO_ARGS =
OPTION_IMPLS[OPTIONS.ECHO] = OPTION_IMPLS[OPTIONS.ECHO] =
@ -211,13 +209,13 @@ OPTION_IMPLS[OPTIONS.TERMINAL_TYPE] = function(bufs, i, event) {
return MORE_DATA_REQUIRED; return MORE_DATA_REQUIRED;
} }
var end = bufs.indexOf(IAC_SE_BUF, 5); // look past header bytes let end = bufs.indexOf(IAC_SE_BUF, 5); // look past header bytes
if(-1 === end) { if(-1 === end) {
return MORE_DATA_REQUIRED; return MORE_DATA_REQUIRED;
} }
// eat up and process the header // eat up and process the header
var buf = bufs.splice(0, 4).toBuffer(); let buf = bufs.splice(0, 4).toBuffer();
binary.parse(buf) binary.parse(buf)
.word8('iac1') .word8('iac1')
.word8('sb') .word8('sb')
@ -237,9 +235,10 @@ OPTION_IMPLS[OPTIONS.TERMINAL_TYPE] = function(bufs, i, event) {
// //
// From this point -> |end| is our ttype // From this point -> |end| is our ttype
// //
// Look for trailing NULL(s). Client such as Netrunner do this. // Look for trailing NULL(s). Clients such as NetRunner do this.
// If none is found, we take the entire buffer
// //
var trimAt = 0; let trimAt = 0;
for(; trimAt < buf.length; ++trimAt) { for(; trimAt < buf.length; ++trimAt) {
if(0x00 === buf[trimAt]) { if(0x00 === buf[trimAt]) {
break; break;
@ -288,7 +287,7 @@ OPTION_IMPLS[OPTIONS.WINDOW_SIZE] = function(bufs, i, event) {
}; };
// Build an array of delimiters for parsing NEW_ENVIRONMENT[_DEP] // Build an array of delimiters for parsing NEW_ENVIRONMENT[_DEP]
var NEW_ENVIRONMENT_DELIMITERS = []; const NEW_ENVIRONMENT_DELIMITERS = [];
Object.keys(NEW_ENVIRONMENT_COMMANDS).forEach(function onKey(k) { Object.keys(NEW_ENVIRONMENT_COMMANDS).forEach(function onKey(k) {
NEW_ENVIRONMENT_DELIMITERS.push(NEW_ENVIRONMENT_COMMANDS[k]); NEW_ENVIRONMENT_DELIMITERS.push(NEW_ENVIRONMENT_COMMANDS[k]);
}); });
@ -308,13 +307,13 @@ OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT] = function(bufs, i, event) {
return MORE_DATA_REQUIRED; return MORE_DATA_REQUIRED;
} }
var end = bufs.indexOf(IAC_SE_BUF, 4); // look past header bytes let end = bufs.indexOf(IAC_SE_BUF, 4); // look past header bytes
if(-1 === end) { if(-1 === end) {
return MORE_DATA_REQUIRED; return MORE_DATA_REQUIRED;
} }
// eat up and process the header // eat up and process the header
var buf = bufs.splice(0, 4).toBuffer(); let buf = bufs.splice(0, 4).toBuffer();
binary.parse(buf) binary.parse(buf)
.word8('iac1') .word8('iac1')
.word8('sb') .word8('sb')
@ -349,10 +348,10 @@ OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT] = function(bufs, i, event) {
// //
// :TODO: Currently not supporting ESCaped values (ESC + <type>). Probably not really in the wild, but we should be compliant // :TODO: Currently not supporting ESCaped values (ESC + <type>). Probably not really in the wild, but we should be compliant
// :TODO: Could probably just convert this to use a regex & handle delims + escaped values... in any case, this is sloppy... // :TODO: Could probably just convert this to use a regex & handle delims + escaped values... in any case, this is sloppy...
var params = []; const params = [];
var p = 0; let p = 0;
var j; let j;
var l; let l;
for(j = 0, l = buf.length; j < l; ++j) { for(j = 0, l = buf.length; j < l; ++j) {
if(NEW_ENVIRONMENT_DELIMITERS.indexOf(buf[j]) === -1) { if(NEW_ENVIRONMENT_DELIMITERS.indexOf(buf[j]) === -1) {
continue; continue;
@ -367,7 +366,7 @@ OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT] = function(bufs, i, event) {
params.push(buf.slice(p, l)); params.push(buf.slice(p, l));
} }
var varName; let varName;
event.envVars = {}; event.envVars = {};
// :TODO: handle cases where a variable was present in a previous exchange, but missing here...e.g removed // :TODO: handle cases where a variable was present in a previous exchange, but missing here...e.g removed
for(j = 0; j < params.length; ++j) { for(j = 0; j < params.length; ++j) {
@ -375,7 +374,7 @@ OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT] = function(bufs, i, event) {
continue; continue;
} }
var cmd = params[j].readUInt8(); let cmd = params[j].readUInt8();
if(cmd === NEW_ENVIRONMENT_COMMANDS.VAR || cmd === NEW_ENVIRONMENT_COMMANDS.USERVAR) { if(cmd === NEW_ENVIRONMENT_COMMANDS.VAR || cmd === NEW_ENVIRONMENT_COMMANDS.USERVAR) {
varName = params[j].slice(1).toString('utf8'); // :TODO: what encoding should this really be? varName = params[j].slice(1).toString('utf8'); // :TODO: what encoding should this really be?
} else { } else {
@ -390,7 +389,7 @@ OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT] = function(bufs, i, event) {
return event; return event;
}; };
var MORE_DATA_REQUIRED = 0xfeedface; const MORE_DATA_REQUIRED = 0xfeedface;
function parseBufs(bufs) { function parseBufs(bufs) {
assert(bufs.length >= 2); assert(bufs.length >= 2);
@ -399,23 +398,25 @@ function parseBufs(bufs) {
} }
function parseCommand(bufs, i, event) { function parseCommand(bufs, i, event) {
var command = bufs.get(i); // :TODO: fix deprecation... [i] is not the same const command = bufs.get(i); // :TODO: fix deprecation... [i] is not the same
event.commandCode = command; event.commandCode = command;
event.command = COMMAND_NAMES[command]; event.command = COMMAND_NAMES[command];
var handler = COMMAND_IMPLS[command]; const handler = COMMAND_IMPLS[command];
if(handler) { if(handler) {
//return COMMAND_IMPLS[command](bufs, i + 1, event);
return handler(bufs, i + 1, event); return handler(bufs, i + 1, event);
} else { } else {
assert(2 == bufs.length, 'Expected bufs length of 2, got ' + bufs.length); // IAC + COMMAND if(2 !== bufs.length) {
Log.warn( { bufsLength : bufs.length }, 'Expected bufs length of 2'); // expected: IAC + COMMAND
}
event.buf = bufs.splice(0, 2).toBuffer(); event.buf = bufs.splice(0, 2).toBuffer();
return event; return event;
} }
} }
function parseOption(bufs, i, event) { function parseOption(bufs, i, event) {
var option = bufs.get(i); // :TODO: fix deprecation... [i] is not the same const option = bufs.get(i); // :TODO: fix deprecation... [i] is not the same
event.optionCode = option; event.optionCode = option;
event.option = OPTION_NAMES[option]; event.option = OPTION_NAMES[option];
return OPTION_IMPLS[option](bufs, i + 1, event); return OPTION_IMPLS[option](bufs, i + 1, event);
@ -425,9 +426,9 @@ function parseOption(bufs, i, event) {
function TelnetClient(input, output) { function TelnetClient(input, output) {
baseClient.Client.apply(this, arguments); baseClient.Client.apply(this, arguments);
var self = this; const self = this;
var bufs = buffers(); let bufs = buffers();
this.bufs = bufs; this.bufs = bufs;
this.setInputOutput(input, output); this.setInputOutput(input, output);
@ -439,10 +440,10 @@ function TelnetClient(input, output) {
newEnvironRequested : false, newEnvironRequested : false,
}; };
this.input.on('data', function onData(b) { this.input.on('data', b => {
bufs.push(b); bufs.push(b);
var i; let i;
while((i = bufs.indexOf(IAC_BUF)) >= 0) { while((i = bufs.indexOf(IAC_BUF)) >= 0) {
// //
@ -486,16 +487,16 @@ function TelnetClient(input, output) {
}); });
this.input.on('end', function() { this.input.on('end', () => {
self.emit('end'); self.emit('end');
}); });
this.input.on('error', function sockError(err) { this.input.on('error', err => {
self.log.debug(err); // :TODO: probably something better... self.log.debug( { err : err }, 'Socket error');
self.emit('end'); self.emit('end');
}); });
this.connectionDebug = function(info, msg) { this.connectionDebug = (info, msg) => {
if(Config.servers.telnet.traceConnections) { if(Config.servers.telnet.traceConnections) {
self.log.trace(info, 'Telnet: ' + msg); self.log.trace(info, 'Telnet: ' + msg);
} }
@ -509,7 +510,8 @@ util.inherits(TelnetClient, baseClient.Client);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
TelnetClient.prototype.handleTelnetEvent = function(evt) { TelnetClient.prototype.handleTelnetEvent = function(evt) {
// handler name e.g. 'handleWontCommand' // handler name e.g. 'handleWontCommand'
var handlerName = 'handle' + evt.command.charAt(0).toUpperCase() + evt.command.substr(1) + 'Command'; //const handlerName = 'handle' + evt.command.charAt(0).toUpperCase() + evt.command.substr(1) + 'Command';
const handlerName = `handle${evt.command.charAt(0).toUpperCase()}${evt.command.substr(1)}Command`;
if(this[handlerName]) { if(this[handlerName]) {
// specialized // specialized
@ -568,17 +570,8 @@ TelnetClient.prototype.handleDontCommand = function(evt) {
this.connectionDebug(evt, 'dont'); this.connectionDebug(evt, 'dont');
}; };
/*
TelnetClient.prototype.setTermType = function(ttype) {
this.term.env.TERM = ttype;
this.term.termType = ttype;
this.log.debug( { termType : ttype }, 'Set terminal type');
};
*/
TelnetClient.prototype.handleSbCommand = function(evt) { TelnetClient.prototype.handleSbCommand = function(evt) {
var self = this; const self = this;
if('terminal type' === evt.option) { if('terminal type' === evt.option) {
// //
@ -650,7 +643,7 @@ TelnetClient.prototype.handleSbCommand = function(evt) {
} }
}; };
var IGNORED_COMMANDS = []; const IGNORED_COMMANDS = [];
[ COMMANDS.EL, COMMANDS.GA, COMMANDS.NOP, COMMANDS.DM, COMMANDS.BRK ].forEach(function onCommandCode(cc) { [ COMMANDS.EL, COMMANDS.GA, COMMANDS.NOP, COMMANDS.DM, COMMANDS.BRK ].forEach(function onCommandCode(cc) {
IGNORED_COMMANDS.push(cc); IGNORED_COMMANDS.push(cc);
}); });
@ -680,7 +673,7 @@ TelnetClient.prototype.handleMiscCommand = function(evt) {
}; };
TelnetClient.prototype.requestTerminalType = function() { TelnetClient.prototype.requestTerminalType = function() {
var buf = new Buffer( [ const buf = new Buffer( [
COMMANDS.IAC, COMMANDS.IAC,
COMMANDS.SB, COMMANDS.SB,
OPTIONS.TERMINAL_TYPE, OPTIONS.TERMINAL_TYPE,
@ -690,7 +683,7 @@ TelnetClient.prototype.requestTerminalType = function() {
this.output.write(buf); this.output.write(buf);
}; };
var WANTED_ENVIRONMENT_VAR_BUFS = [ const WANTED_ENVIRONMENT_VAR_BUFS = [
new Buffer( 'LINES' ), new Buffer( 'LINES' ),
new Buffer( 'COLUMNS' ), new Buffer( 'COLUMNS' ),
new Buffer( 'TERM' ), new Buffer( 'TERM' ),
@ -704,9 +697,9 @@ TelnetClient.prototype.requestNewEnvironment = function() {
return; return;
} }
var self = this; const self = this;
var bufs = buffers(); const bufs = buffers();
bufs.push(new Buffer( [ bufs.push(new Buffer( [
COMMANDS.IAC, COMMANDS.IAC,
COMMANDS.SB, COMMANDS.SB,
@ -714,7 +707,7 @@ TelnetClient.prototype.requestNewEnvironment = function() {
SB_COMMANDS.SEND ] SB_COMMANDS.SEND ]
)); ));
for(var i = 0; i < WANTED_ENVIRONMENT_VAR_BUFS.length; ++i) { for(let i = 0; i < WANTED_ENVIRONMENT_VAR_BUFS.length; ++i) {
bufs.push(new Buffer( [ NEW_ENVIRONMENT_COMMANDS.VAR ] ), WANTED_ENVIRONMENT_VAR_BUFS[i] ); bufs.push(new Buffer( [ NEW_ENVIRONMENT_COMMANDS.VAR ] ), WANTED_ENVIRONMENT_VAR_BUFS[i] );
} }
@ -726,10 +719,6 @@ TelnetClient.prototype.requestNewEnvironment = function() {
}; };
TelnetClient.prototype.banner = function() { TelnetClient.prototype.banner = function() {
// :TODO: See x84 implementation here.
// First, we should probably buffer then send.
this.will.echo(); this.will.echo();
this.will.suppress_go_ahead(); this.will.suppress_go_ahead();
@ -751,10 +740,10 @@ function Command(command, client) {
// Create Command objects with echo, transmit_binary, ... // Create Command objects with echo, transmit_binary, ...
Object.keys(OPTIONS).forEach(function(name) { Object.keys(OPTIONS).forEach(function(name) {
var code = OPTIONS[name]; const code = OPTIONS[name];
Command.prototype[name.toLowerCase()] = function() { Command.prototype[name.toLowerCase()] = function() {
var buf = new Buffer(3); const buf = new Buffer(3);
buf[0] = COMMANDS.IAC; buf[0] = COMMANDS.IAC;
buf[1] = this.command; buf[1] = this.command;
buf[2] = code; buf[2] = code;
@ -764,7 +753,7 @@ Object.keys(OPTIONS).forEach(function(name) {
// Create do, dont, etc. methods on Client // Create do, dont, etc. methods on Client
['do', 'dont', 'will', 'wont'].forEach(function(command) { ['do', 'dont', 'will', 'wont'].forEach(function(command) {
var get = function() { const get = function() {
return new Command(command, this); return new Command(command, this);
}; };
@ -784,13 +773,12 @@ util.inherits(TelnetServerModule, ServerModule);
TelnetServerModule.prototype.createServer = function() { TelnetServerModule.prototype.createServer = function() {
TelnetServerModule.super_.prototype.createServer.call(this); TelnetServerModule.super_.prototype.createServer.call(this);
var server = net.createServer(function onConnection(sock) { const server = net.createServer( (sock) => {
var self = this; const client = new TelnetClient(sock, sock);
var client = new TelnetClient(sock, sock);
client.banner(); client.banner();
self.emit('client', client, sock); server.emit('client', client, sock);
}); });
return server; return server;