+47
-3
@@ -15,7 +15,8 @@ const DEFAULT_TIMEOUT_MS = 30000;
|
||||
const LOCAL_HOST = '127.0.0.1';
|
||||
|
||||
function parseArgs() {
|
||||
const args = process.argv.slice(2);
|
||||
// slice(1): when run as a bundled binary, argv is [binaryPath, ...cliArgs]; slice(2) would drop --key
|
||||
const args = process.argv.slice(1);
|
||||
let key = null;
|
||||
let remotePort = DEFAULT_REMOTE_PORT;
|
||||
let localPort = DEFAULT_LOCAL_PORT;
|
||||
@@ -43,6 +44,42 @@ function emit(line) {
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the port is accepting TCP connections before we report it.
|
||||
* Tries to connect to host:port; resolves when connect succeeds (then we close the socket).
|
||||
* Rejects on error or after timeoutMs.
|
||||
*/
|
||||
function waitUntilPortAccepting(host, port, timeoutMs = 10000, intervalMs = 200) {
|
||||
const deadline = Date.now() + timeoutMs;
|
||||
return new Promise((resolve, reject) => {
|
||||
function tryConnect() {
|
||||
if (Date.now() >= deadline) {
|
||||
reject(new Error('Port did not accept connections within ' + timeoutMs + 'ms'));
|
||||
return;
|
||||
}
|
||||
import('net').then((net) => {
|
||||
const socket = net.createConnection(
|
||||
{ port, host, allowHalfOpen: false },
|
||||
() => {
|
||||
socket.setTimeout(0);
|
||||
socket.destroy();
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
socket.on('error', () => {
|
||||
socket.destroy();
|
||||
setTimeout(tryConnect, intervalMs);
|
||||
});
|
||||
socket.setTimeout(intervalMs, () => {
|
||||
socket.destroy();
|
||||
setTimeout(tryConnect, intervalMs);
|
||||
});
|
||||
}).catch(reject);
|
||||
}
|
||||
tryConnect();
|
||||
});
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const mod = await import('holesail');
|
||||
const Holesail = mod.default || mod;
|
||||
@@ -70,12 +107,17 @@ async function run() {
|
||||
else resolve(port);
|
||||
};
|
||||
|
||||
const hs = new Holesail({
|
||||
const opts = {
|
||||
client: true,
|
||||
key,
|
||||
host: LOCAL_HOST,
|
||||
port: portToUse
|
||||
});
|
||||
};
|
||||
// If the Holesail API supports remotePort, tell it which port on the peer to use (e.g. 22 for SSH).
|
||||
if (remotePort > 0 && remotePort <= 65535) {
|
||||
opts.remotePort = remotePort;
|
||||
}
|
||||
const hs = new Holesail(opts);
|
||||
|
||||
if (typeof hs.on === 'function') {
|
||||
hs.on('error', (err) => {
|
||||
@@ -105,6 +147,8 @@ async function run() {
|
||||
try {
|
||||
const port = await readyPromise;
|
||||
hs = run._hs;
|
||||
// Verify the port is actually accepting connections before reporting it
|
||||
await waitUntilPortAccepting(LOCAL_HOST, port, 10000, 200);
|
||||
emit(JSON.stringify({ local_port: port, ready: true }));
|
||||
} catch (err) {
|
||||
const msg = (err && err.message) ? err.message : String(err);
|
||||
|
||||
Reference in New Issue
Block a user