0.884
This commit is contained in:
1
Source/lib/_run.bat
Normal file
1
Source/lib/_run.bat
Normal file
@@ -0,0 +1 @@
|
||||
browserify test.js > stun-lib.js
|
||||
4
Source/lib/bintrees/index.js
Normal file
4
Source/lib/bintrees/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
RBTree: require('./lib/rbtree'),
|
||||
BinTree: require('./lib/bintree')
|
||||
};
|
||||
108
Source/lib/bintrees/lib/bintree.js
Normal file
108
Source/lib/bintrees/lib/bintree.js
Normal file
@@ -0,0 +1,108 @@
|
||||
|
||||
var TreeBase = require('./treebase');
|
||||
|
||||
function Node(data) {
|
||||
this.data = data;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
|
||||
Node.prototype.get_child = function(dir) {
|
||||
return dir ? this.right : this.left;
|
||||
};
|
||||
|
||||
Node.prototype.set_child = function(dir, val) {
|
||||
if(dir) {
|
||||
this.right = val;
|
||||
}
|
||||
else {
|
||||
this.left = val;
|
||||
}
|
||||
};
|
||||
|
||||
function BinTree(comparator) {
|
||||
this._root = null;
|
||||
this._comparator = comparator;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
BinTree.prototype = new TreeBase();
|
||||
|
||||
// returns true if inserted, false if duplicate
|
||||
BinTree.prototype.insert = function(data) {
|
||||
if(this._root === null) {
|
||||
// empty tree
|
||||
this._root = new Node(data);
|
||||
this.size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
var dir = 0;
|
||||
|
||||
// setup
|
||||
var p = null; // parent
|
||||
var node = this._root;
|
||||
|
||||
// search down
|
||||
while(true) {
|
||||
if(node === null) {
|
||||
// insert new node at the bottom
|
||||
node = new Node(data);
|
||||
p.set_child(dir, node);
|
||||
ret = true;
|
||||
this.size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// stop if found
|
||||
if(this._comparator(node.data, data) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dir = this._comparator(node.data, data) < 0;
|
||||
|
||||
// update helpers
|
||||
p = node;
|
||||
node = node.get_child(dir);
|
||||
}
|
||||
};
|
||||
|
||||
// returns true if removed, false if not found
|
||||
BinTree.prototype.remove = function(data) {
|
||||
if(this._root === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var head = new Node(undefined); // fake tree root
|
||||
var node = head;
|
||||
node.right = this._root;
|
||||
var p = null; // parent
|
||||
var found = null; // found item
|
||||
var dir = 1;
|
||||
|
||||
while(node.get_child(dir) !== null) {
|
||||
p = node;
|
||||
node = node.get_child(dir);
|
||||
var cmp = this._comparator(data, node.data);
|
||||
dir = cmp > 0;
|
||||
|
||||
if(cmp === 0) {
|
||||
found = node;
|
||||
}
|
||||
}
|
||||
|
||||
if(found !== null) {
|
||||
found.data = node.data;
|
||||
p.set_child(p.right === node, node.get_child(node.left === null));
|
||||
|
||||
this._root = head.right;
|
||||
this.size--;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = BinTree;
|
||||
|
||||
218
Source/lib/bintrees/lib/rbtree.js
Normal file
218
Source/lib/bintrees/lib/rbtree.js
Normal file
@@ -0,0 +1,218 @@
|
||||
|
||||
var TreeBase = require('./treebase');
|
||||
|
||||
function Node(data) {
|
||||
this.data = data;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
this.red = true;
|
||||
}
|
||||
|
||||
Node.prototype.get_child = function(dir) {
|
||||
return dir ? this.right : this.left;
|
||||
};
|
||||
|
||||
Node.prototype.set_child = function(dir, val) {
|
||||
if(dir) {
|
||||
this.right = val;
|
||||
}
|
||||
else {
|
||||
this.left = val;
|
||||
}
|
||||
};
|
||||
|
||||
function RBTree(comparator) {
|
||||
this._root = null;
|
||||
this._comparator = comparator;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
RBTree.prototype = new TreeBase();
|
||||
|
||||
// returns true if inserted, false if duplicate
|
||||
RBTree.prototype.insert = function(data) {
|
||||
var ret = false;
|
||||
|
||||
if(this._root === null) {
|
||||
// empty tree
|
||||
this._root = new Node(data);
|
||||
ret = true;
|
||||
this.size++;
|
||||
}
|
||||
else {
|
||||
var head = new Node(undefined); // fake tree root
|
||||
|
||||
var dir = 0;
|
||||
var last = 0;
|
||||
|
||||
// setup
|
||||
var gp = null; // grandparent
|
||||
var ggp = head; // grand-grand-parent
|
||||
var p = null; // parent
|
||||
var node = this._root;
|
||||
ggp.right = this._root;
|
||||
|
||||
// search down
|
||||
while(true) {
|
||||
if(node === null) {
|
||||
// insert new node at the bottom
|
||||
node = new Node(data);
|
||||
p.set_child(dir, node);
|
||||
ret = true;
|
||||
this.size++;
|
||||
}
|
||||
else if(is_red(node.left) && is_red(node.right)) {
|
||||
// color flip
|
||||
node.red = true;
|
||||
node.left.red = false;
|
||||
node.right.red = false;
|
||||
}
|
||||
|
||||
// fix red violation
|
||||
if(is_red(node) && is_red(p)) {
|
||||
var dir2 = ggp.right === gp;
|
||||
|
||||
if(node === p.get_child(last)) {
|
||||
ggp.set_child(dir2, single_rotate(gp, !last));
|
||||
}
|
||||
else {
|
||||
ggp.set_child(dir2, double_rotate(gp, !last));
|
||||
}
|
||||
}
|
||||
|
||||
var cmp = this._comparator(node.data, data);
|
||||
|
||||
// stop if found
|
||||
if(cmp === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
last = dir;
|
||||
dir = cmp < 0;
|
||||
|
||||
// update helpers
|
||||
if(gp !== null) {
|
||||
ggp = gp;
|
||||
}
|
||||
gp = p;
|
||||
p = node;
|
||||
node = node.get_child(dir);
|
||||
}
|
||||
|
||||
// update root
|
||||
this._root = head.right;
|
||||
}
|
||||
|
||||
// make root black
|
||||
this._root.red = false;
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
// returns true if removed, false if not found
|
||||
RBTree.prototype.remove = function(data) {
|
||||
if(this._root === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var head = new Node(undefined); // fake tree root
|
||||
var node = head;
|
||||
node.right = this._root;
|
||||
var p = null; // parent
|
||||
var gp = null; // grand parent
|
||||
var found = null; // found item
|
||||
var dir = 1;
|
||||
|
||||
while(node.get_child(dir) !== null) {
|
||||
var last = dir;
|
||||
|
||||
// update helpers
|
||||
gp = p;
|
||||
p = node;
|
||||
node = node.get_child(dir);
|
||||
|
||||
var cmp = this._comparator(data, node.data);
|
||||
|
||||
dir = cmp > 0;
|
||||
|
||||
// save found node
|
||||
if(cmp === 0) {
|
||||
found = node;
|
||||
}
|
||||
|
||||
// push the red node down
|
||||
if(!is_red(node) && !is_red(node.get_child(dir))) {
|
||||
if(is_red(node.get_child(!dir))) {
|
||||
var sr = single_rotate(node, dir);
|
||||
p.set_child(last, sr);
|
||||
p = sr;
|
||||
}
|
||||
else if(!is_red(node.get_child(!dir))) {
|
||||
var sibling = p.get_child(!last);
|
||||
if(sibling !== null) {
|
||||
if(!is_red(sibling.get_child(!last)) && !is_red(sibling.get_child(last))) {
|
||||
// color flip
|
||||
p.red = false;
|
||||
sibling.red = true;
|
||||
node.red = true;
|
||||
}
|
||||
else {
|
||||
var dir2 = gp.right === p;
|
||||
|
||||
if(is_red(sibling.get_child(last))) {
|
||||
gp.set_child(dir2, double_rotate(p, last));
|
||||
}
|
||||
else if(is_red(sibling.get_child(!last))) {
|
||||
gp.set_child(dir2, single_rotate(p, last));
|
||||
}
|
||||
|
||||
// ensure correct coloring
|
||||
var gpc = gp.get_child(dir2);
|
||||
gpc.red = true;
|
||||
node.red = true;
|
||||
gpc.left.red = false;
|
||||
gpc.right.red = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// replace and remove if found
|
||||
if(found !== null) {
|
||||
found.data = node.data;
|
||||
p.set_child(p.right === node, node.get_child(node.left === null));
|
||||
this.size--;
|
||||
}
|
||||
|
||||
// update root and make it black
|
||||
this._root = head.right;
|
||||
if(this._root !== null) {
|
||||
this._root.red = false;
|
||||
}
|
||||
|
||||
return found !== null;
|
||||
};
|
||||
|
||||
function is_red(node) {
|
||||
return node !== null && node.red;
|
||||
}
|
||||
|
||||
function single_rotate(root, dir) {
|
||||
var save = root.get_child(!dir);
|
||||
|
||||
root.set_child(!dir, save.get_child(dir));
|
||||
save.set_child(dir, root);
|
||||
|
||||
root.red = true;
|
||||
save.red = false;
|
||||
|
||||
return save;
|
||||
}
|
||||
|
||||
function double_rotate(root, dir) {
|
||||
root.set_child(!dir, single_rotate(root.get_child(!dir), !dir));
|
||||
return single_rotate(root, dir);
|
||||
}
|
||||
|
||||
module.exports = RBTree;
|
||||
235
Source/lib/bintrees/lib/treebase.js
Normal file
235
Source/lib/bintrees/lib/treebase.js
Normal file
@@ -0,0 +1,235 @@
|
||||
|
||||
function TreeBase() {}
|
||||
|
||||
// removes all nodes from the tree
|
||||
TreeBase.prototype.clear = function() {
|
||||
this._root = null;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
// returns node data if found, null otherwise
|
||||
TreeBase.prototype.find = function(data) {
|
||||
var res = this._root;
|
||||
|
||||
while(res !== null) {
|
||||
var c = this._comparator(data, res.data);
|
||||
if(c === 0) {
|
||||
return res.data;
|
||||
}
|
||||
else {
|
||||
res = res.get_child(c > 0);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// returns iterator to node if found, null otherwise
|
||||
TreeBase.prototype.findIter = function(data) {
|
||||
var res = this._root;
|
||||
var iter = this.iterator();
|
||||
|
||||
while(res !== null) {
|
||||
var c = this._comparator(data, res.data);
|
||||
if(c === 0) {
|
||||
iter._cursor = res;
|
||||
return iter;
|
||||
}
|
||||
else {
|
||||
iter._ancestors.push(res);
|
||||
res = res.get_child(c > 0);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Returns an iterator to the tree node at or immediately after the item
|
||||
TreeBase.prototype.lowerBound = function(item) {
|
||||
var cur = this._root;
|
||||
var iter = this.iterator();
|
||||
var cmp = this._comparator;
|
||||
|
||||
while(cur !== null) {
|
||||
var c = cmp(item, cur.data);
|
||||
if(c === 0) {
|
||||
iter._cursor = cur;
|
||||
return iter;
|
||||
}
|
||||
iter._ancestors.push(cur);
|
||||
cur = cur.get_child(c > 0);
|
||||
}
|
||||
|
||||
for(var i=iter._ancestors.length - 1; i >= 0; --i) {
|
||||
cur = iter._ancestors[i];
|
||||
if(cmp(item, cur.data) < 0) {
|
||||
iter._cursor = cur;
|
||||
iter._ancestors.length = i;
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
|
||||
iter._ancestors.length = 0;
|
||||
return iter;
|
||||
};
|
||||
|
||||
// Returns an iterator to the tree node immediately after the item
|
||||
TreeBase.prototype.upperBound = function(item) {
|
||||
var iter = this.lowerBound(item);
|
||||
var cmp = this._comparator;
|
||||
|
||||
while(iter.data() !== null && cmp(iter.data(), item) === 0) {
|
||||
iter.next();
|
||||
}
|
||||
|
||||
return iter;
|
||||
};
|
||||
|
||||
// returns null if tree is empty
|
||||
TreeBase.prototype.min = function() {
|
||||
var res = this._root;
|
||||
if(res === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while(res.left !== null) {
|
||||
res = res.left;
|
||||
}
|
||||
|
||||
return res.data;
|
||||
};
|
||||
|
||||
// returns null if tree is empty
|
||||
TreeBase.prototype.max = function() {
|
||||
var res = this._root;
|
||||
if(res === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while(res.right !== null) {
|
||||
res = res.right;
|
||||
}
|
||||
|
||||
return res.data;
|
||||
};
|
||||
|
||||
// returns a null iterator
|
||||
// call next() or prev() to point to an element
|
||||
TreeBase.prototype.iterator = function() {
|
||||
return new Iterator(this);
|
||||
};
|
||||
|
||||
// calls cb on each node's data, in order
|
||||
TreeBase.prototype.each = function(cb) {
|
||||
var it=this.iterator(), data;
|
||||
while((data = it.next()) !== null) {
|
||||
if(cb(data) === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// calls cb on each node's data, in reverse order
|
||||
TreeBase.prototype.reach = function(cb) {
|
||||
var it=this.iterator(), data;
|
||||
while((data = it.prev()) !== null) {
|
||||
if(cb(data) === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function Iterator(tree) {
|
||||
this._tree = tree;
|
||||
this._ancestors = [];
|
||||
this._cursor = null;
|
||||
}
|
||||
|
||||
Iterator.prototype.data = function() {
|
||||
return this._cursor !== null ? this._cursor.data : null;
|
||||
};
|
||||
|
||||
// if null-iterator, returns first node
|
||||
// otherwise, returns next node
|
||||
Iterator.prototype.next = function() {
|
||||
if(this._cursor === null) {
|
||||
var root = this._tree._root;
|
||||
if(root !== null) {
|
||||
this._minNode(root);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(this._cursor.right === null) {
|
||||
// no greater node in subtree, go up to parent
|
||||
// if coming from a right child, continue up the stack
|
||||
var save;
|
||||
do {
|
||||
save = this._cursor;
|
||||
if(this._ancestors.length) {
|
||||
this._cursor = this._ancestors.pop();
|
||||
}
|
||||
else {
|
||||
this._cursor = null;
|
||||
break;
|
||||
}
|
||||
} while(this._cursor.right === save);
|
||||
}
|
||||
else {
|
||||
// get the next node from the subtree
|
||||
this._ancestors.push(this._cursor);
|
||||
this._minNode(this._cursor.right);
|
||||
}
|
||||
}
|
||||
return this._cursor !== null ? this._cursor.data : null;
|
||||
};
|
||||
|
||||
// if null-iterator, returns last node
|
||||
// otherwise, returns previous node
|
||||
Iterator.prototype.prev = function() {
|
||||
if(this._cursor === null) {
|
||||
var root = this._tree._root;
|
||||
if(root !== null) {
|
||||
this._maxNode(root);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(this._cursor.left === null) {
|
||||
var save;
|
||||
do {
|
||||
save = this._cursor;
|
||||
if(this._ancestors.length) {
|
||||
this._cursor = this._ancestors.pop();
|
||||
}
|
||||
else {
|
||||
this._cursor = null;
|
||||
break;
|
||||
}
|
||||
} while(this._cursor.left === save);
|
||||
}
|
||||
else {
|
||||
this._ancestors.push(this._cursor);
|
||||
this._maxNode(this._cursor.left);
|
||||
}
|
||||
}
|
||||
return this._cursor !== null ? this._cursor.data : null;
|
||||
};
|
||||
|
||||
Iterator.prototype._minNode = function(start) {
|
||||
while(start.left !== null) {
|
||||
this._ancestors.push(start);
|
||||
start = start.left;
|
||||
}
|
||||
this._cursor = start;
|
||||
};
|
||||
|
||||
Iterator.prototype._maxNode = function(start) {
|
||||
while(start.right !== null) {
|
||||
this._ancestors.push(start);
|
||||
start = start.right;
|
||||
}
|
||||
this._cursor = start;
|
||||
};
|
||||
|
||||
module.exports = TreeBase;
|
||||
|
||||
22
Source/lib/ntp-client/.gitattributes
vendored
Normal file
22
Source/lib/ntp-client/.gitattributes
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
*.sln merge=union
|
||||
*.csproj merge=union
|
||||
*.vbproj merge=union
|
||||
*.fsproj merge=union
|
||||
*.dbproj merge=union
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
4
Source/lib/ntp-client/.jshintrc
Normal file
4
Source/lib/ntp-client/.jshintrc
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"node": true,
|
||||
"strict": true
|
||||
}
|
||||
3
Source/lib/ntp-client/.npmignore
Normal file
3
Source/lib/ntp-client/.npmignore
Normal file
@@ -0,0 +1,3 @@
|
||||
*.sublime-workspace
|
||||
.idea
|
||||
node_modules/
|
||||
10
Source/lib/ntp-client/.travis.yml
Normal file
10
Source/lib/ntp-client/.travis.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- "0.10"
|
||||
before_script:
|
||||
- npm install -g grunt-cli
|
||||
|
||||
notifications:
|
||||
on_success: never
|
||||
on_failure: always
|
||||
48
Source/lib/ntp-client/Gruntfile.js
Normal file
48
Source/lib/ntp-client/Gruntfile.js
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (grunt) {
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
nodeunit: {
|
||||
files: ['test/**/*_test.js']
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
},
|
||||
gruntfile: {
|
||||
src: 'Gruntfile.js'
|
||||
},
|
||||
lib: {
|
||||
src: ['lib/**/*.js']
|
||||
},
|
||||
test: {
|
||||
src: ['test/**/*.js']
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
gruntfile: {
|
||||
files: '<%= jshint.gruntfile.src %>',
|
||||
tasks: ['jshint:gruntfile']
|
||||
},
|
||||
lib: {
|
||||
files: '<%= jshint.lib.src %>',
|
||||
tasks: ['jshint:lib', 'nodeunit']
|
||||
},
|
||||
test: {
|
||||
files: '<%= jshint.test.src %>',
|
||||
tasks: ['jshint:test', 'nodeunit']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// These plugins provide necessary tasks.
|
||||
grunt.loadNpmTasks('grunt-contrib-nodeunit');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
|
||||
// Default task.
|
||||
grunt.registerTask('default', ['jshint', 'nodeunit']);
|
||||
|
||||
};
|
||||
22
Source/lib/ntp-client/LICENSE-MIT
Normal file
22
Source/lib/ntp-client/LICENSE-MIT
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2013 Clément Bourgeois
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
29
Source/lib/ntp-client/README.md
Normal file
29
Source/lib/ntp-client/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# ntp-client [](http://travis-ci.org/moonpyk/node-ntp-client)
|
||||
|
||||
Pure Javascript implementation of the NTP Client Protocol
|
||||
|
||||
## Getting Started
|
||||
Install the module with: `npm install ntp-client`
|
||||
|
||||
```javascript
|
||||
var ntpClient = require('ntp-client');
|
||||
|
||||
ntpClient.getNetworkTime("pool.ntp.org", 123, function(err, date) {
|
||||
if(err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Current time : ");
|
||||
console.log(date); // Mon Jul 08 2013 21:31:31 GMT+0200 (Paris, Madrid (heure d’été))
|
||||
});
|
||||
```
|
||||
|
||||
## Contributors
|
||||
* Clément Bourgeois (https://github.com/moonpyk)
|
||||
* Callan Bryant (https://github.com/naggie)
|
||||
|
||||
## License
|
||||
Copyright (c) 2014 Clément Bourgeois
|
||||
Licensed under the MIT license.
|
||||
|
||||
3
Source/lib/ntp-client/bin/node-ntp-client
Normal file
3
Source/lib/ntp-client/bin/node-ntp-client
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('../lib/ntp-client.js').demo(process.argv);
|
||||
128
Source/lib/ntp-client/lib/ntp-client.js
Normal file
128
Source/lib/ntp-client/lib/ntp-client.js
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* ntp-client
|
||||
* https://github.com/moonpyk/node-ntp-client
|
||||
*
|
||||
* Copyright (c) 2013 Clément Bourgeois
|
||||
* Licensed under the MIT license.
|
||||
*/
|
||||
|
||||
(function (exports) {
|
||||
"use strict";
|
||||
|
||||
var dgram = require('dgram');
|
||||
|
||||
exports.defaultNtpPort = 123;
|
||||
exports.defaultNtpServer = "pool.ntp.org";
|
||||
|
||||
/**
|
||||
* Amount of acceptable time to await for a response from the remote server.
|
||||
* Configured default to 10 seconds.
|
||||
*/
|
||||
exports.ntpReplyTimeout = 10000;
|
||||
|
||||
/**
|
||||
* Fetches the current NTP Time from the given server and port.
|
||||
* @param {string} server IP/Hostname of the remote NTP Server
|
||||
* @param {number} port Remote NTP Server port number
|
||||
* @param {function(Object, Date)} callback(err, date) Async callback for
|
||||
* the result date or eventually error.
|
||||
*/
|
||||
exports.getNetworkTime = function (server, port, callback) {
|
||||
if (callback === null || typeof callback !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
server = server || exports.defaultNtpServer;
|
||||
port = port || exports.defaultNtpPort;
|
||||
|
||||
var client = dgram.createSocket("udp4"),
|
||||
ntpData = new Buffer(48);
|
||||
|
||||
// RFC 2030 -> LI = 0 (no warning, 2 bits), VN = 3 (IPv4 only, 3 bits), Mode = 3 (Client Mode, 3 bits) -> 1 byte
|
||||
// -> rtol(LI, 6) ^ rotl(VN, 3) ^ rotl(Mode, 0)
|
||||
// -> = 0x00 ^ 0x18 ^ 0x03
|
||||
ntpData[0] = 0x1B;
|
||||
|
||||
for (var i = 1; i < 48; i++) {
|
||||
ntpData[i] = 0;
|
||||
}
|
||||
|
||||
var timeout = setTimeout(function () {
|
||||
client.close();
|
||||
callback("Timeout waiting for NTP response.", null);
|
||||
}, exports.ntpReplyTimeout);
|
||||
|
||||
// Some errors can happen before/after send() or cause send() to was impossible.
|
||||
// Some errors will also be given to the send() callback.
|
||||
// We keep a flag, therefore, to prevent multiple callbacks.
|
||||
// NOTE : the error callback is not generalised, as the client has to lose the connection also, apparently.
|
||||
var errorFired = false;
|
||||
|
||||
client.on('error', function (err) {
|
||||
if (errorFired) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(err, null);
|
||||
errorFired = true;
|
||||
|
||||
clearTimeout(timeout);
|
||||
});
|
||||
|
||||
client.send(ntpData, 0, ntpData.length, port, server, function (err) {
|
||||
if (err) {
|
||||
if (errorFired) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
callback(err, null);
|
||||
errorFired = true;
|
||||
client.close();
|
||||
return;
|
||||
}
|
||||
|
||||
client.once('message', function (msg) {
|
||||
clearTimeout(timeout);
|
||||
client.close();
|
||||
|
||||
// Offset to get to the "Transmit Timestamp" field (time at which the reply
|
||||
// departed the server for the client, in 64-bit timestamp format."
|
||||
var offsetTransmitTime = 40,
|
||||
intpart = 0,
|
||||
fractpart = 0;
|
||||
|
||||
// Get the seconds part
|
||||
for (var i = 0; i <= 3; i++) {
|
||||
intpart = 256 * intpart + msg[offsetTransmitTime + i];
|
||||
}
|
||||
|
||||
// Get the seconds fraction
|
||||
for (i = 4; i <= 7; i++) {
|
||||
fractpart = 256 * fractpart + msg[offsetTransmitTime + i];
|
||||
}
|
||||
|
||||
var milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000);
|
||||
|
||||
// **UTC** time
|
||||
var date = new Date("Jan 01 1900 GMT");
|
||||
date.setUTCMilliseconds(date.getUTCMilliseconds() + milliseconds);
|
||||
|
||||
callback(null, date);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.demo = function (argv) {
|
||||
exports.getNetworkTime(
|
||||
exports.defaultNtpServer,
|
||||
exports.defaultNtpPort,
|
||||
function (err, date) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(date);
|
||||
});
|
||||
};
|
||||
}(exports));
|
||||
12
Source/lib/ntp-client/node-ntp-client.sublime-project
Normal file
12
Source/lib/ntp-client/node-ntp-client.sublime-project
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": ".",
|
||||
"file_exclude_patterns": ["*.sublime-workspace", "*.project"],
|
||||
"folder_exclude_patterns": ["*.*"]
|
||||
}
|
||||
],
|
||||
"ternjs": {
|
||||
"exclude": ["node_modules/**"]
|
||||
}
|
||||
}
|
||||
71
Source/lib/ntp-client/package.json
Normal file
71
Source/lib/ntp-client/package.json
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"_from": "ntp-client",
|
||||
"_id": "ntp-client@0.5.3",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-A8DI2mfj9Jl9oIPUaC3M4NkgijU=",
|
||||
"_location": "/ntp-client",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "ntp-client",
|
||||
"name": "ntp-client",
|
||||
"escapedName": "ntp-client",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ntp-client/-/ntp-client-0.5.3.tgz",
|
||||
"_shasum": "03c0c8da67e3f4997da083d4682dcce0d9208a35",
|
||||
"_spec": "ntp-client",
|
||||
"_where": "C:\\VC++\\NodeJS\\MyMoney\\NW-Build",
|
||||
"author": {
|
||||
"name": "Clément Bourgeois",
|
||||
"email": "moonpyk@gmail.com",
|
||||
"url": "http://www.moonpyk.net"
|
||||
},
|
||||
"bin": {
|
||||
"node-ntp-client": "bin/node-ntp-client"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/moonpyk/node-ntp-client/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Pure Javascript implementation of the NTP Client Protocol",
|
||||
"devDependencies": {
|
||||
"grunt": ">= 0.4.1",
|
||||
"grunt-contrib-jshint": ">= 0.6.0",
|
||||
"grunt-contrib-nodeunit": ">= 0.2.0",
|
||||
"grunt-contrib-watch": ">= 0.4.0",
|
||||
"nodeunit": ">= 0.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
},
|
||||
"homepage": "https://github.com/moonpyk/node-ntp-client",
|
||||
"keywords": [
|
||||
"date",
|
||||
"ntp"
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/moonpyk/node-ntp-client/blob/master/LICENSE-MIT"
|
||||
}
|
||||
],
|
||||
"main": "lib/ntp-client",
|
||||
"name": "ntp-client",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/moonpyk/node-ntp-client.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "grunt jshint nodeunit"
|
||||
},
|
||||
"version": "0.5.3"
|
||||
}
|
||||
11
Source/lib/test.js
Normal file
11
Source/lib/test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
global.Stun = require('stun');
|
||||
|
||||
//var server = Stun.createServer();
|
||||
//console.log("server="+server);
|
||||
//console.log("server");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user