51 lines
1.4 KiB
JavaScript
51 lines
1.4 KiB
JavaScript
// TCP-пинг: меряем время до открытия TCP-соединения с хостом:портом.
|
||
// Это не ICMP-ping, но для VPN-серверов точнее (проверяем именно тот порт, куда подключается клиент).
|
||
|
||
import net from "node:net";
|
||
import dns from "node:dns/promises";
|
||
|
||
const DEFAULT_TIMEOUT = 3000;
|
||
|
||
export async function tcpPing(host, port, timeout = DEFAULT_TIMEOUT) {
|
||
const start = Date.now();
|
||
return new Promise((resolve) => {
|
||
const socket = new net.Socket();
|
||
let done = false;
|
||
|
||
const finish = (result) => {
|
||
if (done) return;
|
||
done = true;
|
||
socket.removeAllListeners();
|
||
socket.destroy();
|
||
resolve(result);
|
||
};
|
||
|
||
socket.setTimeout(timeout);
|
||
socket.once("connect", () =>
|
||
finish({ ok: true, latency: Date.now() - start }),
|
||
);
|
||
socket.once("timeout", () =>
|
||
finish({ ok: false, latency: null, error: "timeout" }),
|
||
);
|
||
socket.once("error", (err) =>
|
||
finish({ ok: false, latency: null, error: err.code || err.message }),
|
||
);
|
||
|
||
try {
|
||
socket.connect(port, host);
|
||
} catch (err) {
|
||
finish({ ok: false, latency: null, error: err.message });
|
||
}
|
||
});
|
||
}
|
||
|
||
export async function resolveHost(host) {
|
||
if (net.isIP(host)) return host;
|
||
try {
|
||
const result = await dns.lookup(host);
|
||
return result.address;
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|