150 lines
18 KiB
JavaScript
150 lines
18 KiB
JavaScript
|
|
"use strict";
|
||
|
|
|
||
|
|
Object.defineProperty(exports, "__esModule", {
|
||
|
|
value: true
|
||
|
|
});
|
||
|
|
exports.connectInParallel = connectInParallel;
|
||
|
|
exports.connectInSequence = connectInSequence;
|
||
|
|
exports.lookupAllAddresses = lookupAllAddresses;
|
||
|
|
var _net = _interopRequireDefault(require("net"));
|
||
|
|
var _nodeUrl = _interopRequireDefault(require("node:url"));
|
||
|
|
var _abortError = _interopRequireDefault(require("./errors/abort-error"));
|
||
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
async function connectInParallel(options, lookup, signal) {
|
||
|
|
if (signal.aborted) {
|
||
|
|
throw new _abortError.default();
|
||
|
|
}
|
||
|
|
const addresses = await lookupAllAddresses(options.host, lookup, signal);
|
||
|
|
return await new Promise((resolve, reject) => {
|
||
|
|
const sockets = new Array(addresses.length);
|
||
|
|
const errors = [];
|
||
|
|
function onError(err) {
|
||
|
|
errors.push(err);
|
||
|
|
this.removeListener('error', onError);
|
||
|
|
this.removeListener('connect', onConnect);
|
||
|
|
this.destroy();
|
||
|
|
if (errors.length === addresses.length) {
|
||
|
|
signal.removeEventListener('abort', onAbort);
|
||
|
|
reject(new AggregateError(errors, 'Could not connect (parallel)'));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function onConnect() {
|
||
|
|
signal.removeEventListener('abort', onAbort);
|
||
|
|
for (let j = 0; j < sockets.length; j++) {
|
||
|
|
const socket = sockets[j];
|
||
|
|
if (this === socket) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
socket.removeListener('error', onError);
|
||
|
|
socket.removeListener('connect', onConnect);
|
||
|
|
socket.destroy();
|
||
|
|
}
|
||
|
|
resolve(this);
|
||
|
|
}
|
||
|
|
const onAbort = () => {
|
||
|
|
for (let j = 0; j < sockets.length; j++) {
|
||
|
|
const socket = sockets[j];
|
||
|
|
socket.removeListener('error', onError);
|
||
|
|
socket.removeListener('connect', onConnect);
|
||
|
|
socket.destroy();
|
||
|
|
}
|
||
|
|
reject(new _abortError.default());
|
||
|
|
};
|
||
|
|
for (let i = 0, len = addresses.length; i < len; i++) {
|
||
|
|
const socket = sockets[i] = _net.default.connect({
|
||
|
|
...options,
|
||
|
|
host: addresses[i].address,
|
||
|
|
family: addresses[i].family
|
||
|
|
});
|
||
|
|
socket.on('error', onError);
|
||
|
|
socket.on('connect', onConnect);
|
||
|
|
}
|
||
|
|
signal.addEventListener('abort', onAbort, {
|
||
|
|
once: true
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
async function connectInSequence(options, lookup, signal) {
|
||
|
|
if (signal.aborted) {
|
||
|
|
throw new _abortError.default();
|
||
|
|
}
|
||
|
|
const errors = [];
|
||
|
|
const addresses = await lookupAllAddresses(options.host, lookup, signal);
|
||
|
|
for (const address of addresses) {
|
||
|
|
try {
|
||
|
|
return await new Promise((resolve, reject) => {
|
||
|
|
const socket = _net.default.connect({
|
||
|
|
...options,
|
||
|
|
host: address.address,
|
||
|
|
family: address.family
|
||
|
|
});
|
||
|
|
const onAbort = () => {
|
||
|
|
socket.removeListener('error', onError);
|
||
|
|
socket.removeListener('connect', onConnect);
|
||
|
|
socket.destroy();
|
||
|
|
reject(new _abortError.default());
|
||
|
|
};
|
||
|
|
const onError = err => {
|
||
|
|
signal.removeEventListener('abort', onAbort);
|
||
|
|
socket.removeListener('error', onError);
|
||
|
|
socket.removeListener('connect', onConnect);
|
||
|
|
socket.destroy();
|
||
|
|
reject(err);
|
||
|
|
};
|
||
|
|
const onConnect = () => {
|
||
|
|
signal.removeEventListener('abort', onAbort);
|
||
|
|
socket.removeListener('error', onError);
|
||
|
|
socket.removeListener('connect', onConnect);
|
||
|
|
resolve(socket);
|
||
|
|
};
|
||
|
|
signal.addEventListener('abort', onAbort, {
|
||
|
|
once: true
|
||
|
|
});
|
||
|
|
socket.on('error', onError);
|
||
|
|
socket.on('connect', onConnect);
|
||
|
|
});
|
||
|
|
} catch (err) {
|
||
|
|
if (err instanceof Error && err.name === 'AbortError') {
|
||
|
|
throw err;
|
||
|
|
}
|
||
|
|
errors.push(err);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
throw new AggregateError(errors, 'Could not connect (sequence)');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Look up all addresses for the given hostname.
|
||
|
|
*/
|
||
|
|
async function lookupAllAddresses(host, lookup, signal) {
|
||
|
|
if (signal.aborted) {
|
||
|
|
throw new _abortError.default();
|
||
|
|
}
|
||
|
|
if (_net.default.isIPv6(host)) {
|
||
|
|
return [{
|
||
|
|
address: host,
|
||
|
|
family: 6
|
||
|
|
}];
|
||
|
|
} else if (_net.default.isIPv4(host)) {
|
||
|
|
return [{
|
||
|
|
address: host,
|
||
|
|
family: 4
|
||
|
|
}];
|
||
|
|
} else {
|
||
|
|
return await new Promise((resolve, reject) => {
|
||
|
|
const onAbort = () => {
|
||
|
|
reject(new _abortError.default());
|
||
|
|
};
|
||
|
|
signal.addEventListener('abort', onAbort);
|
||
|
|
const domainInASCII = _nodeUrl.default.domainToASCII(host);
|
||
|
|
lookup(domainInASCII === '' ? host : domainInASCII, {
|
||
|
|
all: true
|
||
|
|
}, (err, addresses) => {
|
||
|
|
signal.removeEventListener('abort', onAbort);
|
||
|
|
err ? reject(err) : resolve(addresses);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbmV0IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfbm9kZVVybCIsIl9hYm9ydEVycm9yIiwib2JqIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJjb25uZWN0SW5QYXJhbGxlbCIsIm9wdGlvbnMiLCJsb29rdXAiLCJzaWduYWwiLCJhYm9ydGVkIiwiQWJvcnRFcnJvciIsImFkZHJlc3NlcyIsImxvb2t1cEFsbEFkZHJlc3NlcyIsImhvc3QiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsInNvY2tldHMiLCJBcnJheSIsImxlbmd0aCIsImVycm9ycyIsIm9uRXJyb3IiLCJlcnIiLCJwdXNoIiwicmVtb3ZlTGlzdGVuZXIiLCJvbkNvbm5lY3QiLCJkZXN0cm95IiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsIm9uQWJvcnQiLCJBZ2dyZWdhdGVFcnJvciIsImoiLCJzb2NrZXQiLCJpIiwibGVuIiwibmV0IiwiY29ubmVjdCIsImFkZHJlc3MiLCJmYW1pbHkiLCJvbiIsImFkZEV2ZW50TGlzdGVuZXIiLCJvbmNlIiwiY29ubmVjdEluU2VxdWVuY2UiLCJFcnJvciIsIm5hbWUiLCJpc0lQdjYiLCJpc0lQdjQiLCJkb21haW5JbkFTQ0lJIiwidXJsIiwiZG9tYWluVG9BU0NJSSIsImFsbCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25uZWN0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5ldCBmcm9tICduZXQnO1xuaW1wb3J0IGRucywgeyB0eXBlIExvb2t1cEFkZHJlc3MgfSBmcm9tICdkbnMnO1xuXG5pbXBvcnQgdXJsIGZyb20gJ25vZGU6dXJsJztcbmltcG9ydCBBYm9ydEVycm9yIGZyb20gJy4vZXJyb3JzL2Fib3J0LWVycm9yJztcblxudHlwZSBMb29rdXBGdW5jdGlvbiA9IChob3N0bmFtZTogc3RyaW5nLCBvcHRpb25zOiBkbnMuTG9va3VwQWxsT3B0aW9ucywgY2FsbGJhY2s6IChlcnI6IE5vZGVKUy5FcnJub0V4Y2VwdGlvbiB8IG51bGwsIGFkZHJlc3NlczogZG5zLkxvb2t1cEFkZHJlc3NbXSkgPT4gdm9pZCkgPT4gdm9pZDtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbm5lY3RJblBhcmFsbGVsKG9wdGlvbnM6IHsgaG9zdDogc3RyaW5nLCBwb3J0OiBudW1iZXIsIGxvY2FsQWRkcmVzcz86IHN0cmluZyB8IHVuZGVmaW5lZCB9LCBsb29rdXA6IExvb2t1cEZ1bmN0aW9uLCBzaWduYWw6IEFib3J0U2lnbmFsKSB7XG4gIGlmIChzaWduYWwuYWJvcnRlZCkge1xuICAgIHRocm93IG5ldyBBYm9ydEVycm9yKCk7XG4gIH1cblxuICBjb25zdCBhZGRyZXNzZXMgPSBhd2FpdCBsb29rdXBBbGxBZGRyZXNzZXMob3B0aW9ucy5ob3N0LCBsb29rdXAsIHNpZ25hbCk7XG5cbiAgcmV0dXJuIGF3YWl0IG5ldyBQcm9taXNlPG5ldC5Tb2NrZXQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBzb2NrZXRzID0gbmV3IEFycmF5KGFkZHJlc3Nlcy5sZW5ndGgpO1xuXG4gICAgY29uc3QgZXJyb3JzOiBFcnJvcltdID0gW107XG5cbiAgICBmdW5jdGlvbiBvbkVycm9yKHRoaXM6IG5ldC5Tb2NrZXQsIGVycjogRXJyb3IpIHtcbiAgICAgIGVycm9ycy5wdXNoKGVycik7XG5cbiAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25FcnJvcik7XG4gICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKCdjb25uZWN0Jywgb25Db25uZWN0KTtcblxuICAgICAgdGhpcy5kZXN0cm95KCk7XG5cbiAgICAgIGlmIChlcnJvcnMubGVuZ3RoID09PSBhZGRyZXNzZXMubGVuZ3RoKSB7XG4gICAgICAgIHNpZ25hbC5yZW1vdmVFdmVudExpc3RlbmVyKCdhYm9ydCcsIG9uQWJvcnQpO1xuXG4gICAgICAgIHJlamVjdChuZXcgQWdncmVnYXRlRXJyb3IoZXJyb3JzLCAnQ291bGQgbm90IGNvbm5lY3QgKHBhcmFsbGVsKScpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvbkNvbm5lY3QodGhpczogbmV0LlNvY2tldCkge1xuICAgICAgc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Fib3J0Jywgb25BYm9ydCk7XG5cbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgc29ja2V0cy5sZW5ndGg7IGorKykge1xuICAgICAgICBjb25zdCBzb2NrZXQgPSBzb2NrZXRzW2pdO1xuXG4gICAgICAgIGlmICh0aGlzID09PSBzb2NrZXQpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNvY2tldC5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCBvbkVycm9yKTtcbiAgICAgICAgc29ja2V0LnJlbW92ZUxpc3RlbmVyKCdjb25uZWN0Jywgb25Db25uZWN0KTtcbiAgICAgICAgc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgIH1cblxuICAgICAgcmVzb2x2ZSh0aGlzKTtcbiAgICB9XG5cbiAgICBjb25zdCBvbkFib3J0ID0gKCkgPT4ge1xuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBzb2NrZXRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGNvbnN0IHNvY2tldCA9IHNvY2tldHNbal07XG5cbiAgICAgICAgc29ja2V0LnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIG9uRXJyb3IpO1xuICAgICAgICBzb2NrZXQucmVtb3ZlTGlzdGVuZXIoJ2Nvbm5lY3QnLCBvbkNvbm5lY3QpO1xuXG4gICAgICAgIHNvY2tldC5kZXN0cm95KCk7XG4gICAgICB9XG5cbiAgICAgIHJlamVjdChuZXcgQWJvcnRFcnJvcigpKTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IGFkZHJlc3Nlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgY29uc3Qgc29ja2V0ID0gc29ja2V0c1tpXSA9IG5ldC5jb25uZWN0KHtcbiAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgaG9zdDogYWRkcmVzc2VzW2ldLmFkZHJlc3MsXG4gICAgICAgIGZhbWlseTogYWRkcmVzc2VzW2ldLmZhbWlseVxuICAgICAgfSk7XG5cbiAgICAgIHNvY2tldC5vbignZXJyb3InLCBvbkVycm9yKTtcbiAgICAgIHNvY2tldC5vbignY29ubmVjdCcsIG9uQ29ubmVjdCk7XG4gICAgfVxuXG4gICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoJ2Fib3J0Jywgb25BYm9ydCwgeyBvbmNlOiB0cnVlIH0pO1xuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbm5lY3RJblNlcXVlbmNlKG9wdGlvbnM6IHsgaG9zdDogc3RyaW5nLCBwb3J0OiBudW1iZXIsIGxvY2FsQWR
|