Wait for TERMINAL-TYPE SB & respond with real underlying term type. Allows connections to other ENiGMA 1/2 boards!

This commit is contained in:
Bryan Ashby 2016-07-10 22:14:51 -06:00
parent dfb4f17c5f
commit f8b3727163
1 changed files with 48 additions and 6 deletions

View File

@ -1,13 +1,16 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
// ENiGMA½
const MenuModule = require('../core/menu_module.js').MenuModule; const MenuModule = require('../core/menu_module.js').MenuModule;
const resetScreen = require('../core/ansi_term.js').resetScreen; const resetScreen = require('../core/ansi_term.js').resetScreen;
// deps
const async = require('async'); const async = require('async');
const _ = require('lodash'); const _ = require('lodash');
const net = require('net'); const net = require('net');
const EventEmitter = require('events'); const EventEmitter = require('events');
const buffers = require('buffers');
/* /*
Expected configuration block: Expected configuration block:
@ -22,7 +25,6 @@ const EventEmitter = require('events');
} }
*/ */
// :TODO: BUG: When a client disconnects, it's not handled very well -- the log is spammed with tons of errors
// :TODO: ENH: Support nodeMax and tooManyArt // :TODO: ENH: Support nodeMax and tooManyArt
exports.getModule = TelnetBridgeModule; exports.getModule = TelnetBridgeModule;
@ -33,6 +35,8 @@ exports.moduleInfo = {
author : 'Andrew Pamment', author : 'Andrew Pamment',
}; };
const IAC_DO_TERM_TYPE = new Buffer( [ 255, 253, 24 ] );
class TelnetClientConnection extends EventEmitter { class TelnetClientConnection extends EventEmitter {
constructor(client) { constructor(client) {
super(); super();
@ -40,22 +44,36 @@ class TelnetClientConnection extends EventEmitter {
this.client = client; this.client = client;
} }
restorePipe() { restorePipe() {
this.client.term.output.unpipe(this.bridgeConnection); if(!this.pipeRestored) {
this.client.term.output.resume(); this.pipeRestored = true;
this.client.term.output.unpipe(this.bridgeConnection);
this.client.term.output.resume();
}
} }
connect(connectOpts) { connect(connectOpts) {
this.bridgeConnection = net.createConnection(connectOpts, () => { this.bridgeConnection = net.createConnection(connectOpts, () => {
this.emit('connected'); this.emit('connected');
this.pipeRestored = false;
this.client.term.output.pipe(this.bridgeConnection); this.client.term.output.pipe(this.bridgeConnection);
}); });
this.bridgeConnection.on('data', data => { this.bridgeConnection.on('data', data => {
// :TODO: The idea here is that we can handle |data| as if we're the client & respond to commands (cont.) this.client.term.rawWrite(data);
// ...the normal telnet *server* would not.
return this.client.term.rawWrite(data); //
// Wait for a terminal type request, and send it eactly once.
// This is enough (in additional to other negotiations handled in telnet.js)
// to get us in on most systems
//
if(!this.termSent && data.indexOf(IAC_DO_TERM_TYPE) > -1) {
this.termSent = true;
this.bridgeConnection.write(this.getTermTypeNegotiationBuffer());
}
}); });
this.bridgeConnection.once('end', () => { this.bridgeConnection.once('end', () => {
@ -75,6 +93,30 @@ class TelnetClientConnection extends EventEmitter {
} }
} }
getTermTypeNegotiationBuffer() {
//
// Create a TERMINAL-TYPE sub negotiation buffer using the
// actual/current terminal type.
//
let bufs = buffers();
bufs.push(new Buffer(
[
255, // IAC
250, // SB
24, // TERMINAL-TYPE
0, // IS
]
));
bufs.push(
new Buffer(this.client.term.termType), // e.g. "ansi"
new Buffer( [ 255, 240 ] ) // IAC, SE
);
return bufs.toBuffer();
}
} }