Skip to content

Commit 8d325d1

Browse files
committed
Merge pull request #149 from shirish87/fix_partial_bin
Verify downloaded binary before attempting to start tunnel
2 parents c1d5c76 + 0ede6e1 commit 8d325d1

File tree

1 file changed

+75
-1
lines changed

1 file changed

+75
-1
lines changed

lib/local.js

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,81 @@ var Tunnel = function Tunnel(key, port, uniqueIdentifier, callback) {
8989
return options;
9090
}
9191

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 = /version\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) {
93167
if (exists) {
94168
tunnelLauncher();
95169
return;

0 commit comments

Comments
 (0)