@@ -89,7 +89,81 @@ var Tunnel = function Tunnel(key, port, uniqueIdentifier, callback) {
89
89
return options ;
90
90
}
91
91
92
- fs . exists ( localBinary , function ( exists ) {
92
+ function runTunnelCmd ( tunnelOptions , subProcessTimeout , processOutputHook , callback ) {
93
+ var isRunning , subProcess , timeoutHandle ;
94
+
95
+ var callbackOnce = function ( err , result ) {
96
+ clearTimeout ( timeoutHandle ) ;
97
+ if ( subProcess && isRunning ) {
98
+ try {
99
+ process . kill ( subProcess . pid , 'SIGKILL' ) ;
100
+ subProcess = null ;
101
+ } catch ( e ) {
102
+ logger . debug ( '[%s] failed to kill process:' , new Date ( ) , e ) ;
103
+ }
104
+ }
105
+
106
+ callback && callback ( err , result ) ;
107
+ callback = null ;
108
+ } ;
109
+
110
+ isRunning = true ;
111
+
112
+ try {
113
+ subProcess = exec ( localBinary , tunnelOptions , function ( error , stdout ) {
114
+ isRunning = false ;
115
+
116
+ if ( error ) {
117
+ callbackOnce ( new Error ( 'failed to get process output: ' + error ) ) ;
118
+ } else if ( stdout ) {
119
+ processOutputHook ( stdout , callbackOnce ) ;
120
+ }
121
+ } ) ;
122
+
123
+ subProcess . stdout . on ( 'data' , function ( data ) {
124
+ processOutputHook ( data , callbackOnce ) ;
125
+ } ) ;
126
+ } catch ( e ) {
127
+ // Handles EACCESS and other errors when binary file exists,
128
+ // but doesn't have necessary permissions (among other issues)
129
+ callbackOnce ( new Error ( 'failed to get process output: ' + e ) ) ;
130
+ }
131
+
132
+ if ( subProcessTimeout > 0 ) {
133
+ timeoutHandle = setTimeout ( function ( ) {
134
+ callbackOnce ( new Error ( 'failed to get process output: command timeout' ) ) ;
135
+ } , subProcessTimeout ) ;
136
+ }
137
+ }
138
+
139
+ function getTunnelBinaryVersion ( callback ) {
140
+ var subProcessTimeout = 3000 ;
141
+
142
+ runTunnelCmd ( [ '-version' ] , subProcessTimeout , function ( data , done ) {
143
+ var matches = / v e r s i o n \s + ( \d + ( \. \d + ) * ) / . exec ( data ) ;
144
+ var version = ( matches && matches . length > 2 ) && matches [ 1 ] ;
145
+ logger . debug ( '[%s] Tunnel binary: found version' , new Date ( ) , version ) ;
146
+
147
+ done ( isFinite ( version ) ? null : new Error ( 'failed to get binary version' ) , parseFloat ( version ) ) ;
148
+ } , callback ) ;
149
+ }
150
+
151
+ function verifyTunnelBinary ( callback ) {
152
+ logger . debug ( '[%s] Verifying tunnel binary' , new Date ( ) ) ;
153
+
154
+ fs . exists ( localBinary , function ( exists ) {
155
+ if ( ! exists ) {
156
+ logger . debug ( '[%s] Verifying tunnel binary: file does not exist' , new Date ( ) ) ;
157
+ callback ( false ) ;
158
+ } else {
159
+ getTunnelBinaryVersion ( function ( err , version ) {
160
+ callback ( ! err && isFinite ( version ) ) ;
161
+ } ) ;
162
+ }
163
+ } ) ;
164
+ }
165
+
166
+ verifyTunnelBinary ( function ( exists ) {
93
167
if ( exists ) {
94
168
tunnelLauncher ( ) ;
95
169
return ;
0 commit comments