123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- if(!dojo._hasResource["dojox.cometd.timesync"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.cometd.timesync"] = true;
- 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"));
- }
|