Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ntp-time

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ntp-time - npm Package Compare versions

Comparing version 1.1.3 to 2.0.1

4

package.json
{
"name": "ntp-time",
"version": "1.1.3",
"version": "2.0.1",
"description": "A ntp library for nodejs",

@@ -16,3 +16,3 @@ "main": "index.js",

"devDependencies": {
"jest": "^26.4.2"
"jest": "^27.5.1"
},

@@ -19,0 +19,0 @@ "scripts": {

@@ -24,4 +24,4 @@ # ntp-time

```javascript
const NTP = require("ntp-time").Client;
const client = new NTP("a.st1.ntp.br", 123, { timeout: 5000 });
const NTP = require('ntp-time').Client;
const client = new NTP('a.st1.ntp.br', 123, { timeout: 5000 });

@@ -42,3 +42,3 @@ async function sync() {

.syncTime()
.then((time) => console.log(time)) // time is the whole NTP packet
.then(time => console.log(time)) // time is the whole NTP packet
.catch(console.log);

@@ -54,3 +54,3 @@ ```

```javascript
const NTPServer = require("ntp-time").Server;
const NTPServer = require('ntp-time').Server;
const server = new NTPServer();

@@ -60,12 +60,16 @@

server.handle((message, response) => {
console.log("Server message:", message);
message.transmitTimestamp = Date.now();
console.log('Server message:', message);
message.transmitTimestamp = Math.floor(Date.now() / 1000);
response(message);
});
server.listen(3000, (err) => {
// Check if node has the necessary permissions
// to listen on ports less than 1024
// https://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged-ports-on-linux
server.listen(123, err => {
if (err) throw err;
console.log("Server listening");
console.log('Server listening');
});

@@ -72,0 +76,0 @@ ```

@@ -1,19 +0,21 @@

const udp = require("dgram");
const udp = require('dgram');
const Packet = require("./packet");
const { NTPPacket, MODES } = require('./packet');
const NTP_DELTA = 2208988800;
function createPacket() {
const packet = new Packet();
const packet = new NTPPacket(MODES.CLIENT);
packet.mode = Packet.MODES.CLIENT;
packet.originateTimestamp = Date.now();
packet.originateTimestamp = Math.floor(Date.now() / 1000);
return packet.toBuffer();
return packet.bufferize(packet);
}
function parse(buffer) {
const message = Packet.parse(buffer);
message.destinationTimestamp = Date.now();
message.time = new Date(message.transmitTimestamp);
const message = NTPPacket.parse(buffer);
message.destinationTimestamp = Math.floor(Date.now() / 1000) + NTP_DELTA;
message.time = new Date(Math.floor((message.rxTimestamp - NTP_DELTA) * 1000));
// Timestamp Name ID When Generated

@@ -26,4 +28,4 @@ // ------------------------------------------------------------

const T1 = message.originateTimestamp;
const T2 = message.receiveTimestamp;
const T3 = message.transmitTimestamp;
const T2 = message.rxTimestamp;
const T3 = message.txTimestamp;
const T4 = message.destinationTimestamp;

@@ -42,3 +44,3 @@

constructor(
server = "pool.ntp.org",
server = 'pool.ntp.org',
port = 123,

@@ -49,3 +51,3 @@ options = { timeout: 3000 }

this.port = port;
this.socket = udp.createSocket("udp4");
this.socket = udp.createSocket('udp4');
this.options = options;

@@ -58,3 +60,3 @@

return new Promise((resolve, reject) => {
this.socket = udp.createSocket("udp4");
this.socket = udp.createSocket('udp4');

@@ -69,3 +71,3 @@ const {

this.socket.send(packet, 0, packet.length, port, server, (err) => {
this.socket.send(packet, 0, packet.length, port, server, err => {
if (err) return reject(err);

@@ -81,3 +83,3 @@

this.socket.once("message", (data) => {
this.socket.once('message', data => {
clearTimeout(timer);

@@ -88,2 +90,3 @@

this.socket.close();
return resolve(message);

@@ -90,0 +93,0 @@ });

@@ -1,212 +0,139 @@

const assert = require("assert");
/**
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Delay |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Dispersion |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reference Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Reference Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Originate Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Receive Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Transmit Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key Identifier (optional) (32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| |
| Message Digest (optional) (128) |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
function toMsecs(buffer, offset) {
let seconds = 0;
let fraction = 0;
/**
* 1900 ~ 1970
* @docs https://tools.ietf.org/html/rfc4330#section-3
*/
const SEVENTY_YEARS = 2208988800;
for (let i = 0; i < 4; ++i) {
seconds = seconds * 256 + buffer[offset + i];
}
/**
* @rfc https://tools.ietf.org/html/rfc4330
*/
class Packet {
constructor() {
Object.assign(this, {
leapIndicator: 0,
version: 4,
mode: 3,
stratum: 0,
pollInterval: 6,
precision: 236,
referenceIdentifier: 0,
referenceTimestamp: 0,
originateTimestamp: 0,
receiveTimestamp: 0,
transmitTimestamp: 0
});
}
for (let i = 4; i < 8; ++i) {
fraction = fraction * 256 + buffer[offset + i];
}
static parse(buffer) {
assert.equal(buffer.length, 48, "Invalid Package");
const packet = new Packet();
packet.leapIndicator = buffer[0] >> 6;
packet.version = (buffer[0] & 0x38) >> 3;
packet.mode = buffer[0] & 0x7;
packet.stratum = buffer[1];
packet.pollInterval = buffer[2];
packet.precision = buffer[3];
packet.rootDelay = buffer.slice(4, 8);
packet.rootDispersion = buffer.slice(8, 12);
packet.referenceIdentifier = buffer.slice(12, 16);
packet.referenceTimestamp = toMsecs(buffer, 16);
packet.originateTimestamp = toMsecs(buffer, 24);
packet.receiveTimestamp = toMsecs(buffer, 32);
packet.transmitTimestamp = toMsecs(buffer, 40);
return packet;
}
return seconds + fraction / Math.pow(2, 32);
}
toBuffer() {
const buffer = Buffer.alloc(48).fill(0x00);
buffer[0] = 0; // 0b11100011; // LI, Version, Mode
buffer[0] += this.leapIndicator << 6;
buffer[0] += this.version << 3;
buffer[0] += this.mode << 0;
buffer[1] = this.stratum;
buffer[2] = this.pollInterval;
buffer[3] = this.precision;
buffer.writeUInt32BE(this.rootDelay, 4);
buffer.writeUInt32BE(this.rootDispersion, 8);
buffer.writeUInt32BE(this.referenceIdentifier, 12);
writeMsecs(buffer, 16, this.referenceTimestamp);
writeMsecs(buffer, 24, this.originateTimestamp);
writeMsecs(buffer, 32, this.receiveTimestamp);
writeMsecs(buffer, 40, this.transmitTimestamp);
return buffer;
}
const toFrac = ts => {
return Math.floor(Math.abs(ts - Math.floor(ts)) * Math.pow(2, 32));
};
toJSON() {
const output = Object.assign({}, this);
const { leapIndicator, version } = this;
output.version = version;
output.leapIndicator = {
0: "no-warning",
1: "last-minute-61",
2: "last-minute-59",
3: "alarm"
}[leapIndicator];
const sysToNTP = timestamp => timestamp + NTPPacket.NTP_DELTA;
const { mode } = this;
switch (mode) {
case 1:
output.mode = "symmetric-active";
break;
case 2:
output.mode = "symmetric-passive";
break;
case 3:
output.mode = "client";
break;
case 4:
output.mode = "server";
break;
case 5:
output.mode = "broadcast";
break;
case 0:
case 6:
case 7:
output.mode = "reserved";
break;
}
const writeInMillis = (buffer, offset, ts, addDelta) => {
const seconds = addDelta ? ts + NTP_DELTA : ts;
const fraction = toFrac(ts);
const { stratum } = this;
if (stratum === 0) {
output.stratum = "death";
} else if (stratum === 1) {
output.stratum = "primary";
} else if (stratum <= 15) {
output.stratum = "secondary";
} else {
output.stratum = "reserved";
}
// seconds
buffer[offset + 0] = (seconds & 0xff000000) >> 24;
buffer[offset + 1] = (seconds & 0x00ff0000) >> 16;
buffer[offset + 2] = (seconds & 0x0000ff00) >> 8;
buffer[offset + 3] = seconds & 0x000000ff;
output.referenceTimestamp = new Date(this.referenceTimestamp);
output.originateTimestamp = new Date(this.originateTimestamp);
output.receiveTimestamp = new Date(this.receiveTimestamp);
output.transmitTimestamp = new Date(this.transmitTimestamp);
output.destinationTimestamp = new Date(this.destinationTimestamp);
return output;
}
}
// 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Seconds |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Seconds Fraction (0-padded) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// fraction
buffer[offset + 4] = (fraction & 0xff000000) >> 24;
buffer[offset + 5] = (fraction & 0x00ff0000) >> 16;
buffer[offset + 6] = (fraction & 0x0000ff00) >> 8;
buffer[offset + 7] = fraction & 0x000000ff;
function toMsecs(buffer, offset) {
let seconds = 0;
let fraction = 0;
for (let i = 0; i < 4; ++i) {
seconds = seconds * 256 + buffer[offset + i];
}
return buffer;
};
for (let i = 4; i < 8; ++i) {
fraction = fraction * 256 + buffer[offset + i];
}
const MODES = {
CLIENT: 3,
SERVER: 4
};
return (seconds - SEVENTY_YEARS + fraction / Math.pow(2, 32)) * 1000;
}
const NTP_DELTA = 2208988800;
function writeMsecs(buffer, offset, ts) {
// const buffer = Buffer.alloc(8); // 64bits
const seconds = Math.floor(ts / 1000) + SEVENTY_YEARS;
const fraction = Math.round(((ts % 1000) / 1000) * Math.pow(2, 32));
// seconds
buffer[offset + 0] = (seconds & 0xff000000) >> 24;
buffer[offset + 1] = (seconds & 0x00ff0000) >> 16;
buffer[offset + 2] = (seconds & 0x0000ff00) >> 8;
buffer[offset + 3] = seconds & 0x000000ff;
// fraction
buffer[offset + 4] = (fraction & 0xff000000) >> 24;
buffer[offset + 5] = (fraction & 0x00ff0000) >> 16;
buffer[offset + 6] = (fraction & 0x0000ff00) >> 8;
buffer[offset + 7] = fraction & 0x000000ff;
return buffer;
class NTPPacket {
constructor(mode) {
Object.assign(this, {
mode: mode || 4,
leap: 0,
version: 3,
stratum: 0,
poll: 0,
precision: 0,
rootDelay: 0,
rootDispersion: 0,
referenceId: 0,
referenceTimestamp: 0,
originateTimestamp: 0,
rxTimestamp: 0,
txTimestamp: 0
});
}
static parse(data) {
if (data.length < 48) {
throw new Error('Invalid NTP Package');
}
const packet = new NTPPacket(4);
// Control bytes
packet.leap = (data[0] >> 6) & 0x3;
packet.version = (data[0] >> 3) & 0x7;
packet.mode = data[0] & 0x7;
packet.stratum = parseInt(data[1]) || 2;
packet.poll = parseInt(data[2]) || 10;
packet.precision = parseInt(data[3]);
packet.rootDelay = data.slice(4, 8).readFloatBE(0) / 2 ** 16;
packet.rootDispersion = data.slice(8, 12).readFloatBE(0) / 2 ** 16;
packet.referenceId = data.slice(12, 16);
// Timestamps where the 4 first bytes are the
// int part and the 4 last are the frac part
// const refTimestampHigh = data.slice(16, 20).readUint32BE();
// const refTimestampLow = data.slice(20, 24).readFloatBE();
packet.referenceTimestamp = toMsecs(data, 16);
// const origTimestampHigh = data.slice(24, 28).readUint32BE();
// const origTimestampLow = data.slice(28, 32).readUint32BE();
packet.originateTimestamp = toMsecs(data, 24);
// const rxTimestampHigh = data.slice(32, 36).readUint32BE();
// const rxTimestampLow = data.slice(36, 40).readUint32BE();
packet.rxTimestamp = toMsecs(data, 32);
// const txTimestampHigh = data.slice(40, 44).readUint32BE();
// const txTimestampLow = data.slice(44, 48).readUint32BE();
packet.txTimestamp = toMsecs(data, 40);
return packet;
}
bufferize(packet) {
const buffer = Buffer.alloc(48).fill(0x00);
buffer[0] = (packet.leap << 6) | (packet.version << 3) | (this.mode << 0);
buffer[1] = packet.stratum;
buffer[2] = packet.poll;
buffer[3] = packet.precision;
buffer.writeUInt32BE(packet.rootDelay, 4);
buffer.writeUInt32BE(packet.rootDispersion, 8);
buffer.writeUInt32BE(packet.referenceId, 12);
// Reference Timestamp
writeInMillis(buffer, 16, packet.referenceTimestamp, true);
// Originate timestamp
writeInMillis(
buffer,
24,
packet.originateTimestamp,
this.mode !== MODES.SERVER // Don't add NTP_DELTA if the packet is server mode
);
// RX Timestamp
writeInMillis(buffer, 32, packet.rxTimestamp, true);
// TX Timestamp
writeInMillis(buffer, 40, packet.txTimestamp, true);
return buffer;
}
}
// Mode Meaning
// ------------------------------------
// 0 reserved
// 1 symmetric active
// 2 symmetric passive
// 3 client
// 4 server
// 5 broadcast
// 6 reserved for NTP control message
// 7 reserved for private use
Packet.MODES = {
CLIENT: 3,
SERVER: 4
};
module.exports = Packet;
module.exports = { NTPPacket, sysToNTP, MODES };

@@ -1,4 +0,4 @@

const udp = require("dgram");
const EventEmitter = require("events");
const Packet = require("./packet");
const udp = require('dgram');
const EventEmitter = require('events');
const { NTPPacket, MODES } = require('./packet');

@@ -9,4 +9,4 @@ class Server extends EventEmitter {

this.socket = udp.createSocket("udp4");
this.socket.on("message", this.parse.bind(this));
this.socket = udp.createSocket('udp4');
this.socket.on('message', this.parse.bind(this));

@@ -17,13 +17,15 @@ return this;

handle(handler) {
this.on("request", handler);
this.on('request', handler);
}
send(rinfo, message, callback) {
if (message instanceof Packet) {
message.mode = Packet.MODES.SERVER; // mark mode as server
message = message.toBuffer();
if (message instanceof NTPPacket) {
const sendPackage = new NTPPacket(MODES.SERVER).bufferize(message);
this.socket.send(sendPackage, rinfo.port, rinfo.server, callback);
return this;
} else {
throw new Error('Invalid response packet');
}
this.socket.send(message, rinfo.port, rinfo.server, callback);
return this;
}

@@ -42,6 +44,11 @@

parse(message, rinfo) {
const packet = Packet.parse(message);
packet.receiveTimestamp = Date.now();
const packet = NTPPacket.parse(message);
const rxTimestamp = Math.floor(Date.now() / 1000);
this.emit("request", packet, this.send.bind(this, rinfo));
packet.originateTimestamp = Math.floor(packet.txTimestamp);
packet.referenceTimestamp = rxTimestamp - 5;
packet.rxTimestamp = rxTimestamp;
this.emit('request', packet, this.send.bind(this, rinfo));
return;

@@ -48,0 +55,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc