arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
socketioMEANseed/server/node_modules/engine.io-client/lib/transports/polling.js
server/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 yeast = require('yeast');
 10var debug = require('debug')('engine.io-client:polling');
 11
 12/**
 13 * Module exports.
 14 */
 15
 16module.exports = Polling;
 17
 18/**
 19 * Is XHR2 supported?
 20 */
 21
 22var hasXHR2 = (function () {
 23  var XMLHttpRequest = require('xmlhttprequest-ssl');
 24  var xhr = new XMLHttpRequest({ xdomain: false });
 25  return null != xhr.responseType;
 26})();
 27
 28/**
 29 * Polling interface.
 30 *
 31 * @param {Object} opts
 32 * @api private
 33 */
 34
 35function Polling (opts) {
 36  var forceBase64 = (opts && opts.forceBase64);
 37  if (!hasXHR2 || forceBase64) {
 38    this.supportsBinary = false;
 39  }
 40  Transport.call(this, opts);
 41}
 42
 43/**
 44 * Inherits from Transport.
 45 */
 46
 47inherit(Polling, Transport);
 48
 49/**
 50 * Transport name.
 51 */
 52
 53Polling.prototype.name = 'polling';
 54
 55/**
 56 * Opens the socket (triggers polling). We write a PING message to determine
 57 * when the transport is open.
 58 *
 59 * @api private
 60 */
 61
 62Polling.prototype.doOpen = function () {
 63  this.poll();
 64};
 65
 66/**
 67 * Pauses polling.
 68 *
 69 * @param {Function} callback upon buffers are flushed and transport is paused
 70 * @api private
 71 */
 72
 73Polling.prototype.pause = function (onPause) {
 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  parser.encodePayload(packets, this.supportsBinary, function (data) {
206    self.doWrite(data, callbackfn);
207  });
208};
209
210/**
211 * Generates uri for connection.
212 *
213 * @api private
214 */
215
216Polling.prototype.uri = function () {
217  var query = this.query || {};
218  var schema = this.secure ? 'https' : 'http';
219  var port = '';
220
221  // cache busting is forced
222  if (false !== this.timestampRequests) {
223    query[this.timestampParam] = yeast();
224  }
225
226  if (!this.supportsBinary && !query.sid) {
227    query.b64 = 1;
228  }
229
230  query = parseqs.encode(query);
231
232  // avoid port if default for schema
233  if (this.port && (('https' === schema && Number(this.port) !== 443) ||
234     ('http' === schema && Number(this.port) !== 80))) {
235    port = ':' + this.port;
236  }
237
238  // prepend ? to query
239  if (query.length) {
240    query = '?' + query;
241  }
242
243  var ipv6 = this.hostname.indexOf(':') !== -1;
244  return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
245};