//>>built // wrapped by build app define("dojox/xmpp/TransportSession", ["dijit","dojo","dojox","dojo/require!dojox/xmpp/bosh,dojox/xmpp/util,dojox/data/dom"], function(dijit,dojo,dojox){ dojo.provide("dojox.xmpp.TransportSession"); dojo.require("dojox.xmpp.bosh"); dojo.require("dojox.xmpp.util"); dojo.require("dojox.data.dom"); dojox.xmpp.TransportSession = function(props) { // we have to set this here because "this" doesn't work // in the dojo.extend call. this.sendTimeout = (this.wait+20)*1000; //mixin any options that we want to provide to this service if (props && dojo.isObject(props)) { dojo.mixin(this, props); if(this.useScriptSrcTransport){ this.transportIframes = []; } } }; dojo.extend(dojox.xmpp.TransportSession, { /* options/defaults */ rid: 0, hold: 1, polling:1000, secure: false, wait: 60, lang: 'en', submitContentType: 'text/xml; charset=utf=8', serviceUrl: '/httpbind', defaultResource: "dojoIm", domain: 'imserver.com', sendTimeout: 0, //(this.wait+20)*1000 useScriptSrcTransport:false, keepAliveTimer:null, //status state: "NotReady", transmitState: "Idle", protocolPacketQueue: [], outboundQueue: [], outboundRequests: {}, inboundQueue: [], deferredRequests: {}, matchTypeIdAttribute: {}, open: function() { this.status = "notReady"; this.rid = Math.round(Math.random() * 1000000000); this.protocolPacketQueue = []; this.outboundQueue = []; this.outboundRequests = {}; this.inboundQueue = []; this.deferredRequests = {}; this.matchTypeIdAttribute = {}; this.keepAliveTimer = setTimeout(dojo.hitch(this, "_keepAlive"), 10000); if(this.useScriptSrcTransport){ dojox.xmpp.bosh.initialize({ iframes: this.hold+1, load: dojo.hitch(this, function(){ this._sendLogin(); }) }); } else { this._sendLogin(); } }, _sendLogin: function() { var rid = this.rid++; var req = { content: this.submitContentType, hold: this.hold, rid: rid, to: this.domain, secure: this.secure, wait: this.wait, "xml:lang": this.lang, "xmpp:version": "1.0", xmlns: dojox.xmpp.xmpp.BODY_NS, "xmlns:xmpp": "urn:xmpp:xbosh" }; var msg = dojox.xmpp.util.createElement("body", req, true); this.addToOutboundQueue(msg, rid); }, _sendRestart: function(){ var rid = this.rid++; var req = { rid: rid, sid: this.sid, to: this.domain, "xmpp:restart": "true", "xml:lang": this.lang, xmlns: dojox.xmpp.xmpp.BODY_NS, "xmlns:xmpp": "urn:xmpp:xbosh" }; var msg = dojox.xmpp.util.createElement("body", req, true); this.addToOutboundQueue(msg, rid); }, processScriptSrc: function(msg, rid) { //console.log("processScriptSrc::", rid, msg); // var msgDom = dojox.xml.DomParser.parse(msg); var msgDom = dojox.xml.parser.parse(msg, "text/xml"); //console.log("parsed mgs", msgDom); //console.log("Queue", this.outboundQueue); if(msgDom) { this.processDocument(msgDom, rid); } else { //console.log("Recived bad document from server",msg); } }, _keepAlive: function(){ if (this.state=="wait" || this.isTerminated()) { return; } this._dispatchPacket(); this.keepAliveTimer = setTimeout(dojo.hitch(this, "_keepAlive"), 10000); }, close: function(protocolMsg){ var rid = this.rid++; var req = { sid: this.sid, rid: rid, type: "terminate" }; var envelope = null; if (protocolMsg) { envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, false)); envelope.append(protocolMsg); envelope.append(""); } else { envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, false)); } // this.sendXml(envelope,rid); this.addToOutboundQueue(envelope.toString(), rid); this.state=="Terminate"; }, dispatchPacket: function(msg, protocolMatchType, matchId, matchProperty){ // summary // Main Packet dispatcher, most calls should be made with this other // than a few setup calls which use add items to the queue directly //protocolMatchType, matchId, and matchProperty are optional params //that allow a deferred to be tied to a protocol response instad of the whole //rid // //console.log("In dispatchPacket ", msg, protocolMatchType, matchId, matchProperty); if (msg){ this.protocolPacketQueue.push(msg); } var def = new dojo.Deferred(); //def.rid = req.rid; if (protocolMatchType && matchId){ def.protocolMatchType = protocolMatchType; def.matchId = matchId; def.matchProperty = matchProperty || "id"; if(def.matchProperty != "id") { this.matchTypeIdAttribute[protocolMatchType] = def.matchProperty; } } this.deferredRequests[def.protocolMatchType + "-" +def.matchId]=def; if(!this.dispatchTimer) { this.dispatchTimer = setTimeout(dojo.hitch(this, "_dispatchPacket"), 600); } return def; }, _dispatchPacket: function(){ clearTimeout(this.dispatchTimer); delete this.dispatchTimer; if (!this.sid){ console.debug("TransportSession::dispatchPacket() No SID, packet dropped.") return; } if (!this.authId){ //FIXME according to original nodes, this should wait a little while and try // again up to three times to see if we get this data. console.debug("TransportSession::dispatchPacket() No authId, packet dropped [FIXME]") return; } //if there is a pending request with the server, don't poll if (this.transmitState != "error" && (this.protocolPacketQueue.length == 0) && (this.outboundQueue.length > 0)) { return; } if (this.state=="wait" || this.isTerminated()) { return; } var req = { sid: this.sid, xmlns: dojox.xmpp.xmpp.BODY_NS } var envelope if (this.protocolPacketQueue.length > 0){ req.rid= this.rid++; envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, false)); envelope.append(this.processProtocolPacketQueue()); envelope.append(""); delete this.lastPollTime; } else { //console.log("Nothing to send, I'm just polling."); if(this.lastPollTime) { var now = new Date().getTime(); if(now - this.lastPollTime < this.polling) { //console.log("Waiting to poll ", this.polling - (now - this.lastPollTime)+10); this.dispatchTimer = setTimeout(dojo.hitch(this, "_dispatchPacket"), this.polling - (now - this.lastPollTime)+10); return; } } req.rid= this.rid++; this.lastPollTime = new Date().getTime(); envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, true)); } this.addToOutboundQueue(envelope.toString(),req.rid); }, redispatchPacket: function(rid){ var env = this.outboundRequests[rid]; this.sendXml(env, rid); }, addToOutboundQueue: function(msg, rid){ this.outboundQueue.push({msg: msg,rid: rid}); this.outboundRequests[rid]=msg; this.sendXml(msg, rid); }, removeFromOutboundQueue: function(rid){ for(var i=0; i element ", doc, " RID: ", rid); } if (this.outboundQueue.length<1){return false;} var expectedId = this.outboundQueue[0]["rid"]; //console.log("expectedId", expectedId); if (rid==expectedId){ this.removeFromOutboundQueue(rid); this.processResponse(body, rid); this.processInboundQueue(); }else{ //console.log("TransportSession::processDocument() rid: ", rid, " expected: ", expectedId); var gap = rid-expectedId; if (gap < this.hold + 2){ this.addToInboundQueue(doc,rid); }else{ //console.log("TransportSession::processDocument() RID is outside of the expected response window"); } } return doc; }, processInboundQueue: function(){ while (this.inboundQueue.length > 0) { var item = this.inboundQueue.shift(); this.processDocument(item["doc"], item["rid"]); } }, addToInboundQueue: function(doc,rid){ for (var i=0; i= 400 && httpStatusCode < 500){ /* Any status code between 400 and 500 should terminate * the connection */ this.setState("Terminate", errorMessage); return false; }else{ this.removeFromOutboundQueue(rid); setTimeout(dojo.hitch(this, function(){ this.dispatchPacket(); }), 200); return true; } return false; } if (err && err.dojoType && err.dojoType=="timeout"){ //console.log("Wait timeout"); } this.removeFromOutboundQueue(rid); //FIXME conditional processing if request will be needed based on type of error. if(err && err.firstChild) { //console.log("Error ", err.firstChild.getAttribute("type") + " status code " + httpStatusCode); if (err.firstChild.getAttribute("type")=='terminate'){ var reasonNode = err.firstChild.firstChild; var errorMessage = ""; if(reasonNode && reasonNode.nodeName == "conflict") { errorMessage = "conflict" } this.setState("Terminate", errorMessage); return false; } } this.transmitState = "error"; setTimeout(dojo.hitch(this, function(){ this.dispatchPacket(); }), 200); //console.log("Error: ", arguments); return true; }, //events onTerminate: function(newState, oldState, message){ }, onProcessProtocolResponse: function(msg){}, onReady: function(newState, oldState){} }); });