summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/cometd/timesync.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/cometd/timesync.js')
-rw-r--r--js/dojo/dojox/cometd/timesync.js146
1 files changed, 146 insertions, 0 deletions
diff --git a/js/dojo/dojox/cometd/timesync.js b/js/dojo/dojox/cometd/timesync.js
new file mode 100644
index 0000000..586f65d
--- /dev/null
+++ b/js/dojo/dojox/cometd/timesync.js
@@ -0,0 +1,146 @@
+//>>built
+// wrapped by build app
+define("dojox/cometd/timesync", ["dijit","dojo","dojox","dojo/require!dojox/cometd/_base"], function(dijit,dojo,dojox){
+dojo.provide("dojox.cometd.timesync");
+dojo.require("dojox.cometd._base");
+
+/**
+ * this file provides the time synchronization extension to cometd.
+ * Timesync allows the client and server to exchange time information on every
+ * handshake and connect message so that the client may calculate an approximate
+ * offset from it's own clock epoch to that of the server.
+ *
+ * With each handshake or connect, the extension sends timestamps within the
+ * ext field like: <code>{ext:{timesync:{tc:12345567890,l:23,o:4567},...},...}</code>
+ * where:<ul>
+ * <li>tc is the client timestamp in ms since 1970 of when the message was sent.
+ * <li>l is the network lag that the client has calculated.
+ * <li>o is the clock offset that the client has calculated.
+ * </ul>
+ * The accuracy of the offset and lag may be calculated with tc-now-l-o,
+ * which should be zero if the calculated offset and lag are perfectly
+ * accurate.
+ * <p>
+ * A cometd server that supports timesync, should respond only if the
+ * measured accuracy value is greater than accuracy target. The response
+ * will be an ext field like: <code>{ext:{timesync:{tc:12345567890,ts:1234567900,p:123,a:3},...},...}</code>
+ * where:<ul>
+ * <li>tc is the client timestamp of when the message was sent,
+ * <li>ts is the server timestamp of when the message was received
+ * <li>p is the poll duration in ms - ie the time the server took before sending the response.
+ * <li>a is the measured accuracy of the calculated offset and lag sent by the client
+ * </ul>
+ *
+ * On receipt of the response, the client is able to use current time to determine
+ * the total trip time, from which p is subtracted to determine an approximate
+ * two way network traversal time. The measured accuracy is used to adjust the assumption
+ * that the network is symmetric for traversal time, so: <ul>
+ * <li>lag = (now-tc-p)/2-a
+ * <li>offset = ts-tc-lag
+ * </ul>
+ *
+ * In order to smooth over any transient fluctuations, the extension keeps a sliding
+ * average of the offsets received. By default this is over 10 messages, but this can
+ * be changed with the dojox.cometd.timesync._window element.
+ */
+dojox.cometd.timesync = new function(){
+ this._window = 10; // The window size for the sliding average of offset samples.
+ this._lags = []; // The samples used to calculate the average lag.
+ this._offsets = []; // The samples used to calculate the average offset.
+ this.lag=0; // The calculated network lag from client to server
+ this.offset = 0; // The offset in ms between the clients clock and the servers clock.
+ this.samples = 0; // The number of samples used to calculate the offset. If 0, the offset is not valid.
+
+ this.getServerTime = function(){ // return: long
+ // Summary:
+ // Calculate the current time on the server
+ //
+ return new Date().getTime()+this.offset;
+ }
+
+ this.getServerDate = function(){ // return: Date
+ // Summary:
+ // Calculate the current time on the server
+ //
+ return new Date(this.getServerTime());
+ }
+
+ this.setTimeout = function(/*function*/call, /*long|Date*/atTimeOrDate){
+ // Summary:
+ // Set a timeout function relative to server time
+ // call:
+ // the function to call when the timeout occurs
+ // atTimeOrTime:
+ // a long timestamp or a Date representing the server time at
+ // which the timeout should occur.
+
+ var ts = (atTimeOrDate instanceof Date) ? atTimeOrDate.getTime() : (0 + atTimeOrDate);
+ var tc = ts - this.offset;
+ var interval = tc - new Date().getTime();
+ if(interval <= 0){
+ interval = 1;
+ }
+ return setTimeout(call,interval);
+ }
+
+ this._in = function(/*Object*/msg){
+ // Summary:
+ // Handle incoming messages for the timesync extension.
+ // description:
+ // Look for ext:{timesync:{}} field and calculate offset if present.
+ // msg:
+ // The incoming bayeux message
+
+ var channel = msg.channel;
+ if(channel && channel.indexOf('/meta/') == 0){
+ if(msg.ext && msg.ext.timesync){
+ var sync = msg.ext.timesync;
+ var now = new Date().getTime();
+ var l=(now-sync.tc-sync.p)/2-sync.a;
+ var o=sync.ts-sync.tc-l;
+
+ this._lags.push(l);
+ this._offsets.push(o);
+ if(this._offsets.length > this._window){
+ this._offsets.shift();
+ this._lags.shift();
+ }
+ this.samples++;
+ l=0;
+ o=0;
+ for(var i in this._offsets){
+ l+=this._lags[i];
+ o+=this._offsets[i];
+ }
+ this.offset = parseInt((o / this._offsets.length).toFixed());
+ this.lag = parseInt((l / this._lags.length).toFixed());
+
+ }
+ }
+ return msg;
+ }
+
+ this._out = function(msg){
+ // Summary:
+ // Handle outgoing messages for the timesync extension.
+ // description:
+ // Look for handshake and connect messages and add the ext:{timesync:{}} fields
+ // msg:
+ // The outgoing bayeux message
+
+ var channel = msg.channel;
+ if(channel && channel.indexOf('/meta/') == 0){
+ var now = new Date().getTime();
+ if(!msg.ext){
+ msg.ext = {};
+ }
+ msg.ext.timesync = {tc:now,l:this.lag,o:this.offset};
+ }
+ return msg;
+ }
+};
+
+dojox.cometd._extendInList.push(dojo.hitch(dojox.cometd.timesync, "_in"));
+dojox.cometd._extendOutList.push(dojo.hitch(dojox.cometd.timesync, "_out"));
+
+});