-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
nts.js
83 lines (74 loc) · 3.19 KB
/
nts.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
;(function(){
var Gun = (typeof window !== "undefined")? window.Gun : require('./gun');
var dam = 'nts';
var smooth = 2;
Gun.on('create', function(root){ // switch to DAM, deprecated old
Gun.log.once("nts", "gun/nts is removed deprecated old");
this.to.next(root);
return ; // stub out for now. TODO: IMPORTANT! re-add back in later.
var opt = root.opt, mesh = opt.mesh;
if(!mesh) return;
// Track connections
var connections = [];
root.on('hi', function(peer) {
this.to.next(peer);
connections.push({peer, latency: 0, offset: 0, next: 0});
});
root.on('bye', function(peer) {
this.to.next(peer);
var found = connections.find(connection => connection.peer.id == peer.id);
if (!found) return;
connections.splice(connections.indexOf(found), 1);
});
function response(msg, connection) {
var now = Date.now(); // Lack of drift intentional, provides more accurate RTT
connection.latency = (now - msg.nts[0]) / 2;
connection.offset = (msg.nts[1] + connection.latency) - (now + Gun.state.drift);
console.log(connection.offset);
Gun.state.drift += connection.offset / (connections.length + smooth);
console.log(`Update time by local: ${connection.offset} / ${connections.length + smooth}`);
}
// Handle echo & setting based on known connection latency as well
mesh.hear[dam] = function(msg, peer) {
console.log('MSG', msg);
var now = Date.now() + Gun.state.drift;
var connection = connections.find(connection => connection.peer.id == peer.id);
if (!connection) return;
if (msg.nts.length >= 2) return response(msg, connection);
mesh.say({dam, '@': msg['#'], nts: msg.nts.concat(now)}, peer);
connection.offset = msg.nts[0] + connection.latency - now;
Gun.state.drift += connection.offset / (connections.length + smooth);
console.log(`Update time by remote: ${connection.offset} / ${connections.length + smooth}`);
};
// Handle ping transmission
setTimeout(function trigger() {
console.log('TRIGGER');
if (!connections.length) return setTimeout(trigger, 100);
var now = Date.now(); // Lack of drift intentional, provides more accurate RTT & NTP reference
// Send pings
connections.forEach(function(connection) {
if (connection.next > now) return;
mesh.say({
dam,
'#': String.random(3),
nts: [now],
});
});
// Plan next round of pings
connections.forEach(function(connection) {
if (connection.next > now) return;
// https://discord.com/channels/612645357850984470/612645357850984473/755334349699809300
var delay = Math.min(2e4, Math.max(250, 150000 / Math.abs((connection.offset)||1)));
connection.next = now + delay;
});
// Plan next trigger round
// May overshoot by runtime of this function
var nextRound = Infinity;
connections.forEach(function(connection) {
nextRound = Math.min(nextRound, connection.next);
});
setTimeout(trigger, nextRound - now);
console.log(`Next sync round in ${(nextRound - now) / 1000} seconds`);
}, 1);
});
}());