Mercurial > eldonilo > lightstring
comparison lightstring.js @ 67:1c8f326fe3ef
Several fixes and comments updated/added.
author | Sonny Piers <sonny.piers@gmail.com> |
---|---|
date | Wed, 01 Feb 2012 22:45:48 +0100 |
parents | 2e8fbf3bce7f |
children | e1ccfb580228 |
comparison
equal
deleted
inserted
replaced
66:fa184759fc41 | 67:1c8f326fe3ef |
---|---|
33 * @namespace Holds XMPP stanza builders. | 33 * @namespace Holds XMPP stanza builders. |
34 */ | 34 */ |
35 stanzas: { | 35 stanzas: { |
36 stream: { | 36 stream: { |
37 open: function(aService) { | 37 open: function(aService) { |
38 //FIXME no ending "/" - node-xmpp-bosh bug | 38 //WORKAROUND: no ending "/" - node-xmpp-bosh bug |
39 return "<stream:stream to='" + aService + "'" + | 39 return "<stream:stream to='" + aService + "'" + |
40 " xmlns='" + Lightstring.ns['jabber_client'] + "'" + | 40 " xmlns='" + Lightstring.ns['jabber_client'] + "'" + |
41 " xmlns:stream='" + Lightstring.ns['streams'] + "'" + | 41 " xmlns:stream='" + Lightstring.ns['streams'] + "'" + |
42 " version='1.0'/>"; | 42 " version='1.0'/>"; |
43 }, | 43 }, |
56 "</error>" + | 56 "</error>" + |
57 "</iq>"; | 57 "</iq>"; |
58 } | 58 } |
59 } | 59 } |
60 }, | 60 }, |
61 /** | |
62 * @namespace Holds Lightstring plugins | |
63 */ | |
61 plugins: {}, | 64 plugins: {}, |
62 /** | 65 /** |
63 * @private | 66 * @private |
64 */ | 67 */ |
65 parser: new DOMParser(), | 68 parser: new DOMParser(), |
76 var DOM = null; | 79 var DOM = null; |
77 try { | 80 try { |
78 DOM = this.parser.parseFromString(aString, 'text/xml').documentElement; | 81 DOM = this.parser.parseFromString(aString, 'text/xml').documentElement; |
79 } | 82 } |
80 catch (e) { | 83 catch (e) { |
81 alert(e); | 84 //TODO: error |
82 } | 85 } |
83 finally { | 86 finally { |
84 return DOM; | 87 return DOM; |
85 }; | 88 }; |
86 }, | 89 }, |
93 var XML = null; | 96 var XML = null; |
94 try { | 97 try { |
95 XML = this.serializer.serializeToString(aElement); | 98 XML = this.serializer.serializeToString(aElement); |
96 } | 99 } |
97 catch (e) { | 100 catch (e) { |
98 //TODO throw error | 101 //TODO: error |
99 } | 102 } |
100 finally { | 103 finally { |
101 return XML; | 104 return XML; |
102 }; | 105 }; |
103 }, | 106 }, |
122 * @memberOf Lightstring | 125 * @memberOf Lightstring |
123 */ | 126 */ |
124 Lightstring.Connection = function(aService) { | 127 Lightstring.Connection = function(aService) { |
125 if (aService) | 128 if (aService) |
126 this.service = aService; | 129 this.service = aService; |
130 /** | |
131 * @namespace Holds connection events handlers | |
132 */ | |
127 this.handlers = {}; | 133 this.handlers = {}; |
134 /** | |
135 * @namespace Holds connection iq callbacks | |
136 */ | |
128 this.callbacks = {}; | 137 this.callbacks = {}; |
129 }; | 138 }; |
130 Lightstring.Connection.prototype = { | 139 Lightstring.Connection.prototype = { |
131 /** | 140 /** |
132 * @function Create and open a websocket then go though the XMPP authentification process. | 141 * @function Create and open a websocket then go though the XMPP authentification process. |
138 this.jid = new Lightstring.JID(aJid); | 147 this.jid = new Lightstring.JID(aJid); |
139 if (aPassword) | 148 if (aPassword) |
140 this.password = aPassword; | 149 this.password = aPassword; |
141 | 150 |
142 if (!this.jid.bare) | 151 if (!this.jid.bare) |
143 throw 'Lightstring: Connection.jid is undefined.'; | 152 return; //TODO: error |
144 if (!this.service) | 153 if (!this.service) |
145 throw 'Lightstring: Connection.service is undefined.'; | 154 return; //TODO: error |
146 | 155 |
147 if(typeof(WebSocket) === "function") { | 156 if(typeof(WebSocket) === "function") { |
148 this.socket = new WebSocket(this.service, 'xmpp'); | 157 this.socket = new WebSocket(this.service, 'xmpp'); |
149 } | 158 } |
150 else if(typeof(MozWebSocket) === "function") { | 159 else if(typeof(MozWebSocket) === "function") { |
151 this.socket = new MozWebSocket(this.service, 'xmpp'); | 160 this.socket = new MozWebSocket(this.service, 'xmpp'); |
152 } | 161 } |
153 else { | 162 else { |
154 throw new Error('WebSocket not available.'); | 163 return; //TODO: error |
155 } | 164 } |
156 | 165 |
157 var that = this; | 166 var Conn = this; |
158 this.socket.addEventListener('open', function() { | 167 this.socket.addEventListener('open', function() { |
159 //TODO: if (this.protocol !== 'xmpp') | 168 if (this.protocol !== 'xmpp') |
160 | 169 return; //TODO: error |
161 var stream = Lightstring.stanzas.stream.open(that.jid.domain); | 170 |
162 //TODO: Use Lightstring.Connection.send (problem with parsing steam); | 171 var stream = Lightstring.stanzas.stream.open(Conn.jid.domain); |
163 that.socket.send(stream); | 172 //FIXME: Use Lightstring.Connection.send (problem with parsing steam); |
173 Conn.socket.send(stream); | |
164 var stanza = { | 174 var stanza = { |
165 XML: stream | 175 XML: stream |
166 }; | 176 }; |
167 that.emit('output', stanza); | 177 Conn.emit('output', stanza); |
168 }); | 178 }); |
169 this.socket.addEventListener('error', function(e) { | 179 this.socket.addEventListener('error', function(e) { |
170 that.emit('error', e.data); | 180 Conn.emit('disconnecting', e.data); |
171 console.log(e.data); | 181 //TODO: error |
172 }); | 182 }); |
173 this.socket.addEventListener('close', function(e) { | 183 this.socket.addEventListener('close', function(e) { |
174 that.emit('disconnected', e.data); | 184 Conn.emit('disconnected', e.data); |
175 }); | 185 }); |
176 this.socket.addEventListener('message', function(e) { | 186 this.socket.addEventListener('message', function(e) { |
177 var stanza = new Lightstring.Stanza(e.data); | 187 var stanza = new Lightstring.Stanza(e.data); |
178 | 188 |
179 //TODO node-xmpp-bosh sends a self-closing stream:stream tag; it is wrong! | 189 //FIXME: node-xmpp-bosh sends a self-closing stream:stream tag; it is wrong! |
180 that.emit('input', stanza); | 190 Conn.emit('input', stanza); |
181 | 191 |
182 if(!stanza.DOM) | 192 if(!stanza.DOM) |
183 return; | 193 return; |
184 | 194 |
185 | |
186 var name = stanza.DOM.localName; | 195 var name = stanza.DOM.localName; |
196 | |
197 //Authentication | |
187 //FIXME SASL mechanisms and XMPP features can be both in a stream:features | 198 //FIXME SASL mechanisms and XMPP features can be both in a stream:features |
188 if (name === 'features') { | 199 if (name === 'features') { |
189 //SASL mechanisms | 200 //SASL mechanisms |
190 if (stanza.DOM.firstChild.localName === 'mechanisms') { | 201 if (stanza.DOM.firstChild.localName === 'mechanisms') { |
191 stanza.mechanisms = []; | 202 stanza.mechanisms = []; |
192 var nodes = stanza.DOM.querySelectorAll('mechanism'); | 203 var nodes = stanza.DOM.querySelectorAll('mechanism'); |
193 for (var i = 0; i < nodes.length; i++) | 204 for (var i = 0; i < nodes.length; i++) |
194 stanza.mechanisms.push(nodes[i].textContent); | 205 stanza.mechanisms.push(nodes[i].textContent); |
195 that.emit('mechanisms', stanza); | 206 Conn.emit('mechanisms', stanza); |
196 } | 207 } |
197 //XMPP features | 208 //XMPP features |
198 else { | 209 else { |
199 //TODO: stanza.features | 210 //TODO: stanza.features |
200 that.emit('features', stanza); | 211 Conn.emit('features', stanza); |
201 } | 212 } |
202 } | 213 } |
203 else if (name === 'challenge') { | 214 else if (name === 'challenge') { |
204 that.emit('challenge', stanza); | 215 Conn.emit('challenge', stanza); |
205 } | |
206 else if (name === 'response') { | |
207 | |
208 | |
209 } | 216 } |
210 else if (name === 'failure') { | 217 else if (name === 'failure') { |
211 that.emit('failure', stanza); | 218 Conn.emit('failure', stanza); |
212 } | 219 } |
213 else if (name === 'success') { | 220 else if (name === 'success') { |
214 that.emit('success', stanza); | 221 Conn.emit('success', stanza); |
215 } | 222 } |
216 else if(name === 'stream') { | |
217 | |
218 | |
219 } | |
220 | |
221 | |
222 | 223 |
223 //Iq callbacks | 224 //Iq callbacks |
224 else if (name === 'iq') { | 225 else if (name === 'iq') { |
225 var payload = stanza.DOM.firstChild; | 226 var payload = stanza.DOM.firstChild; |
226 if (payload) | 227 if (payload) |
227 that.emit('iq/' + payload.namespaceURI + ':' + payload.localName, stanza); | 228 Conn.emit('iq/' + payload.namespaceURI + ':' + payload.localName, stanza); |
228 | 229 |
229 var id = stanza.DOM.getAttributeNS(null, 'id'); | 230 var id = stanza.DOM.getAttributeNS(null, 'id'); |
230 if (!(id && id in that.callbacks)) | 231 if (!(id && id in Conn.callbacks)) |
231 return; | 232 return; |
232 | 233 |
233 var type = stanza.DOM.getAttributeNS(null, 'type'); | 234 var type = stanza.DOM.getAttributeNS(null, 'type'); |
234 if (type !== 'result' && type !== 'error') | 235 if (type !== 'result' && type !== 'error') |
235 return; //TODO: emit an warning, perhaps. | 236 return; //TODO: warning |
236 | 237 |
237 var callback = that.callbacks[id]; | 238 var callback = Conn.callbacks[id]; |
238 if (type === 'result' && callback.success) | 239 if (type === 'result' && callback.success) |
239 callback.success(stanza); | 240 callback.success(stanza); |
240 else if (type === 'error' && callback.error) | 241 else if (type === 'error' && callback.error) |
241 callback.error(stanza); | 242 callback.error(stanza); |
242 | 243 |
243 delete that.callbacks[id]; | 244 delete Conn.callbacks[id]; |
244 } | 245 } |
245 }); | 246 }); |
246 }, | 247 }, |
247 /** | 248 /** |
248 * @function Send a message. | 249 * @function Send a message. |
259 return; | 260 return; |
260 | 261 |
261 if (stanza.DOM.tagName === 'iq') { | 262 if (stanza.DOM.tagName === 'iq') { |
262 var type = stanza.DOM.getAttributeNS(null, 'type'); | 263 var type = stanza.DOM.getAttributeNS(null, 'type'); |
263 if (type !== 'get' || type !== 'set') | 264 if (type !== 'get' || type !== 'set') |
264 ; //TODO: emit an error. | 265 ; //TODO: error |
265 | 266 |
266 var callback = {success: aSuccess, error: aError}; | 267 var callback = {success: aSuccess, error: aError}; |
267 | 268 |
268 var id = stanza.DOM.getAttributeNS(null, 'id'); | 269 var id = stanza.DOM.getAttributeNS(null, 'id'); |
269 if (!id) | 270 if (!id) |
270 ; //TODO: emit an warning. | 271 ; //TODO: warning |
271 else | 272 else |
272 this.callbacks[id] = callback; | 273 this.callbacks[id] = callback; |
273 | 274 |
274 } else if (aSuccess || aError) | 275 } else if (aSuccess || aError) |
275 ; //TODO: callback can’t be called with non-iq stanza. | 276 ; //TODO: warning (no callback without iq) |
276 | 277 |
277 | 278 |
278 //TODO this.socket.send(stanza.XML); (need some work on Lightstring.Stanza) | 279 //FIXME this.socket.send(stanza.XML); (need some work on Lightstring.Stanza) |
279 var fixme = Lightstring.DOM2XML(stanza.DOM); | 280 var fixme = Lightstring.DOM2XML(stanza.DOM); |
280 stanza.XML = fixme; | 281 stanza.XML = fixme; |
281 this.socket.send(fixme); | 282 this.socket.send(fixme); |
282 this.emit('output', stanza); | 283 this.emit('output', stanza); |
283 }, | 284 }, |
293 }, | 294 }, |
294 load: function() { | 295 load: function() { |
295 for (var i = 0; i < arguments.length; i++) { | 296 for (var i = 0; i < arguments.length; i++) { |
296 var name = arguments[i]; | 297 var name = arguments[i]; |
297 if (!(name in Lightstring.plugins)) | 298 if (!(name in Lightstring.plugins)) |
298 continue; //TODO: throw an error? | 299 continue; //TODO: error |
299 | 300 |
300 var plugin = Lightstring.plugins[name]; | 301 var plugin = Lightstring.plugins[name]; |
301 | 302 |
302 //Namespaces | 303 //Namespaces |
303 for (var ns in plugin.namespaces) | 304 for (var ns in plugin.namespaces) |
340 | 341 |
341 var ret; | 342 var ret; |
342 for (var i = 0; i < handlers.length; i++) { | 343 for (var i = 0; i < handlers.length; i++) { |
343 ret = handlers[i].call(this, aData); | 344 ret = handlers[i].call(this, aData); |
344 if (typeof ret !== 'boolean') | 345 if (typeof ret !== 'boolean') |
345 return; //TODO: emit a big error! | 346 return; //TODO: error |
346 | 347 |
347 if (ret) | 348 if (ret) |
348 return; | 349 return; |
349 } | 350 } |
350 | 351 |