116 lines
2.5 KiB
JavaScript
Executable file
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])))
|