"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // index.ts var src_exports = {}; __export(src_exports, { createPinger: () => createPinger }); module.exports = __toCommonJS(src_exports); var import_node_assert = __toESM(require("node:assert")); var import_node_dgram = require("node:dgram"); var import_promises = require("node:dns/promises"); var import_node_events = require("node:events"); var import_node_net = require("node:net"); var import_node_os = require("node:os"); var import_ping = __toESM(require("../native/ping.cjs")); var import_protocol = require("./protocol.cjs"); async function createPinger(to, options = {}) { const { protocol = (0, import_node_net.isIPv6)(to) ? "ipv6" : "ipv4", timeout = 3e4, interval = 1e3, from, source } = options; const family = protocol === "ipv6" ? import_ping.default.AF_INET6 : protocol === "ipv4" ? import_ping.default.AF_INET : void 0; (0, import_node_assert.default)(family === import_ping.default.AF_INET || family === import_ping.default.AF_INET6, `Invalid protocol "${protocol}" specified`); const target = (0, import_node_net.isIP)(to) ? to : protocol === "ipv6" ? (await (0, import_promises.resolve6)(to).catch(() => []))[0] : protocol === "ipv4" ? (await (0, import_promises.resolve4)(to).catch(() => []))[0] : ( /* coverage ignore next */ void 0 ); if (!target) { throw new Error(`Unable to resolve ping target "${to}" as an ${protocol} address`); } else if ((0, import_node_net.isIPv4)(target) && protocol != "ipv4") { throw new Error(`Invalid IPv4 ping target "${target}"`); } else if ((0, import_node_net.isIPv6)(target) && protocol != "ipv6") { throw new Error(`Invalid IPv6 ping target "${target}"`); } if (from) { if ((0, import_node_net.isIPv4)(from) && protocol != "ipv4") { throw new Error(`Invalid IPv6 address to ping from "${from}"`); } else if ((0, import_node_net.isIPv6)(from) && protocol != "ipv6") { throw new Error(`Invalid IPv4 address to ping from "${from}"`); } else if (!(0, import_node_net.isIP)(from)) { throw new Error(`Invalid IP address to ping from "${from}"`); } } if (source && !(0, import_node_os.networkInterfaces)()[source]) { throw new Error(`Invalid source interface name "${source}"`); } return new Promise((resolve, reject) => { import_ping.default.open(family, from, source, (error, fd) => { if (error) { Error.captureStackTrace(error); return reject(error); } else if (fd) { return resolve(new PingerImpl(from, source, target, timeout, interval, protocol, fd)); } else { return reject(new Error(`Unknown error (fd=${fd})`)); } }); }); } var PingerImpl = class extends import_node_events.EventEmitter { constructor(from, source, target, timeout, interval, protocol, fd) { super(); this.from = from; this.source = source; this.target = target; this.timeout = timeout; this.interval = interval; this.protocol = protocol; const type = protocol === "ipv4" ? "udp4" : "udp6"; this.__handler = new import_protocol.ProtocolHandler(protocol === "ipv6"); this.__socket = (0, import_node_dgram.createSocket)({ type }, (buffer, info) => { if (info.address !== target) return; const latency = this.__handler.incoming(buffer); if (latency < 0n) { const warning = (0, import_protocol.getWarning)(latency); this.emit("warning", warning.code, warning.message); return; } this.emit("pong", Number(latency) / 1e6); this.__latency += latency; this.__received++; }).bind({ fd }, () => { Object.defineProperty(this, "__fd", { value: fd }); }); this.__socket.on("close", () => this.__closed = true); } __handler; __socket; __timer; __sent = 0; __received = 0; __latency = 0n; __closed = false; get running() { return !!this.__timer; } get closed() { return this.__closed; } // wrap "emit" so that "error" events won't throw when no listeners are there emit(eventName, ...args) { if (this.listenerCount(eventName) < 1) return false; return super.emit(eventName, ...args); } ping(callback) { if (!callback) { return new Promise((resolve, reject) => { this.ping((error) => error ? reject(error) : resolve()); }); } const buffer = this.__handler.outgoing(); this.__socket.send(buffer, 1, this.target, (error) => { if (error) { this.emit("error", error); void this.close(); callback(error); } else { this.__sent++; callback(null); } }); } start() { if (this.__closed) throw new Error("Socket closed"); if (this.__timer) return; this.__timer = setInterval(() => this.ping(() => void 0), this.interval).unref(); } stop() { if (this.__timer) clearInterval(this.__timer); this.__timer = void 0; } close() { return new Promise((resolve) => { if (this.__closed) return resolve(); this.__socket.close(resolve); this.__closed = true; this.stop(); }); } stats() { const latency = this.__received < 1 ? NaN : Number(this.__latency / BigInt(this.__received)) / 1e6; const stats = { sent: this.__sent, received: this.__received, latency }; this.__sent = 0; this.__received = 0; this.__latency = 0n; return stats; } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createPinger }); //# sourceMappingURL=index.cjs.map