source: Dev/branches/rest-dojo-ui/client/dojox/cometd/_base.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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