2016-04-07 19:22:13 -06:00
'use strict' ;
2016-04-08 18:25:08 -06:00
var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol ? "symbol" : typeof obj ; } ;
2016-04-07 19:22:13 -06:00
var _createClass = function ( ) { function defineProperties ( target , props ) { for ( var i = 0 ; i < props . length ; i ++ ) { var descriptor = props [ i ] ; descriptor . enumerable = descriptor . enumerable || false ; descriptor . configurable = true ; if ( "value" in descriptor ) descriptor . writable = true ; Object . defineProperty ( target , descriptor . key , descriptor ) ; } } return function ( Constructor , protoProps , staticProps ) { if ( protoProps ) defineProperties ( Constructor . prototype , protoProps ) ; if ( staticProps ) defineProperties ( Constructor , staticProps ) ; return Constructor ; } ; } ( ) ;
var _child _process = require ( 'child_process' ) ;
var _events = require ( 'events' ) ;
2016-04-08 10:48:25 -06:00
var _portfinder = require ( 'portfinder' ) ;
var _portfinder2 = _interopRequireDefault ( _portfinder ) ;
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
2016-04-07 19:22:13 -06:00
function _classCallCheck ( instance , Constructor ) { if ( ! ( instance instanceof Constructor ) ) { throw new TypeError ( "Cannot call a class as a function" ) ; } }
function _possibleConstructorReturn ( self , call ) { if ( ! self ) { throw new ReferenceError ( "this hasn't been initialised - super() hasn't been called" ) ; } return call && ( typeof call === "object" || typeof call === "function" ) ? call : self ; }
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 ; }
2016-04-08 01:35:38 -06:00
/ * A u t o S S H c l a s s
* /
2016-04-07 19:22:13 -06:00
2016-04-08 01:35:38 -06:00
var AutoSSH = function ( _EventEmitter ) {
_inherits ( AutoSSH , _EventEmitter ) ;
function AutoSSH ( ) {
2016-04-07 19:22:13 -06:00
var conf = arguments . length <= 0 || arguments [ 0 ] === undefined ? { } : arguments [ 0 ] ;
2016-04-08 01:35:38 -06:00
_classCallCheck ( this , AutoSSH ) ;
2016-04-07 19:22:13 -06:00
2016-04-08 01:35:38 -06:00
var _this = _possibleConstructorReturn ( this , Object . getPrototypeOf ( AutoSSH ) . call ( this ) ) ;
2016-04-07 19:22:13 -06:00
_this . host = conf . host ;
2016-04-08 18:25:08 -06:00
_this . username = conf . username || 'root' ;
2016-04-07 19:22:13 -06:00
_this . remotePort = conf . remotePort ;
2016-04-08 18:25:08 -06:00
_this . localPort = conf . localPort || 'auto' ;
2016-04-07 19:22:13 -06:00
2016-04-08 19:32:09 -06:00
_this . debounceCount = 0 ;
_this . maxDebounceCount = 25 ;
_this . debounceTimeout = 50 ;
2016-04-07 19:22:13 -06:00
setImmediate ( function ( ) {
2016-04-08 18:25:08 -06:00
var confErrors = _this . getConfErrors ( conf ) ;
if ( confErrors . length ) return confErrors . forEach ( function ( err ) {
return _this . emit ( 'error' , err ) ;
} ) ;
2016-04-07 19:22:13 -06:00
2016-04-08 18:25:08 -06:00
var port = _this . localPort === 'auto' ? _this . generateRandomPort ( ) : _this . localPort ;
console . log ( 'checkpoint 1' ) ;
_portfinder2 . default . getPort ( { port : port } , function ( err , freePort ) {
2016-04-08 14:28:58 -06:00
if ( err ) return _this . emit ( 'error' , 'Port error: ' + err ) ;
if ( _this . localPort !== 'auto' && _this . localPort !== freePort ) return _this . emit ( 'error' , 'Port ' + _this . localPort + ' is not available' ) ;
_this . localPort = freePort ;
2016-04-08 18:25:08 -06:00
_this . execTunnel ( function ( ) {
2016-04-08 19:32:09 -06:00
_this . debounceConnection ( function ( ) {
_this . emit ( 'connect' , {
kill : _this . kill ,
pid : _this . currentProcess . pid ,
host : _this . host ,
username : _this . username ,
remotePort : _this . remotePort ,
localPort : _this . localPort
} ) ;
2016-04-08 18:25:08 -06:00
} ) ;
2016-04-08 14:28:58 -06:00
} ) ;
} ) ;
2016-04-08 01:35:38 -06:00
} ) ;
process . on ( 'exit' , function ( ) {
_this . kill ( ) ;
2016-04-07 19:22:13 -06:00
} ) ;
return _this ;
}
2016-04-08 01:35:38 -06:00
_createClass ( AutoSSH , [ {
2016-04-08 19:32:09 -06:00
key : 'debounceConnection' ,
value : function debounceConnection ( cb ) {
var _this2 = this ;
if ( this . debounceCount >= this . maxDebounceCount ) {
this . emit ( 'error' , 'Max debounce count reached. Aborting...' ) ;
return this . kill ( ) ;
}
this . isConnectionEstablished ( function ( result ) {
if ( result ) return cb ( ) ;
console . log ( 'Not Ready... Debounce!!!' ) ;
setTimeout ( function ( ) {
_this2 . debounceCount ++ ;
_this2 . debounceConnection ( cb ) ;
} , _this2 . debounceTimeout ) ;
} ) ;
}
} , {
key : 'isConnectionEstablished' ,
value : function isConnectionEstablished ( cb ) {
var _this3 = this ;
_portfinder2 . default . getPort ( { port : this . localPort } , function ( err , freePort ) {
if ( err ) return cb ( false ) ;
if ( _this3 . localPort === freePort ) return cb ( false ) ; else return cb ( true ) ;
} ) ;
}
} , {
2016-04-08 18:25:08 -06:00
key : 'getConfErrors' ,
value : function getConfErrors ( conf ) {
var errors = [ ] ;
if ( ! conf . localPort ) errors . push ( 'Missing localPort' ) ; else if ( typeof conf . localPort !== 'number' && conf . localPort !== 'auto' ) errors . push ( 'Invalid localPort' ) ;
if ( ! conf . host ) errors . push ( 'Missing host' ) ; else if ( typeof conf . host !== 'string' ) errors . push ( 'host must be type "string". was given ' + _typeof ( conf . host ) ) ;
if ( ! conf . username ) errors . push ( 'Missing username' ) ; else if ( typeof conf . username !== 'string' ) errors . push ( 'username must be type "string". was given ' + _typeof ( conf . username ) ) ;
if ( ! conf . remotePort ) errors . push ( 'Missing remotePort' ) ; else if ( typeof conf . remotePort !== 'number' ) errors . push ( 'remotePort must be type "number". was given ' + _typeof ( conf . remotePort ) ) ;
return errors ;
}
} , {
2016-04-08 14:28:58 -06:00
key : 'generateRandomPort' ,
value : function generateRandomPort ( ) {
var minPort = 3000 ;
var maxPort = 65535 ;
return Math . floor ( Math . random ( ) * ( maxPort - minPort + 1 ) ) + minPort ;
}
} , {
2016-04-08 18:25:08 -06:00
key : 'generateExecString' ,
value : function generateExecString ( ) {
2016-04-08 01:35:38 -06:00
var bindAddress = this . localPort + ':localhost:' + this . remotePort ;
var userAtHost = this . username + '@' + this . host ;
var exitOnFailure = '-o "ExitOnForwardFailure yes"' ;
2016-04-08 18:25:08 -06:00
return 'ssh -NL ' + bindAddress + ' ' + exitOnFailure + ' ' + userAtHost ;
}
} , {
key : 'execTunnel' ,
value : function execTunnel ( cb ) {
2016-04-08 19:32:09 -06:00
var _this4 = this ;
2016-04-08 14:28:58 -06:00
2016-04-08 18:25:08 -06:00
this . currentProcess = ( 0 , _child _process . exec ) ( this . generateExecString ( ) , function ( err , stdout , stderr ) {
2016-04-08 01:35:38 -06:00
if ( /Address already in use/i . test ( stderr ) ) {
2016-04-08 19:32:09 -06:00
_this4 . kill ( ) ;
return _this4 . emit ( 'error' , stderr ) ;
2016-04-08 01:35:38 -06:00
}
2016-04-07 19:22:13 -06:00
2016-04-08 19:32:09 -06:00
if ( err ) _this4 . emit ( 'error' , err ) ;
2016-04-07 19:22:13 -06:00
2016-04-08 19:32:09 -06:00
if ( ! _this4 . killed ) _this4 . execTunnel ( function ( ) {
2016-04-08 18:25:08 -06:00
return console . log ( 'Restarting autossh...' ) ;
} ) ;
} ) ;
if ( typeof cb === 'function' ) setImmediate ( function ( ) {
return cb ( ) ;
2016-04-07 19:22:13 -06:00
} ) ;
}
} , {
key : 'kill' ,
value : function kill ( ) {
this . killed = true ;
2016-04-08 18:25:08 -06:00
if ( this . currentProcess && typeof this . currentProcess . kill === 'function' ) this . currentProcess . kill ( ) ;
2016-04-07 19:22:13 -06:00
return this ;
}
} ] ) ;
2016-04-08 01:35:38 -06:00
return AutoSSH ;
2016-04-07 19:22:13 -06:00
} ( _events . EventEmitter ) ;
2016-04-08 18:25:08 -06:00
module . exports = function ( conf ) {
var autossh = new AutoSSH ( conf ) ;
/ * C r e a t e i n t e r f a c e o b j e c t
A new object creates an abstraction from class implementation
* /
var autosshInterface = {
2016-04-08 01:35:38 -06:00
on : function on ( evt ) {
for ( var _len = arguments . length , args = Array ( _len > 1 ? _len - 1 : 0 ) , _key = 1 ; _key < _len ; _key ++ ) {
args [ _key - 1 ] = arguments [ _key ] ;
}
2016-04-08 18:25:08 -06:00
autossh . on . apply ( autossh , [ evt ] . concat ( args ) ) ;
2016-04-08 01:35:38 -06:00
return this ;
} ,
kill : function kill ( ) {
2016-04-08 18:25:08 -06:00
autossh . kill ( ) ;
2016-04-08 01:35:38 -06:00
return this ;
}
} ;
2016-04-08 18:25:08 -06:00
Object . defineProperty ( autosshInterface , 'pid' , {
2016-04-08 01:35:38 -06:00
get : function get ( ) {
2016-04-08 18:25:08 -06:00
return autossh . currentProcess . pid ;
2016-04-08 01:35:38 -06:00
}
} ) ;
2016-04-07 19:22:13 -06:00
2016-04-08 18:25:08 -06:00
return autosshInterface ;
} ;