Vydané zdroje
Stáhnout zdroje ZIP
CH-J Server Manager
Procházejte adresáře a soubory konkrétního vydání aplikace.
Zdroje jsou zveřejněny pod CH-J Proprietary Software License 1.14. Jejich dostupnost nemění licenční podmínky ani neposkytuje další oprávnění.
1
"use strict";3
const { execFile } = require("node:child_process");4
const net = require("node:net");5
const { performance } = require("node:perf_hooks");7
function parsePing(stdout) {8
// Parse the reply, not the average or a process duration. Windows localizes9
// "time", so accept the numeric '=…ms' field without relying on that word.10
const match = String(stdout).match(/(?:time\s*[=<]|[=<])\s*(\d+(?:[.,]\d+)?)\s*ms\b/i);11
if (!match) return null;12
const value = Number(match[1].replace(",", "."));13
// '<1ms' is an upper bound, not an exact measurement.14
return Number.isFinite(value) && value > 0 && !/<\s*\d+(?:[.,]\d+)?\s*ms/i.test(stdout) ? value : null;15
}17
function measurePing(address, { signal, platform = process.platform, run = execFile } = {}) {18
if (!net.isIP(address) || !["win32", "darwin", "linux"].includes(platform)) return Promise.resolve(null);19
const ipv6 = net.isIP(address) === 6;20
const executable = platform === "darwin" ? (ipv6 ? "/sbin/ping6" : "/sbin/ping") : platform === "win32" ? "ping.exe" : "ping";21
const args = platform === "win32" ? [ipv6 ? "-6" : "-4", "-n", "1", "-w", "4000", address]22
: platform === "darwin" ? ["-n", "-c", "1", ...(ipv6 ? [] : ["-W", "4000"]), address]23
: [ipv6 ? "-6" : "-4", "-n", "-c", "1", "-W", "4", address];24
return new Promise((resolve) => {25
run(executable, args, { shell: false, windowsHide: true, timeout: 5000, maxBuffer: 32 * 1024, signal, env: { ...process.env, LC_ALL: "C", LANG: "C" } },26
(error, stdout) => resolve(error ? null : parsePing(stdout)));27
});28
}30
class LatencyMonitor {31
constructor({ ping = measurePing, now = () => performance.now(), intervalMs = 12000 } = {}) {32
this.ping = ping;33
this.now = now;34
this.intervalMs = intervalMs;35
}37
start(record, request, publish) {38
const controller = new AbortController();39
let timer;40
let stopped = false;41
const sample = async () => {42
const started = this.now();43
const ssh = Promise.resolve().then(request).then(() => {44
const elapsed = this.now() - started;45
return Number.isFinite(elapsed) && elapsed > 0 ? elapsed : null;46
}).catch(() => null);47
const ping = Promise.resolve().then(() => this.ping(record.address, { signal: controller.signal })).catch(() => null);48
const [pingMs, sshRttMs] = await Promise.all([ping, ssh]);49
if (stopped) return;50
const valid = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;51
publish({ pingMs: valid(pingMs), sshRttMs: valid(sshRttMs), measuredAt: new Date().toISOString() });52
// Schedule only after both finish: no overlapping probes or intervals.53
timer = setTimeout(sample, this.intervalMs);54
timer.unref?.();55
};56
void sample();57
return () => { stopped = true; clearTimeout(timer); controller.abort(); };58
}59
}61
module.exports = { LatencyMonitor, measurePing, parsePing };SHA-256: 750792eb3fda2fd855a5fdbfa87ead97a99f5fe4e2adc12f0c37488961f795ef
SHA-256 archivu: 5ac91caf4fa32a6fdb114f2430deed486fbe7489d5eea343d1f034169fafb5e0