// Generated by CoffeeScript 2.6.1 (function() { // telnetInput.coffee // Copyright 2017 Patrick Meade. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . //---------------------------------------------------------------------------- var DEFAULT_SUBNEGOTIATION_BUFFER_SIZE, DEFAULT_SUBNEGOTIATION_ERROR_POLICY, TELNET_COMMAND, TELNET_DATA, TELNET_DO, TELNET_DONT, TELNET_IAC, TELNET_OPTION, TELNET_SUBNEG, TELNET_SUBNEG_COMMAND, TELNET_SUB_BEGIN, TELNET_SUB_END, TELNET_WILL, TELNET_WONT, TelnetInput, Transform; DEFAULT_SUBNEGOTIATION_BUFFER_SIZE = 8192; DEFAULT_SUBNEGOTIATION_ERROR_POLICY = "keepBoth"; TELNET_COMMAND = "TELNET_COMMAND"; TELNET_DATA = "TELNET_DATA"; TELNET_OPTION = "TELNET_OPTION"; TELNET_SUBNEG = "TELNET_SUBNEG"; TELNET_SUBNEG_COMMAND = "TELNET_SUBNEG_COMMAND"; TELNET_DO = 253; TELNET_DONT = 254; TELNET_IAC = 255; TELNET_SUB_BEGIN = 250; TELNET_SUB_END = 240; TELNET_WILL = 251; TELNET_WONT = 252; ({Transform} = require("stream")); TelnetInput = class TelnetInput extends Transform { constructor(opt) { var options; options = opt || {}; super(options); this.state = TELNET_DATA; this.subBufSize = options.bufferSize || DEFAULT_SUBNEGOTIATION_BUFFER_SIZE; this.subBuf = Buffer.alloc(this.subBufSize); this.errorPolicy = options.errorPolicy || DEFAULT_SUBNEGOTIATION_ERROR_POLICY; } _transform(chunk, encoding, callback) { var byte, i, len; this.dataBuf = Buffer.alloc(chunk.length * 2); this.dataBufIndex = 0; for (i = 0, len = chunk.length; i < len; i++) { byte = chunk[i]; this._handle(byte); } if (this.dataBufIndex > 0) { this.push(this.dataBuf.slice(0, this.dataBufIndex)); } return callback(); } _handle(chunkData) { switch (this.state) { case TELNET_DATA: switch (chunkData) { case TELNET_IAC: return this.state = TELNET_COMMAND; default: this.dataBuf[this.dataBufIndex] = chunkData; return this.dataBufIndex++; } break; case TELNET_COMMAND: switch (chunkData) { case TELNET_IAC: this.state = TELNET_DATA; this.dataBuf[this.dataBufIndex] = TELNET_IAC; return this.dataBufIndex++; case TELNET_DO: case TELNET_DONT: case TELNET_WILL: case TELNET_WONT: case TELNET_SUB_BEGIN: this.state = TELNET_OPTION; return this.command = chunkData; default: this.state = TELNET_DATA; return this.emit("command", chunkData); } break; case TELNET_OPTION: switch (this.command) { case TELNET_DO: this.state = TELNET_DATA; return this.emit("do", chunkData); case TELNET_DONT: this.state = TELNET_DATA; return this.emit("dont", chunkData); case TELNET_WILL: this.state = TELNET_DATA; return this.emit("will", chunkData); case TELNET_WONT: this.state = TELNET_DATA; return this.emit("wont", chunkData); case TELNET_SUB_BEGIN: this.state = TELNET_SUBNEG; this.option = chunkData; this.subBufIndex = 0; return this.subOverflowEmit = false; } break; case TELNET_SUBNEG: switch (chunkData) { case TELNET_IAC: return this.state = TELNET_SUBNEG_COMMAND; default: return this._handleSub(chunkData); } break; case TELNET_SUBNEG_COMMAND: switch (chunkData) { case TELNET_IAC: this.state = TELNET_SUBNEG; return this._handleSub(TELNET_IAC); case TELNET_SUB_END: this.state = TELNET_DATA; return this.emit("sub", this.option, this.subBuf.slice(0, this.subBufIndex)); default: this.state = TELNET_SUBNEG; this.emit("error", new Error("expected IAC or SE")); switch (this.errorPolicy) { case "discardBoth": break; case "keepData": return this._handleSub(chunkData); default: // "keepBoth" this._handleSub(TELNET_IAC); return this._handleSub(chunkData); } } } } _handleSub(subByte) { if (this.subBufIndex >= this.subBufSize) { if (!this.subOverflowEmit) { this.subOverflowEmit = true; this.emit("error", new Error("subnegotiation buffer overflow")); } return; } this.subBuf[this.subBufIndex] = subByte; return this.subBufIndex++; } }; exports.TelnetInput = TelnetInput; //---------------------------------------------------------------------------- // end of telnetInput.coffee }).call(this);