comparison transports/bosh.js @ 108:5cb4733c5189

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