arnaucube
arnaucube/raspberryGPIOhtmlserverPublic Self-hosted repository
raspberryGPIOhtmlserver/node_modules/engine.io-client/lib/transports/websocket.js
node_modules/engine.io-client/lib/transports/websocket.jsRaw
  1/**
  2 * Module dependencies.
  3 */
  4
  5var Transport = require('../transport');
  6var parser = require('engine.io-parser');
  7var parseqs = require('parseqs');
  8var inherit = require('component-inherit');
  9var debug = require('debug')('engine.io-client:websocket');
 10
 11/**
 12 * `ws` exposes a WebSocket-compatible interface in
 13 * Node, or the `WebSocket` or `MozWebSocket` globals
 14 * in the browser.
 15 */
 16
 17var WebSocket = require('ws');
 18
 19/**
 20 * Module exports.
 21 */
 22
 23module.exports = WS;
 24
 25/**
 26 * WebSocket transport constructor.
 27 *
 28 * @api {Object} connection options
 29 * @api public
 30 */
 31
 32function WS(opts){
 33  var forceBase64 = (opts && opts.forceBase64);
 34  if (forceBase64) {
 35    this.supportsBinary = false;
 36  }
 37  Transport.call(this, opts);
 38}
 39
 40/**
 41 * Inherits from Transport.
 42 */
 43
 44inherit(WS, Transport);
 45
 46/**
 47 * Transport name.
 48 *
 49 * @api public
 50 */
 51
 52WS.prototype.name = 'websocket';
 53
 54/*
 55 * WebSockets support binary
 56 */
 57
 58WS.prototype.supportsBinary = true;
 59
 60/**
 61 * Opens socket.
 62 *
 63 * @api private
 64 */
 65
 66WS.prototype.doOpen = function(){
 67  if (!this.check()) {
 68    // let probe timeout
 69    return;
 70  }
 71
 72  var self = this;
 73  var uri = this.uri();
 74  var protocols = void(0);
 75  var opts = { agent: this.agent };
 76
 77  this.ws = new WebSocket(uri, protocols, opts);
 78
 79  if (this.ws.binaryType === undefined) {
 80    this.supportsBinary = false;
 81  }
 82
 83  this.ws.binaryType = 'arraybuffer';
 84  this.addEventListeners();
 85};
 86
 87/**
 88 * Adds event listeners to the socket
 89 *
 90 * @api private
 91 */
 92
 93WS.prototype.addEventListeners = function(){
 94  var self = this;
 95
 96  this.ws.onopen = function(){
 97    self.onOpen();
 98  };
 99  this.ws.onclose = function(){
100    self.onClose();
101  };
102  this.ws.onmessage = function(ev){
103    self.onData(ev.data);
104  };
105  this.ws.onerror = function(e){
106    self.onError('websocket error', e);
107  };
108};
109
110/**
111 * Override `onData` to use a timer on iOS.
112 * See: https://gist.github.com/mloughran/2052006
113 *
114 * @api private
115 */
116
117if ('undefined' != typeof navigator
118  && /iPad|iPhone|iPod/i.test(navigator.userAgent)) {
119  WS.prototype.onData = function(data){
120    var self = this;
121    setTimeout(function(){
122      Transport.prototype.onData.call(self, data);
123    }, 0);
124  };
125}
126
127/**
128 * Writes data to socket.
129 *
130 * @param {Array} array of packets.
131 * @api private
132 */
133
134WS.prototype.write = function(packets){
135  var self = this;
136  this.writable = false;
137  // encodePacket efficient as it uses WS framing
138  // no need for encodePayload
139  for (var i = 0, l = packets.length; i < l; i++) {
140    parser.encodePacket(packets[i], this.supportsBinary, function(data) {
141      //Sometimes the websocket has already been closed but the browser didn't
142      //have a chance of informing us about it yet, in that case send will
143      //throw an error
144      try {
145        self.ws.send(data);
146      } catch (e){
147        debug('websocket closed before onclose event');
148      }
149    });
150  }
151
152  function ondrain() {
153    self.writable = true;
154    self.emit('drain');
155  }
156  // fake drain
157  // defer to next tick to allow Socket to clear writeBuffer
158  setTimeout(ondrain, 0);
159};
160
161/**
162 * Called upon close
163 *
164 * @api private
165 */
166
167WS.prototype.onClose = function(){
168  Transport.prototype.onClose.call(this);
169};
170
171/**
172 * Closes socket.
173 *
174 * @api private
175 */
176
177WS.prototype.doClose = function(){
178  if (typeof this.ws !== 'undefined') {
179    this.ws.close();
180  }
181};
182
183/**
184 * Generates uri for connection.
185 *
186 * @api private
187 */
188
189WS.prototype.uri = function(){
190  var query = this.query || {};
191  var schema = this.secure ? 'wss' : 'ws';
192  var port = '';
193
194  // avoid port if default for schema
195  if (this.port && (('wss' == schema && this.port != 443)
196    || ('ws' == schema && this.port != 80))) {
197    port = ':' + this.port;
198  }
199
200  // append timestamp to URI
201  if (this.timestampRequests) {
202    query[this.timestampParam] = +new Date;
203  }
204
205  // communicate binary support capabilities
206  if (!this.supportsBinary) {
207    query.b64 = 1;
208  }
209
210  query = parseqs.encode(query);
211
212  // prepend ? to query
213  if (query.length) {
214    query = '?' + query;
215  }
216
217  return schema + '://' + this.hostname + port + this.path + query;
218};
219
220/**
221 * Feature detection for WebSocket.
222 *
223 * @return {Boolean} whether this transport is available.
224 * @api public
225 */
226
227WS.prototype.check = function(){
228  return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
229};