webtimediff/index.js
2025-04-27 15:18:52 +05:00

116 lines
2.5 KiB
JavaScript
Executable file

#!/usr/bin/env node
var { Client } = require('undici');
var { parseArgs } = require('node:util');
var { values, positionals } = parseArgs({
options: {
help: {
type: 'boolean'
}
},
allowPositionals: true,
});
var help =
`Usage: webtimediff <URL>
Calculate system clock difference between this host and a web server.
--help display this help and exit
`;
if (values.help || positionals.length != 1) {
console.log(help);
return;
}
function sleep(ms) {
return new Promise((res, rej) => setTimeout(_ => res(), ms));
}
((async function(url) {
var conn = new Client(url.origin, {
pipelining: 1000,
headersTimeout: 10e3,
bodyTimeout: 10e3,
});
let step = 20;
let end = 2000;
let errors = [];
let resps = [];
let firstRemoteTime = undefined;
let foundChange = undefined;
let reqtempl = {
method: "OPTIONS",
path: url.pathname + url.search,
headers: {
"user-agent": "webtimediff"
},
blocking: false,
idempotent: true,
}
await conn.request(reqtempl);
for (let i = 0; (!foundChange) && i < end; i += step) {
if (errors.length > 0)
break;
let date = new Date();
let ii=i;
let res = conn.request(reqtempl).then(e => (
e.date = new Date(e.headers.date),
firstRemoteTime = firstRemoteTime ?? e.date,
e.madeAt = date,
e.doneAt = new Date(),
foundChange = foundChange ??
((firstRemoteTime && (firstRemoteTime.getTime() != e.date.getTime()))
? {
remoteTime: e.date.getTime()/1000,
beginTime: e.madeAt.getTime()/1000,
endTime: e.doneAt.getTime()/1000,
}
: foundChange),
e));
res.catch(e => errors.push(res));
resps.push(res);
if (i + step < end)
await sleep(step);
}
if (errors.length > 0)
await Promise.all(errors);
Promise.all(resps).catch(e => {});
if (!foundChange) {
throw new Error("The remote clock does not work.");
}
let firstReq = [await (resps[0])].map(res => ({
remoteTime: res.date.getTime()/1000,
beginTime: res.madeAt.getTime()/1000,
endTime: res.doneAt.getTime()/1000,
}))[0];
let reqEnds = (foundChange.endTime - firstReq.endTime);
let reqBegins = (foundChange.beginTime - firstReq.beginTime)
let lag = reqEnds / reqBegins;
if (!(lag < 1.08)) {
console.error("WARNING: Big Lag ("
+reqEnds+
"s / "
+reqBegins+
"s) detected, reported result may be inaccurate.");
}
let diff = (foundChange.remoteTime - (foundChange.beginTime + foundChange.endTime) / 2);
console.log("remote_time = local_time "+(diff < 0 ? "-" : "+")+" " + Math.abs(Math.round(diff*1000)/1000)+ " s");
process.exit();
})(new URL(positionals[0])))