UNPKG

@juit/lib-ping

Version:

ICMPv4/ICMPv6 Ping library for NodeJS

102 lines (101 loc) 3.93 kB
// protocol.ts import { randomBytes } from "node:crypto"; var ERR_WRONG_LENGTH = -1n; var ERR_WRONG_CORRELATION = -2n; var ERR_WRONG_ICMP_TYPE = -3n; var ERR_WRONG_ICMP_CODE = -4n; var ERR_WRONG_SEQUENCE = -5n; var ERR_SEQUENCE_TOO_BIG = -6n; var ERR_SEQUENCE_TOO_SMALL = -7n; var ERR_LATENCY_NEGATIVE = -8n; function getWarning(num) { if (num >= 0) return { code: "OK", message: `Latency is ${Number(num) / 1e6} ms` }; switch (num) { case ERR_WRONG_LENGTH: return { code: "ERR_WRONG_LENGTH", message: "Received packet with invalid length" }; case ERR_WRONG_CORRELATION: return { code: "ERR_WRONG_CORRELATION", message: "Received packet with invalid correlation data" }; case ERR_WRONG_ICMP_TYPE: return { code: "ERR_WRONG_ICMP_TYPE", message: "Received packet with invalid ICMP type" }; case ERR_WRONG_ICMP_CODE: return { code: "ERR_WRONG_ICMP_CODE", message: "Received packet with invalid ICMP code" }; case ERR_WRONG_SEQUENCE: return { code: "ERR_WRONG_SEQUENCE", message: "Received packet with mismatched sequence in header/payload" }; case ERR_SEQUENCE_TOO_BIG: return { code: "ERR_SEQUENCE_TOO_BIG", message: "Received packet with sequence in the future" }; case ERR_SEQUENCE_TOO_SMALL: return { code: "ERR_SEQUENCE_TOO_SMALL", message: "Received packet with sequence in the past (duplicate packet?)" }; case ERR_LATENCY_NEGATIVE: return { code: "ERR_LATENCY_NEGATIVE", message: "Received packet with negative latence (time travel is possible!)" }; default: return { code: "ERR_UNKNOWN", message: `Unknown error code (code=${num})` }; } } var ProtocolHandler = class { __packet = randomBytes(64); __type; __seq_out = 0; __seq_in = 0; constructor(v6) { this.__type = v6 ? 129 : 0; this.__packet.writeUInt32BE(v6 ? 2147483648 : 134217728, 0); this.__packet.writeUInt16BE(process.pid % 65535, 4); this.__packet.writeUInt16BE(this.__seq_out, 6); this.__packet.writeBigUInt64BE(0n, 8); } outgoing() { const buffer = Buffer.from(this.__packet); buffer.writeUInt32BE(++this.__seq_out, 16); buffer.writeUInt16BE(this.__seq_out & 255, 6); buffer.writeBigUInt64BE(process.hrtime.bigint(), 8); buffer.writeUInt16BE(rfc1071crc(buffer), 2); return buffer; } incoming(buffer, now = process.hrtime.bigint()) { if (buffer.length > 64) { const first = buffer.readUInt8(0); const version = first >> 4; if (version === 6) { if (buffer.length === 104) buffer = buffer.subarray(40); } else if (version === 4) { const length = (first & 15) * 4; if (buffer.length === length + 64) buffer = buffer.subarray(length); } } if (buffer.length !== 64) return ERR_WRONG_LENGTH; if (buffer.compare(this.__packet, 20, 64, 20, 64) !== 0) return ERR_WRONG_CORRELATION; const type = buffer.readUInt8(0); if (type !== this.__type) return ERR_WRONG_ICMP_TYPE; const code = buffer.readUInt8(1); if (code !== 0) return ERR_WRONG_ICMP_CODE; const sequence = buffer.readUInt32BE(16); if ((buffer.readUInt16BE(6) & 255) != (sequence & 255)) return ERR_WRONG_SEQUENCE; if (sequence > this.__seq_out) return ERR_SEQUENCE_TOO_BIG; if (sequence <= this.__seq_in) return ERR_SEQUENCE_TOO_SMALL; const latency = now - buffer.readBigInt64BE(8); if (latency < 0n) return ERR_LATENCY_NEGATIVE; this.__seq_in = sequence; return latency; } }; function rfc1071crc(buffer) { let sum = 0; for (let i = 0; i < buffer.length; i += 2) { sum = (sum + buffer.readUInt16BE(i)) % 65535; } return ~sum & 65535; } export { ERR_LATENCY_NEGATIVE, ERR_SEQUENCE_TOO_BIG, ERR_SEQUENCE_TOO_SMALL, ERR_WRONG_CORRELATION, ERR_WRONG_ICMP_CODE, ERR_WRONG_ICMP_TYPE, ERR_WRONG_LENGTH, ERR_WRONG_SEQUENCE, ProtocolHandler, getWarning, rfc1071crc }; //# sourceMappingURL=protocol.mjs.map