Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

engine.io

Package Overview
Dependencies
Maintainers
1
Versions
152
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

engine.io - npm Package Compare versions

Comparing version 1.5.4 to 1.6.0

LICENSE

21

History.md
1.6.0 / 2015-11-28
==================
* add support for environments that extend `Object.prototype`
* remove listeners upon `clearTransport`
* support for all versions of node
* fix linering sockets that can stay open when upgrade failed
* ensure sockets are closed on error
* bump `ws` for several improvements
* fix for a rare race condition on some error scenarios
* support custom socket id
* use container-based infrastructure for faster build
* fix package.json wrongly referrering to self
* allow overriding the `cookiePath`
* fix potential encoding errors under certain conditions
* support compression
1.5.4 / 2015-09-09

@@ -34,4 +51,4 @@ ==================

* package: bump `ws` to fix fd leaks
* socket: flush the write buffer before closing the socket [nkzawa]
* polling: close the pending poll request when closing transport [nkzawa]
* socket: flush the write buffer before closing the socket [lpinca]
* polling: close the pending poll request when closing transport [lpinca]

@@ -38,0 +55,0 @@ 1.4.2 / 2014-10-08

2

lib/engine.io.js

@@ -48,3 +48,3 @@ /**

/**
* Expose Server constructor.
* Expose Socket constructor.
*

@@ -51,0 +51,0 @@ * @api public

@@ -47,6 +47,18 @@

this.cookie = false !== opts.cookie ? (opts.cookie || 'io') : false;
this.cookiePath = false !== opts.cookiePath ? (opts.cookiePath || false) : false;
this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || true) : false;
this.httpCompression = false !== opts.httpCompression ? (opts.httpCompression || {}) : false;
if (true === this.httpCompression) this.httpCompression = {};
if (this.httpCompression && null == this.httpCompression.threshold) {
this.httpCompression.threshold = 1024;
}
// initialize websocket server
if (~this.transports.indexOf('websocket')) {
this.ws = new WebSocketServer({ noServer: true, clientTracking: false });
this.ws = new WebSocketServer({
noServer: true,
clientTracking: false,
perMessageDeflate: this.perMessageDeflate
});
}

@@ -156,3 +168,5 @@ }

for (var i in this.clients) {
this.clients[i].close();
if (this.clients.hasOwnProperty(i)) {
this.clients[i].close();
}
}

@@ -216,2 +230,14 @@ return this;

/**
* generate a socket id.
* Overwrite this method to generate your custom socket id
*
* @param {Object} request object
* @api public
*/
Server.prototype.generateId = function(req){
return base64id.generateId();
};
/**
* Handshakes a new client.

@@ -225,3 +251,3 @@ *

Server.prototype.handshake = function(transport, req){
var id = base64id.generateId();
var id = this.generateId(req);

@@ -235,2 +261,3 @@ debug('handshaking client "%s"', id);

transport.maxHttpBufferSize = this.maxHttpBufferSize;
transport.httpCompression = this.httpCompression;
}

@@ -253,3 +280,7 @@

transport.on('headers', function(headers){
headers['Set-Cookie'] = self.cookie + '=' + id;
var cookie = self.cookie + '=' + id;
if(false !== self.cookiePath) {
cookie += '; path=' + self.cookiePath;
}
headers['Set-Cookie'] = cookie;
});

@@ -319,6 +350,10 @@ }

if (id) {
if (!this.clients[id]) {
var client = this.clients[id];
if (!client) {
debug('upgrade attempt for closed client');
socket.close();
} else if (this.clients[id].upgraded) {
} else if (client.upgrading) {
debug('transport has already been trying to upgrade');
socket.close();
} else if (client.upgraded) {
debug('transport had already been upgraded');

@@ -334,3 +369,3 @@ socket.close();

}
this.clients[id].maybeUpgrade(transport);
client.maybeUpgrade(transport);
}

@@ -337,0 +372,0 @@ } else {

@@ -23,2 +23,3 @@ /**

this.server = server;
this.upgrading = false;
this.upgraded = false;

@@ -29,2 +30,3 @@ this.readyState = 'opening';

this.sentCallbackFn = [];
this.cleanupFn = [];
this.request = req;

@@ -144,9 +146,21 @@

Socket.prototype.setTransport = function (transport) {
var onError = this.onError.bind(this);
var onPacket = this.onPacket.bind(this);
var flush = this.flush.bind(this);
var onClose = this.onClose.bind(this, 'transport close');
this.transport = transport;
this.transport.once('error', this.onError.bind(this));
this.transport.on('packet', this.onPacket.bind(this));
this.transport.on('drain', this.flush.bind(this));
this.transport.once('close', this.onClose.bind(this, 'transport close'));
this.transport.once('error', onError);
this.transport.on('packet', onPacket);
this.transport.on('drain', flush);
this.transport.once('close', onClose);
//this function will manage packet events (also message callbacks)
this.setupSendCallback();
this.cleanupFn.push(function() {
transport.removeListener('error', onError);
transport.removeListener('packet', onPacket);
transport.removeListener('drain', flush);
transport.removeListener('close', onClose);
});
};

@@ -165,2 +179,4 @@

this.upgrading = true;
var self = this;

@@ -171,4 +187,3 @@

debug('client did not complete upgrade - closing transport');
clearInterval(self.checkIntervalTimer);
self.checkIntervalTimer = null;
cleanup();
if ('open' == transport.readyState) {

@@ -181,3 +196,4 @@ transport.close();

if ('ping' == packet.type && 'probe' == packet.data) {
transport.send([{ type: 'pong', data: 'probe' }]);
transport.send([{ type: 'pong', data: 'probe', options: { compress: true } }]);
self.emit('upgrading', transport);
clearInterval(self.checkIntervalTimer);

@@ -187,2 +203,3 @@ self.checkIntervalTimer = setInterval(check, 100);

debug('got upgrade packet - upgrading');
cleanup();
self.upgraded = true;

@@ -194,6 +211,2 @@ self.clearTransport();

self.flush();
clearInterval(self.checkIntervalTimer);
self.checkIntervalTimer = null;
clearTimeout(self.upgradeTimeoutTimer);
transport.removeListener('packet', onPacket);
if (self.readyState == 'closing') {

@@ -205,2 +218,3 @@ transport.close(function () {

} else {
cleanup();
transport.close();

@@ -214,7 +228,41 @@ }

debug('writing a noop packet to polling for fast upgrade');
self.transport.send([{ type: 'noop' }]);
self.transport.send([{ type: 'noop', options: { compress: true } }]);
}
}
function cleanup() {
self.upgrading = false;
clearInterval(self.checkIntervalTimer);
self.checkIntervalTimer = null;
clearTimeout(self.upgradeTimeoutTimer);
self.upgradeTimeoutTimer = null;
transport.removeListener('packet', onPacket);
transport.removeListener('close', onTransportClose);
transport.removeListener('error', onError);
self.removeListener('close', onClose);
}
function onError(err) {
debug('client did not complete upgrade - %s', err);
cleanup();
transport.close();
transport = null;
}
function onTransportClose(){
onError("transport closed");
}
function onClose() {
onError("socket closed");
}
transport.on('packet', onPacket);
transport.once('close', onTransportClose);
transport.once('error', onError);
self.once('close', onClose);
};

@@ -229,2 +277,5 @@

Socket.prototype.clearTransport = function () {
var cleanup;
while (cleanup = this.cleanupFn.shift()) cleanup();
// silence further transport errors and prevent uncaught exceptions

@@ -234,2 +285,6 @@ this.transport.on('error', function(){

});
// ensure transport won't stay open
this.transport.close();
clearTimeout(this.pingTimeoutTimer);

@@ -246,2 +301,3 @@ };

if ('closed' != this.readyState) {
this.readyState = 'closed';
clearTimeout(this.pingTimeoutTimer);

@@ -260,3 +316,2 @@ clearInterval(this.checkIntervalTimer);

this.clearTransport();
this.readyState = 'closed';
this.emit('close', reason, description);

@@ -274,4 +329,10 @@ }

var self = this;
this.transport.on('drain', onDrain);
this.cleanupFn.push(function() {
self.transport.removeListener('drain', onDrain);
});
//the message was sent successfully, execute the callback
this.transport.on('drain', function() {
function onDrain() {
if (self.sentCallbackFn.length > 0) {

@@ -291,3 +352,3 @@ var seqFn = self.sentCallbackFn.splice(0,1)[0];

}
});
}
};

@@ -299,2 +360,3 @@

* @param {String} message
* @param {Object} options
* @param {Function} callback

@@ -306,4 +368,4 @@ * @return {Socket} for chaining

Socket.prototype.send =
Socket.prototype.write = function(data, callback){
this.sendPacket('message', data, callback);
Socket.prototype.write = function(data, options, callback){
this.sendPacket('message', data, options, callback);
return this;

@@ -317,10 +379,22 @@ };

* @param {String} optional, data
* @param {Object} options
* @api private
*/
Socket.prototype.sendPacket = function (type, data, callback) {
Socket.prototype.sendPacket = function (type, data, options, callback) {
if ('function' == typeof options) {
callback = options;
options = null;
}
options = options || {};
options.compress = false !== options.compress;
if ('closing' != this.readyState) {
debug('sending packet "%s" (%s)', type, data);
var packet = { type: type };
var packet = {
type: type,
options: options
};
if (data) packet.data = data;

@@ -327,0 +401,0 @@

@@ -32,3 +32,3 @@

function Transport (req) {
this.readyState = 'opening';
this.readyState = 'open';
};

@@ -61,2 +61,4 @@

Transport.prototype.close = function (fn) {
if ('closed' == this.readyState || 'closing' == this.readyState) return;
this.readyState = 'closing';

@@ -63,0 +65,0 @@ this.doClose(fn || noop);

@@ -63,3 +63,3 @@

JSONP.prototype.doWrite = function (data) {
JSONP.prototype.doWrite = function (data, options, callback) {
// we must output valid javascript, not valid json

@@ -74,17 +74,3 @@ // see: http://timelessrepo.com/json-isnt-a-javascript-subset

// explicit UTF-8 is required for pages not served under utf
var headers = {
'Content-Type': 'text/javascript; charset=UTF-8',
'Content-Length': Buffer.byteLength(data)
};
// prevent XSS warnings on IE
// https://github.com/LearnBoost/socket.io/pull/1333
var ua = this.req.headers['user-agent'];
if (ua && (~ua.indexOf(';MSIE') || ~ua.indexOf('Trident/'))) {
headers['X-XSS-Protection'] = '0';
}
this.res.writeHead(200, this.headers(this.req, headers));
this.res.end(data);
Polling.prototype.doWrite.call(this, data, options, callback);
};

@@ -91,0 +77,0 @@

@@ -52,32 +52,2 @@

/**
* Frames data prior to write.
*
* @api private
*/
XHR.prototype.doWrite = function(data){
// explicit UTF-8 is required for pages not served under utf
var isString = typeof data == 'string';
var contentType = isString
? 'text/plain; charset=UTF-8'
: 'application/octet-stream';
var contentLength = '' + (isString ? Buffer.byteLength(data) : data.length);
var headers = {
'Content-Type': contentType,
'Content-Length': contentLength
};
// prevent XSS warnings on IE
// https://github.com/LearnBoost/socket.io/pull/1333
var ua = this.req.headers['user-agent'];
if (ua && (~ua.indexOf(';MSIE') || ~ua.indexOf('Trident/'))) {
headers['X-XSS-Protection'] = '0';
}
this.res.writeHead(200, this.headers(this.req, headers));
this.res.end(data);
};
/**
* Returns headers for a response.

@@ -84,0 +54,0 @@ *

@@ -8,4 +8,11 @@

, parser = require('engine.io-parser')
, zlib = require('zlib')
, accepts = require('accepts')
, debug = require('debug')('engine:polling');
var compressionMethods = {
gzip: zlib.createGzip,
deflate: zlib.createDeflate
};
/**

@@ -25,2 +32,4 @@ * Exports the constructor.

Transport.call(this, req);
this.closeTimeout = 30 * 1000;
}

@@ -76,2 +85,3 @@

res.writeHead(500);
res.end();
return;

@@ -105,3 +115,3 @@ }

debug('triggering empty send to append close packet');
this.send([{ type: 'noop' }]);
this.send([{ type: 'noop', options: { compress: true } }]);
}

@@ -121,2 +131,3 @@ };

res.writeHead(500);
res.end();
return;

@@ -185,5 +196,5 @@ }

req.on('close', onClose);
if (!isBinary) req.setEncoding('utf8');
req.on('data', onData);
req.on('end', onEnd);
if (!isBinary) req.setEncoding('utf8');
};

@@ -223,3 +234,3 @@

// close pending poll request
this.send([{ type: 'noop' }]);
this.send([{ type: 'noop', options: { compress: true } }]);
}

@@ -237,5 +248,7 @@ Transport.prototype.onClose.call(this);

Polling.prototype.send = function (packets) {
this.writable = false;
if (this.shouldClose) {
debug('appending close packet to payload');
packets.push({ type: 'close' });
packets.push({ type: 'close', options: { compress: true } });
this.shouldClose();

@@ -247,3 +260,6 @@ this.shouldClose = null;

parser.encodePayload(packets, this.supportsBinary, function(data) {
self.write(data);
var compress = packets.some(function(packet) {
return packet.options && packet.options.compress;
});
self.write(data, { compress: compress });
});

@@ -256,13 +272,102 @@ };

* @param {String} data
* @param {Object} options
* @api private
*/
Polling.prototype.write = function (data) {
Polling.prototype.write = function (data, options) {
debug('writing "%s"', data);
this.doWrite(data);
this.req.cleanup();
this.writable = false;
var self = this;
this.doWrite(data, options, function() {
self.req.cleanup();
});
};
/**
* Performs the write.
*
* @api private
*/
Polling.prototype.doWrite = function (data, options, callback) {
var self = this;
// explicit UTF-8 is required for pages not served under utf
var isString = typeof data == 'string';
var contentType = isString
? 'text/plain; charset=UTF-8'
: 'application/octet-stream';
var headers = {
'Content-Type': contentType
};
// prevent XSS warnings on IE
// https://github.com/LearnBoost/socket.io/pull/1333
var ua = this.req.headers['user-agent'];
if (ua && (~ua.indexOf(';MSIE') || ~ua.indexOf('Trident/'))) {
headers['X-XSS-Protection'] = '0';
}
if (!this.httpCompression || !options.compress) {
respond(data);
return;
}
var len = isString ? Buffer.byteLength(data) : data.length;
if (len < this.httpCompression.threshold) {
respond(data);
return;
}
var encoding = accepts(this.req).encodings(['gzip', 'deflate']);
if (!encoding) {
respond(data);
return;
}
this.compress(data, encoding, function(err, data) {
if (err) {
self.res.writeHead(500);
self.res.end();
callback(err);
return;
}
headers['Content-Encoding'] = encoding;
respond(data);
});
function respond(data) {
headers['Content-Length'] = 'string' == typeof data ? Buffer.byteLength(data) : data.length;
self.res.writeHead(200, self.headers(self.req, headers));
self.res.end(data);
callback();
}
};
/**
* Comparesses data.
*
* @api private
*/
Polling.prototype.compress = function (data, encoding, callback) {
debug('compressing');
var buffers = [];
var nread = 0;
compressionMethods[encoding](this.httpCompression)
.on('error', callback)
.on('data', function(chunk) {
buffers.push(chunk);
nread += chunk.length;
})
.on('end', function() {
callback(null, Buffer.concat(buffers, nread));
})
.end(data);
};
/**
* Closes the transport.

@@ -276,2 +381,5 @@ *

var self = this;
var closeTimeoutTimer;
if (this.dataReq) {

@@ -284,8 +392,15 @@ debug('aborting ongoing data request');

debug('transport writable - closing right away');
this.send([{ type: 'close' }]);
fn();
this.send([{ type: 'close', options: { compress: true } }]);
onClose();
} else {
debug('transport not writable - buffering orderly close');
this.shouldClose = fn;
this.shouldClose = onClose;
closeTimeoutTimer = setTimeout(onClose, this.closeTimeout);
}
function onClose() {
clearTimeout(closeTimeoutTimer);
fn();
self.onClose();
}
};

@@ -87,7 +87,7 @@

var self = this;
for (var i = 0, l = packets.length; i < l; i++) {
parser.encodePacket(packets[i], this.supportsBinary, function(data) {
packets.forEach(function(packet) {
parser.encodePacket(packet, self.supportsBinary, function(data) {
debug('writing "%s"', data);
self.writable = false;
self.socket.send(data, function (err){
self.socket.send(data, packet.options, function (err){
if (err) return self.onError('write error', err.stack);

@@ -98,3 +98,3 @@ self.writable = true;

});
}
});
};

@@ -101,0 +101,0 @@

{
"name": "engine.io",
"version": "1.5.4",
"version": "1.6.0",
"description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server",
"main": "./lib/engine.io",
"author": "Guillermo Rauch <guillermo@learnboost.com>",
"homepage": "https://github.com/LearnBoost/engine.io",
"homepage": "https://github.com/socketio/engine.io",
"contributors": [

@@ -26,14 +26,16 @@ {

],
"license": "MIT",
"dependencies": {
"base64id": "0.1.0",
"debug": "1.0.3",
"debug": "2.2.0",
"ws": "0.8.0",
"engine.io-parser": "1.2.2",
"ws": "0.8.0"
"accepts": "1.1.4"
},
"devDependencies": {
"mocha": "1.12.0",
"engine.io-client": "1.6.0",
"expect.js": "0.2.0",
"superagent": "0.15.4",
"engine.io-client": "1.5.4",
"s": "0.1.1"
"mocha": "2.3.4",
"s": "0.1.1",
"superagent": "0.15.4"
},

@@ -45,4 +47,4 @@ "scripts": {

"type": "git",
"url": "git@github.com:Automattic/engine.io.git"
"url": "git@github.com:socketio/engine.io.git"
}
}
# Engine.IO: the realtime engine
[![Build Status](https://secure.travis-ci.org/Automattic/engine.io.png)](http://travis-ci.org/Automattic/engine.io)
[![NPM version](https://badge.fury.io/js/engine.io.png)](http://badge.fury.io/js/engine.io)
[![Build Status](https://secure.travis-ci.org/socketio/engine.io.svg)](http://travis-ci.org/socketio/engine.io)
[![NPM version](https://badge.fury.io/js/engine.io.svg)](http://badge.fury.io/js/engine.io)
`Engine.IO` is the implementation of transport-based
cross-browser/cross-device bi-directional communication layer for
[Socket.IO](http://github.com/learnboost/socket.io).
[Socket.IO](http://github.com/socketio/socket.io).

@@ -215,5 +215,13 @@ ## How to use

(`true`)
- `perMessageDeflate` (`Object|Boolean`): parameters of the WebSocket permessage-deflate extension
(see [ws module](https://github.com/einaros/ws) api docs). Set to `false` to disable. (`true`)
- `httpCompression` (`Object|Boolean`): parameters of the http compression for the polling transports
(see [zlib](http://nodejs.org/api/zlib.html#zlib_options) api docs). Set to `false` to disable. (`true`)
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`)
- `cookie` (`String|Boolean`): name of the HTTP cookie that
contains the client sid to send as part of handshake response
headers. Set to `false` to not send one. (`io`)
- `cookiePath` (`String|Boolean`): path of the above `cookie`
option. If false, no path will be sent, which means browsers will only send the cookie on the engine.io attached path (`/engine.io`).
Set this to `/` to send the io cookie on all requests. (`false`)
- `close`

@@ -246,2 +254,8 @@ - Closes all clients

- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`)
- `generateId`
- Generate a socket id.
- Overwrite this method to generate your custom socket id.
- **Parameters**
- `http.ServerRequest`: a node request object
- **Returns** A socket id for connected client.

@@ -302,3 +316,6 @@ <hr><br>

- `String` | `Buffer` | `ArrayBuffer` | `ArrayBufferView`: a string or any object implementing `toString()`, with outgoing data, or a Buffer or ArrayBuffer with binary data. Also any ArrayBufferView can be sent as is.
- `Object`: optional, options object
- `Function`: optional, a callback executed when the message gets flushed out by the transport
- **Options**
- `compress` (`Boolean`): whether to compress sending data. This option might be ignored and forced to be `true` when using polling. (`true`)
- **Returns** `Socket` for chaining

@@ -316,3 +333,3 @@ - `close`

For the client API refer to the
For the client API refer to the
[engine-client](http://github.com/learnboost/engine.io-client) repository.

@@ -396,3 +413,3 @@

- _B: Network traffic_<br>
WebSocket is designed around the premise that each message frame has to be
WebSocket is designed around the premise that each message frame has to be
surrounded by the least amount of data. In HTTP 1.1 transports, each message

@@ -431,3 +448,3 @@ frame is surrounded by HTTP headers and chunked encoding frames. If you try to

nature of the evolution of the WebSocket protocol. Applications therefore end up
inevitably using long polling, but the seamless installation experience of
inevitably using long polling, but the seamless installation experience of
Socket.IO we strive for (_"require() it and it just works"_) disappears.

@@ -474,3 +491,3 @@

Absolutely. Although the recommended framework for building realtime applications
is Socket.IO, since it provides fundamental features for real-world applications
is Socket.IO, since it provides fundamental features for real-world applications
such as multiplexing, reconnection support, etc.

@@ -500,3 +517,3 @@

## License
## License

@@ -525,2 +542,1 @@ (The MIT License)

SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc