Deployed the page to Github Pages.
This commit is contained in:
parent
1d79754e93
commit
2c89899458
62797 changed files with 6551425 additions and 15279 deletions
18
node_modules/sntp/.npmignore
generated
vendored
Normal file
18
node_modules/sntp/.npmignore
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
.idea
|
||||
*.iml
|
||||
npm-debug.log
|
||||
dump.rdb
|
||||
node_modules
|
||||
results.tap
|
||||
results.xml
|
||||
npm-shrinkwrap.json
|
||||
config.json
|
||||
.DS_Store
|
||||
*/.DS_Store
|
||||
*/*/.DS_Store
|
||||
._*
|
||||
*/._*
|
||||
*/*/._*
|
||||
coverage.*
|
||||
lib-cov
|
||||
|
5
node_modules/sntp/.travis.yml
generated
vendored
Executable file
5
node_modules/sntp/.travis.yml
generated
vendored
Executable file
|
@ -0,0 +1,5 @@
|
|||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 0.10
|
||||
|
24
node_modules/sntp/LICENSE
generated
vendored
Executable file
24
node_modules/sntp/LICENSE
generated
vendored
Executable file
|
@ -0,0 +1,24 @@
|
|||
Copyright (c) 2012-2013, Eran Hammer.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Eran Hammer nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
11
node_modules/sntp/Makefile
generated
vendored
Executable file
11
node_modules/sntp/Makefile
generated
vendored
Executable file
|
@ -0,0 +1,11 @@
|
|||
test:
|
||||
@./node_modules/.bin/lab
|
||||
test-cov:
|
||||
@./node_modules/.bin/lab -r threshold -t 100
|
||||
test-cov-html:
|
||||
@./node_modules/.bin/lab -r html -o coverage.html
|
||||
complexity:
|
||||
@./node_modules/.bin/cr -o complexity.md -f markdown lib
|
||||
|
||||
.PHONY: test test-cov test-cov-html complexity
|
||||
|
68
node_modules/sntp/README.md
generated
vendored
Executable file
68
node_modules/sntp/README.md
generated
vendored
Executable file
|
@ -0,0 +1,68 @@
|
|||
# sntp
|
||||
|
||||
An SNTP v4 client (RFC4330) for node. Simpy connects to the NTP or SNTP server requested and returns the server time
|
||||
along with the roundtrip duration and clock offset. To adjust the local time to the NTP time, add the returned `t` offset
|
||||
to the local time.
|
||||
|
||||
[](http://travis-ci.org/hueniverse/sntp)
|
||||
|
||||
# Usage
|
||||
|
||||
```javascript
|
||||
var Sntp = require('sntp');
|
||||
|
||||
// All options are optional
|
||||
|
||||
var options = {
|
||||
host: 'nist1-sj.ustiming.org', // Defaults to pool.ntp.org
|
||||
port: 123, // Defaults to 123 (NTP)
|
||||
resolveReference: true, // Default to false (not resolving)
|
||||
timeout: 1000 // Defaults to zero (no timeout)
|
||||
};
|
||||
|
||||
// Request server time
|
||||
|
||||
Sntp.time(options, function (err, time) {
|
||||
|
||||
if (err) {
|
||||
console.log('Failed: ' + err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('Local clock is off by: ' + time.t + ' milliseconds');
|
||||
process.exit(0);
|
||||
});
|
||||
```
|
||||
|
||||
If an application needs to maintain continuous time synchronization, the module provides a stateful method for
|
||||
querying the current offset only when the last one is too old (defaults to daily).
|
||||
|
||||
```javascript
|
||||
// Request offset once
|
||||
|
||||
Sntp.offset(function (err, offset) {
|
||||
|
||||
console.log(offset); // New (served fresh)
|
||||
|
||||
// Request offset again
|
||||
|
||||
Sntp.offset(function (err, offset) {
|
||||
|
||||
console.log(offset); // Identical (served from cache)
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
To set a background offset refresh, start the interval and use the provided now() method. If for any reason the
|
||||
client fails to obtain an up-to-date offset, the current system clock is used.
|
||||
|
||||
```javascript
|
||||
var before = Sntp.now(); // System time without offset
|
||||
|
||||
Sntp.start(function () {
|
||||
|
||||
var now = Sntp.now(); // With offset
|
||||
Sntp.stop();
|
||||
});
|
||||
```
|
||||
|
16
node_modules/sntp/examples/offset.js
generated
vendored
Executable file
16
node_modules/sntp/examples/offset.js
generated
vendored
Executable file
|
@ -0,0 +1,16 @@
|
|||
var Sntp = require('../lib');
|
||||
|
||||
// Request offset once
|
||||
|
||||
Sntp.offset(function (err, offset) {
|
||||
|
||||
console.log(offset); // New (served fresh)
|
||||
|
||||
// Request offset again
|
||||
|
||||
Sntp.offset(function (err, offset) {
|
||||
|
||||
console.log(offset); // Identical (served from cache)
|
||||
});
|
||||
});
|
||||
|
25
node_modules/sntp/examples/time.js
generated
vendored
Executable file
25
node_modules/sntp/examples/time.js
generated
vendored
Executable file
|
@ -0,0 +1,25 @@
|
|||
var Sntp = require('../lib');
|
||||
|
||||
// All options are optional
|
||||
|
||||
var options = {
|
||||
host: 'nist1-sj.ustiming.org', // Defaults to pool.ntp.org
|
||||
port: 123, // Defaults to 123 (NTP)
|
||||
resolveReference: true, // Default to false (not resolving)
|
||||
timeout: 1000 // Defaults to zero (no timeout)
|
||||
};
|
||||
|
||||
// Request server time
|
||||
|
||||
Sntp.time(options, function (err, time) {
|
||||
|
||||
if (err) {
|
||||
console.log('Failed: ' + err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(time);
|
||||
console.log('Local clock is off by: ' + time.t + ' milliseconds');
|
||||
process.exit(0);
|
||||
});
|
||||
|
1
node_modules/sntp/index.js
generated
vendored
Executable file
1
node_modules/sntp/index.js
generated
vendored
Executable file
|
@ -0,0 +1 @@
|
|||
module.exports = require('./lib');
|
409
node_modules/sntp/lib/index.js
generated
vendored
Executable file
409
node_modules/sntp/lib/index.js
generated
vendored
Executable file
|
@ -0,0 +1,409 @@
|
|||
// Load modules
|
||||
|
||||
var Dgram = require('dgram');
|
||||
var Dns = require('dns');
|
||||
var Hoek = require('hoek');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
exports.time = function (options, callback) {
|
||||
|
||||
if (arguments.length !== 2) {
|
||||
callback = arguments[0];
|
||||
options = {};
|
||||
}
|
||||
|
||||
var settings = Hoek.clone(options);
|
||||
settings.host = settings.host || 'pool.ntp.org';
|
||||
settings.port = settings.port || 123;
|
||||
settings.resolveReference = settings.resolveReference || false;
|
||||
|
||||
// Declare variables used by callback
|
||||
|
||||
var timeoutId = 0;
|
||||
var sent = 0;
|
||||
|
||||
// Ensure callback is only called once
|
||||
|
||||
var isFinished = false;
|
||||
var finish = function (err, result) {
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = 0;
|
||||
}
|
||||
|
||||
if (!isFinished) {
|
||||
isFinished = true;
|
||||
socket.removeAllListeners();
|
||||
socket.close();
|
||||
return callback(err, result);
|
||||
}
|
||||
};
|
||||
|
||||
// Create UDP socket
|
||||
|
||||
var socket = Dgram.createSocket('udp4');
|
||||
|
||||
socket.once('error', function (err) {
|
||||
|
||||
return finish(err);
|
||||
});
|
||||
|
||||
// Listen to incoming messages
|
||||
|
||||
socket.on('message', function (buffer, rinfo) {
|
||||
|
||||
var received = Date.now();
|
||||
|
||||
var message = new internals.NtpMessage(buffer);
|
||||
if (!message.isValid) {
|
||||
return finish(new Error('Invalid server response'), message);
|
||||
}
|
||||
|
||||
if (message.originateTimestamp !== sent) {
|
||||
return finish(new Error('Wrong originate timestamp'), message);
|
||||
}
|
||||
|
||||
// Timestamp Name ID When Generated
|
||||
// ------------------------------------------------------------
|
||||
// Originate Timestamp T1 time request sent by client
|
||||
// Receive Timestamp T2 time request received by server
|
||||
// Transmit Timestamp T3 time reply sent by server
|
||||
// Destination Timestamp T4 time reply received by client
|
||||
//
|
||||
// The roundtrip delay d and system clock offset t are defined as:
|
||||
//
|
||||
// d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2
|
||||
|
||||
var T1 = message.originateTimestamp;
|
||||
var T2 = message.receiveTimestamp;
|
||||
var T3 = message.transmitTimestamp;
|
||||
var T4 = received;
|
||||
|
||||
message.d = (T4 - T1) - (T3 - T2);
|
||||
message.t = ((T2 - T1) + (T3 - T4)) / 2;
|
||||
message.receivedLocally = received;
|
||||
|
||||
if (!settings.resolveReference ||
|
||||
message.stratum !== 'secondary') {
|
||||
|
||||
return finish(null, message);
|
||||
}
|
||||
|
||||
// Resolve reference IP address
|
||||
|
||||
Dns.reverse(message.referenceId, function (err, domains) {
|
||||
|
||||
if (!err) {
|
||||
message.referenceHost = domains[0];
|
||||
}
|
||||
|
||||
return finish(null, message);
|
||||
});
|
||||
});
|
||||
|
||||
// Set timeout
|
||||
|
||||
if (settings.timeout) {
|
||||
timeoutId = setTimeout(function () {
|
||||
|
||||
timeoutId = 0;
|
||||
return finish(new Error('Timeout'));
|
||||
}, settings.timeout);
|
||||
}
|
||||
|
||||
// Construct NTP message
|
||||
|
||||
var message = new Buffer(48);
|
||||
for (var i = 0; i < 48; i++) { // Zero message
|
||||
message[i] = 0;
|
||||
}
|
||||
|
||||
message[0] = (0 << 6) + (4 << 3) + (3 << 0) // Set version number to 4 and Mode to 3 (client)
|
||||
sent = Date.now();
|
||||
internals.fromMsecs(sent, message, 40); // Set transmit timestamp (returns as originate)
|
||||
|
||||
// Send NTP request
|
||||
|
||||
socket.send(message, 0, message.length, settings.port, settings.host, function (err, bytes) {
|
||||
|
||||
if (err ||
|
||||
bytes !== 48) {
|
||||
|
||||
return finish(err || new Error('Could not send entire message'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
internals.NtpMessage = function (buffer) {
|
||||
|
||||
this.isValid = false;
|
||||
|
||||
// Validate
|
||||
|
||||
if (buffer.length !== 48) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Leap indicator
|
||||
|
||||
var li = (buffer[0] >> 6);
|
||||
switch (li) {
|
||||
case 0: this.leapIndicator = 'no-warning'; break;
|
||||
case 1: this.leapIndicator = 'last-minute-61'; break;
|
||||
case 2: this.leapIndicator = 'last-minute-59'; break;
|
||||
case 3: this.leapIndicator = 'alarm'; break;
|
||||
}
|
||||
|
||||
// Version
|
||||
|
||||
var vn = ((buffer[0] & 0x38) >> 3);
|
||||
this.version = vn;
|
||||
|
||||
// Mode
|
||||
|
||||
var mode = (buffer[0] & 0x7);
|
||||
switch (mode) {
|
||||
case 1: this.mode = 'symmetric-active'; break;
|
||||
case 2: this.mode = 'symmetric-passive'; break;
|
||||
case 3: this.mode = 'client'; break;
|
||||
case 4: this.mode = 'server'; break;
|
||||
case 5: this.mode = 'broadcast'; break;
|
||||
case 0:
|
||||
case 6:
|
||||
case 7: this.mode = 'reserved'; break;
|
||||
}
|
||||
|
||||
// Stratum
|
||||
|
||||
var stratum = buffer[1];
|
||||
if (stratum === 0) {
|
||||
this.stratum = 'death';
|
||||
}
|
||||
else if (stratum === 1) {
|
||||
this.stratum = 'primary';
|
||||
}
|
||||
else if (stratum <= 15) {
|
||||
this.stratum = 'secondary';
|
||||
}
|
||||
else {
|
||||
this.stratum = 'reserved';
|
||||
}
|
||||
|
||||
// Poll interval (msec)
|
||||
|
||||
this.pollInterval = Math.round(Math.pow(2, buffer[2])) * 1000;
|
||||
|
||||
// Precision (msecs)
|
||||
|
||||
this.precision = Math.pow(2, buffer[3]) * 1000;
|
||||
|
||||
// Root delay (msecs)
|
||||
|
||||
var rootDelay = 256 * (256 * (256 * buffer[4] + buffer[5]) + buffer[6]) + buffer[7];
|
||||
this.rootDelay = 1000 * (rootDelay / 0x10000);
|
||||
|
||||
// Root dispersion (msecs)
|
||||
|
||||
this.rootDispersion = ((buffer[8] << 8) + buffer[9] + ((buffer[10] << 8) + buffer[11]) / Math.pow(2, 16)) * 1000;
|
||||
|
||||
// Reference identifier
|
||||
|
||||
this.referenceId = '';
|
||||
switch (this.stratum) {
|
||||
case 'death':
|
||||
case 'primary':
|
||||
this.referenceId = String.fromCharCode(buffer[12]) + String.fromCharCode(buffer[13]) + String.fromCharCode(buffer[14]) + String.fromCharCode(buffer[15]);
|
||||
break;
|
||||
case 'secondary':
|
||||
this.referenceId = '' + buffer[12] + '.' + buffer[13] + '.' + buffer[14] + '.' + buffer[15];
|
||||
break;
|
||||
}
|
||||
|
||||
// Reference timestamp
|
||||
|
||||
this.referenceTimestamp = internals.toMsecs(buffer, 16);
|
||||
|
||||
// Originate timestamp
|
||||
|
||||
this.originateTimestamp = internals.toMsecs(buffer, 24);
|
||||
|
||||
// Receive timestamp
|
||||
|
||||
this.receiveTimestamp = internals.toMsecs(buffer, 32);
|
||||
|
||||
// Transmit timestamp
|
||||
|
||||
this.transmitTimestamp = internals.toMsecs(buffer, 40);
|
||||
|
||||
// Validate
|
||||
|
||||
if (this.version === 4 &&
|
||||
this.stratum !== 'reserved' &&
|
||||
this.mode === 'server' &&
|
||||
this.originateTimestamp &&
|
||||
this.receiveTimestamp &&
|
||||
this.transmitTimestamp) {
|
||||
|
||||
this.isValid = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
internals.toMsecs = function (buffer, offset) {
|
||||
|
||||
var seconds = 0;
|
||||
var fraction = 0;
|
||||
|
||||
for (var i = 0; i < 4; ++i) {
|
||||
seconds = (seconds * 256) + buffer[offset + i];
|
||||
}
|
||||
|
||||
for (i = 4; i < 8; ++i) {
|
||||
fraction = (fraction * 256) + buffer[offset + i];
|
||||
}
|
||||
|
||||
return ((seconds - 2208988800 + (fraction / Math.pow(2, 32))) * 1000);
|
||||
};
|
||||
|
||||
|
||||
internals.fromMsecs = function (ts, buffer, offset) {
|
||||
|
||||
var seconds = Math.floor(ts / 1000) + 2208988800;
|
||||
var fraction = Math.round((ts % 1000) / 1000 * Math.pow(2, 32));
|
||||
|
||||
buffer[offset + 0] = (seconds & 0xFF000000) >> 24;
|
||||
buffer[offset + 1] = (seconds & 0x00FF0000) >> 16;
|
||||
buffer[offset + 2] = (seconds & 0x0000FF00) >> 8;
|
||||
buffer[offset + 3] = (seconds & 0x000000FF);
|
||||
|
||||
buffer[offset + 4] = (fraction & 0xFF000000) >> 24;
|
||||
buffer[offset + 5] = (fraction & 0x00FF0000) >> 16;
|
||||
buffer[offset + 6] = (fraction & 0x0000FF00) >> 8;
|
||||
buffer[offset + 7] = (fraction & 0x000000FF);
|
||||
};
|
||||
|
||||
|
||||
// Offset singleton
|
||||
|
||||
internals.last = {
|
||||
offset: 0,
|
||||
expires: 0,
|
||||
host: '',
|
||||
port: 0
|
||||
};
|
||||
|
||||
|
||||
exports.offset = function (options, callback) {
|
||||
|
||||
if (arguments.length !== 2) {
|
||||
callback = arguments[0];
|
||||
options = {};
|
||||
}
|
||||
|
||||
var now = Date.now();
|
||||
var clockSyncRefresh = options.clockSyncRefresh || 24 * 60 * 60 * 1000; // Daily
|
||||
|
||||
if (internals.last.offset &&
|
||||
internals.last.host === options.host &&
|
||||
internals.last.port === options.port &&
|
||||
now < internals.last.expires) {
|
||||
|
||||
process.nextTick(function () {
|
||||
|
||||
callback(null, internals.last.offset);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exports.time(options, function (err, time) {
|
||||
|
||||
if (err) {
|
||||
return callback(err, 0);
|
||||
}
|
||||
|
||||
internals.last = {
|
||||
offset: Math.round(time.t),
|
||||
expires: now + clockSyncRefresh,
|
||||
host: options.host,
|
||||
port: options.port
|
||||
};
|
||||
|
||||
return callback(null, internals.last.offset);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Now singleton
|
||||
|
||||
internals.now = {
|
||||
intervalId: 0
|
||||
};
|
||||
|
||||
|
||||
exports.start = function (options, callback) {
|
||||
|
||||
if (arguments.length !== 2) {
|
||||
callback = arguments[0];
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (internals.now.intervalId) {
|
||||
process.nextTick(function () {
|
||||
|
||||
callback();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exports.offset(options, function (err, offset) {
|
||||
|
||||
internals.now.intervalId = setInterval(function () {
|
||||
|
||||
exports.offset(options, function () { });
|
||||
}, options.clockSyncRefresh || 24 * 60 * 60 * 1000); // Daily
|
||||
|
||||
return callback();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
exports.stop = function () {
|
||||
|
||||
if (!internals.now.intervalId) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearInterval(internals.now.intervalId);
|
||||
internals.now.intervalId = 0;
|
||||
};
|
||||
|
||||
|
||||
exports.isLive = function () {
|
||||
|
||||
return !!internals.now.intervalId;
|
||||
};
|
||||
|
||||
|
||||
exports.now = function () {
|
||||
|
||||
var now = Date.now();
|
||||
if (!exports.isLive() ||
|
||||
now >= internals.last.expires) {
|
||||
|
||||
return now;
|
||||
}
|
||||
|
||||
return now + internals.last.offset;
|
||||
};
|
||||
|
33
node_modules/sntp/package.json
generated
vendored
Executable file
33
node_modules/sntp/package.json
generated
vendored
Executable file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "sntp",
|
||||
"description": "SNTP Client",
|
||||
"version": "0.2.4",
|
||||
"author": "Eran Hammer <eran@hueniverse.com> (http://hueniverse.com)",
|
||||
"contributors": [],
|
||||
"repository": "git://github.com/hueniverse/sntp",
|
||||
"main": "index",
|
||||
"keywords": [
|
||||
"sntp",
|
||||
"ntp",
|
||||
"time"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoek": "0.9.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lab": "0.1.x",
|
||||
"complexity-report": "0.x.x"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test-cov"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "BSD",
|
||||
"url": "http://github.com/hueniverse/sntp/raw/master/LICENSE"
|
||||
}
|
||||
]
|
||||
}
|
359
node_modules/sntp/test/index.js
generated
vendored
Executable file
359
node_modules/sntp/test/index.js
generated
vendored
Executable file
|
@ -0,0 +1,359 @@
|
|||
// Load modules
|
||||
|
||||
var Dgram = require('dgram');
|
||||
var Lab = require('lab');
|
||||
var Sntp = require('../lib');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Test shortcuts
|
||||
|
||||
var expect = Lab.expect;
|
||||
var before = Lab.before;
|
||||
var after = Lab.after;
|
||||
var describe = Lab.experiment;
|
||||
var it = Lab.test;
|
||||
|
||||
|
||||
describe('SNTP', function () {
|
||||
|
||||
describe('#time', function () {
|
||||
|
||||
it('returns consistent result over multiple tries', function (done) {
|
||||
|
||||
Sntp.time(function (err, time) {
|
||||
|
||||
expect(err).to.not.exist;
|
||||
expect(time).to.exist;
|
||||
var t1 = time.t;
|
||||
|
||||
Sntp.time(function (err, time) {
|
||||
|
||||
expect(err).to.not.exist;
|
||||
expect(time).to.exist;
|
||||
var t2 = time.t;
|
||||
expect(Math.abs(t1 - t2)).is.below(200);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('resolves reference IP', function (done) {
|
||||
|
||||
Sntp.time({ host: 'ntp.exnet.com', resolveReference: true }, function (err, time) {
|
||||
|
||||
expect(err).to.not.exist;
|
||||
expect(time).to.exist;
|
||||
expect(time.referenceHost).to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('times out on no response', function (done) {
|
||||
|
||||
Sntp.time({ port: 124, timeout: 100 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time).to.not.exist;
|
||||
expect(err.message).to.equal('Timeout');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('errors on error event', function (done) {
|
||||
|
||||
var orig = Dgram.createSocket;
|
||||
Dgram.createSocket = function (type) {
|
||||
|
||||
Dgram.createSocket = orig;
|
||||
var socket = Dgram.createSocket(type);
|
||||
process.nextTick(function () { socket.emit('error', new Error('Fake')) });
|
||||
return socket;
|
||||
};
|
||||
|
||||
Sntp.time(function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time).to.not.exist;
|
||||
expect(err.message).to.equal('Fake');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('times out on invalid host', function (done) {
|
||||
|
||||
Sntp.time({ host: 'error', timeout: 10000 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time).to.not.exist;
|
||||
expect(err.message).to.equal('getaddrinfo ENOTFOUND');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad response buffer size', function (done) {
|
||||
|
||||
var server = Dgram.createSocket('udp4');
|
||||
server.on('message', function (message, remote) {
|
||||
var message = new Buffer(10);
|
||||
server.send(message, 0, message.length, remote.port, remote.address, function (err, bytes) {
|
||||
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
server.bind(49123);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(err.message).to.equal('Invalid server response');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
var messup = function (bytes) {
|
||||
|
||||
var server = Dgram.createSocket('udp4');
|
||||
server.on('message', function (message, remote) {
|
||||
|
||||
var message = new Buffer([
|
||||
0x24, 0x01, 0x00, 0xe3,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x41, 0x43, 0x54, 0x53,
|
||||
0xd4, 0xa8, 0x2d, 0xc7,
|
||||
0x1c, 0x5d, 0x49, 0x1b,
|
||||
0xd4, 0xa8, 0x2d, 0xe6,
|
||||
0x67, 0xef, 0x9d, 0xb2,
|
||||
0xd4, 0xa8, 0x2d, 0xe6,
|
||||
0x71, 0xed, 0xb5, 0xfb,
|
||||
0xd4, 0xa8, 0x2d, 0xe6,
|
||||
0x71, 0xee, 0x6c, 0xc5
|
||||
]);
|
||||
|
||||
for (var i = 0, il = bytes.length; i < il; ++i) {
|
||||
message[bytes[i][0]] = bytes[i][1];
|
||||
}
|
||||
|
||||
server.send(message, 0, message.length, remote.port, remote.address, function (err, bytes) {
|
||||
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
server.bind(49123);
|
||||
};
|
||||
|
||||
it('fails on bad version', function (done) {
|
||||
|
||||
messup([[0, (0 << 6) + (3 << 3) + (4 << 0)]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time.version).to.equal(3);
|
||||
expect(err.message).to.equal('Invalid server response');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad originate timestamp and alarm li', function (done) {
|
||||
|
||||
messup([[0, (3 << 6) + (4 << 3) + (4 << 0)]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(err.message).to.equal('Wrong originate timestamp');
|
||||
expect(time.leapIndicator).to.equal('alarm');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns time with death stratum and last61 li', function (done) {
|
||||
|
||||
messup([[0, (1 << 6) + (4 << 3) + (4 << 0)], [1, 0]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(time.stratum).to.equal('death');
|
||||
expect(time.leapIndicator).to.equal('last-minute-61');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns time with reserved stratum and last59 li', function (done) {
|
||||
|
||||
messup([[0, (2 << 6) + (4 << 3) + (4 << 0)], [1, 0x1f]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(time.stratum).to.equal('reserved');
|
||||
expect(time.leapIndicator).to.equal('last-minute-59');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad mode (symmetric-active)', function (done) {
|
||||
|
||||
messup([[0, (0 << 6) + (4 << 3) + (1 << 0)]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time.mode).to.equal('symmetric-active');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad mode (symmetric-passive)', function (done) {
|
||||
|
||||
messup([[0, (0 << 6) + (4 << 3) + (2 << 0)]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time.mode).to.equal('symmetric-passive');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad mode (client)', function (done) {
|
||||
|
||||
messup([[0, (0 << 6) + (4 << 3) + (3 << 0)]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time.mode).to.equal('client');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad mode (broadcast)', function (done) {
|
||||
|
||||
messup([[0, (0 << 6) + (4 << 3) + (5 << 0)]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time.mode).to.equal('broadcast');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad mode (reserved)', function (done) {
|
||||
|
||||
messup([[0, (0 << 6) + (4 << 3) + (6 << 0)]]);
|
||||
|
||||
Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(time.mode).to.equal('reserved');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#offset', function () {
|
||||
|
||||
it('gets the current offset', function (done) {
|
||||
|
||||
Sntp.offset(function (err, offset) {
|
||||
|
||||
expect(err).to.not.exist;
|
||||
expect(offset).to.not.equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('gets the current offset from cache', function (done) {
|
||||
|
||||
Sntp.offset(function (err, offset) {
|
||||
|
||||
expect(err).to.not.exist;
|
||||
expect(offset).to.not.equal(0);
|
||||
var offset1 = offset;
|
||||
Sntp.offset({}, function (err, offset) {
|
||||
|
||||
expect(err).to.not.exist;
|
||||
expect(offset).to.equal(offset1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('fails getting the current offset on invalid server', function (done) {
|
||||
|
||||
Sntp.offset({ host: 'error' }, function (err, offset) {
|
||||
|
||||
expect(err).to.exist;
|
||||
expect(offset).to.equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#now', function () {
|
||||
|
||||
it('starts auto-sync, gets now, then stops', function (done) {
|
||||
|
||||
Sntp.stop();
|
||||
|
||||
var before = Sntp.now();
|
||||
expect(before).to.equal(Date.now());
|
||||
|
||||
Sntp.start(function () {
|
||||
|
||||
var now = Sntp.now();
|
||||
expect(now).to.not.equal(Date.now());
|
||||
Sntp.stop();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('starts twice', function (done) {
|
||||
|
||||
Sntp.start(function () {
|
||||
|
||||
Sntp.start(function () {
|
||||
|
||||
var now = Sntp.now();
|
||||
expect(now).to.not.equal(Date.now());
|
||||
Sntp.stop();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('starts auto-sync, gets now, waits, gets again after timeout', function (done) {
|
||||
|
||||
Sntp.stop();
|
||||
|
||||
var before = Sntp.now();
|
||||
expect(before).to.equal(Date.now());
|
||||
|
||||
Sntp.start({ clockSyncRefresh: 100 }, function () {
|
||||
|
||||
var now = Sntp.now();
|
||||
expect(now).to.not.equal(Date.now());
|
||||
expect(now).to.equal(Sntp.now());
|
||||
|
||||
setTimeout(function () {
|
||||
|
||||
expect(Sntp.now()).to.not.equal(now);
|
||||
Sntp.stop();
|
||||
done();
|
||||
}, 110);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue