]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojox/cometd/timesync.js
Comment class stub
[eow] / static / dojo-release-1.1.1 / dojox / cometd / timesync.js
1 if(!dojo._hasResource["dojox.cometd.timesync"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojox.cometd.timesync"] = true;
3 dojo.provide("dojox.cometd.timesync");
4 dojo.require("dojox.cometd");
5
6 /**
7  * this file provides the time synchronization extension to cometd.
8  * Timesync allows the client and server to exchange time information on every 
9  * handshake and connect message so that the client may calculate an approximate
10  * offset from it's own clock epoch to that of the server.
11  *
12  * With each handshake or connect, the extension sends timestamps within the 
13  * ext field like: {ext:{timesync:{tc:12345567890},...},...}
14  * where ts is the timestamp in ms since 1970 of when the message was sent.
15  *
16  * A cometd server that supports timesync, should respond with and ext field
17  * like: {ext:{timesync:{tc:12345567890,ts:1234567900,p:123},...},...}
18  * where ts is the timestamp sent by the client, te is the timestamp on the server
19  * of when the message was received and p is the poll duration in ms - ie the
20  * time the server took before sending the response.
21  *
22  * On receipt of the response, the client is able to use current time to determine
23  * the total trip time, from which p is subtracted to determine an approximate
24  * two way network traversal time. The assumption is made that the network is
25  * symmetric for traversal time, so the offset between the two clocks is 
26  * ts-tc-(now-tc-p)/2. In practise networks (and the cometd client/server software)
27  * is never perfectly symmetric, so accuracy is limited by the difference, which 
28  * can be 10s of milliseconds.
29  *
30  * In order to smooth over any transient fluctuations, the extension keeps a sliding
31  * average of the offsets received. By default this is over 10 messages, but this can
32  * be changed with the dojox.cometd.timesync._window element.
33  */
34 dojox.cometd.timesync= new function(){
35
36         this._window=10;// The window size for the sliding average of offset samples.
37         this._minWindow=4;// The window size for the sliding average of offset samples.
38         this._offsets=new Array(); // The samples used to calculate the average offset.
39         this.offset=0;  // The offset in ms between the clients clock and the servers clock. Add this to the local
40                         // time epoch to obtain server time.
41         this.samples=0; // The number of samples used to calculate the offset. If 0, the offset is not valid.
42         
43         this.getServerTime=function(){ // return: long
44                 // Summary:
45                 //      Calculate the current time on the server
46                 // 
47                 return new Date().getTime()+this.offset;
48         }
49         
50         this.getServerDate=function(){ // return: Date
51                 // Summary:
52                 //      Calculate the current time on the server
53                 // 
54                 return new Date(this.getServerTime());
55         }
56         
57         this.setTimeout=function(/*function*/call,/*long|Date*/atTimeOrDate){
58                 // Summary:
59                 //      Set a timeout function relative to server time
60                 // call:
61                 //      the function to call when the timeout occurs
62                 // atTimeOrTime: 
63                 //      a long timestamp or a Date representing the server time at
64                 //      which the timeout should occur.
65                 
66                 var ts=(atTimeOrDate instanceof Date)?atTimeOrDate.getTime():(0+atTimeOrDate);
67                 var tc=ts-this.offset;
68                 var interval=tc-new Date().getTime();
69                 if (interval<=0)
70                         interval=1;
71                 return setTimeout(call,interval);
72         }
73
74         this._in=function(/*Object*/msg){
75                 // Summary:
76                 //      Handle incoming messages for the timesync extension.
77                 // description:
78                 //      Look for ext:{timesync:{}} field and calculate offset if present.
79                 // msg: 
80                 //      The incoming bayeux message
81                 
82                 var channel=msg.channel;
83                 if (channel &&  channel.indexOf('/meta/')==0){
84                         if (msg.ext && msg.ext.timesync){
85                                 var sync=msg.ext.timesync;
86                                 var now=new Date().getTime();
87                                 
88                                 this._offsets.push(sync.ts-sync.tc-(now-sync.tc-sync.p)/2);
89                                 if (this._offsets.length>this._window)
90                                         this._offsets.shift();          
91                                 this.samples++;
92                                 var total=0;
93                                 for (var i in this._offsets)
94                                         total+=this._offsets[i];
95                                 this.offset=parseInt((total/this._offsets.length).toFixed());
96                                 
97                                 if (this.samples<this._minWindow)
98                                         setTimeout(dojox._scopeName + ".cometd.publish('/meta/ping',null)",100);
99                         }
100                 }
101                 return msg;
102         }
103
104         this._out=function(msg){
105                 // Summary:
106                 //      Handle outgoing messages for the timesync extension.
107                 // description:
108                 //      Look for handshake and connect messages and add the ext:{timesync:{}} fields
109                 // msg: 
110                 //      The outgoing bayeux message
111                 
112                 var channel=msg.channel;
113                 if (channel &&  channel.indexOf('/meta/')==0){
114                         var now=new Date().getTime();
115                         if (!msg.ext)
116                                 msg.ext={};
117                         msg.ext.timesync={tc: now};
118                 }
119                 return msg;
120         }
121 };
122
123 dojox.cometd._extendInList.push(dojo.hitch(dojox.cometd.timesync,"_in"));
124 dojox.cometd._extendOutList.push(dojo.hitch(dojox.cometd.timesync,"_out"));
125
126 }