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 ) ;
2016-04-19 20:21:30 -06:00
/ *
* /
2016-04-08 01:35:38 -06:00
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:35:38 -06:00
_this . pollCount = 0 ;
2016-04-28 13:39:14 -06:00
_this . maxPollCount = conf . maxPollCount || 30 ;
2016-04-08 19:35:38 -06:00
_this . pollTimeout = 50 ;
2016-04-08 19:32:09 -06:00
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-19 20:21:30 -06:00
_this . connect ( conf ) ;
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-19 20:21:30 -06:00
/ *
* /
2016-04-08 01:35:38 -06:00
_createClass ( AutoSSH , [ {
2016-04-19 20:21:30 -06:00
key : 'connect' ,
value : function connect ( conf ) {
2016-04-08 19:32:09 -06:00
var _this2 = this ;
2016-04-19 20:21:30 -06:00
var port = this . localPort === 'auto' ? this . generateRandomPort ( ) : this . localPort ;
_portfinder2 . default . getPort ( { port : port } , function ( err , freePort ) {
if ( err ) return _this2 . emit ( 'error' , 'Port error: ' + err ) ;
if ( _this2 . localPort !== 'auto' && _this2 . localPort !== freePort ) return _this2 . emit ( 'error' , 'Port ' + _this2 . localPort + ' is not available' ) ;
_this2 . localPort = freePort ;
// creates tunnel and then polls port until connection is established
_this2 . execTunnel ( function ( ) {
_this2 . pollConnection ( ) ;
} ) ;
} ) ;
}
/ * f i r e d w h e n c o n n e c t i o n e s t a b l i s h e d
* /
} , {
key : 'emitConnect' ,
value : function emitConnect ( ) {
this . emit ( 'connect' , {
kill : this . kill ,
pid : this . currentProcess . pid ,
host : this . host ,
username : this . username ,
remotePort : this . remotePort ,
localPort : this . localPort
} ) ;
}
/ * s t a r t s p o l l i n g t h e p o r t t o s e e i f c o n n e c t i o n e s t a b l i s h e d
* /
} , {
key : 'pollConnection' ,
value : function pollConnection ( ) {
var _this3 = this ;
2016-04-28 13:39:14 -06:00
if ( this . maxPollCount && this . pollCount >= this . maxPollCount ) {
2016-04-08 19:35:38 -06:00
this . emit ( 'error' , 'Max poll count reached. Aborting...' ) ;
2016-04-08 19:32:09 -06:00
return this . kill ( ) ;
}
this . isConnectionEstablished ( function ( result ) {
2016-04-19 20:21:30 -06:00
if ( result ) return _this3 . emitConnect ( ) ;
2016-04-08 19:32:09 -06:00
setTimeout ( function ( ) {
2016-04-19 20:21:30 -06:00
_this3 . pollCount ++ ;
_this3 . pollConnection ( ) ;
} , _this3 . pollTimeout ) ;
2016-04-08 19:32:09 -06:00
} ) ;
}
2016-04-19 20:21:30 -06:00
/ * c h e c k s i f c o n n e c t i o n i s e s t a b l i s h e d a t p o r t
* /
2016-04-08 19:32:09 -06:00
} , {
key : 'isConnectionEstablished' ,
value : function isConnectionEstablished ( cb ) {
2016-04-19 20:21:30 -06:00
var _this4 = this ;
2016-04-08 19:32:09 -06:00
_portfinder2 . default . getPort ( { port : this . localPort } , function ( err , freePort ) {
if ( err ) return cb ( false ) ;
2016-04-19 20:21:30 -06:00
if ( _this4 . localPort === freePort ) return cb ( false ) ; else return cb ( true ) ;
2016-04-08 19:32:09 -06:00
} ) ;
}
2016-04-19 20:21:30 -06:00
/ * p a r s e s t h e c o n f f o r e r r o r s
* /
2016-04-08 19:32:09 -06:00
} , {
2016-04-08 18:25:08 -06:00
key : 'getConfErrors' ,
value : function getConfErrors ( conf ) {
var errors = [ ] ;
2016-04-19 20:21:30 -06:00
2016-04-08 18:25:08 -06:00
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-19 20:21:30 -06:00
/ *
* /
2016-04-08 18:25:08 -06:00
} , {
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-19 20:21:30 -06:00
/ *
* /
2016-04-08 14:28:58 -06:00
} , {
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 ;
}
2016-04-19 20:21:30 -06:00
/ *
* /
2016-04-08 18:25:08 -06:00
} , {
key : 'execTunnel' ,
value : function execTunnel ( cb ) {
2016-04-19 20:21:30 -06:00
var _this5 = 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-19 20:21:30 -06:00
_this5 . kill ( ) ;
return _this5 . emit ( 'error' , stderr ) ;
2016-04-08 01:35:38 -06:00
}
2016-04-07 19:22:13 -06:00
2016-04-19 20:21:30 -06:00
if ( err ) _this5 . emit ( 'error' , err ) ;
2016-04-07 19:22:13 -06:00
2016-04-19 20:21:30 -06:00
if ( ! _this5 . killed ) _this5 . 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
} ) ;
}
2016-04-19 20:21:30 -06:00
/ *
* /
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 19:35:38 -06:00
/ * E x p o r t
* /
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 ;
} ;