* Fix file transfer bug for WebSockets and SSH. Set/restore temp data handler belongs in base client.

* Lint some files
This commit is contained in:
Bryan Ashby 2018-05-12 09:33:41 -06:00
parent b2ae81c59e
commit 388e581b90
4 changed files with 57 additions and 53 deletions

View File

@ -100,6 +100,16 @@ function Client(/*input, output*/) {
}
});
this.setTemporaryDirectDataHandler = function(handler) {
this.input.removeAllListeners('data');
this.input.on('data', handler);
};
this.restoreDataHandler = function() {
this.input.removeAllListeners('data');
this.input.on('data', this.dataHandler);
};
//
// Peek at incoming |data| and emit events for any special

View File

@ -129,6 +129,10 @@ function SSHClient(clientConn) {
}
});
this.dataHandler = function(data) {
self.emit('data', data);
};
this.updateTermInfo = function(info) {
//
// From ssh2 docs:
@ -167,7 +171,7 @@ function SSHClient(clientConn) {
self.log.info('SSH authentication success');
clientConn.on('session', accept => {
const session = accept();
session.on('pty', function pty(accept, reject, info) {
@ -191,9 +195,7 @@ function SSHClient(clientConn) {
self.setInputOutput(channel.stdin, channel.stdout);
channel.stdin.on('data', data => {
self.emit('data', data);
});
channel.stdin.on('data', self.dataHandler);
if(self.cachedPtyInfo) {
self.updateTermInfo(self.cachedPtyInfo);
@ -207,7 +209,7 @@ function SSHClient(clientConn) {
session.on('window-change', (accept, reject, info) => {
self.log.debug(info, 'SSH window-change event');
self.updateTermInfo(info);
});
@ -237,13 +239,13 @@ exports.getModule = class SSHServerModule extends LoginServerModule {
hostKeys : [
{
key : fs.readFileSync(Config.loginServers.ssh.privateKeyPem),
passphrase : Config.loginServers.ssh.privateKeyPass,
passphrase : Config.loginServers.ssh.privateKeyPass,
}
],
ident : 'enigma-bbs-' + enigVersion + '-srv',
// Note that sending 'banner' breaks at least EtherTerm!
debug : (sshDebugLine) => {
debug : (sshDebugLine) => {
if(true === Config.loginServers.ssh.traceConnections) {
Log.trace(`SSH: ${sshDebugLine}`);
}

View File

@ -39,8 +39,8 @@ exports.TelnetClient = TelnetClient;
* Document OPTIONS -- add any missing
* Internally handle OPTIONS:
* Some should be emitted generically
* Some shoudl be handled internally -- denied, handled, etc.
*
* Some shoudl be handled internally -- denied, handled, etc.
*
* Allow term (ttype) to be set by environ sub negotiation
@ -67,7 +67,7 @@ const COMMANDS = {
EL : 248, // Erase Line
GA : 249, // Go Ahead
SB : 250, // Start Sub-Negotiation Parameters
WILL : 251, //
WILL : 251, //
WONT : 252,
DO : 253,
DONT : 254,
@ -101,7 +101,7 @@ const OPTIONS = {
TIMING_MARK : 6, // http://tools.ietf.org/html/rfc860
//RC_TRANS_AND_ECHO : 7, // aka 'RCTE' @ http://www.rfc-base.org/txt/rfc-726.txt
//OUPUT_LINE_WIDTH : 8,
//OUTPUT_PAGE_SIZE : 9, //
//OUTPUT_PAGE_SIZE : 9, //
//OUTPUT_CARRIAGE_RETURN_DISP : 10, // RFC 652
//OUTPUT_HORIZ_TABSTOPS : 11, // RFC 653
//OUTPUT_HORIZ_TAB_DISP : 12, // RFC 654
@ -195,15 +195,15 @@ function unknownOption(bufs, i, event) {
const OPTION_IMPLS = {};
// :TODO: fill in the rest...
OPTION_IMPLS.NO_ARGS =
OPTION_IMPLS[OPTIONS.ECHO] =
OPTION_IMPLS[OPTIONS.ECHO] =
OPTION_IMPLS[OPTIONS.STATUS] =
OPTION_IMPLS[OPTIONS.LINEMODE] =
OPTION_IMPLS[OPTIONS.TRANSMIT_BINARY] =
OPTION_IMPLS[OPTIONS.LINEMODE] =
OPTION_IMPLS[OPTIONS.TRANSMIT_BINARY] =
OPTION_IMPLS[OPTIONS.AUTHENTICATION] =
OPTION_IMPLS[OPTIONS.TERMINAL_SPEED] =
OPTION_IMPLS[OPTIONS.REMOTE_FLOW_CONTROL] =
OPTION_IMPLS[OPTIONS.X_DISPLAY_LOCATION] =
OPTION_IMPLS[OPTIONS.SEND_LOCATION] =
OPTION_IMPLS[OPTIONS.SEND_LOCATION] =
OPTION_IMPLS[OPTIONS.ARE_YOU_THERE] =
OPTION_IMPLS[OPTIONS.SUPPRESS_GO_AHEAD] = function(bufs, i, event) {
event.buf = bufs.splice(0, i).toBuffer();
@ -453,7 +453,7 @@ function parseCommand(bufs, i, event) {
}
event.buf = bufs.splice(0, 2).toBuffer();
return event;
return event;
}
}
@ -486,16 +486,6 @@ function TelnetClient(input, output) {
newEnvironRequested : false,
};
this.setTemporaryDirectDataHandler = function(handler) {
this.input.removeAllListeners('data');
this.input.on('data', handler);
};
this.restoreDataHandler = function() {
this.input.removeAllListeners('data');
this.input.on('data', this.dataHandler);
};
this.dataHandler = function(b) {
if(!Buffer.isBuffer(b)) {
EnigAssert(false, `Cannot push non-buffer ${typeof b}`);
@ -516,15 +506,15 @@ function TelnetClient(input, output) {
}
EnigAssert(bufs.length > (i + 1));
if(i > 0) {
self.emit('data', bufs.splice(0, i).toBuffer());
}
i = parseBufs(bufs);
if(MORE_DATA_REQUIRED === i) {
break;
break;
} else if(i) {
if(i.option) {
self.emit(i.option, i); // "transmit binary", "echo", ...
@ -589,7 +579,7 @@ util.inherits(TelnetClient, baseClient.Client);
// Telnet Command/Option handling
///////////////////////////////////////////////////////////////////////////////
TelnetClient.prototype.handleTelnetEvent = function(evt) {
if(!evt.command) {
return this.connectionWarn( { evt : evt }, 'No command for event');
}
@ -611,7 +601,7 @@ TelnetClient.prototype.handleWillCommand = function(evt) {
//
// See RFC 1091 @ http://www.faqs.org/rfcs/rfc1091.html
//
this.requestTerminalType();
this.requestTerminalType();
} else if('new environment' === evt.option) {
//
// See RFC 1572 @ http://www.faqs.org/rfcs/rfc1572.html
@ -630,7 +620,7 @@ TelnetClient.prototype.handleWontCommand = function(evt) {
this.sentDont[evt.option] = true;
if('new environment' === evt.option) {
if('new environment' === evt.option) {
this.dont.new_environment();
} else {
this.connectionTrace(evt, 'WONT');
@ -693,16 +683,16 @@ TelnetClient.prototype.handleSbCommand = function(evt) {
self.term.termHeight = parseInt(evt.envVars[name]);
self.clearMciCache(); // term size changes = invalidate cache
self.connectionDebug({ termHeight : self.term.termHeight, source : 'NEW-ENVIRON'}, 'Window height updated');
} else {
} else {
if(name in self.term.env) {
EnigAssert(
SB_COMMANDS.INFO === evt.type || SB_COMMANDS.IS === evt.type,
SB_COMMANDS.INFO === evt.type || SB_COMMANDS.IS === evt.type,
'Unexpected type: ' + evt.type
);
self.connectionWarn(
{ varName : name, value : evt.envVars[name], existingValue : self.term.env[name] },
{ varName : name, value : evt.envVars[name], existingValue : self.term.env[name] },
'Environment variable already exists'
);
} else {
@ -719,7 +709,7 @@ TelnetClient.prototype.handleSbCommand = function(evt) {
//
self.term.termWidth = evt.width;
self.term.termHeight = evt.height;
if(evt.width > 0) {
self.term.env.COLUMNS = evt.height;
}
@ -752,11 +742,11 @@ TelnetClient.prototype.handleMiscCommand = function(evt) {
if('ip' === evt.command) {
// Interrupt Process (IP)
this.log.debug('Interrupt Process (IP) - Ending');
this.input.end();
} else if('ayt' === evt.command) {
this.output.write('\b');
this.log.debug('Are You There (AYT) - Replied "\\b"');
} else if(IGNORED_COMMANDS.indexOf(evt.commandCode)) {
this.log.debug({ evt : evt }, 'Ignoring command');
@ -767,11 +757,11 @@ TelnetClient.prototype.handleMiscCommand = function(evt) {
TelnetClient.prototype.requestTerminalType = function() {
const buf = Buffer.from( [
COMMANDS.IAC,
COMMANDS.SB,
OPTIONS.TERMINAL_TYPE,
SB_COMMANDS.SEND,
COMMANDS.IAC,
COMMANDS.IAC,
COMMANDS.SB,
OPTIONS.TERMINAL_TYPE,
SB_COMMANDS.SEND,
COMMANDS.IAC,
COMMANDS.SE ]);
this.output.write(buf);
};
@ -790,15 +780,15 @@ TelnetClient.prototype.requestNewEnvironment = function() {
return;
}
const self = this;
const self = this;
const bufs = buffers();
bufs.push(Buffer.from( [
COMMANDS.IAC,
COMMANDS.SB,
OPTIONS.NEW_ENVIRONMENT,
COMMANDS.IAC,
COMMANDS.SB,
OPTIONS.NEW_ENVIRONMENT,
SB_COMMANDS.SEND ]
));
));
for(let i = 0; i < WANTED_ENVIRONMENT_VAR_BUFS.length; ++i) {
bufs.push(Buffer.from( [ NEW_ENVIRONMENT_COMMANDS.VAR ] ), WANTED_ENVIRONMENT_VAR_BUFS[i] );
@ -828,7 +818,7 @@ TelnetClient.prototype.banner = function() {
function Command(command, client) {
this.command = COMMANDS[command.toUpperCase()];
this.client = client;
this.client = client;
}
// Create Command objects with echo, transmit_binary, ...

View File

@ -30,6 +30,10 @@ function WebSocketClient(ws, req, serverType) {
const self = this;
this.dataHandler = function(data) {
self.socketBridge.emit('data', data);
};
//
// This bridge makes accessible various calls that client sub classes
// want to access on I/O socket
@ -65,9 +69,7 @@ function WebSocketClient(ws, req, serverType) {
}
}(ws);
ws.on('message', data => {
this.socketBridge.emit('data', data);
});
ws.on('message', this.dataHandler);
ws.on('close', () => {
// we'll remove client connection which will in turn end() via our SocketBridge above