comparison bosh.js @ 99:f14558915187

bosh support
author Sonny Piers <sonny.piers@gmail.com>
date Tue, 12 Jun 2012 19:44:53 +0200
parents
children
comparison
equal deleted inserted replaced
98:6ec16b3e9cfc 99:f14558915187
1 'use strict';
2
3 (function() {
4 Lightstring.BOSHConnection = function(aService) {
5 this.service = aService;
6 this.rid = 1337;
7 this.currentRequests = 0;
8 this.maxHTTPRetries = 5;
9 this.maxRequests = 2;
10 this.queue = [];
11 };
12 Lightstring.BOSHConnection.prototype = new EventEmitter();
13 Lightstring.BOSHConnection.prototype.open = function() {
14 var that = this;
15
16 var attrs = {
17 wait: '60',
18 hold: '1',
19 to: 'yuilop',
20 content: 'text/xml; charset=utf-8',
21 ver: '1.6',
22 'xmpp:version': '1.0',
23 'xmlns:xmpp': 'urn:xmpp:xbosh',
24 };
25
26 this.request(attrs, null, function(data) {
27 that.emit('open');
28 that.sid = data.getAttribute('sid');
29 that.maxRequests = data.getAttribute('maxRequests') || that.maxRequests;
30 });
31
32
33 this.on('in', function(stanza) {
34 if (stanza.localName === 'success') {
35 that.request({
36 'xmpp:restart': 'true',
37 'xmlns:xmpp': 'urn:xmpp:xbosh'
38 })
39 }
40 })
41 };
42 Lightstring.BOSHConnection.prototype.request = function(attrs, children, aOnSuccess, aOnError, aRetry) {
43 // if (children && children[0] && children[0].name === 'body') {
44 // var body = children[0];
45 // }
46 // else {
47 // var body = new ltx.Element('body');
48 // if (children) {
49 // if(util.isArray(children))
50 // for (var k in children)
51 // body.cnode(children[k]);
52 // else
53 // body.cnode(children);
54 // }
55 // }
56
57 var body = '<body rid="' + this.rid++ + '" xmlns="http://jabber.org/protocol/httpbind"/>';
58 var body = Lightstring.XML2DOM(body);
59
60 //sid
61 if (this.sid)
62 body.setAttribute('sid', this.sid);
63
64 //attributes on body
65 for (var i in attrs)
66 body.setAttribute(i, attrs[i]);
67
68 //children
69 for (var i in children)
70 body.appendChild(children[i]);
71
72
73
74 var retry = aRetry || 0;
75
76 var req = new XMLHttpRequest();
77 req.open('POST', this.service);
78
79
80 // req.upload.addEventListener("progress", updateProgress, false);
81 // req.upload.addEventListener("load", transferComplete, false);
82 // req.upload.addEventListener("error", transferFailed, false);
83 // req.upload.addEventListener("abort", transferCanceled, false);
84
85 // req.addEventListener("progress", updateProgress, false);
86 // req.addEventListener("load", transferComplete, false);
87 // req.addEventListener("error", transferFailed, false);
88 // req.addEventListener("abort", transferCanceled, false);
89
90 var that = this;
91 // req.responseType = 'document';
92 req.addEventListener("load", function() {
93 if (req.status < 200 || req.status >= 400) {
94 that.emit('error', "HTTP status " + req.status);
95 that.emit('close');
96 return;
97 }
98 that.currentRequests--;
99
100 var body = this.response;
101 that.emit('rawin', body);
102 var bodyEl = Lightstring.XML2DOM(body);
103 that.processResponse(bodyEl)
104 if (aOnSuccess)
105 aOnSuccess(bodyEl);
106
107 }, false);
108 // req.on('error', function(error) {
109 // if (retry < that.maxHTTPRetries) {
110 // that.request(attrs, children, aOnSuccess, aOnError, ++retry);
111 // }
112 // else {
113 // that.emit('close');
114 // that.emit('error', error);
115 // if (aOnError)
116 // aOnError(error);
117 // }
118 // });
119 // this.emit('rawout', body.toString());
120
121 for(var i = 0; i < body.children.length; i++) {
122 var child = body.children[i];
123 that.emit('out', child);
124 }
125 this.emit('rawout', Lightstring.DOM2XML(body))
126
127 req.send(Lightstring.DOM2XML(body));
128 this.currentRequests++;
129 };
130 Lightstring.BOSHConnection.prototype.send = function(aData) {
131 if (!aData) {
132 var el = '';
133 }
134
135 else if(typeof aData == 'string') {
136 try {
137 var el = Lightstring.XML2DOM(aData);
138 }
139 catch(e) {
140 console.log(e);
141 console.log(aData);
142 }
143 }
144 else {
145 var el = aData.root();
146 }
147
148 var that = this;
149
150 this.queue.push(el);
151
152 setTimeout(this.mayRequest.bind(this), 0)
153
154 };
155 Lightstring.BOSHConnection.prototype.end = function(stanzas) {
156 var that = this;
157
158 stanzas = stanzas || [];
159 if (typeof stanzas !== 'array')
160 stanzas = [stanzas];
161
162 stanzas = this.queue.concat(stanzas);
163 this.queue = [];
164 this.request({type: 'terminate'}, stanzas,
165 function(err, bodyEl) {
166 that.emit('end');
167 that.emit('close');
168 delete that.sid;
169 });
170 };
171 Lightstring.BOSHConnection.prototype.processResponse = function(bodyEl) {
172 if (bodyEl && bodyEl.children) {
173 for(var i = 0; i < bodyEl.children.length; i++) {
174 var child = bodyEl.children[i];
175 this.emit('in', child);
176 }
177 }
178 if (bodyEl && bodyEl.getAttribute('type') === 'terminate') {
179 var condition = bodyEl.getAttribute('condition');
180 this.emit('error',
181 new Error(condition || "Session terminated"));
182 this.emit('close');
183 }
184 };
185 Lightstring.BOSHConnection.prototype.mayRequest = function() {
186 var canRequest =
187 this.sid && (this.currentRequests === 0 || ((this.queue.length > 0 && this.currentRequests < this.maxRequests))
188 );
189
190 if (!canRequest)
191 return;
192
193 var stanzas = this.queue;
194 this.queue = [];
195 //~ this.rid++;
196
197 var that = this;
198 this.request({}, stanzas,
199 //success
200 function(data) {
201 //if (data)
202 //that.processResponse(data);
203
204 setTimeout(that.mayRequest.bind(that), 0);
205
206 },
207 //error
208 function(error) {
209 that.emit('error', error);
210 that.emit('close');
211 delete that.sid;
212 }
213 );
214 };
215 })();