Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: socketio/engine.io
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 935b155c21d4776d921728e9dac25447ff3472e5
Choose a base ref
...
head repository: socketio/engine.io
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1a685c02e19a6a70f7bacda71aed2bec5312f6cb
Choose a head ref
  • 14 commits
  • 13 files changed
  • 6 contributors

Commits on Apr 28, 2017

  1. Copy the full SHA
    e76e035 View commit details

Commits on Aug 31, 2017

  1. [fix] Use workaround for setEncoding bug in node 0.10+ (#527)

    The server often crashes with 'TypeError: "list" argument must be an Array of Buffers' errors,
    which is caused by a bug in new versions of node, where setEncoding call does not work for messages
    that are already in the queue.
    
    This pull request makes sure that concat is never called in the non binary case, even if
    setEncoding does not work properly.
    nightwing authored and darrachequesne committed Aug 31, 2017
    Copy the full SHA
    3dcc2d5 View commit details

Commits on Sep 1, 2017

  1. [fix] Fix undeterministic error in polling buffer processing (#529)

    Ensure all assignments for chunks are Buffer when they should, even when onData is supposed to not
    be called again.
    raulmt authored and darrachequesne committed Sep 1, 2017
    Copy the full SHA
    7f63d38 View commit details
  2. Copy the full SHA
    fd20b91 View commit details

Commits on Sep 2, 2017

  1. [docs] Fix wsEngine default value in README (#526)

    Merge #459 (release 2.0.0) changed default wsEngine to uws. Updating README to reflect this change.
    st0ck53y authored and darrachequesne committed Sep 2, 2017
    Copy the full SHA
    f9d3f06 View commit details
  2. [fix] Use explicit require of wsEngine (#523)

    Because WebPack does not support variables in require statements.
    
    Closes #522
    markbjerke authored and darrachequesne committed Sep 2, 2017
    Copy the full SHA
    38d639a View commit details
  3. [fix] Check whether 'Origin' header has invalid characters (#531)

    Since the 'Origin' header is used as response header, a value with invalid characters would trigger
    'The header content contains invalid characters' errors.
    
    Closes #517
    darrachequesne authored Sep 2, 2017
    Copy the full SHA
    e0d720c View commit details
  4. [chore] Release 3.1.1

    darrachequesne committed Sep 2, 2017
    Copy the full SHA
    a8ff89c View commit details

Commits on Sep 27, 2017

  1. [chore] Release 3.1.2

    darrachequesne committed Sep 27, 2017
    Copy the full SHA
    bf24359 View commit details

Commits on Oct 10, 2017

  1. Copy the full SHA
    3c77780 View commit details

Commits on Oct 11, 2017

  1. Copy the full SHA
    49362ab View commit details
  2. [chore] Release 3.1.3

    darrachequesne committed Oct 11, 2017
    Copy the full SHA
    3ee803a View commit details

Commits on Nov 12, 2017

  1. Copy the full SHA
    b3f1d35 View commit details
  2. [chore] Release 3.1.4

    darrachequesne committed Nov 12, 2017
    Copy the full SHA
    1a685c0 View commit details
Showing with 166 additions and 754 deletions.
  1. +0 −3 .gitignore
  2. +1 −1 .travis.yml
  3. +0 −608 History.md
  4. +0 −16 Makefile
  5. +1 −1 README.md
  6. +0 −52 gulpfile.js
  7. +0 −4 index.js
  8. +72 −11 lib/server.js
  9. +5 −2 lib/socket.js
  10. +7 −8 lib/transports/polling.js
  11. +14 −15 package.json
  12. +7 −7 test/jsonp.js
  13. +59 −26 test/server.js
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
node_modules
npm-debug.log
coverage.html
lib-cov/
dist
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ language: node_js
node_js:
- "4"
- "6"
- "7"
- "8"
git:
depth: 1
notifications:
608 changes: 0 additions & 608 deletions History.md

This file was deleted.

16 changes: 0 additions & 16 deletions Makefile

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -226,7 +226,7 @@ to a single process.
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 false to not save io cookie on all requests. (`/`)
- `cookieHttpOnly` (`Boolean`): If `true` HttpOnly io cookie cannot be accessed by client-side APIs, such as JavaScript. (`true`) _This option has no effect if `cookie` or `cookiePath` is set to `false`._
- `wsEngine` (`String`): what WebSocket server implementation to use. Specified module must conform to the `ws` interface (see [ws module api docs](https://github.com/websockets/ws/blob/master/doc/ws.md)). Default value is `ws`. An alternative c++ addon is also available by installing `uws` module.
- `wsEngine` (`String`): what WebSocket server implementation to use. Specified module must conform to the `ws` interface (see [ws module api docs](https://github.com/websockets/ws/blob/master/doc/ws.md)). Default value is `uws` (see [µWebSockets](https://github.com/uWebSockets/uWebSockets)).
- `initialPacket` (`Object`): an optional packet which will be concatenated to the handshake packet emitted by Engine.IO.
- `close`
- Closes all clients
52 changes: 0 additions & 52 deletions gulpfile.js

This file was deleted.

4 changes: 0 additions & 4 deletions index.js

This file was deleted.

83 changes: 72 additions & 11 deletions lib/server.js
Original file line number Diff line number Diff line change
@@ -91,14 +91,6 @@ Server.errorMessages = {

util.inherits(Server, EventEmitter);

/**
* Hash of open clients.
*
* @api public
*/

Server.prototype.clients;

/**
* Initialize websocket server
*
@@ -112,7 +104,11 @@ Server.prototype.init = function () {

var wsModule;
try {
wsModule = require(this.wsEngine);
switch (this.wsEngine) {
case 'uws': wsModule = require('uws'); break;
case 'ws': wsModule = require('ws'); break;
default: throw new Error('unknown wsEngine');
}
} catch (ex) {
this.wsEngine = 'ws';
// keep require('ws') as separate expression for packers (browserify, etc)
@@ -154,6 +150,13 @@ Server.prototype.verify = function (req, upgrade, fn) {
return fn(Server.errors.UNKNOWN_TRANSPORT, false);
}

// 'Origin' header check
var isOriginInvalid = checkInvalidHeaderChar(req.headers.origin);
if (isOriginInvalid) {
req.headers.origin = null;
return fn(Server.errors.BAD_REQUEST, false);
}

// sid check
var sid = req._query.sid;
if (sid) {
@@ -355,7 +358,7 @@ Server.prototype.handleUpgrade = function (req, socket, upgradeHead) {
return;
}

var head = new Buffer(upgradeHead.length);
var head = new Buffer(upgradeHead.length); // eslint-disable-line node/no-deprecated-api
upgradeHead.copy(head);
upgradeHead = null;

@@ -503,7 +506,7 @@ Server.prototype.attach = function (server, options) {

function abortConnection (socket, code) {
if (socket.writable) {
var message = Server.errorMessages.hasOwnProperty(code) ? Server.errorMessages[code] : code;
var message = Server.errorMessages.hasOwnProperty(code) ? Server.errorMessages[code] : (code || '');
var length = Buffer.byteLength(message);
socket.write(
'HTTP/1.1 400 Bad Request\r\n' +
@@ -516,3 +519,61 @@ function abortConnection (socket, code) {
}
socket.destroy();
}

/* eslint-disable */

/**
* From https://github.com/nodejs/node/blob/v8.4.0/lib/_http_common.js#L303-L354
*
* True if val contains an invalid field-vchar
* field-value = *( field-content / obs-fold )
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
* field-vchar = VCHAR / obs-text
*
* checkInvalidHeaderChar() is currently designed to be inlinable by v8,
* so take care when making changes to the implementation so that the source
* code size does not exceed v8's default max_inlined_source_size setting.
**/
var validHdrChars = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ...
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255
];

function checkInvalidHeaderChar(val) {
val += '';
if (val.length < 1)
return false;
if (!validHdrChars[val.charCodeAt(0)])
return true;
if (val.length < 2)
return false;
if (!validHdrChars[val.charCodeAt(1)])
return true;
if (val.length < 3)
return false;
if (!validHdrChars[val.charCodeAt(2)])
return true;
if (val.length < 4)
return false;
if (!validHdrChars[val.charCodeAt(3)])
return true;
for (var i = 4; i < val.length; ++i) {
if (!validHdrChars[val.charCodeAt(i)])
return true;
}
return false;
}
7 changes: 5 additions & 2 deletions lib/socket.js
Original file line number Diff line number Diff line change
@@ -31,7 +31,11 @@ function Socket (id, server, transport, req) {
this.request = req;

// Cache IP since it might not be in the req later
this.remoteAddress = req.connection.remoteAddress;
if (req.websocket && req.websocket._socket) {
this.remoteAddress = req.websocket._socket.remoteAddress;
} else {
this.remoteAddress = req.connection.remoteAddress;
}

this.checkIntervalTimer = null;
this.upgradeTimeoutTimer = null;
@@ -91,7 +95,6 @@ Socket.prototype.onPacket = function (packet) {
this.setPingTimeout();

switch (packet.type) {

case 'ping':
debug('got ping');
this.sendPacket('pong');
15 changes: 7 additions & 8 deletions lib/transports/polling.js
Original file line number Diff line number Diff line change
@@ -136,15 +136,14 @@ Polling.prototype.onDataRequest = function (req, res) {
this.dataReq = req;
this.dataRes = res;

var chunks = isBinary ? new Buffer(0) : '';
var chunks = isBinary ? new Buffer(0) : ''; // eslint-disable-line node/no-deprecated-api
var self = this;

function cleanup () {
chunks = isBinary ? new Buffer(0) : '';
req.removeListener('data', onData);
req.removeListener('end', onEnd);
req.removeListener('close', onClose);
self.dataReq = self.dataRes = null;
self.dataReq = self.dataRes = chunks = null;
}

function onClose () {
@@ -154,16 +153,16 @@ Polling.prototype.onDataRequest = function (req, res) {

function onData (data) {
var contentLength;
if (typeof data === 'string') {
chunks += data;
contentLength = Buffer.byteLength(chunks);
} else {
if (isBinary) {
chunks = Buffer.concat([chunks, data]);
contentLength = chunks.length;
} else {
chunks += data;
contentLength = Buffer.byteLength(chunks);
}

if (contentLength > self.maxHttpBufferSize) {
chunks = '';
chunks = isBinary ? new Buffer(0) : ''; // eslint-disable-line node/no-deprecated-api
req.connection.destroy();
}
}
29 changes: 14 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "engine.io",
"version": "3.1.0",
"version": "3.1.4",
"description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server",
"main": "./lib/engine.io",
"main": "lib/engine.io",
"author": "Guillermo Rauch <guillermo@learnboost.com>",
"homepage": "https://github.com/socketio/engine.io",
"contributors": [
@@ -27,23 +27,22 @@
"dependencies": {
"accepts": "1.3.3",
"base64id": "1.0.0",
"debug": "~2.6.4",
"debug": "~2.6.9",
"engine.io-parser": "~2.1.0",
"ws": "~2.3.1",
"ws": "~3.3.1",
"cookie": "0.3.1"
},
"devDependencies": {
"babel-eslint": "5.0.0",
"babel-eslint": "^7.2.3",
"babel-preset-es2015": "^6.24.0",
"engine.io-client": "3.1.0",
"eslint-config-standard": "4.4.0",
"eslint-plugin-standard": "1.3.2",
"engine.io-client": "3.1.4",
"eslint": "^4.5.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.1.1",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"expect.js": "^0.3.1",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-eslint": "1.1.1",
"gulp-mocha": "^4.3.0",
"gulp-nsp": "^2.4.1",
"mocha": "^3.2.0",
"s": "0.1.1",
"superagent": "0.15.4"
@@ -52,14 +51,14 @@
"uws": "~0.14.4"
},
"scripts": {
"test": "gulp test; EIO_WS_ENGINE=ws gulp test;"
"lint": "eslint lib/ test/ *.js",
"test": "npm run lint && mocha && EIO_WS_ENGINE=ws mocha"
},
"repository": {
"type": "git",
"url": "git@github.com:socketio/engine.io.git"
},
"files": [
"index.js",
"lib/"
]
}
14 changes: 7 additions & 7 deletions test/jsonp.js
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ var request = require('superagent');
describe('JSONP', function () {
before(function () {
// we have to override the browser's functionality for JSONP
document = { // eslint-disable-line no-native-reassign, no-undef
document = { // eslint-disable-line no-global-assign
body: {
appendChild: function () {},
removeChild: function () {}
@@ -44,10 +44,10 @@ describe('JSONP', function () {
appendChild: function () {},
submit: function () {
request
.post(this.action)
.type('form')
.send({ d: self.areaValue })
.end(function () {});
.post(this.action)
.type('form')
.send({ d: self.areaValue })
.end(function () {});
}
};
return form;
@@ -156,7 +156,7 @@ describe('JSONP', function () {
});

it('should arrive from server to client and back with binary data (pollingJSONP)', function (done) {
var binaryData = new Buffer(5);
var binaryData = Buffer.allocUnsafe(5);
for (var i = 0; i < 5; i++) binaryData[i] = i;
engine.on('connection', function (conn) {
conn.on('message', function (msg) {
@@ -178,7 +178,7 @@ describe('JSONP', function () {
it('should trigger when server closes a client', function (done) {
var engine = listen({ allowUpgrades: false, transports: ['polling'] }, function (port) {
var socket = new eioc.Socket('ws://localhost:' + port,
{ transports: ['polling'], forceJSONP: true, upgrade: false });
{ transports: ['polling'], forceJSONP: true, upgrade: false });
var total = 2;

engine.on('connection', function (conn) {
85 changes: 59 additions & 26 deletions test/server.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable standard/no-callback-literal */

/**
* Tests dependencies.
@@ -92,6 +93,15 @@ describe('server', function () {
});
});
});

it('should disallow connection that are rejected by `allowRequest`', function (done) {
listen({ allowRequest: function (req, fn) { fn(null, false); } }, function (port) {
var client = eioc('ws://localhost:%d'.s(port), { transports: ['websocket'] });
client.on('error', function () {
done();
});
});
});
});

describe('handshake', function () {
@@ -343,18 +353,18 @@ describe('server', function () {
var socket = new eioc.Socket('ws://localhost:%d'.s(port));
socket.on('open', function () {
request.get('http://localhost:%d/engine.io/'.s(port))
.set({ connection: 'close' })
.query({ transport: 'websocket', sid: socket.id })
.end(function (err, res) {
expect(err).to.be(null);
expect(res.status).to.be(400);
expect(res.body.code).to.be(3);
socket.send('echo');
socket.on('message', function (msg) {
expect(msg).to.be('echo');
done();
.set({ connection: 'close' })
.query({ transport: 'websocket', sid: socket.id })
.end(function (err, res) {
expect(err).to.be(null);
expect(res.status).to.be(400);
expect(res.body.code).to.be(3);
socket.send('echo');
socket.on('message', function (msg) {
expect(msg).to.be('echo');
done();
});
});
});
});
});
});
@@ -1344,7 +1354,7 @@ describe('server', function () {
});

it('should arrive when binary data is sent as Buffer (ws)', function (done) {
var binaryData = new Buffer(5);
var binaryData = Buffer.allocUnsafe(5);
for (var i = 0; i < binaryData.length; i++) {
binaryData.writeInt8(i, i);
}
@@ -1370,7 +1380,7 @@ describe('server', function () {
});

it('should arrive when binary data sent as Buffer (polling)', function (done) {
var binaryData = new Buffer(5);
var binaryData = Buffer.allocUnsafe(5);
for (var i = 0; i < binaryData.length; i++) {
binaryData.writeInt8(i, i);
}
@@ -1397,7 +1407,7 @@ describe('server', function () {
});

it('should arrive as ArrayBuffer if requested when binary data sent as Buffer (ws)', function (done) {
var binaryData = new Buffer(5);
var binaryData = Buffer.allocUnsafe(5);
for (var i = 0; i < binaryData.length; i++) {
binaryData.writeInt8(i, i);
}
@@ -1426,7 +1436,7 @@ describe('server', function () {
});

it('should arrive as ArrayBuffer if requested when binary data sent as Buffer (polling)', function (done) {
var binaryData = new Buffer(5);
var binaryData = Buffer.allocUnsafe(5);
for (var i = 0; i < binaryData.length; i++) {
binaryData.writeInt8(i, i);
}
@@ -1507,8 +1517,8 @@ describe('server', function () {
var socket = new eioc.Socket('ws://localhost:%d'.s(port), { transports: ['websocket'] });
socket.on('open', function () {
for (var i = 0; i < messageCount; i++) {
// connection.send('message: ' + i); // works
connection.send(messagePayload + '|message: ' + i); // does not work
// connection.send('message: ' + i); // works
connection.send(messagePayload + '|message: ' + i); // does not work
}
var receivedCount = 0;
socket.on('message', function (msg) {
@@ -1605,7 +1615,8 @@ describe('server', function () {
key: fs.readFileSync('test/fixtures/server.key'),
cert: fs.readFileSync('test/fixtures/server.crt'),
ca: fs.readFileSync('test/fixtures/ca.crt'),
requestCert: true
requestCert: true,
rejectUnauthorized: false
};

var opts = {
@@ -2300,7 +2311,7 @@ describe('server', function () {
it('should compress by default', function (done) {
var engine = listen({ transports: ['polling'] }, function (port) {
engine.on('connection', function (conn) {
var buf = new Buffer(1024);
var buf = Buffer.allocUnsafe(1024);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf);
});
@@ -2328,7 +2339,7 @@ describe('server', function () {
it('should compress using deflate', function (done) {
var engine = listen({ transports: ['polling'] }, function (port) {
engine.on('connection', function (conn) {
var buf = new Buffer(1024);
var buf = Buffer.allocUnsafe(1024);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf);
});
@@ -2356,7 +2367,7 @@ describe('server', function () {
it('should set threshold', function (done) {
var engine = listen({ transports: ['polling'], httpCompression: { threshold: 0 } }, function (port) {
engine.on('connection', function (conn) {
var buf = new Buffer(10);
var buf = Buffer.allocUnsafe(10);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf);
});
@@ -2381,7 +2392,7 @@ describe('server', function () {
it('should disable compression', function (done) {
var engine = listen({ transports: ['polling'], httpCompression: false }, function (port) {
engine.on('connection', function (conn) {
var buf = new Buffer(1024);
var buf = Buffer.allocUnsafe(1024);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf);
});
@@ -2406,7 +2417,7 @@ describe('server', function () {
it('should disable compression per message', function (done) {
var engine = listen({ transports: ['polling'] }, function (port) {
engine.on('connection', function (conn) {
var buf = new Buffer(1024);
var buf = Buffer.allocUnsafe(1024);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf, { compress: false });
});
@@ -2431,7 +2442,7 @@ describe('server', function () {
it('should not compress when the byte size is below threshold', function (done) {
var engine = listen({ transports: ['polling'] }, function (port) {
engine.on('connection', function (conn) {
var buf = new Buffer(100);
var buf = Buffer.allocUnsafe(100);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf);
});
@@ -2469,7 +2480,7 @@ describe('server', function () {
done();
};

var buf = new Buffer(100);
var buf = Buffer.allocUnsafe(100);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf, { compress: true });
});
@@ -2491,7 +2502,7 @@ describe('server', function () {
done();
};

var buf = new Buffer(100);
var buf = Buffer.allocUnsafe(100);
for (var i = 0; i < buf.length; i++) buf[i] = i % 0xff;
conn.send(buf, { compress: true });
});
@@ -2640,4 +2651,26 @@ describe('server', function () {
});
});
});

describe('remoteAddress', function () {
it('should be defined (polling)', function (done) {
var engine = listen({ transports: ['polling'] }, port => {
eioc('ws://localhost:%d'.s(port), { transports: ['polling'] });
engine.on('connection', socket => {
expect(socket.remoteAddress).to.be('::ffff:127.0.0.1');
done();
});
});
});

it('should be defined (ws)', function (done) {
var engine = listen({ transports: ['websocket'] }, port => {
eioc('ws://localhost:%d'.s(port), { transports: ['websocket'] });
engine.on('connection', socket => {
expect(socket.remoteAddress).to.be('::ffff:127.0.0.1');
done();
});
});
});
});
});