diff --git a/.eslint.log b/.eslint.log index 8b13789..c2cf947 100644 --- a/.eslint.log +++ b/.eslint.log @@ -1 +1,27 @@ +/home/hiro/Documents/Projects/autossh/src/index.js + 28:2 warning Expected indentation of 6 space characters but found 0 indent + 32:12 warning This function has too many statements (14). Maximum allowed is 12 max-statements + 68:12 warning Closing curly brace appears on the same line as the subsequent block brace-style + 142:12 warning Closing curly brace appears on the same line as the subsequent block brace-style + 274:5 warning Expected indentation of 2 space characters but found 4 indent + 275:2 warning Expected indentation of 6 space characters but found 0 indent + 276:2 warning Expected indentation of 6 space characters but found 0 indent + 276:23 warning Multiple spaces found before '&&' no-multi-spaces + 277:7 warning Expected indentation of 2 space characters but found 6 indent + 279:5 warning Expected indentation of 6 space characters but found 4 indent + 282:7 warning Expected indentation of 8 space characters but found 6 indent + 286:7 warning Expected indentation of 8 space characters but found 6 indent + 292:7 warning Expected indentation of 8 space characters but found 6 indent + 299:11 warning Closing curly brace appears on the same line as the subsequent block brace-style + 302:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 302:4 warning Expected indentation of 8 space characters but found 0 indent + 302:4 warning Unnecessary { after 'if' condition curly + 303:15 warning Expected indentation of 2 space characters but found 14 indent + 304:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 305:5 warning Expected indentation of 6 space characters but found 4 indent + 307:5 warning Expected indentation of 6 space characters but found 4 indent + 309:3 warning Expected indentation of 4 space characters but found 2 indent + +✖ 22 problems (2 errors, 20 warnings) + \ No newline at end of file diff --git a/index.js b/index.js index ff8cbbd..ce75ec1 100644 --- a/index.js +++ b/index.js @@ -21,12 +21,12 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* AutoSSH class -*/ + */ var AutoSSH = function (_EventEmitter) { _inherits(AutoSSH, _EventEmitter); /* - */ + */ function AutoSSH() { var conf = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; @@ -35,7 +35,6 @@ var AutoSSH = function (_EventEmitter) { var _this = _possibleConstructorReturn(this, (AutoSSH.__proto__ || Object.getPrototypeOf(AutoSSH)).call(this)); _this.configure(conf); - setImmediate(function () { var confErrors = _this.getConfErrors(conf); @@ -61,6 +60,7 @@ var AutoSSH = function (_EventEmitter) { this.username = conf.username || 'root'; this.remotePort = conf.remotePort; + this.autoRemote = conf.remotePort === 'auto'; if (this.reverse) this.localPort = parseInt(conf.localPort) || 22;else this.localPort = conf.localPort || 'auto'; @@ -77,7 +77,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'connect', @@ -90,7 +90,9 @@ var AutoSSH = function (_EventEmitter) { _this2.pollConnection(); }); } else { - _portfinder2.default.getPort({ port: port }, function (portfinderErr, freePort) { + _portfinder2.default.getPort({ + port: port + }, function (portfinderErr, freePort) { if (_this2.killed) return; if (portfinderErr) _this2.emit('error', 'Port error: ' + portfinderErr); if (_this2.localPort !== 'auto' && _this2.localPort !== freePort) _this2.emit('error', 'Port ' + _this2.localPort + ' is not available');else { @@ -105,7 +107,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'getConnectionInfo', @@ -133,7 +135,7 @@ var AutoSSH = function (_EventEmitter) { } /* fired when connection established - */ + */ }, { key: 'emitConnect', @@ -142,7 +144,7 @@ var AutoSSH = function (_EventEmitter) { } /* fired when timeout error occurs - */ + */ }, { key: 'emitTimeout', @@ -163,7 +165,7 @@ var AutoSSH = function (_EventEmitter) { } /* starts polling the port to see if connection established - */ + */ }, { key: 'pollConnection', @@ -188,7 +190,7 @@ var AutoSSH = function (_EventEmitter) { } /* checks if connection is established at port - */ + */ }, { key: 'isConnectionEstablished', @@ -200,7 +202,9 @@ var AutoSSH = function (_EventEmitter) { return; } - _portfinder2.default.getPort({ port: this.localPort }, function (portfinderErr, freePort) { + _portfinder2.default.getPort({ + port: this.localPort + }, function (portfinderErr, freePort) { if (portfinderErr) return connEstablishedCb(false); if (_this6.localPort === freePort) return connEstablishedCb(false);else return connEstablishedCb(true); @@ -210,7 +214,7 @@ var AutoSSH = function (_EventEmitter) { } /* parses the conf for errors - */ + */ }, { key: 'getConfErrors', @@ -227,7 +231,7 @@ var AutoSSH = function (_EventEmitter) { errors.push('username must be type "string". was given "' + _typeof(conf.username) + '"'); } - if (!conf.remotePort) errors.push('Missing remotePort');else if (isNaN(parseInt(conf.remotePort))) { + if (!conf.remotePort) errors.push('Missing remotePort');else if (isNaN(parseInt(conf.remotePort)) && !this.reverse && this.autoRemote) { errors.push('remotePort must be type "number". was given "' + _typeof(conf.remotePort) + '"'); } @@ -239,7 +243,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'generateRandomPort', @@ -250,7 +254,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'generateDefaultOptions', @@ -261,7 +265,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'generateServerAliveOptions', @@ -272,7 +276,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'generateExecOptions', @@ -287,7 +291,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'generateExecString', @@ -303,14 +307,18 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'execTunnel', value: function execTunnel(execTunnelCb) { var _this7 = this; + console.log(this.remotePort); + if (this.autoRemote && isNaN(this.remotePort)) this.remotePort = this.generateRandomPort(); + this.execString = this.generateExecString(); + this.currentProcess = (0, _child_process.exec)(this.execString, function (execErr, stdout, stderr) { if (_this7.killed) return; @@ -321,12 +329,19 @@ var AutoSSH = function (_EventEmitter) { } if (execErr) { - if (/(timeout)|(timed out)/i.test(stderr)) _this7.emitTimeout();else _this7.emit('error', execErr); + if (/(timeout)|(timed out)/i.test(stderr)) _this7.emitTimeout();else if (/remote port forwarding failed for listen/i.test(stderr) && _this7.autoRemote) { + _this7.execTunnel(function () { + return console.log('Trying another port...'); + }); + return; + } else _this7.emit('error', execErr); } - if (!_this7.killed) _this7.execTunnel(function () { - return console.log('Restarting autossh...'); - }); + if (!_this7.killed) { + _this7.execTunnel(function () { + return console.log('Restarting autossh...'); + }); + } }); if (typeof execTunnelCb === 'function') setImmediate(function () { @@ -335,7 +350,7 @@ var AutoSSH = function (_EventEmitter) { } /* - */ + */ }, { key: 'kill', @@ -350,14 +365,14 @@ var AutoSSH = function (_EventEmitter) { }(_events.EventEmitter); /* Export -*/ + */ module.exports = function (conf) { var autossh = new AutoSSH(conf); /* Create interface object - A new object creates an abstraction from class implementation + A new object creates an abstraction from class implementation */ var autosshInterface = { on: function on(evt) { diff --git a/src/index.js b/src/index.js index 6697dc0..ef0ce01 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,20 @@ -import { exec } from 'child_process'; -import { EventEmitter } from 'events'; +import { + exec +} from 'child_process'; +import { + EventEmitter +} from 'events'; import portfinder from 'portfinder'; /* AutoSSH class -*/ + */ class AutoSSH extends EventEmitter { /* - */ + */ constructor(conf = {}) { super(); this.configure(conf); - setImmediate(() => { const confErrors = this.getConfErrors(conf); @@ -22,7 +25,7 @@ class AutoSSH extends EventEmitter { }); process.on('exit', () => { - this.kill(); + this.kill(); }); } @@ -33,6 +36,7 @@ class AutoSSH extends EventEmitter { this.username = conf.username || 'root'; this.remotePort = conf.remotePort; + this.autoRemote = conf.remotePort === 'auto'; if (this.reverse) this.localPort = parseInt(conf.localPort) || 22; @@ -54,16 +58,17 @@ class AutoSSH extends EventEmitter { } /* - */ + */ connect(conf) { const port = this.localPort === 'auto' ? this.generateRandomPort() : this.localPort; if (this.reverse || this.localHost !== 'localhost') { this.execTunnel(() => { this.pollConnection(); }); - } - else { - portfinder.getPort({ port }, (portfinderErr, freePort) => { + } else { + portfinder.getPort({ + port + }, (portfinderErr, freePort) => { if (this.killed) return; if (portfinderErr) @@ -82,7 +87,7 @@ class AutoSSH extends EventEmitter { } /* - */ + */ getConnectionInfo() { const infoObj = { kill: () => this.kill, @@ -106,13 +111,13 @@ class AutoSSH extends EventEmitter { } /* fired when connection established - */ + */ emitConnect() { this.emit('connect', this.getConnectionInfo()); } /* fired when timeout error occurs - */ + */ emitTimeout() { this.emit('timeout', { kill: () => this.kill, @@ -126,7 +131,7 @@ class AutoSSH extends EventEmitter { } /* starts polling the port to see if connection established - */ + */ pollConnection() { if (this.killed) return; @@ -134,8 +139,7 @@ class AutoSSH extends EventEmitter { if (this.maxPollCount && this.pollCount >= this.maxPollCount) { this.emit('error', 'Max poll count reached. Aborting...'); this.kill(); - } - else { + } else { this.isConnectionEstablished(result => { if (result) this.emitConnect(); @@ -150,14 +154,16 @@ class AutoSSH extends EventEmitter { } /* checks if connection is established at port - */ + */ isConnectionEstablished(connEstablishedCb) { if (this.localHost !== 'localhost' || this.reverse) { connEstablishedCb(true); return; } - portfinder.getPort({ port: this.localPort }, (portfinderErr, freePort) => { + portfinder.getPort({ + port: this.localPort + }, (portfinderErr, freePort) => { if (portfinderErr) return connEstablishedCb(false); @@ -171,7 +177,7 @@ class AutoSSH extends EventEmitter { } /* parses the conf for errors - */ + */ getConfErrors(conf) { const errors = []; if (!conf.localPort) @@ -199,7 +205,7 @@ class AutoSSH extends EventEmitter { if (!conf.remotePort) errors.push('Missing remotePort'); - else if (isNaN(parseInt(conf.remotePort))) { + else if (isNaN(parseInt(conf.remotePort)) && (!this.reverse && this.autoRemote)) { errors.push( 'remotePort must be type "number". was given "' + typeof conf.remotePort + '"' ); @@ -215,7 +221,7 @@ class AutoSSH extends EventEmitter { } /* - */ + */ generateRandomPort() { const minPort = 3000; const maxPort = 65535; @@ -223,7 +229,7 @@ class AutoSSH extends EventEmitter { } /* - */ + */ generateDefaultOptions() { const exitOnFailure = '-o ExitOnForwardFailure=yes'; const strictHostCheck = `-o StrictHostKeyChecking=no`; @@ -231,7 +237,7 @@ class AutoSSH extends EventEmitter { } /* - */ + */ generateServerAliveOptions() { const serverAliveInterval = `-o ServerAliveInterval=${this.serverAliveInterval}`; const serverAliveCountMax = `-o ServerAliveCountMax=${this.serverAliveCountMax}`; @@ -239,7 +245,7 @@ class AutoSSH extends EventEmitter { } /* - */ + */ generateExecOptions() { const serverAliveOpts = this.generateServerAliveOptions(); const defaultOpts = this.generateDefaultOptions(); @@ -251,7 +257,7 @@ class AutoSSH extends EventEmitter { } /* - */ + */ generateExecString() { const startPort = this.reverse ? this.remotePort : this.localPort; const endPort = this.reverse ? this.localPort : this.remotePort; @@ -264,13 +270,19 @@ class AutoSSH extends EventEmitter { } /* - */ - execTunnel(execTunnelCb) { + */ + execTunnel(execTunnelCb) { + console.log(this.remotePort); + if (this.autoRemote && isNaN(this.remotePort)) + this.remotePort = this.generateRandomPort(); + this.execString = this.generateExecString(); - this.currentProcess = exec(this.execString, (execErr, stdout, stderr) => { + + this.currentProcess = exec(this.execString, (execErr, stdout, stderr) => { if (this.killed) return; + if (/Address already in use/i.test(stderr)) { this.kill(); this.emit('error', stderr); @@ -280,12 +292,16 @@ class AutoSSH extends EventEmitter { if (execErr) { if ((/(timeout)|(timed out)/i).test(stderr)) this.emitTimeout(); - else + else if (/remote port forwarding failed for listen/i.test(stderr) && this.autoRemote) { + this.execTunnel(() => console.log('Trying another port...')); + return; + } else this.emit('error', execErr); } - if (!this.killed) - this.execTunnel(() => console.log('Restarting autossh...')); + if (!this.killed) { + this.execTunnel(() => console.log('Restarting autossh...')); + } }); if (typeof execTunnelCb === 'function') @@ -293,7 +309,7 @@ class AutoSSH extends EventEmitter { } /* - */ + */ kill() { this.killed = true; if (this.currentProcess && typeof this.currentProcess.kill === 'function') @@ -304,12 +320,12 @@ class AutoSSH extends EventEmitter { /* Export -*/ + */ module.exports = function(conf) { const autossh = new AutoSSH(conf); /* Create interface object - A new object creates an abstraction from class implementation + A new object creates an abstraction from class implementation */ const autosshInterface = { on(evt, ...args) {