_base.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.cometd._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.cometd._base"] = true;
  8. dojo.provide("dojox.cometd._base");
  9. dojo.require("dojo.AdapterRegistry");
  10. /*
  11. * this file defines Comet protocol client. Actual message transport is
  12. * deferred to one of several connection type implementations. The default is a
  13. * long-polling implementation. A single global object named "dojox.cometd" is
  14. * used to mediate for these connection types in order to provide a stable
  15. * interface.
  16. *
  17. * extensions modules may be loaded (eg "dojox.cometd.timestamp", that use
  18. * the cometd._extendInList and cometd._extendOutList fields to provide functions
  19. * that extend and handling incoming and outgoing messages.
  20. *
  21. * By default the long-polling and callback-polling transports will be required.
  22. * If specific or alternative transports are required, then they can be directly
  23. * loaded. For example dojo.require('dojox.cometd.longPollTransportJsonEncoded')
  24. * will load cometd with only the json encoded variant of the long polling transport.
  25. */
  26. dojox.cometd = {
  27. Connection: function(prefix){ // This constructor is stored as dojox.cometd.Connection
  28. // summary
  29. // This constructor is used to create new cometd connections. Generally, you should use
  30. // one cometd connection for each server you connect to. A default connection instance is
  31. // created at dojox.cometd.
  32. // To connect to a new server you can create an instance like:
  33. // var cometd = new dojox.cometd.Connection("/otherServer");
  34. // cometd.init("http://otherServer.com/cometd");
  35. //
  36. // prefix is the prefix for all the events that are published in the Dojo pub/sub system.
  37. // You must include this prefix, and it should start with a slash like "/myprefix".
  38. // cometd states:
  39. // unconnected, handshaking, connecting, connected, disconnected
  40. dojo.mixin(this, {
  41. prefix: prefix,
  42. _status: "unconnected",
  43. _handshook: false,
  44. _initialized: false,
  45. _polling: false,
  46. expectedNetworkDelay: 10000, // expected max network delay
  47. connectTimeout: 0, // If set, used as ms to wait for a connect response and sent as the advised timeout
  48. version: "1.0",
  49. minimumVersion: "0.9",
  50. clientId: null,
  51. messageId: 0,
  52. batch: 0,
  53. _isXD: false,
  54. handshakeReturn: null,
  55. currentTransport: null,
  56. url: null,
  57. lastMessage: null,
  58. _messageQ: [],
  59. handleAs: "json",
  60. _advice: {},
  61. _backoffInterval: 0,
  62. _backoffIncrement: 1000,
  63. _backoffMax: 60000,
  64. _deferredSubscribes: {},
  65. _deferredUnsubscribes: {},
  66. _subscriptions: [],
  67. _extendInList: [], // List of functions invoked before delivering messages
  68. _extendOutList: [] // List of functions invoked before sending messages
  69. });
  70. this.state = function() {
  71. return this._status;
  72. }
  73. this.init = function( /*String*/ root,
  74. /*Object?*/ props,
  75. /*Object?*/ bargs){ // return: dojo.Deferred
  76. // summary:
  77. // Initialize the cometd implementation of the Bayeux protocol
  78. // description:
  79. // Initialize the cometd implementation of the Bayeux protocol by
  80. // sending a handshake message. The cometd state will be changed to CONNECTING
  81. // until a handshake response is received and the first successful connect message
  82. // has returned.
  83. // The protocol state changes may be monitored
  84. // by subscribing to the dojo topic "/prefix/meta" (typically "/cometd/meta") where
  85. // events are published in the form
  86. // {cometd:this,action:"handshake",successful:true,state:this.state()}
  87. // root:
  88. // The URL of the cometd server. If the root is absolute, the host
  89. // is examined to determine if xd transport is needed. Otherwise the
  90. // same domain is assumed.
  91. // props:
  92. // An optional object that is used as the basis of the handshake message
  93. // bargs:
  94. // An optional object of bind args mixed in with the send of the handshake
  95. // example:
  96. // | dojox.cometd.init("/cometd");
  97. // | dojox.cometd.init("http://xdHost/cometd",{ext:{user:"fred",pwd:"secret"}});
  98. // FIXME: if the root isn't from the same host, we should automatically
  99. // try to select an XD-capable transport
  100. props = props || {};
  101. // go ask the short bus server what we can support
  102. props.version = this.version;
  103. props.minimumVersion = this.minimumVersion;
  104. props.channel = "/meta/handshake";
  105. props.id = "" + this.messageId++;
  106. this.url = root || dojo.config["cometdRoot"];
  107. if(!this.url){
  108. throw "no cometd root";
  109. return null;
  110. }
  111. // Are we x-domain? borrowed from dojo.uri.Uri in lieu of fixed host and port properties
  112. var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
  113. var parts = ("" + window.location).match(new RegExp(regexp));
  114. if(parts[4]){
  115. var tmp = parts[4].split(":");
  116. var thisHost = tmp[0];
  117. var thisPort = tmp[1]||"80"; // FIXME: match 443
  118. parts = this.url.match(new RegExp(regexp));
  119. if(parts[4]){
  120. tmp = parts[4].split(":");
  121. var urlHost = tmp[0];
  122. var urlPort = tmp[1]||"80";
  123. this._isXD = ((urlHost != thisHost)||(urlPort != thisPort));
  124. }
  125. }
  126. if(!this._isXD){
  127. props.supportedConnectionTypes = dojo.map(dojox.cometd.connectionTypes.pairs, "return item[0]");
  128. }
  129. props = this._extendOut(props);
  130. var bindArgs = {
  131. url: this.url,
  132. handleAs: this.handleAs,
  133. content: { "message": dojo.toJson([props]) },
  134. load: dojo.hitch(this,function(msg){
  135. this._backon();
  136. this._finishInit(msg);
  137. }),
  138. error: dojo.hitch(this,function(e){
  139. this._backoff();
  140. this._finishInit(e);
  141. }),
  142. timeout: this.expectedNetworkDelay
  143. };
  144. if(bargs){
  145. dojo.mixin(bindArgs, bargs);
  146. }
  147. this._props = props;
  148. for(var tname in this._subscriptions){
  149. for(var sub in this._subscriptions[tname]){
  150. if(this._subscriptions[tname][sub].topic){
  151. dojo.unsubscribe(this._subscriptions[tname][sub].topic);
  152. }
  153. }
  154. }
  155. this._messageQ = [];
  156. this._subscriptions = [];
  157. this._initialized = true;
  158. this._status = "handshaking";
  159. this.batch = 0;
  160. this.startBatch();
  161. var r;
  162. // if xdomain, then we assume jsonp for handshake
  163. if(this._isXD){
  164. bindArgs.callbackParamName = "jsonp";
  165. r = dojo.io.script.get(bindArgs);
  166. }else{
  167. r = dojo.xhrPost(bindArgs);
  168. }
  169. return r;
  170. }
  171. this.publish = function(/*String*/ channel, /*Object*/ data, /*Object?*/ props){
  172. // summary:
  173. // publishes the passed message to the cometd server for delivery
  174. // on the specified topic
  175. // channel:
  176. // the destination channel for the message
  177. // data:
  178. // a JSON object containing the message "payload"
  179. // properties:
  180. // Optional. Other meta-data to be mixed into the top-level of the
  181. // message
  182. var message = {
  183. data: data,
  184. channel: channel
  185. };
  186. if(props){
  187. dojo.mixin(message, props);
  188. }
  189. this._sendMessage(message);
  190. }
  191. this.subscribe = function( /*String */ channel,
  192. /*Object */ objOrFunc,
  193. /*String */ funcName,
  194. /*Object?*/ props){ // return: dojo.Deferred
  195. // summary:
  196. // inform the server of this client's interest in channel
  197. // description:
  198. // `dojox.cometd.subscribe()` handles all the hard work of telling
  199. // the server that we want to be notified when events are
  200. // published on a particular topic. `subscribe` accepts a function
  201. // to handle messages and returns a `dojo.Deferred` object which
  202. // has an extra property added to it which makes it suitable for
  203. // passing to `dojox.cometd.unsubscribe()` as a "subscription
  204. // handle" (much like the handle object that `dojo.connect()`
  205. // produces and which `dojo.disconnect()` expects).
  206. //
  207. // Note that of a subscription is registered before a connection
  208. // with the server is established, events sent before the
  209. // connection is established will not be delivered to this client.
  210. // The deferred object which `subscribe` returns will callback
  211. // when the server successfuly acknolwedges receipt of our
  212. // "subscribe" request.
  213. // channel:
  214. // name of the cometd channel to subscribe to
  215. // objOrFunc:
  216. // an object scope for funcName or the name or reference to a
  217. // function to be called when messages are delivered to the
  218. // channel
  219. // funcName:
  220. // the second half of the objOrFunc/funcName pair for identifying
  221. // a callback function to notifiy upon channel message delivery
  222. // example:
  223. // Simple subscribe use-case
  224. // | dojox.cometd.init("http://myserver.com:8080/cometd");
  225. // | // log out all incoming messages on /foo/bar
  226. // | dojox.cometd.subscribe("/foo/bar", console, "debug");
  227. // example:
  228. // Subscribe before connection is initialized
  229. // | dojox.cometd.subscribe("/foo/bar", console, "debug");
  230. // | dojox.cometd.init("http://myserver.com:8080/cometd");
  231. // example:
  232. // Subscribe an unsubscribe
  233. // | dojox.cometd.init("http://myserver.com:8080/cometd");
  234. // | var h = dojox.cometd.subscribe("/foo/bar", console, "debug");
  235. // | dojox.cometd.unsubscribe(h);
  236. // example:
  237. // Listen for successful subscription:
  238. // | dojox.cometd.init("http://myserver.com:8080/cometd");
  239. // | var h = dojox.cometd.subscribe("/foo/bar", console, "debug");
  240. // | h.addCallback(function(){
  241. // | console.debug("subscription to /foo/bar established");
  242. // | });
  243. props = props||{};
  244. if(objOrFunc){
  245. var tname = prefix + channel;
  246. var subs = this._subscriptions[tname];
  247. if(!subs || subs.length == 0){
  248. subs = [];
  249. props.channel = "/meta/subscribe";
  250. props.subscription = channel;
  251. this._sendMessage(props);
  252. var _ds = this._deferredSubscribes;
  253. if(_ds[channel]){
  254. _ds[channel].cancel();
  255. delete _ds[channel];
  256. }
  257. _ds[channel] = new dojo.Deferred();
  258. }
  259. for(var i in subs){
  260. if(subs[i].objOrFunc === objOrFunc && (!subs[i].funcName&&!funcName||subs[i].funcName==funcName) ){
  261. return null;
  262. }
  263. }
  264. var topic = dojo.subscribe(tname, objOrFunc, funcName);
  265. subs.push({
  266. topic: topic,
  267. objOrFunc: objOrFunc,
  268. funcName: funcName
  269. });
  270. this._subscriptions[tname] = subs;
  271. }
  272. var ret = this._deferredSubscribes[channel] || {};
  273. ret.args = dojo._toArray(arguments);
  274. return ret; // dojo.Deferred
  275. }
  276. this.unsubscribe = function( /*String*/ channel,
  277. /*Object?*/ objOrFunc,
  278. /*String?*/ funcName,
  279. /*Object?*/ props){
  280. // summary:
  281. // inform the server of this client's disinterest in channel
  282. // channel:
  283. // name of the cometd channel to unsubscribe from
  284. // objOrFunc:
  285. // an object scope for funcName or the name or reference to a
  286. // function to be called when messages are delivered to the
  287. // channel. If null then all subscribers to the channel are unsubscribed.
  288. // funcName:
  289. // the second half of the objOrFunc/funcName pair for identifying
  290. // a callback function to notifiy upon channel message delivery
  291. if(
  292. (arguments.length == 1) &&
  293. (!dojo.isString(channel)) &&
  294. (channel.args)
  295. ){
  296. // it's a subscription handle, unroll
  297. return this.unsubscribe.apply(this, channel.args);
  298. }
  299. var tname = prefix + channel;
  300. var subs = this._subscriptions[tname];
  301. if(!subs || subs.length==0){
  302. return null;
  303. }
  304. var s=0;
  305. for(var i in subs){
  306. var sb = subs[i];
  307. if((!objOrFunc) ||
  308. (
  309. sb.objOrFunc===objOrFunc &&
  310. (!sb.funcName && !funcName || sb.funcName==funcName)
  311. )
  312. ){
  313. dojo.unsubscribe(subs[i].topic);
  314. delete subs[i];
  315. }else{
  316. s++;
  317. }
  318. }
  319. if(s == 0){
  320. props = props || {};
  321. props.channel = "/meta/unsubscribe";
  322. props.subscription = channel;
  323. delete this._subscriptions[tname];
  324. this._sendMessage(props);
  325. this._deferredUnsubscribes[channel] = new dojo.Deferred();
  326. if(this._deferredSubscribes[channel]){
  327. this._deferredSubscribes[channel].cancel();
  328. delete this._deferredSubscribes[channel];
  329. }
  330. }
  331. return this._deferredUnsubscribes[channel]; // dojo.Deferred
  332. }
  333. this.disconnect = function(){
  334. // summary:
  335. // Disconnect from the server.
  336. // description:
  337. // Disconnect from the server by sending a disconnect message
  338. // example:
  339. // | dojox.cometd.disconnect();
  340. for(var tname in this._subscriptions){
  341. for(var sub in this._subscriptions[tname]){
  342. if(this._subscriptions[tname][sub].topic){
  343. dojo.unsubscribe(this._subscriptions[tname][sub].topic);
  344. }
  345. }
  346. }
  347. this._subscriptions = [];
  348. this._messageQ = [];
  349. if(this._initialized && this.currentTransport){
  350. this._initialized=false;
  351. this.currentTransport.disconnect();
  352. }
  353. if(!this._polling) {
  354. this._publishMeta("connect",false);
  355. }
  356. this._initialized=false;
  357. this._handshook=false;
  358. this._status = "disconnected"; //should be disconnecting, but we ignore the reply to this message
  359. this._publishMeta("disconnect",true);
  360. }
  361. // public extension points
  362. this.subscribed = function( /*String*/channel, /*Object*/message){ }
  363. this.unsubscribed = function(/*String*/channel, /*Object*/message){ }
  364. // private methods (TODO name all with leading _)
  365. this.tunnelInit = function(childLocation, childDomain){
  366. // placeholder - replaced by _finishInit
  367. }
  368. this.tunnelCollapse = function(){
  369. // placeholder - replaced by _finishInit
  370. }
  371. this._backoff = function(){
  372. if(!this._advice){
  373. this._advice={reconnect:"retry",interval:0};
  374. }else if(!this._advice.interval){
  375. this._advice.interval = 0;
  376. }
  377. if(this._backoffInterval < this._backoffMax){
  378. this._backoffInterval += this._backoffIncrement;
  379. }
  380. }
  381. this._backon = function(){
  382. this._backoffInterval=0;
  383. }
  384. this._interval = function(){
  385. var i = this._backoffInterval + (this._advice ? (this._advice.interval ? this._advice.interval : 0) : 0);
  386. if (i>0){
  387. console.log("Retry in interval+backoff=" + this._advice.interval + "+" + this._backoffInterval+"="+i+"ms");
  388. }
  389. return i;
  390. }
  391. this._publishMeta = function(action,successful,props){
  392. try {
  393. var meta = {cometd:this,action:action,successful:successful,state:this.state()};
  394. if (props){
  395. dojo.mixin(meta, props);
  396. }
  397. dojo.publish(this.prefix + "/meta", [meta]);
  398. } catch(e) {
  399. console.log(e);
  400. }
  401. }
  402. this._finishInit = function(data){
  403. // summary:
  404. // Handle the handshake return from the server and initialize
  405. // connection if all is OK
  406. if(this._status!="handshaking") {return;}
  407. var wasHandshook = this._handshook;
  408. var successful = false;
  409. var metaMsg = {};
  410. if (data instanceof Error) {
  411. dojo.mixin(metaMsg,{
  412. reestablish:false,
  413. failure: true,
  414. error: data,
  415. advice: this._advice
  416. });
  417. } else {
  418. data = data[0];
  419. data = this._extendIn(data);
  420. this.handshakeReturn = data;
  421. // remember any advice
  422. if(data["advice"]){
  423. this._advice = data.advice;
  424. }
  425. successful = data.successful ? data.successful : false;
  426. // check version
  427. if(data.version < this.minimumVersion){
  428. if (console.log)
  429. console.log("cometd protocol version mismatch. We wanted", this.minimumVersion, "but got", data.version);
  430. successful=false;
  431. this._advice.reconnect="none";
  432. }
  433. dojo.mixin(metaMsg,{reestablish: successful && wasHandshook, response:data});
  434. }
  435. this._publishMeta("handshake",successful,metaMsg);
  436. //in the meta listeners, disconnect() may have been called, so recheck it now to
  437. //prevent resends or continuing with initializing the protocol
  438. if(this._status!="handshaking") {return;}
  439. // If all OK
  440. if(successful){
  441. this._status = "connecting";
  442. this._handshook = true;
  443. // pick a transport
  444. this.currentTransport = dojox.cometd.connectionTypes.match(
  445. data.supportedConnectionTypes,
  446. data.version,
  447. this._isXD
  448. );
  449. var transport = this.currentTransport;
  450. // initialize the transport
  451. transport._cometd = this;
  452. transport.version = data.version;
  453. this.clientId = data.clientId;
  454. this.tunnelInit = transport.tunnelInit && dojo.hitch(transport, "tunnelInit");
  455. this.tunnelCollapse = transport.tunnelCollapse && dojo.hitch(transport, "tunnelCollapse");
  456. transport.startup(data);
  457. }else{
  458. // If there is a problem follow advice
  459. if(!this._advice || this._advice["reconnect"] != "none"){
  460. setTimeout(dojo.hitch(this, "init", this.url, this._props), this._interval());
  461. }
  462. }
  463. }
  464. // FIXME: lots of repeated code...why?
  465. this._extendIn = function(message){
  466. // summary: Handle extensions for inbound messages
  467. dojo.forEach(dojox.cometd._extendInList, function(f){
  468. message = f(message) || message;
  469. });
  470. return message;
  471. }
  472. this._extendOut = function(message){
  473. // summary: Handle extensions for inbound messages
  474. dojo.forEach(dojox.cometd._extendOutList, function(f){
  475. message = f(message) || message;
  476. });
  477. return message;
  478. }
  479. this.deliver = function(messages){
  480. dojo.forEach(messages, this._deliver, this);
  481. return messages;
  482. }
  483. this._deliver = function(message){
  484. // dipatch events along the specified path
  485. message = this._extendIn(message);
  486. if(!message["channel"]){
  487. if(message["success"] !== true){
  488. return;
  489. }
  490. }
  491. this.lastMessage = message;
  492. if(message.advice){
  493. this._advice = message.advice; // TODO maybe merge?
  494. }
  495. // check to see if we got a /meta channel message that we care about
  496. var deferred=null;
  497. if( (message["channel"]) &&
  498. (message.channel.length > 5) &&
  499. (message.channel.substr(0, 5) == "/meta")){
  500. // check for various meta topic actions that we need to respond to
  501. switch(message.channel){
  502. case "/meta/connect":
  503. var metaMsg = {response: message};
  504. if(message.successful) {
  505. if (this._status != "connected"){
  506. this._status = "connected";
  507. this.endBatch();
  508. }
  509. }
  510. if(this._initialized){
  511. this._publishMeta("connect",message.successful, metaMsg);
  512. }
  513. break;
  514. case "/meta/subscribe":
  515. deferred = this._deferredSubscribes[message.subscription];
  516. try
  517. {
  518. if(!message.successful){
  519. if(deferred){
  520. deferred.errback(new Error(message.error));
  521. }
  522. this.currentTransport.cancelConnect();
  523. return;
  524. }
  525. if(deferred){
  526. deferred.callback(true);
  527. }
  528. this.subscribed(message.subscription, message);
  529. } catch(e) {
  530. log.warn(e);
  531. }
  532. break;
  533. case "/meta/unsubscribe":
  534. deferred = this._deferredUnsubscribes[message.subscription];
  535. try
  536. {
  537. if(!message.successful){
  538. if(deferred){
  539. deferred.errback(new Error(message.error));
  540. }
  541. this.currentTransport.cancelConnect();
  542. return;
  543. }
  544. if(deferred){
  545. deferred.callback(true);
  546. }
  547. this.unsubscribed(message.subscription, message);
  548. } catch(e) {
  549. log.warn(e);
  550. }
  551. break;
  552. default:
  553. if(message.successful && !message.successful){
  554. this.currentTransport.cancelConnect();
  555. return;
  556. }
  557. }
  558. }
  559. // send the message down for processing by the transport
  560. this.currentTransport.deliver(message);
  561. if(message.data){
  562. // dispatch the message to any locally subscribed listeners
  563. try{
  564. var messages = [message];
  565. // Determine target topic
  566. var tname = prefix + message.channel;
  567. // Deliver to globs that apply to target topic
  568. var tnameParts = message.channel.split("/");
  569. var tnameGlob = prefix;
  570. for (var i = 1; i < tnameParts.length - 1; i++){
  571. dojo.publish(tnameGlob + "/**", messages);
  572. tnameGlob += "/" + tnameParts[i];
  573. }
  574. dojo.publish(tnameGlob + "/**", messages);
  575. dojo.publish(tnameGlob + "/*", messages);
  576. // deliver to target topic
  577. dojo.publish(tname,messages);
  578. }catch(e){
  579. console.log(e);
  580. }
  581. }
  582. }
  583. this._sendMessage = function(/* object */ message){
  584. if(this.currentTransport && !this.batch){
  585. return this.currentTransport.sendMessages([message]);
  586. }else{
  587. this._messageQ.push(message);
  588. return null;
  589. }
  590. }
  591. this.startBatch = function(){
  592. this.batch++;
  593. }
  594. this.endBatch = function(){
  595. if(--this.batch <= 0 && this.currentTransport && this._status == "connected"){
  596. this.batch = 0;
  597. var messages = this._messageQ;
  598. this._messageQ = [];
  599. if(messages.length > 0){
  600. this.currentTransport.sendMessages(messages);
  601. }
  602. }
  603. }
  604. this._onUnload = function(){
  605. // make this the last of the onUnload method
  606. dojo.addOnUnload(dojox.cometd, "disconnect");
  607. }
  608. this._connectTimeout = function(){
  609. // summary: Return the connect timeout in ms, calculated as the minimum of the advised timeout
  610. // and the configured timeout. Else 0 to indicate no client side timeout
  611. var advised=0;
  612. if(this._advice && this._advice.timeout && this.expectedNetworkDelay > 0){
  613. advised = this._advice.timeout + this.expectedNetworkDelay;
  614. }
  615. if(this.connectTimeout > 0 && this.connectTimeout < advised){
  616. return this.connectTimeout;
  617. }
  618. return advised;
  619. }
  620. },
  621. // connectionTypes are shared by all cometd Connection.
  622. connectionTypes : new dojo.AdapterRegistry(true)
  623. }
  624. // create the default instance
  625. dojox.cometd.Connection.call(dojox.cometd,"/cometd");
  626. /*
  627. FIXME: TODOC: this info should be part of the relevant functions and/or overview so
  628. the parser can find it.
  629. transport objects MUST expose the following methods:
  630. - check
  631. - startup
  632. - sendMessages
  633. - deliver
  634. - disconnect
  635. optional, standard but transport dependent methods are:
  636. - tunnelCollapse
  637. - tunnelInit
  638. Transports SHOULD be namespaced under the cometd object and transports MUST
  639. register themselves with cometd.connectionTypes
  640. here's a stub transport defintion:
  641. cometd.blahTransport = new function(){
  642. this._connectionType="my-polling";
  643. this._cometd=null;
  644. this.lastTimestamp = null;
  645. this.check = function(types, version, xdomain){
  646. // summary:
  647. // determines whether or not this transport is suitable given a
  648. // list of transport types that the server supports
  649. return dojo.inArray(types, "blah");
  650. }
  651. this.startup = function(){
  652. if(dojox.cometd._polling){ return; }
  653. // FIXME: fill in startup routine here
  654. dojox.cometd._polling = true;
  655. }
  656. this.sendMessages = function(message){
  657. // FIXME: fill in message array sending logic
  658. }
  659. this.deliver = function(message){
  660. }
  661. this.disconnect = function(){
  662. // send orderly disconnect message
  663. }
  664. this.cancelConnect = function(){
  665. // cancel the current connection
  666. }
  667. }
  668. cometd.connectionTypes.register("blah", cometd.blahTransport.check, cometd.blahTransport);
  669. */
  670. dojo.addOnUnload(dojox.cometd, "_onUnload");
  671. }