comunicationLeap/node_modules/engine.io-client/lib/transports/polling.js
node_modules/engine.io-client/lib/transports/polling.jsRaw
1/**
2 * Module dependencies.
3 */
4
5var Transport = require('../transport');
6var parseqs = require('parseqs');
7var parser = require('engine.io-parser');
8var inherit = require('component-inherit');
9var debug = require('debug')('engine.io-client:polling');
10
11/**
12 * Module exports.
13 */
14
15module.exports = Polling;
16
17/**
18 * Is XHR2 supported?
19 */
20
21var hasXHR2 = (function() {
22 var XMLHttpRequest = require('xmlhttprequest');
23 var xhr = new XMLHttpRequest({ xdomain: false });
24 return null != xhr.responseType;
25})();
26
27/**
28 * Polling interface.
29 *
30 * @param {Object} opts
31 * @api private
32 */
33
34function Polling(opts){
35 var forceBase64 = (opts && opts.forceBase64);
36 if (!hasXHR2 || forceBase64) {
37 this.supportsBinary = false;
38 }
39 Transport.call(this, opts);
40}
41
42/**
43 * Inherits from Transport.
44 */
45
46inherit(Polling, Transport);
47
48/**
49 * Transport name.
50 */
51
52Polling.prototype.name = 'polling';
53
54/**
55 * Opens the socket (triggers polling). We write a PING message to determine
56 * when the transport is open.
57 *
58 * @api private
59 */
60
61Polling.prototype.doOpen = function(){
62 this.poll();
63};
64
65/**
66 * Pauses polling.
67 *
68 * @param {Function} callback upon buffers are flushed and transport is paused
69 * @api private
70 */
71
72Polling.prototype.pause = function(onPause){
73 var pending = 0;
74 var self = this;
75
76 this.readyState = 'pausing';
77
78 function pause(){
79 debug('paused');
80 self.readyState = 'paused';
81 onPause();
82 }
83
84 if (this.polling || !this.writable) {
85 var total = 0;
86
87 if (this.polling) {
88 debug('we are currently polling - waiting to pause');
89 total++;
90 this.once('pollComplete', function(){
91 debug('pre-pause polling complete');
92 --total || pause();
93 });
94 }
95
96 if (!this.writable) {
97 debug('we are currently writing - waiting to pause');
98 total++;
99 this.once('drain', function(){
100 debug('pre-pause writing complete');
101 --total || pause();
102 });
103 }
104 } else {
105 pause();
106 }
107};
108
109/**
110 * Starts polling cycle.
111 *
112 * @api public
113 */
114
115Polling.prototype.poll = function(){
116 debug('polling');
117 this.polling = true;
118 this.doPoll();
119 this.emit('poll');
120};
121
122/**
123 * Overloads onData to detect payloads.
124 *
125 * @api private
126 */
127
128Polling.prototype.onData = function(data){
129 var self = this;
130 debug('polling got data %s', data);
131 var callback = function(packet, index, total) {
132 // if its the first message we consider the transport open
133 if ('opening' == self.readyState) {
134 self.onOpen();
135 }
136
137 // if its a close packet, we close the ongoing requests
138 if ('close' == packet.type) {
139 self.onClose();
140 return false;
141 }
142
143 // otherwise bypass onData and handle the message
144 self.onPacket(packet);
145 };
146
147 // decode payload
148 parser.decodePayload(data, this.socket.binaryType, callback);
149
150 // if an event did not trigger closing
151 if ('closed' != this.readyState) {
152 // if we got data we're not polling
153 this.polling = false;
154 this.emit('pollComplete');
155
156 if ('open' == this.readyState) {
157 this.poll();
158 } else {
159 debug('ignoring poll - transport state "%s"', this.readyState);
160 }
161 }
162};
163
164/**
165 * For polling, send a close packet.
166 *
167 * @api private
168 */
169
170Polling.prototype.doClose = function(){
171 var self = this;
172
173 function close(){
174 debug('writing close packet');
175 self.write([{ type: 'close' }]);
176 }
177
178 if ('open' == this.readyState) {
179 debug('transport open - closing');
180 close();
181 } else {
182 // in case we're trying to close while
183 // handshaking is in progress (GH-164)
184 debug('transport not open - deferring close');
185 this.once('open', close);
186 }
187};
188
189/**
190 * Writes a packets payload.
191 *
192 * @param {Array} data packets
193 * @param {Function} drain callback
194 * @api private
195 */
196
197Polling.prototype.write = function(packets){
198 var self = this;
199 this.writable = false;
200 var callbackfn = function() {
201 self.writable = true;
202 self.emit('drain');
203 };
204
205 var self = this;
206 parser.encodePayload(packets, this.supportsBinary, function(data) {
207 self.doWrite(data, callbackfn);
208 });
209};
210
211/**
212 * Generates uri for connection.
213 *
214 * @api private
215 */
216
217Polling.prototype.uri = function(){
218 var query = this.query || {};
219 var schema = this.secure ? 'https' : 'http';
220 var port = '';
221
222 // cache busting is forced
223 if (false !== this.timestampRequests) {
224 query[this.timestampParam] = +new Date + '-' + Transport.timestamps++;
225 }
226
227 if (!this.supportsBinary && !query.sid) {
228 query.b64 = 1;
229 }
230
231 query = parseqs.encode(query);
232
233 // avoid port if default for schema
234 if (this.port && (('https' == schema && this.port != 443) ||
235 ('http' == schema && this.port != 80))) {
236 port = ':' + this.port;
237 }
238
239 // prepend ? to query
240 if (query.length) {
241 query = '?' + query;
242 }
243
244 return schema + '://' + this.hostname + port + this.path + query;
245};