/platforms/ios/www/js/socket.io.js
JavaScript | 6065 lines | 3324 code | 957 blank | 1784 comment | 921 complexity | 8c821c2b1818c013e88dbd2ea16bbf87 MD5 | raw file
Possible License(s): Apache-2.0, MIT
Large files files are truncated, but you can click here to view the full file
1!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.io=e():"undefined"!=typeof global?global.io=e():"undefined"!=typeof self&&(self.io=e())}(function(){var define,module,exports;
2return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
3
4module.exports = require('./lib/');
5
6},{"./lib/":2}],2:[function(require,module,exports){
7
8/**
9 * Module dependencies.
10 */
11
12var url = require('./url');
13var parser = require('socket.io-parser');
14var Manager = require('./manager');
15var debug = require('debug')('socket.io-client');
16
17/**
18 * Module exports.
19 */
20
21module.exports = exports = lookup;
22
23/**
24 * Managers cache.
25 */
26
27var cache = exports.managers = {};
28
29/**
30 * Looks up an existing `Manager` for multiplexing.
31 * If the user summons:
32 *
33 * `io('http://localhost/a');`
34 * `io('http://localhost/b');`
35 *
36 * We reuse the existing instance based on same scheme/port/host,
37 * and we initialize sockets for each namespace.
38 *
39 * @api public
40 */
41
42function lookup(uri, opts) {
43 if (typeof uri == 'object') {
44 opts = uri;
45 uri = undefined;
46 }
47
48 opts = opts || {};
49
50 var parsed = url(uri);
51 var href = parsed.href;
52 var id = parsed.id;
53 var io;
54
55 if (opts.forceNew || false === opts.multiplex) {
56 debug('ignoring socket cache for %s', href);
57 io = Manager(href, opts);
58 } else {
59 if (!cache[id]) {
60 debug('new io instance for %s', href);
61 cache[id] = Manager(href, opts);
62 }
63 io = cache[id];
64 }
65
66 return io.socket(parsed.path);
67}
68
69/**
70 * Protocol version.
71 *
72 * @api public
73 */
74
75exports.protocol = parser.protocol;
76
77/**
78 * `connect`.
79 *
80 * @param {String} uri
81 * @api public
82 */
83
84exports.connect = lookup;
85
86/**
87 * Expose constructors for standalone build.
88 *
89 * @api public
90 */
91
92exports.Manager = require('./manager');
93exports.Socket = require('./socket');
94
95},{"./manager":3,"./socket":5,"./url":6,"debug":9,"socket.io-parser":39}],3:[function(require,module,exports){
96
97/**
98 * Module dependencies.
99 */
100
101var url = require('./url');
102var eio = require('engine.io-client');
103var Socket = require('./socket');
104var Emitter = require('emitter');
105var parser = require('socket.io-parser');
106var on = require('./on');
107var bind = require('bind');
108var object = require('object-component');
109var debug = require('debug')('socket.io-client:manager');
110
111/**
112 * Module exports
113 */
114
115module.exports = Manager;
116
117/**
118 * `Manager` constructor.
119 *
120 * @param {String} engine instance or engine uri/opts
121 * @param {Object} options
122 * @api public
123 */
124
125function Manager(uri, opts){
126 if (!(this instanceof Manager)) return new Manager(uri, opts);
127 if ('object' == typeof uri) {
128 opts = uri;
129 uri = undefined;
130 }
131 opts = opts || {};
132
133 opts.path = opts.path || '/socket.io';
134 this.nsps = {};
135 this.subs = [];
136 this.opts = opts;
137 this.reconnection(opts.reconnection !== false);
138 this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
139 this.reconnectionDelay(opts.reconnectionDelay || 1000);
140 this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
141 this.timeout(null == opts.timeout ? 20000 : opts.timeout);
142 this.readyState = 'closed';
143 this.uri = uri;
144 this.connected = 0;
145 this.attempts = 0;
146 this.encoding = false;
147 this.packetBuffer = [];
148 this.encoder = new parser.Encoder();
149 this.decoder = new parser.Decoder();
150 this.open();
151}
152
153/**
154 * Mix in `Emitter`.
155 */
156
157Emitter(Manager.prototype);
158
159/**
160 * Sets the `reconnection` config.
161 *
162 * @param {Boolean} true/false if it should automatically reconnect
163 * @return {Manager} self or value
164 * @api public
165 */
166
167Manager.prototype.reconnection = function(v){
168 if (!arguments.length) return this._reconnection;
169 this._reconnection = !!v;
170 return this;
171};
172
173/**
174 * Sets the reconnection attempts config.
175 *
176 * @param {Number} max reconnection attempts before giving up
177 * @return {Manager} self or value
178 * @api public
179 */
180
181Manager.prototype.reconnectionAttempts = function(v){
182 if (!arguments.length) return this._reconnectionAttempts;
183 this._reconnectionAttempts = v;
184 return this;
185};
186
187/**
188 * Sets the delay between reconnections.
189 *
190 * @param {Number} delay
191 * @return {Manager} self or value
192 * @api public
193 */
194
195Manager.prototype.reconnectionDelay = function(v){
196 if (!arguments.length) return this._reconnectionDelay;
197 this._reconnectionDelay = v;
198 return this;
199};
200
201/**
202 * Sets the maximum delay between reconnections.
203 *
204 * @param {Number} delay
205 * @return {Manager} self or value
206 * @api public
207 */
208
209Manager.prototype.reconnectionDelayMax = function(v){
210 if (!arguments.length) return this._reconnectionDelayMax;
211 this._reconnectionDelayMax = v;
212 return this;
213};
214
215/**
216 * Sets the connection timeout. `false` to disable
217 *
218 * @return {Manager} self or value
219 * @api public
220 */
221
222Manager.prototype.timeout = function(v){
223 if (!arguments.length) return this._timeout;
224 this._timeout = v;
225 return this;
226};
227
228/**
229 * Starts trying to reconnect if reconnection is enabled and we have not
230 * started reconnecting yet
231 *
232 * @api private
233 */
234
235Manager.prototype.maybeReconnectOnOpen = function() {
236 if (!this.openReconnect && !this.reconnecting && this._reconnection) {
237 // keeps reconnection from firing twice for the same reconnection loop
238 this.openReconnect = true;
239 this.reconnect();
240 }
241};
242
243
244/**
245 * Sets the current transport `socket`.
246 *
247 * @param {Function} optional, callback
248 * @return {Manager} self
249 * @api public
250 */
251
252Manager.prototype.open =
253Manager.prototype.connect = function(fn){
254 debug('readyState %s', this.readyState);
255 if (~this.readyState.indexOf('open')) return this;
256
257 debug('opening %s', this.uri);
258 this.engine = eio(this.uri, this.opts);
259 var socket = this.engine;
260 var self = this;
261 this.readyState = 'opening';
262
263 // emit `open`
264 var openSub = on(socket, 'open', function() {
265 self.onopen();
266 fn && fn();
267 });
268
269 // emit `connect_error`
270 var errorSub = on(socket, 'error', function(data){
271 debug('connect_error');
272 self.cleanup();
273 self.readyState = 'closed';
274 self.emit('connect_error', data);
275 if (fn) {
276 var err = new Error('Connection error');
277 err.data = data;
278 fn(err);
279 }
280
281 self.maybeReconnectOnOpen();
282 });
283
284 // emit `connect_timeout`
285 if (false !== this._timeout) {
286 var timeout = this._timeout;
287 debug('connect attempt will timeout after %d', timeout);
288
289 // set timer
290 var timer = setTimeout(function(){
291 debug('connect attempt timed out after %d', timeout);
292 openSub.destroy();
293 socket.close();
294 socket.emit('error', 'timeout');
295 self.emit('connect_timeout', timeout);
296 }, timeout);
297
298 this.subs.push({
299 destroy: function(){
300 clearTimeout(timer);
301 }
302 });
303 }
304
305 this.subs.push(openSub);
306 this.subs.push(errorSub);
307
308 return this;
309};
310
311/**
312 * Called upon transport open.
313 *
314 * @api private
315 */
316
317Manager.prototype.onopen = function(){
318 debug('open');
319
320 // clear old subs
321 this.cleanup();
322
323 // mark as open
324 this.readyState = 'open';
325 this.emit('open');
326
327 // add new subs
328 var socket = this.engine;
329 this.subs.push(on(socket, 'data', bind(this, 'ondata')));
330 this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
331 this.subs.push(on(socket, 'error', bind(this, 'onerror')));
332 this.subs.push(on(socket, 'close', bind(this, 'onclose')));
333};
334
335/**
336 * Called with data.
337 *
338 * @api private
339 */
340
341Manager.prototype.ondata = function(data){
342 this.decoder.add(data);
343};
344
345/**
346 * Called when parser fully decodes a packet.
347 *
348 * @api private
349 */
350
351Manager.prototype.ondecoded = function(packet) {
352 this.emit('packet', packet);
353};
354
355/**
356 * Called upon socket error.
357 *
358 * @api private
359 */
360
361Manager.prototype.onerror = function(err){
362 debug('error', err);
363 this.emit('error', err);
364};
365
366/**
367 * Creates a new socket for the given `nsp`.
368 *
369 * @return {Socket}
370 * @api public
371 */
372
373Manager.prototype.socket = function(nsp){
374 var socket = this.nsps[nsp];
375 if (!socket) {
376 socket = new Socket(this, nsp);
377 this.nsps[nsp] = socket;
378 var self = this;
379 socket.on('connect', function(){
380 self.connected++;
381 });
382 }
383 return socket;
384};
385
386/**
387 * Called upon a socket close.
388 *
389 * @param {Socket} socket
390 */
391
392Manager.prototype.destroy = function(socket){
393 --this.connected || this.close();
394};
395
396/**
397 * Writes a packet.
398 *
399 * @param {Object} packet
400 * @api private
401 */
402
403Manager.prototype.packet = function(packet){
404 debug('writing packet %j', packet);
405 var self = this;
406
407 if (!self.encoding) {
408 // encode, then write to engine with result
409 self.encoding = true;
410 this.encoder.encode(packet, function(encodedPackets) {
411 for (var i = 0; i < encodedPackets.length; i++) {
412 self.engine.write(encodedPackets[i]);
413 }
414 self.encoding = false;
415 self.processPacketQueue();
416 });
417 } else { // add packet to the queue
418 self.packetBuffer.push(packet);
419 }
420};
421
422/**
423 * If packet buffer is non-empty, begins encoding the
424 * next packet in line.
425 *
426 * @api private
427 */
428
429Manager.prototype.processPacketQueue = function() {
430 if (this.packetBuffer.length > 0 && !this.encoding) {
431 var pack = this.packetBuffer.shift();
432 this.packet(pack);
433 }
434};
435
436/**
437 * Clean up transport subscriptions and packet buffer.
438 *
439 * @api private
440 */
441
442Manager.prototype.cleanup = function(){
443 var sub;
444 while (sub = this.subs.shift()) sub.destroy();
445
446 this.packetBuffer = [];
447 this.encoding = false;
448
449 this.decoder.destroy();
450};
451
452/**
453 * Close the current socket.
454 *
455 * @api private
456 */
457
458Manager.prototype.close =
459Manager.prototype.disconnect = function(){
460 this.skipReconnect = true;
461 this.engine.close();
462};
463
464/**
465 * Called upon engine close.
466 *
467 * @api private
468 */
469
470Manager.prototype.onclose = function(reason){
471 debug('close');
472 this.cleanup();
473 this.readyState = 'closed';
474 this.emit('close', reason);
475 if (this._reconnection && !this.skipReconnect) {
476 this.reconnect();
477 }
478};
479
480/**
481 * Attempt a reconnection.
482 *
483 * @api private
484 */
485
486Manager.prototype.reconnect = function(){
487 if (this.reconnecting) return this;
488
489 var self = this;
490 this.attempts++;
491
492 if (this.attempts > this._reconnectionAttempts) {
493 debug('reconnect failed');
494 this.emit('reconnect_failed');
495 this.reconnecting = false;
496 } else {
497 var delay = this.attempts * this.reconnectionDelay();
498 delay = Math.min(delay, this.reconnectionDelayMax());
499 debug('will wait %dms before reconnect attempt', delay);
500
501 this.reconnecting = true;
502 var timer = setTimeout(function(){
503 debug('attempting reconnect');
504 self.emit('reconnect_attempt');
505 self.open(function(err){
506 if (err) {
507 debug('reconnect attempt error');
508 self.reconnecting = false;
509 self.reconnect();
510 self.emit('reconnect_error', err.data);
511 } else {
512 debug('reconnect success');
513 self.onreconnect();
514 }
515 });
516 }, delay);
517
518 this.subs.push({
519 destroy: function(){
520 clearTimeout(timer);
521 }
522 });
523 }
524};
525
526/**
527 * Called upon successful reconnect.
528 *
529 * @api private
530 */
531
532Manager.prototype.onreconnect = function(){
533 var attempt = this.attempts;
534 this.attempts = 0;
535 this.reconnecting = false;
536 this.emit('reconnect', attempt);
537};
538
539},{"./on":4,"./socket":5,"./url":6,"bind":8,"debug":9,"emitter":10,"engine.io-client":11,"object-component":36,"socket.io-parser":39}],4:[function(require,module,exports){
540
541/**
542 * Module exports.
543 */
544
545module.exports = on;
546
547/**
548 * Helper for subscriptions.
549 *
550 * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
551 * @param {String} event name
552 * @param {Function} callback
553 * @api public
554 */
555
556function on(obj, ev, fn) {
557 obj.on(ev, fn);
558 return {
559 destroy: function(){
560 obj.removeListener(ev, fn);
561 }
562 };
563}
564
565},{}],5:[function(require,module,exports){
566
567/**
568 * Module dependencies.
569 */
570
571var parser = require('socket.io-parser');
572var Emitter = require('emitter');
573var toArray = require('to-array');
574var on = require('./on');
575var bind = require('bind');
576var debug = require('debug')('socket.io-client:socket');
577var hasBin = require('has-binary-data');
578var indexOf = require('indexof');
579
580/**
581 * Module exports.
582 */
583
584module.exports = exports = Socket;
585
586/**
587 * Internal events (blacklisted).
588 * These events can't be emitted by the user.
589 *
590 * @api private
591 */
592
593var events = {
594 connect: 1,
595 disconnect: 1,
596 error: 1
597};
598
599/**
600 * Shortcut to `Emitter#emit`.
601 */
602
603var emit = Emitter.prototype.emit;
604
605/**
606 * `Socket` constructor.
607 *
608 * @api public
609 */
610
611function Socket(io, nsp){
612 this.io = io;
613 this.nsp = nsp;
614 this.json = this; // compat
615 this.ids = 0;
616 this.acks = {};
617 this.open();
618 this.buffer = [];
619 this.connected = false;
620 this.disconnected = true;
621}
622
623/**
624 * Mix in `Emitter`.
625 */
626
627Emitter(Socket.prototype);
628
629/**
630 * Called upon engine `open`.
631 *
632 * @api private
633 */
634
635Socket.prototype.open =
636Socket.prototype.connect = function(){
637 if (this.connected) return this;
638 var io = this.io;
639 io.open(); // ensure open
640 this.subs = [
641 on(io, 'open', bind(this, 'onopen')),
642 on(io, 'error', bind(this, 'onerror')),
643 on(io, 'packet', bind(this, 'onpacket')),
644 on(io, 'close', bind(this, 'onclose'))
645 ];
646 if ('open' == this.io.readyState) this.onopen();
647 return this;
648};
649
650/**
651 * Sends a `message` event.
652 *
653 * @return {Socket} self
654 * @api public
655 */
656
657Socket.prototype.send = function(){
658 var args = toArray(arguments);
659 args.unshift('message');
660 this.emit.apply(this, args);
661 return this;
662};
663
664/**
665 * Override `emit`.
666 * If the event is in `events`, it's emitted normally.
667 *
668 * @param {String} event name
669 * @return {Socket} self
670 * @api public
671 */
672
673Socket.prototype.emit = function(ev){
674 if (events.hasOwnProperty(ev)) {
675 emit.apply(this, arguments);
676 return this;
677 }
678
679 var args = toArray(arguments);
680 var parserType = parser.EVENT; // default
681 if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
682 var packet = { type: parserType, data: args };
683
684 // event ack callback
685 if ('function' == typeof args[args.length - 1]) {
686 debug('emitting packet with ack id %d', this.ids);
687 this.acks[this.ids] = args.pop();
688 packet.id = this.ids++;
689 }
690
691 this.packet(packet);
692
693 return this;
694};
695
696/**
697 * Sends a packet.
698 *
699 * @param {Object} packet
700 * @api private
701 */
702
703Socket.prototype.packet = function(packet){
704 packet.nsp = this.nsp;
705 this.io.packet(packet);
706};
707
708/**
709 * Called upon `error`.
710 *
711 * @param {Object} data
712 * @api private
713 */
714
715Socket.prototype.onerror = function(data){
716 this.emit('error', data);
717};
718
719/**
720 * "Opens" the socket.
721 *
722 * @api private
723 */
724
725Socket.prototype.onopen = function(){
726 debug('transport is open - connecting');
727
728 // write connect packet if necessary
729 if ('/' != this.nsp) {
730 this.packet({ type: parser.CONNECT });
731 }
732};
733
734/**
735 * Called upon engine `close`.
736 *
737 * @param {String} reason
738 * @api private
739 */
740
741Socket.prototype.onclose = function(reason){
742 debug('close (%s)', reason);
743 this.connected = false;
744 this.disconnected = true;
745 this.emit('disconnect', reason);
746};
747
748/**
749 * Called with socket packet.
750 *
751 * @param {Object} packet
752 * @api private
753 */
754
755Socket.prototype.onpacket = function(packet){
756 if (packet.nsp != this.nsp) return;
757
758 switch (packet.type) {
759 case parser.CONNECT:
760 this.onconnect();
761 break;
762
763 case parser.EVENT:
764 this.onevent(packet);
765 break;
766
767 case parser.BINARY_EVENT:
768 this.onevent(packet);
769 break;
770
771 case parser.ACK:
772 this.onack(packet);
773 break;
774
775 case parser.DISCONNECT:
776 this.ondisconnect();
777 break;
778
779 case parser.ERROR:
780 this.emit('error', packet.data);
781 break;
782 }
783};
784
785/**
786 * Called upon a server event.
787 *
788 * @param {Object} packet
789 * @api private
790 */
791
792Socket.prototype.onevent = function(packet){
793 var args = packet.data || [];
794 debug('emitting event %j', args);
795
796 if (null != packet.id) {
797 debug('attaching ack callback to event');
798 args.push(this.ack(packet.id));
799 }
800
801 if (this.connected) {
802 emit.apply(this, args);
803 } else {
804 this.buffer.push(args);
805 }
806};
807
808/**
809 * Produces an ack callback to emit with an event.
810 *
811 * @api private
812 */
813
814Socket.prototype.ack = function(id){
815 var self = this;
816 var sent = false;
817 return function(){
818 // prevent double callbacks
819 if (sent) return;
820 sent = true;
821 var args = toArray(arguments);
822 debug('sending ack %j', args);
823 self.packet({
824 type: parser.ACK,
825 id: id,
826 data: args
827 });
828 };
829};
830
831/**
832 * Called upon a server acknowlegement.
833 *
834 * @param {Object} packet
835 * @api private
836 */
837
838Socket.prototype.onack = function(packet){
839 debug('calling ack %s with %j', packet.id, packet.data);
840 var fn = this.acks[packet.id];
841 fn.apply(this, packet.data);
842 delete this.acks[packet.id];
843};
844
845/**
846 * Called upon server connect.
847 *
848 * @api private
849 */
850
851Socket.prototype.onconnect = function(){
852 this.connected = true;
853 this.disconnected = false;
854 this.emit('connect');
855 this.emitBuffered();
856};
857
858/**
859 * Emit buffered events.
860 *
861 * @api private
862 */
863
864Socket.prototype.emitBuffered = function(){
865 for (var i = 0; i < this.buffer.length; i++) {
866 emit.apply(this, this.buffer[i]);
867 }
868 this.buffer = [];
869};
870
871/**
872 * Called upon server disconnect.
873 *
874 * @api private
875 */
876
877Socket.prototype.ondisconnect = function(){
878 debug('server disconnect (%s)', this.nsp);
879 this.destroy();
880 this.onclose('io server disconnect');
881};
882
883/**
884 * Called upon forced client/server side disconnections,
885 * this method ensures the manager stops tracking us and
886 * that reconnections don't get triggered for this.
887 *
888 * @api private.
889 */
890
891Socket.prototype.destroy = function(){
892 // clean subscriptions to avoid reconnections
893 for (var i = 0; i < this.subs.length; i++) {
894 this.subs[i].destroy();
895 }
896
897 this.io.destroy(this);
898};
899
900/**
901 * Disconnects the socket manually.
902 *
903 * @return {Socket} self
904 * @api public
905 */
906
907Socket.prototype.close =
908Socket.prototype.disconnect = function(){
909 if (!this.connected) return this;
910
911 debug('performing disconnect (%s)', this.nsp);
912 this.packet({ type: parser.DISCONNECT });
913
914 // remove socket from pool
915 this.destroy();
916
917 // fire events
918 this.onclose('io client disconnect');
919 return this;
920};
921
922},{"./on":4,"bind":8,"debug":9,"emitter":10,"has-binary-data":31,"indexof":35,"socket.io-parser":39,"to-array":42}],6:[function(require,module,exports){
923var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
924/**
925 * Module dependencies.
926 */
927
928var parseuri = require('parseuri');
929var debug = require('debug')('socket.io-client:url');
930
931/**
932 * Module exports.
933 */
934
935module.exports = url;
936
937/**
938 * URL parser.
939 *
940 * @param {String} url
941 * @param {Object} An object meant to mimic window.location.
942 * Defaults to window.location.
943 * @api public
944 */
945
946function url(uri, loc){
947 var obj = uri;
948
949 // default to window.location
950 var loc = loc || global.location;
951 if (null == uri) uri = loc.protocol + '//' + loc.hostname;
952
953 // relative path support
954 if ('string' == typeof uri) {
955 if ('/' == uri.charAt(0)) {
956 if ('undefined' != typeof loc) {
957 uri = loc.hostname + uri;
958 }
959 }
960
961 if (!/^(https?|wss?):\/\//.test(uri)) {
962 debug('protocol-less url %s', uri);
963 if ('undefined' != typeof loc) {
964 uri = loc.protocol + '//' + uri;
965 } else {
966 uri = 'https://' + uri;
967 }
968 }
969
970 // parse
971 debug('parse %s', uri);
972 obj = parseuri(uri);
973 }
974
975 // make sure we treat `localhost:80` and `localhost` equally
976 if ((/(http|ws)/.test(obj.protocol) && 80 == obj.port) ||
977 (/(http|ws)s/.test(obj.protocol) && 443 == obj.port)) {
978 delete obj.port;
979 }
980
981 obj.path = obj.path || '/';
982
983 // define unique id
984 obj.id = obj.protocol + obj.host + (obj.port ? (':' + obj.port) : '');
985
986 // define href
987 obj.href = obj.protocol + '://' + obj.host + (obj.port ? (':' + obj.port) : '');
988
989 return obj;
990}
991
992},{"debug":9,"parseuri":37}],7:[function(require,module,exports){
993/*
994 * base64-arraybuffer
995 * https://github.com/niklasvh/base64-arraybuffer
996 *
997 * Copyright (c) 2012 Niklas von Hertzen
998 * Licensed under the MIT license.
999 */
1000(function(chars){
1001 "use strict";
1002
1003 exports.encode = function(arraybuffer) {
1004 var bytes = new Uint8Array(arraybuffer),
1005 i, len = bytes.buffer.byteLength, base64 = "";
1006
1007 for (i = 0; i < len; i+=3) {
1008 base64 += chars[bytes.buffer[i] >> 2];
1009 base64 += chars[((bytes.buffer[i] & 3) << 4) | (bytes.buffer[i + 1] >> 4)];
1010 base64 += chars[((bytes.buffer[i + 1] & 15) << 2) | (bytes.buffer[i + 2] >> 6)];
1011 base64 += chars[bytes.buffer[i + 2] & 63];
1012 }
1013
1014 if ((len % 3) === 2) {
1015 base64 = base64.substring(0, base64.length - 1) + "=";
1016 } else if (len % 3 === 1) {
1017 base64 = base64.substring(0, base64.length - 2) + "==";
1018 }
1019
1020 return base64;
1021 };
1022
1023 exports.decode = function(base64) {
1024 var bufferLength = base64.length * 0.75,
1025 len = base64.length, i, p = 0,
1026 encoded1, encoded2, encoded3, encoded4;
1027
1028 if (base64[base64.length - 1] === "=") {
1029 bufferLength--;
1030 if (base64[base64.length - 2] === "=") {
1031 bufferLength--;
1032 }
1033 }
1034
1035 var arraybuffer = new ArrayBuffer(bufferLength),
1036 bytes = new Uint8Array(arraybuffer);
1037
1038 for (i = 0; i < len; i+=4) {
1039 encoded1 = chars.indexOf(base64[i]);
1040 encoded2 = chars.indexOf(base64[i+1]);
1041 encoded3 = chars.indexOf(base64[i+2]);
1042 encoded4 = chars.indexOf(base64[i+3]);
1043
1044 bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
1045 bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
1046 bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
1047 }
1048
1049 return arraybuffer;
1050 };
1051})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
1052},{}],8:[function(require,module,exports){
1053
1054/**
1055 * Slice reference.
1056 */
1057
1058var slice = [].slice;
1059
1060/**
1061 * Bind `obj` to `fn`.
1062 *
1063 * @param {Object} obj
1064 * @param {Function|String} fn or string
1065 * @return {Function}
1066 * @api public
1067 */
1068
1069module.exports = function(obj, fn){
1070 if ('string' == typeof fn) fn = obj[fn];
1071 if ('function' != typeof fn) throw new Error('bind() requires a function');
1072 var args = [].slice.call(arguments, 2);
1073 return function(){
1074 return fn.apply(obj, args.concat(slice.call(arguments)));
1075 }
1076};
1077
1078},{}],9:[function(require,module,exports){
1079
1080/**
1081 * Expose `debug()` as the module.
1082 */
1083
1084module.exports = debug;
1085
1086/**
1087 * Create a debugger with the given `name`.
1088 *
1089 * @param {String} name
1090 * @return {Type}
1091 * @api public
1092 */
1093
1094function debug(name) {
1095 if (!debug.enabled(name)) return function(){};
1096
1097 return function(fmt){
1098 fmt = coerce(fmt);
1099
1100 var curr = new Date;
1101 var ms = curr - (debug[name] || curr);
1102 debug[name] = curr;
1103
1104 fmt = name
1105 + ' '
1106 + fmt
1107 + ' +' + debug.humanize(ms);
1108
1109 // This hackery is required for IE8
1110 // where `console.log` doesn't have 'apply'
1111 window.console
1112 && console.log
1113 && Function.prototype.apply.call(console.log, console, arguments);
1114 }
1115}
1116
1117/**
1118 * The currently active debug mode names.
1119 */
1120
1121debug.names = [];
1122debug.skips = [];
1123
1124/**
1125 * Enables a debug mode by name. This can include modes
1126 * separated by a colon and wildcards.
1127 *
1128 * @param {String} name
1129 * @api public
1130 */
1131
1132debug.enable = function(name) {
1133 try {
1134 localStorage.debug = name;
1135 } catch(e){}
1136
1137 var split = (name || '').split(/[\s,]+/)
1138 , len = split.length;
1139
1140 for (var i = 0; i < len; i++) {
1141 name = split[i].replace('*', '.*?');
1142 if (name[0] === '-') {
1143 debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
1144 }
1145 else {
1146 debug.names.push(new RegExp('^' + name + '$'));
1147 }
1148 }
1149};
1150
1151/**
1152 * Disable debug output.
1153 *
1154 * @api public
1155 */
1156
1157debug.disable = function(){
1158 debug.enable('');
1159};
1160
1161/**
1162 * Humanize the given `ms`.
1163 *
1164 * @param {Number} m
1165 * @return {String}
1166 * @api private
1167 */
1168
1169debug.humanize = function(ms) {
1170 var sec = 1000
1171 , min = 60 * 1000
1172 , hour = 60 * min;
1173
1174 if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
1175 if (ms >= min) return (ms / min).toFixed(1) + 'm';
1176 if (ms >= sec) return (ms / sec | 0) + 's';
1177 return ms + 'ms';
1178};
1179
1180/**
1181 * Returns true if the given mode name is enabled, false otherwise.
1182 *
1183 * @param {String} name
1184 * @return {Boolean}
1185 * @api public
1186 */
1187
1188debug.enabled = function(name) {
1189 for (var i = 0, len = debug.skips.length; i < len; i++) {
1190 if (debug.skips[i].test(name)) {
1191 return false;
1192 }
1193 }
1194 for (var i = 0, len = debug.names.length; i < len; i++) {
1195 if (debug.names[i].test(name)) {
1196 return true;
1197 }
1198 }
1199 return false;
1200};
1201
1202/**
1203 * Coerce `val`.
1204 */
1205
1206function coerce(val) {
1207 if (val instanceof Error) return val.stack || val.message;
1208 return val;
1209}
1210
1211// persist
1212
1213try {
1214 if (window.localStorage) debug.enable(localStorage.debug);
1215} catch(e){}
1216
1217},{}],10:[function(require,module,exports){
1218
1219/**
1220 * Module dependencies.
1221 */
1222
1223var index = require('indexof');
1224
1225/**
1226 * Expose `Emitter`.
1227 */
1228
1229module.exports = Emitter;
1230
1231/**
1232 * Initialize a new `Emitter`.
1233 *
1234 * @api public
1235 */
1236
1237function Emitter(obj) {
1238 if (obj) return mixin(obj);
1239};
1240
1241/**
1242 * Mixin the emitter properties.
1243 *
1244 * @param {Object} obj
1245 * @return {Object}
1246 * @api private
1247 */
1248
1249function mixin(obj) {
1250 for (var key in Emitter.prototype) {
1251 obj[key] = Emitter.prototype[key];
1252 }
1253 return obj;
1254}
1255
1256/**
1257 * Listen on the given `event` with `fn`.
1258 *
1259 * @param {String} event
1260 * @param {Function} fn
1261 * @return {Emitter}
1262 * @api public
1263 */
1264
1265Emitter.prototype.on = function(event, fn){
1266 this._callbacks = this._callbacks || {};
1267 (this._callbacks[event] = this._callbacks[event] || [])
1268 .push(fn);
1269 return this;
1270};
1271
1272/**
1273 * Adds an `event` listener that will be invoked a single
1274 * time then automatically removed.
1275 *
1276 * @param {String} event
1277 * @param {Function} fn
1278 * @return {Emitter}
1279 * @api public
1280 */
1281
1282Emitter.prototype.once = function(event, fn){
1283 var self = this;
1284 this._callbacks = this._callbacks || {};
1285
1286 function on() {
1287 self.off(event, on);
1288 fn.apply(this, arguments);
1289 }
1290
1291 fn._off = on;
1292 this.on(event, on);
1293 return this;
1294};
1295
1296/**
1297 * Remove the given callback for `event` or all
1298 * registered callbacks.
1299 *
1300 * @param {String} event
1301 * @param {Function} fn
1302 * @return {Emitter}
1303 * @api public
1304 */
1305
1306Emitter.prototype.off =
1307Emitter.prototype.removeListener =
1308Emitter.prototype.removeAllListeners = function(event, fn){
1309 this._callbacks = this._callbacks || {};
1310
1311 // all
1312 if (0 == arguments.length) {
1313 this._callbacks = {};
1314 return this;
1315 }
1316
1317 // specific event
1318 var callbacks = this._callbacks[event];
1319 if (!callbacks) return this;
1320
1321 // remove all handlers
1322 if (1 == arguments.length) {
1323 delete this._callbacks[event];
1324 return this;
1325 }
1326
1327 // remove specific handler
1328 var i = index(callbacks, fn._off || fn);
1329 if (~i) callbacks.splice(i, 1);
1330 return this;
1331};
1332
1333/**
1334 * Emit `event` with the given args.
1335 *
1336 * @param {String} event
1337 * @param {Mixed} ...
1338 * @return {Emitter}
1339 */
1340
1341Emitter.prototype.emit = function(event){
1342 this._callbacks = this._callbacks || {};
1343 var args = [].slice.call(arguments, 1)
1344 , callbacks = this._callbacks[event];
1345
1346 if (callbacks) {
1347 callbacks = callbacks.slice(0);
1348 for (var i = 0, len = callbacks.length; i < len; ++i) {
1349 callbacks[i].apply(this, args);
1350 }
1351 }
1352
1353 return this;
1354};
1355
1356/**
1357 * Return array of callbacks for `event`.
1358 *
1359 * @param {String} event
1360 * @return {Array}
1361 * @api public
1362 */
1363
1364Emitter.prototype.listeners = function(event){
1365 this._callbacks = this._callbacks || {};
1366 return this._callbacks[event] || [];
1367};
1368
1369/**
1370 * Check if this emitter has `event` handlers.
1371 *
1372 * @param {String} event
1373 * @return {Boolean}
1374 * @api public
1375 */
1376
1377Emitter.prototype.hasListeners = function(event){
1378 return !! this.listeners(event).length;
1379};
1380
1381},{"indexof":35}],11:[function(require,module,exports){
1382
1383module.exports = require('./lib/');
1384
1385},{"./lib/":13}],12:[function(require,module,exports){
1386
1387/**
1388 * Module dependencies.
1389 */
1390
1391var Emitter = require('emitter');
1392
1393/**
1394 * Module exports.
1395 */
1396
1397module.exports = Emitter;
1398
1399/**
1400 * Compatibility with `WebSocket#addEventListener`.
1401 *
1402 * @api public
1403 */
1404
1405Emitter.prototype.addEventListener = Emitter.prototype.on;
1406
1407/**
1408 * Compatibility with `WebSocket#removeEventListener`.
1409 *
1410 * @api public
1411 */
1412
1413Emitter.prototype.removeEventListener = Emitter.prototype.off;
1414
1415/**
1416 * Node-compatible `EventEmitter#removeListener`
1417 *
1418 * @api public
1419 */
1420
1421Emitter.prototype.removeListener = Emitter.prototype.off;
1422
1423},{"emitter":10}],13:[function(require,module,exports){
1424
1425module.exports = require('./socket');
1426
1427/**
1428 * Exports parser
1429 *
1430 * @api public
1431 *
1432 */
1433module.exports.parser = require('engine.io-parser');
1434
1435},{"./socket":14,"engine.io-parser":24}],14:[function(require,module,exports){
1436var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};/**
1437 * Module dependencies.
1438 */
1439
1440var util = require('./util');
1441var transports = require('./transports');
1442var Emitter = require('./emitter');
1443var debug = require('debug')('engine.io-client:socket');
1444var index = require('indexof');
1445var parser = require('engine.io-parser');
1446var parseuri = require('parseuri');
1447var parsejson = require('parsejson');
1448
1449/**
1450 * Module exports.
1451 */
1452
1453module.exports = Socket;
1454
1455/**
1456 * Noop function.
1457 *
1458 * @api private
1459 */
1460
1461function noop(){}
1462
1463/**
1464 * Socket constructor.
1465 *
1466 * @param {String|Object} uri or options
1467 * @param {Object} options
1468 * @api public
1469 */
1470
1471function Socket(uri, opts){
1472 if (!(this instanceof Socket)) return new Socket(uri, opts);
1473
1474 opts = opts || {};
1475
1476 if (uri && 'object' == typeof uri) {
1477 opts = uri;
1478 uri = null;
1479 }
1480
1481 if (uri) {
1482 uri = parseuri(uri);
1483 opts.host = uri.host;
1484 opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
1485 opts.port = uri.port;
1486 if (uri.query) opts.query = uri.query;
1487 }
1488
1489 this.secure = null != opts.secure ? opts.secure :
1490 (global.location && 'https:' == location.protocol);
1491
1492 if (opts.host) {
1493 var pieces = opts.host.split(':');
1494 opts.hostname = pieces.shift();
1495 if (pieces.length) opts.port = pieces.pop();
1496 }
1497
1498 this.agent = opts.agent || false;
1499 this.hostname = opts.hostname ||
1500 (global.location ? location.hostname : 'localhost');
1501 this.port = opts.port || (global.location && location.port ?
1502 location.port :
1503 (this.secure ? 443 : 80));
1504 this.query = opts.query || {};
1505 if ('string' == typeof this.query) this.query = util.qsParse(this.query);
1506 this.upgrade = false !== opts.upgrade;
1507 this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
1508 this.forceJSONP = !!opts.forceJSONP;
1509 this.forceBase64 = !!opts.forceBase64;
1510 this.timestampParam = opts.timestampParam || 't';
1511 this.timestampRequests = opts.timestampRequests;
1512 this.flashPath = opts.flashPath || '';
1513 this.transports = opts.transports || ['polling', 'websocket', 'flashsocket'];
1514 this.readyState = '';
1515 this.writeBuffer = [];
1516 this.callbackBuffer = [];
1517 this.policyPort = opts.policyPort || 843;
1518 this.rememberUpgrade = opts.rememberUpgrade || false;
1519 this.open();
1520 this.binaryType = null;
1521 this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
1522}
1523
1524Socket.priorWebsocketSuccess = false;
1525
1526/**
1527 * Mix in `Emitter`.
1528 */
1529
1530Emitter(Socket.prototype);
1531
1532/**
1533 * Protocol version.
1534 *
1535 * @api public
1536 */
1537
1538Socket.protocol = parser.protocol; // this is an int
1539
1540/**
1541 * Expose deps for legacy compatibility
1542 * and standalone browser access.
1543 */
1544
1545Socket.Socket = Socket;
1546Socket.Transport = require('./transport');
1547Socket.Emitter = require('./emitter');
1548Socket.transports = require('./transports');
1549Socket.util = require('./util');
1550Socket.parser = require('engine.io-parser');
1551
1552/**
1553 * Creates transport of the given type.
1554 *
1555 * @param {String} transport name
1556 * @return {Transport}
1557 * @api private
1558 */
1559
1560Socket.prototype.createTransport = function (name) {
1561 debug('creating transport "%s"', name);
1562 var query = clone(this.query);
1563
1564 // append engine.io protocol identifier
1565 query.EIO = parser.protocol;
1566
1567 // transport name
1568 query.transport = name;
1569
1570 // session id if we already have one
1571 if (this.id) query.sid = this.id;
1572
1573 var transport = new transports[name]({
1574 agent: this.agent,
1575 hostname: this.hostname,
1576 port: this.port,
1577 secure: this.secure,
1578 path: this.path,
1579 query: query,
1580 forceJSONP: this.forceJSONP,
1581 forceBase64: this.forceBase64,
1582 timestampRequests: this.timestampRequests,
1583 timestampParam: this.timestampParam,
1584 flashPath: this.flashPath,
1585 policyPort: this.policyPort,
1586 socket: this
1587 });
1588
1589 return transport;
1590};
1591
1592function clone (obj) {
1593 var o = {};
1594 for (var i in obj) {
1595 if (obj.hasOwnProperty(i)) {
1596 o[i] = obj[i];
1597 }
1598 }
1599 return o;
1600}
1601
1602/**
1603 * Initializes transport to use and starts probe.
1604 *
1605 * @api private
1606 */
1607Socket.prototype.open = function () {
1608 var transport;
1609 if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
1610 transport = 'websocket';
1611 } else {
1612 transport = this.transports[0];
1613 }
1614 this.readyState = 'opening';
1615 var transport = this.createTransport(transport);
1616 transport.open();
1617 this.setTransport(transport);
1618};
1619
1620/**
1621 * Sets the current transport. Disables the existing one (if any).
1622 *
1623 * @api private
1624 */
1625
1626Socket.prototype.setTransport = function(transport){
1627 debug('setting transport %s', transport.name);
1628 var self = this;
1629
1630 if (this.transport) {
1631 debug('clearing existing transport %s', this.transport.name);
1632 this.transport.removeAllListeners();
1633 }
1634
1635 // set up transport
1636 this.transport = transport;
1637
1638 // set up transport listeners
1639 transport
1640 .on('drain', function(){
1641 self.onDrain();
1642 })
1643 .on('packet', function(packet){
1644 self.onPacket(packet);
1645 })
1646 .on('error', function(e){
1647 self.onError(e);
1648 })
1649 .on('close', function(){
1650 self.onClose('transport close');
1651 });
1652};
1653
1654/**
1655 * Probes a transport.
1656 *
1657 * @param {String} transport name
1658 * @api private
1659 */
1660
1661Socket.prototype.probe = function (name) {
1662 debug('probing transport "%s"', name);
1663 var transport = this.createTransport(name, { probe: 1 })
1664 , failed = false
1665 , self = this;
1666
1667 Socket.priorWebsocketSuccess = false;
1668
1669 transport.once('open', function () {
1670 if (this.onlyBinaryUpgrades) {
1671 var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
1672 failed = failed || upgradeLosesBinary;
1673 }
1674 if (failed) return;
1675
1676 debug('probe transport "%s" opened', name);
1677 transport.send([{ type: 'ping', data: 'probe' }]);
1678 transport.once('packet', function (msg) {
1679 if (failed) return;
1680 if ('pong' == msg.type && 'probe' == msg.data) {
1681 debug('probe transport "%s" pong', name);
1682 self.upgrading = true;
1683 self.emit('upgrading', transport);
1684 Socket.priorWebsocketSuccess = 'websocket' == transport.name;
1685
1686 debug('pausing current transport "%s"', self.transport.name);
1687 self.transport.pause(function () {
1688 if (failed) return;
1689 if ('closed' == self.readyState || 'closing' == self.readyState) {
1690 return;
1691 }
1692 debug('changing transport and sending upgrade packet');
1693 transport.removeListener('error', onerror);
1694 self.setTransport(transport);
1695 transport.send([{ type: 'upgrade' }]);
1696 self.emit('upgrade', transport);
1697 transport = null;
1698 self.upgrading = false;
1699 self.flush();
1700 });
1701 } else {
1702 debug('probe transport "%s" failed', name);
1703 var err = new Error('probe error');
1704 err.transport = transport.name;
1705 self.emit('upgradeError', err);
1706 }
1707 });
1708 });
1709
1710 transport.once('error', onerror);
1711 function onerror(err) {
1712 if (failed) return;
1713
1714 // Any callback called by transport should be ignored since now
1715 failed = true;
1716
1717 var error = new Error('probe error: ' + err);
1718 error.transport = transport.name;
1719
1720 transport.close();
1721 transport = null;
1722
1723 debug('probe transport "%s" failed because of error: %s', name, err);
1724
1725 self.emit('upgradeError', error);
1726 }
1727
1728 transport.open();
1729
1730 this.once('close', function () {
1731 if (transport) {
1732 debug('socket closed prematurely - aborting probe');
1733 failed = true;
1734 transport.close();
1735 transport = null;
1736 }
1737 });
1738
1739 this.once('upgrading', function (to) {
1740 if (transport && to.name != transport.name) {
1741 debug('"%s" works - aborting "%s"', to.name, transport.name);
1742 transport.close();
1743 transport = null;
1744 }
1745 });
1746};
1747
1748/**
1749 * Called when connection is deemed open.
1750 *
1751 * @api public
1752 */
1753
1754Socket.prototype.onOpen = function () {
1755 debug('socket open');
1756 this.readyState = 'open';
1757 Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
1758 this.emit('open');
1759 this.onopen && this.onopen.call(this);
1760 this.flush();
1761
1762 // we check for `readyState` in case an `open`
1763 // listener already closed the socket
1764 if ('open' == this.readyState && this.upgrade && this.transport.pause) {
1765 debug('starting upgrade probes');
1766 for (var i = 0, l = this.upgrades.length; i < l; i++) {
1767 this.probe(this.upgrades[i]);
1768 }
1769 }
1770};
1771
1772/**
1773 * Handles a packet.
1774 *
1775 * @api private
1776 */
1777
1778Socket.prototype.onPacket = function (packet) {
1779 if ('opening' == this.readyState || 'open' == this.readyState) {
1780 debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
1781
1782 this.emit('packet', packet);
1783
1784 // Socket is live - any packet counts
1785 this.emit('heartbeat');
1786
1787 switch (packet.type) {
1788 case 'open':
1789 this.onHandshake(parsejson(packet.data));
1790 break;
1791
1792 case 'pong':
1793 this.setPing();
1794 break;
1795
1796 case 'error':
1797 var err = new Error('server error');
1798 err.code = packet.data;
1799 this.emit('error', err);
1800 break;
1801
1802 case 'message':
1803 this.emit('data', packet.data);
1804 this.emit('message', packet.data);
1805 var event = { data: packet.data };
1806 event.toString = function () {
1807 return packet.data;
1808 };
1809
1810 this.onmessage && this.onmessage.call(this, event);
1811 break;
1812 }
1813 } else {
1814 debug('packet received with socket readyState "%s"', this.readyState);
1815 }
1816};
1817
1818/**
1819 * Called upon handshake completion.
1820 *
1821 * @param {Object} handshake obj
1822 * @api private
1823 */
1824
1825Socket.prototype.onHandshake = function (data) {
1826 this.emit('handshake', data);
1827 this.id = data.sid;
1828 this.transport.query.sid = data.sid;
1829 this.upgrades = this.filterUpgrades(data.upgrades);
1830 this.pingInterval = data.pingInterval;
1831 this.pingTimeout = data.pingTimeout;
1832 this.onOpen();
1833 this.setPing();
1834
1835 // Prolong liveness of socket on heartbeat
1836 this.removeListener('heartbeat', this.onHeartbeat);
1837 this.on('heartbeat', this.onHeartbeat);
1838};
1839
1840/**
1841 * Resets ping timeout.
1842 *
1843 * @api private
1844 */
1845
1846Socket.prototype.onHeartbeat = function (timeout) {
1847 clearTimeout(this.pingTimeoutTimer);
1848 var self = this;
1849 self.pingTimeoutTimer = setTimeout(function () {
1850 if ('closed' == self.readyState) return;
1851 self.onClose('ping timeout');
1852 }, timeout || (self.pingInterval + self.pingTimeout));
1853};
1854
1855/**
1856 * Pings server every `this.pingInterval` and expects response
1857 * within `this.pingTimeout` or closes connection.
1858 *
1859 * @api private
1860 */
1861
1862Socket.prototype.setPing = function () {
1863 var self = this;
1864 clearTimeout(self.pingIntervalTimer);
1865 self.pingIntervalTimer = setTimeout(function () {
1866 debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
1867 self.ping();
1868 self.onHeartbeat(self.pingTimeout);
1869 }, self.pingInterval);
1870};
1871
1872/**
1873* Sends a ping packet.
1874*
1875* @api public
1876*/
1877
1878Socket.prototype.ping = function () {
1879 this.sendPacket('ping');
1880};
1881
1882/**
1883 * Called on `drain` event
1884 *
1885 * @api private
1886 */
1887
1888Socket.prototype.onDrain = function() {
1889 for (var i = 0; i < this.prevBufferLen; i++) {
1890 if (this.callbackBuffer[i]) {
1891 this.callbackBuffer[i]();
1892 }
1893 }
1894
1895 this.writeBuffer.splice(0, this.prevBufferLen);
1896 this.callbackBuffer.splice(0, this.prevBufferLen);
1897
1898 // setting prevBufferLen = 0 is very important
1899 // for example, when upgrading, upgrade packet is sent over,
1900 // and a nonzero prevBufferLen could cause problems on `drain`
1901 this.prevBufferLen = 0;
1902
1903 if (this.writeBuffer.length == 0) {
1904 this.emit('drain');
1905 } else {
1906 this.flush();
1907 }
1908};
1909
1910/**
1911 * Flush write buffers.
1912 *
1913 * @api private
1914 */
1915
1916Socket.prototype.flush = function () {
1917 if ('closed' != this.readyState && this.transport.writable &&
1918 !this.upgrading && this.writeBuffer.length) {
1919 debug('flushing %d packets in socket', this.writeBuffer.length);
1920 this.transport.send(this.writeBuffer);
1921 // keep track of current length of writeBuffer
1922 // splice writeBuffer and callbackBuffer on `drain`
1923 this.prevBufferLen = this.writeBuffer.length;
1924 this.emit('flush');
1925 }
1926};
1927
1928/**
1929 * Sends a message.
1930 *
1931 * @param {String} message.
1932 * @param {Function} callback function.
1933 * @return {Socket} for chaining.
1934 * @api public
1935 */
1936
1937Socket.prototype.write =
1938Socket.prototype.send = function (msg, fn) {
1939 this.sendPacket('message', msg, fn);
1940 return this;
1941};
1942
1943/**
1944 * Sends a packet.
1945 *
1946 * @param {String} packet type.
1947 * @param {String} data.
1948 * @param {Function} callback function.
1949 * @api private
1950 */
1951
1952Socket.prototype.sendPacket = function (type, data, fn) {
1953 var packet = { type: type, data: data };
1954 this.emit('packetCreate', packet);
1955 this.writeBuffer.push(packet);
1956 this.callbackBuffer.push(fn);
1957 this.flush();
1958};
1959
1960/**
1961 * Closes the connection.
1962 *
1963 * @api private
1964 */
1965
1966Socket.prototype.close = function () {
1967 if ('opening' == this.readyState || 'open' == this.readyState) {
1968 this.onClose('forced close');
1969 debug('socket closing - telling transport to close');
1970 this.transport.close();
1971 }
1972
1973 return this;
1974};
1975
1976/**
1977 * Called upon transport error
1978 *
1979 * @api private
1980 */
1981
1982Socket.prototype.onError = function (err) {
1983 debug('socket error %j', err);
1984 Socket.priorWebsocketSuccess = false;
1985 this.emit('error', err);
1986 this.onerror && this.onerror.call(this, err);
1987 this.onClose('transport error', err);
1988};
1989
1990/**
1991 * Called upon transport close.
1992 *
1993 * @api private
1994 */
1995
1996Socket.prototype.onClose = function (reason, desc) {
1997 if ('opening' == this.readyState || 'open' == this.readyState) {
1998 debug('socket close with reason: "%s"', reason);
1999 var self = this;
2000
2001 // clear timers
2002 clearTimeout(this.pingIntervalTimer);
2003 clearTimeout(this.pingTimeoutTimer);
2004
2005 // clean buffers in next tick, so developers can still
2006 // grab the buffers on `close` event
2007 setTimeout(function() {
2008 self.writeBuffer = [];
2009 self.callbackBuffer = [];
2010 self.prevBufferLen = 0;
2011 }, 0);
2012
2013 // ignore further transport communication
2014 this.transport.removeAllListeners();
2015
2016 // set ready state
2017 this.readyState = 'closed';
2018
2019 // clear session id
2020 this.id = null;
2021
2022 // emit close event
2023 this.emit('close', reason, desc);
2024 this.onclose && this.onclose.call(this);
2025 }
2026};
2027
2028/**
2029 * Filters upgrades, returning only those matching client transports.
2030 *
2031 * @param {Array} server upgrades
2032 * @api private
2033 *
2034 */
2035
2036Socket.prototype.filterUpgrades = function (upgrades) {
2037 var filteredUpgrades = [];
2038 for (var i = 0, j = upgrades.length; i<j; i++) {
2039 if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
2040 }
2041 return filteredUpgrades;
2042};
2043
2044},{"./emitter":12,"./transport":15,"./transports":17,"./util":22,"debug":9,"engine.io-parser":24,"indexof":35,"parsejson":29,"parseuri":37}],15:[function(require,module,exports){
2045/**
2046 * Module dependencies.
2047 */
2048
2049var util = require('./util');
2050var parser = require('engine.io-parser');
2051var Emitter = require('./emitter');
2052
2053/**
2054 * Module exports.
2055 */
2056
2057module.exports = Transport;
2058
2059/**
2060 * Transport abstract constructor.
2061 *
2062 * @param {Object} options.
2063 * @api private
2064 */
2065
2066function Transport (opts) {
2067 this.path = opts.path;
2068 this.hostname = opts.hostname;
2069 this.port = opts.port;
2070 this.secure = opts.secure;
2071 this.query = opts.query;
2072 this.timestampParam = opts.timestampParam;
2073 this.timestampRequests = opts.timestampRequests;
2074 this.readyState = '';
2075 this.agent = opts.agent || false;
2076 this.socket = opts.socket;
2077}
2078
2079/**
2080 * Mix in `Emitter`.
2081 */
2082
2083Emitter(Transport.prototype);
2084
2085/**
2086 * Emits an error.
2087 *
2088 * @param {String} str
2089 * @return {Transport} for chaining
2090 * @api public
2091 */
2092
2093Transport.prototype.onError = function (msg, desc) {
2094 var err = new Error(msg);
2095 err.type = 'TransportError';
2096 err.description = desc;
2097 this.emit('error', err);
2098 return this;
2099};
2100
2101/**
2102 * Opens the transport.
2103 *
2104 * @api public
2105 */
2106
2107Transport.prototype.open = function () {
2108 if ('closed' == this.readyState || '' == this.readyState) {
2109 this.readyState = 'opening';
2110 this.doOpen();
2111 }
2112
2113 return this;
2114};
2115
2116/**
2117 * Closes the transport.
2118 *
2119 * @api private
2120 */
2121
2122Transport.prototype.close = function () {
2123 if ('opening' == this.readyState || 'open' == this.readyState) {
2124 this.doClose();
2125 this.onClose();
2126 }
2127
2128 return this;
2129};
2130
2131/**
2132 * Sends multiple packets.
2133 *
2134 * @param {Array} packets
2135 * @api private
2136 */
2137
2138Transport.prototype.send = function(packets){
2139 if ('open' == this.readyState) {
2140 this.write(packets);
2141 } else {
2142 throw new Error('Transport not open');
2143 }
2144};
2145
2146/**
2147 * Called upon open
2148 *
2149 * @api private
2150 */
2151
2152Transport.prototype.onOpen = function () {
2153 this.readyState = 'open';
2154 this.writable = true;
2155 this.emit('open');
2156};
2157
2158/**
2159 * Called with data.
2160 *
2161 * @param {String} data
2162 * @api private
2163 */
2164
2165Transport.prototype.onData = function (data) {
2166 this.onPacket(parser.decodePacket(data, this.socket.binaryType));
2167};
2168
2169/**
2170 * Called with a decoded packet.
2171 */
2172
2173Transport.prototype.onPacket = function (packet) {
2174 this.emit('packet', packet);
2175};
2176
2177/**
2178 * Called upon close.
2179 *
2180 * @api private
2181 */
2182
2183Transport.prototype.onClose = function () {
2184 this.readyState = 'closed';
2185 this.emit('close');
2186};
2187
2188},{"./emitter":12,"./util":22,"engine.io-parser":24}],16:[function(require,module,exports){
2189var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
2190/**
2191 * Module dependencies.
2192 */
2193
2194var WS = require('./websocket');
2195var util = require('../util');
2196var debug = require('debug')('engine.io-client:flashsocket');
2197
2198/**
2199 * Module exports.
2200 */
2201
2202module.exports = FlashWS;
2203
2204/**
2205 * Obfuscated key for Blue Coat.
2206 */
2207
2208var xobject = global[['Active'].concat('Object').join('X')];
2209
2210/**
2211 * FlashWS constructor.
2212 *
2213 * @api public
2214 */
2215
2216function FlashWS(options){
2217 WS.call(this, options);
2218 this.flashPath = options.flashPath;
2219 this.policyPort = options.policyPort;
2220}
2221
2222/**
2223 * Inherits from WebSocket.
2224 */
2225
2226util.inherits(FlashWS, WS);
2227
2228/**
2229 * Transport name.
2230 *
2231 * @api public
2232 */
2233
2234FlashWS.prototype.name = 'flashsocket';
2235
2236/*
2237 * FlashSockets only support binary as base64 encoded strings
2238 */
2239
2240FlashWS.prototype.supportsBinary = false;
2241
2242/**
2243 * Opens the transport.
2244 *
2245 * @api public
2246 */
2247
2248FlashWS.prototype.doOpen = function(){
2249 if (!this.check()) {
2250 // let the probe timeout
2251 return;
2252 }
2253
2254 // instrument websocketjs logging
2255 function log(type){
2256 return function(){
2257 var str = Array.prototype.join.call(arguments, ' ');
2258 debug('[websocketjs %s] %s', type, str);
2259 };
2260 }
2261
2262 global.WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') };
2263 global.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
2264 global.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
2265
2266 if (!global.WEB_SOCKET_SWF_LOCATION) {
2267 global.WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf';
2268 }
2269
2270 // dependencies
2271 var deps = [this.flashPath + 'web_socket.js'];
2272
2273 if (!global.swfobject) {
2274 deps.unshift(this.flashPath + 'swfobject.js');
2275 }
2276
2277 var self = this;
2278
2279 load(deps, function(){
2280 self.ready(function(){
2281 WebSocket.__addTask(function () {
2282 self.ws = new WebSocket(self.uri());
2283 self.addEventListeners();
2284 });
2285 });
2286 });
2287};
2288
2289/**
2290 * Override to prevent closing uninitialized flashsocket.
2291 *
2292 * @api private
2293 */
2294
2295FlashWS.prototype.doClose = function(){
2296 if (!this.ws) return;
2297 var self = this;
2298 WebSocket.__addTask(function(){
2299 WS.prototype.doClose.call(self);
2300 });
2301};
2302
2303/**
2304 * Writes to the Flash socket.
2305 *
2306 * @api private
2307 */
2308
2309FlashWS.prototype.write = function(){
2310 var self = this, args = arguments;
2311 WebSocket.__addTask(function(){
2312 WS.prototype.write.apply(self, args);
2313 });
2314};
2315
2316/**
2317 * Called upon dependencies are loaded.
2318 *
2319 * @api private
2320 */
2321
2322FlashWS.prototype.ready = function(fn){
2323 if (typeof WebSocket == 'undefined' ||
2324 !('__initialize' in WebSocket) || !global.swfobject) {
2325 return;
2326 }
2327
2328 if (global.swfobject.getFlashPlayerVersion().major < 10) {
2329 return;
2330 }
2331
2332 function init () {
2333 // only start downloading the swf file when
2334 // we checked that this browser actually supports it
2335 if (!FlashWS.loaded) {
2336 if (843 != self.policyPort) {
2337 var policy = 'xmlsocket://' + self.hostname + ':' + self.policyPort;
2338 WebSocket.loadFlashPolicyFile(policy);
2339 }
2340
2341 WebSocket.__initialize();
2342 FlashWS.loaded = true;
2343 }
2344
2345 fn.call(self);
2346 }
2347
2348 var self = this;
2349 if (document.body) {
2350 return init();
2351 }
2352
2353 util.load(init);
2354};
2355
2356/**
2357 * Feature detection for flashsocket.
2358 *
2359 * @return {Boolean} whether this transport is available.
2360 * @api public
2361 */
2362
2363FlashWS.prototype.check = function(){
2364 if ('undefined' == typeof window) {
2365 return false;
2366 }
2367
2368 if (typeof WebSocket != 'undefined' && !('__initialize' in WebSocket)) {
2369 return false;
2370 }
2371
2372 if (xobject) {
2373 var control = null;
2374 try {
2375 control = new xobject('ShockwaveFlash.ShockwaveFlash');
2376 } catch (e) { }
2377 if (control) {
2378 return true;
2379 }
2380 } else {
2381 for (var i = 0, l = navigator.plugins.length; i < l; i++) {
2382 for (var j = 0, m = navigator.plugins[i].length; j < m;…
Large files files are truncated, but you can click here to view the full file