timesync.js 5.2 KB

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