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

ws

Package Overview
Dependencies
Maintainers
1
Versions
169
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ws - npm Package Compare versions

Comparing version 0.4.3 to 0.4.5

12

History.md

@@ -0,1 +1,13 @@

v0.4.5 - Feb 7th 2012
=====================
* Corrected regression bug in handling of connections with the initial frame delivered across both http upgrade head and a standalone packet. This would lead to a race condition, which in some cases could cause message corruption. [einaros]
v0.4.4 - Feb 6th 2012
=====================
* Pass original request object to verifyClient, for cookie or authentication verifications. [einaros]
* Implemented addEventListener and slightly improved the emulation API by adding a MessageEvent with a readonly data attribute. [aslakhellesoy]
* Rewrite parts of hybi receiver to avoid stack overflows for large amounts of packets bundled in the same buffer / packet. [einaros]
v0.4.3 - Feb 4th 2012

@@ -2,0 +14,0 @@ =====================

8

lib/Receiver.hixie.js

@@ -47,3 +47,3 @@ /*!

if (self.state == EMPTY && data[0] != 0x00) {
self.error('payload must start with 0x00 byte');
self.error('payload must start with 0x00 byte', true);
return;

@@ -58,3 +58,3 @@ }

}
else self.spanLength += data.length;
else self.spanLength += data.length;
}

@@ -95,5 +95,5 @@ while(data) data = doAdd();

Receiver.prototype.error = function (reason) {
Receiver.prototype.error = function (reason, terminate) {
this.reset();
this.emit('error', reason);
this.emit('error', reason, terminate);
return this;

@@ -100,0 +100,0 @@ }

@@ -25,3 +25,3 @@ /*!

function Receiver () {
function Receiver () {
// memory pool for fragmented messages

@@ -32,7 +32,7 @@ var fragmentedPoolPrevUsed = -1;

}, function(db) {
return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ?
(fragmentedPoolPrevUsed + db.used) / 2 :
return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ?
(fragmentedPoolPrevUsed + db.used) / 2 :
db.used;
});
// memory pool for unfragmented messages

@@ -43,7 +43,7 @@ var unfragmentedPoolPrevUsed = -1;

}, function(db) {
return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ?
return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ?
(unfragmentedPoolPrevUsed + db.used) / 2 :
db.used;
});
this.state = {

@@ -57,3 +57,3 @@ activeFragmentedOperation: null,

this.overflow = [];
this.headerBuffer = new Buffer(10);
this.headerBuffer = new Buffer(10);
this.expectOffset = 0;

@@ -81,2 +81,4 @@ this.expectBuffer = null;

Receiver.prototype.add = function(data) {
var dataLength = data.length;
if (dataLength == 0) return;
if (this.expectBuffer == null) {

@@ -86,29 +88,9 @@ this.overflow.push(data);

}
var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset);
var dest = this.expectBuffer;
var offset = this.expectOffset;
switch (toRead) {
default: data.copy(dest, offset, 0, toRead); break;
case 16: dest[offset+15] = data[15];
case 15: dest[offset+14] = data[14];
case 14: dest[offset+13] = data[13];
case 13: dest[offset+12] = data[12];
case 12: dest[offset+11] = data[11];
case 11: dest[offset+10] = data[10];
case 10: dest[offset+9] = data[9];
case 9: dest[offset+8] = data[8];
case 8: dest[offset+7] = data[7];
case 7: dest[offset+6] = data[6];
case 6: dest[offset+5] = data[5];
case 5: dest[offset+4] = data[4];
case 4: dest[offset+3] = data[3];
case 3: dest[offset+2] = data[2];
case 2: dest[offset+1] = data[1];
case 1: dest[offset] = data[0];
}
var toRead = Math.min(dataLength, this.expectBuffer.length - this.expectOffset);
fastCopy(toRead, data, this.expectBuffer, this.expectOffset);
this.expectOffset += toRead;
if (toRead < data.length) {
this.overflow.push(data.slice(toRead, data.length));
if (toRead < dataLength) {
this.overflow.push(data.slice(toRead, dataLength));
}
if (this.expectOffset == this.expectBuffer.length) {
while (this.expectBuffer && this.expectOffset == this.expectBuffer.length) {
var bufferForHandler = this.expectBuffer;

@@ -136,6 +118,7 @@ this.expectBuffer = null;

while (toRead > 0 && this.overflow.length > 0) {
var buf = this.overflow.pop();
if (toRead < buf.length) this.overflow.push(buf.slice(toRead));
var read = Math.min(buf.length, toRead);
this.add(buf.slice(0, read));
var fromOverflow = this.overflow.pop();
if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead));
var read = Math.min(fromOverflow.length, toRead);
fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset);
this.expectOffset += read;
toRead -= read;

@@ -157,10 +140,10 @@ }

this.expectBuffer = this.allocateFromPool(length, this.state.fragmentedOperation);
this.expectOffset = 0;
this.expectHandler = handler;
var toRead = length;
while (toRead > 0 && this.overflow.length > 0) {
var buf = this.overflow.pop();
if (toRead < buf.length) this.overflow.push(buf.slice(toRead));
var read = Math.min(buf.length, toRead);
this.add(buf.slice(0, read));
var fromOverflow = this.overflow.pop();
if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead));
var read = Math.min(fromOverflow.length, toRead);
fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset);
this.expectOffset += read;
toRead -= read;

@@ -321,2 +304,24 @@ }

function fastCopy(length, srcBuffer, dstBuffer, dstOffset) {
switch (length) {
default: srcBuffer.copy(dstBuffer, dstOffset, 0, length); break;
case 16: dstBuffer[dstOffset+15] = srcBuffer[15];
case 15: dstBuffer[dstOffset+14] = srcBuffer[14];
case 14: dstBuffer[dstOffset+13] = srcBuffer[13];
case 13: dstBuffer[dstOffset+12] = srcBuffer[12];
case 12: dstBuffer[dstOffset+11] = srcBuffer[11];
case 11: dstBuffer[dstOffset+10] = srcBuffer[10];
case 10: dstBuffer[dstOffset+9] = srcBuffer[9];
case 9: dstBuffer[dstOffset+8] = srcBuffer[8];
case 8: dstBuffer[dstOffset+7] = srcBuffer[7];
case 7: dstBuffer[dstOffset+6] = srcBuffer[6];
case 6: dstBuffer[dstOffset+5] = srcBuffer[5];
case 5: dstBuffer[dstOffset+4] = srcBuffer[4];
case 4: dstBuffer[dstOffset+3] = srcBuffer[3];
case 3: dstBuffer[dstOffset+2] = srcBuffer[2];
case 2: dstBuffer[dstOffset+1] = srcBuffer[1];
case 1: dstBuffer[dstOffset] = srcBuffer[0];
}
}
/**

@@ -323,0 +328,0 @@ * Opcode handlers

@@ -55,3 +55,5 @@ /*!

if (Object.prototype.toString.call(address) == '[object Array]') initAsServerClient.apply(this, address.concat(options));
if (Object.prototype.toString.call(address) == '[object Array]') {
initAsServerClient.apply(this, address.concat(options));
}
else initAsClient.apply(this, arguments);

@@ -61,2 +63,8 @@ }

/**
* Inherits from EventEmitter.
*/
util.inherits(WebSocket, events.EventEmitter);
/**
* Ready States

@@ -80,8 +88,2 @@ */

/**
* Inherits from EventEmitter.
*/
util.inherits(WebSocket, events.EventEmitter);
/**
* Gracefully closes the connection, after sending a description message to the server

@@ -243,3 +245,3 @@ *

/**
* Emulates the Browser based WebSocket interface.
* Emulates the W3C Browser based WebSocket interface using function members.
*

@@ -274,18 +276,3 @@ * @see http://dev.w3.org/html5/websockets/#the-websocket-interface

this.removeAllListeners(method);
if (typeof listener === 'function') {
// Special case for messages as we need to wrap the response here to
// emulate a WebSocket event response.
if (method === 'message') {
function message (data) {
listener.call(this, { data: data });
}
// store a reference so we can return the origional function again
message._listener = listener;
this.on(method, message);
} else {
this.on(method, listener);
}
}
this.addEventListener(method, listener);
}

@@ -295,5 +282,42 @@ });

/**
* Emulates the W3C Browser based WebSocket interface using addEventListener.
*
* @see https://developer.mozilla.org/en/DOM/element.addEventListener
* @see http://dev.w3.org/html5/websockets/#the-websocket-interface
* @api public
*/
WebSocket.prototype.addEventListener = function(method, listener) {
if (typeof listener === 'function') {
// Special case for messages as we need to wrap the data
// in a MessageEvent object.
if (method === 'message') {
function onMessage (data) {
listener.call(this, new MessageEvent(data));
}
// store a reference so we can return the origional function again
onMessage._listener = listener;
this.on(method, onMessage);
} else {
this.on(method, listener);
}
}
}
module.exports = WebSocket;
/**
* W3C MessageEvent
*
* @see http://www.w3.org/TR/html5/comms.html
* @api private
*/
function MessageEvent(dataArg) {
// Currently only the data attribute is implemented. More can be added later if needed.
Object.defineProperty(this, 'data', { writable: false, value: dataArg });
}
/**
* Entirely private apis,

@@ -433,2 +457,4 @@ * which may or may not be bound to a sepcific WebSocket instance.

var self = this;
// socket cleanup handlers
socket.on('end', function() {

@@ -464,5 +490,32 @@ if (self.readyState == WebSocket.CLOSED) return;

var receiver = new ReceiverClass();
socket.on('data', function (data) {
// ensure that the upgradeHead is added to the receiver
function firstHandler(data) {
if (upgradeHead != null) {
var head = upgradeHead;
upgradeHead = null;
receiver.add(head);
}
dataHandler = realHandler;
receiver.add(data);
});
}
// subsequent packets are pushed straight to the receiver
function realHandler(data) { receiver.add(data); }
var dataHandler = firstHandler;
socket.on('data', dataHandler);
// if data was passed along with the http upgrade,
// this will schedule a push of that on to the receiver.
// this has to be done on next tick, since the caller
// hasn't had a chance to set event handlers on this client
// object yet.
if (upgradeHead && upgradeHead.length > 0) {
process.nextTick(function() {
if (upgradeHead) {
var toSend = upgradeHead;
upgradeHead = null;
receiver.add(toSend);
}
});
}
// receiver event handlers
receiver.on('text', function (data, flags) {

@@ -497,2 +550,3 @@ flags = flags || {};

// finalize the client
Object.defineProperty(this, '_sender', { value: new SenderClass(socket) });

@@ -504,8 +558,2 @@ this._sender.on('error', function(error) {

this.emit('open');
if (upgradeHead && upgradeHead.length > 0) {
process.nextTick(function() {
receiver.add(upgradeHead);
});
}
}

@@ -512,0 +560,0 @@

@@ -178,3 +178,4 @@ /*!

origin: origin,
secure: typeof req.connection.encrypted !== 'undefined'
secure: typeof req.connection.encrypted !== 'undefined',
req: req
};

@@ -246,3 +247,4 @@ if (!this.options.verifyClient(info)) {

origin: origin,
secure: typeof req.connection.encrypted !== 'undefined'
secure: typeof req.connection.encrypted !== 'undefined',
req: req
};

@@ -249,0 +251,0 @@ if (!this.options.verifyClient(info)) {

@@ -5,3 +5,3 @@ {

"description": "simple to use, blazing fast and thoroughly tested websocket client, server and console for node.js, up-to-date against RFC-6455",
"version": "0.4.3",
"version": "0.4.5",
"repository": {

@@ -8,0 +8,0 @@ "type": "git",

@@ -6,7 +6,7 @@ var assert = require('assert')

describe('Receiver', function() {
describe('Receiver', function() {
it('can parse text message', function() {
var p = new Receiver();
var packet = '00 48 65 6c 6c 6f ff';
var gotData = false;

@@ -17,3 +17,3 @@ p.on('text', function(data) {

});
p.add(getBufferFromHexString(packet));

@@ -26,3 +26,3 @@ gotData.should.be.ok;

var packet = '00 48 65 6c 6c 6f ff 00 48 65 6c 6c 6f ff';
var gotData = false;

@@ -34,3 +34,3 @@ var messages = [];

});
p.add(getBufferFromHexString(packet));

@@ -53,3 +53,3 @@ gotData.should.be.ok;

];
var gotData = false;

@@ -61,3 +61,3 @@ var messages = [];

});
for (var i = 0; i < packets.length; ++i) {

@@ -82,3 +82,3 @@ p.add(getBufferFromHexString(packets[i]));

];
var gotData = false;

@@ -90,3 +90,3 @@ var messages = [];

});
for (var i = 0; i < packets.length; ++i) {

@@ -115,3 +115,3 @@ p.add(getBufferFromHexString(packets[i]));

];
var gotData = false;

@@ -124,6 +124,6 @@ var gotError = false;

});
p.on('error', function() {
gotError = true;
p.on('error', function(reason, code) {
gotError = code == true;
});
for (var i = 0; i < packets.length && !gotError; ++i) {

@@ -130,0 +130,0 @@ p.add(getBufferFromHexString(packets[i]));

@@ -1107,3 +1107,3 @@ var assert = require('assert')

describe('API emulation', function() {
describe('W3C API emulation', function() {
it('should not throw errors when getting and setting', function(done) {

@@ -1138,4 +1138,4 @@ server.createServer(++port, function(srv) {

ws.onmessage = function(data) {
assert.ok(!!data.data);
ws.onmessage = function(messageEvent) {
assert.ok(!!messageEvent.data);
++message;

@@ -1170,2 +1170,18 @@ ws.close();

});
it('should receive text data wrapped in a MessageEvent when using addEventListener', function(done) {
server.createServer(++port, function(srv) {
var ws = new WebSocket('ws://localhost:' + port);
ws.addEventListener('open', function() {
ws.send('hi');
});
ws.addEventListener('message', function(messageEvent) {
assert.equal('hi', messageEvent.data);
ws.terminate();
srv.close();
done();
});
});
});
});

@@ -1172,0 +1188,0 @@

@@ -394,4 +394,6 @@ var http = require('http')

it('verifyClient gets client origin', function(done) {
var verifyClientCalled = false;
var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
info.origin.should.eql('http://foobarbaz.com');
verifyClientCalled = true;
return false;

@@ -413,2 +415,3 @@ }}, function() {

req.on('response', function(res) {
verifyClientCalled.should.be.ok;
wss.close();

@@ -421,2 +424,31 @@ done();

it('verifyClient gets original request', function(done) {
var verifyClientCalled = false;
var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
info.req.headers['sec-websocket-key'].should.eql('dGhlIHNhbXBsZSBub25jZQ==');
verifyClientCalled = true;
return false;
}}, function() {
var options = {
port: port,
host: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket',
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
'Sec-WebSocket-Version': 13,
'Origin': 'http://foobarbaz.com'
}
};
var req = http.request(options);
req.end();
req.on('response', function(res) {
verifyClientCalled.should.be.ok;
wss.close();
done();
});
});
wss.on('error', function() {});
});
it('verifyClient has secure:true for ssl connections', function(done) {

@@ -500,3 +532,3 @@ var options = {

wss.close();
done();
done();
});

@@ -507,17 +539,25 @@ });

});
describe('messaging', function() {
it('can send data', function(done) {
it('can send and receive data', function(done) {
var data = new Array(65*1024);
for (var i = 0; i < data.length; ++i) {
data[i] = String.fromCharCode(65 + ~~(25 * Math.random()));
}
data = data.join('');
var wss = new WebSocketServer({port: ++port}, function() {
var ws = new WebSocket('ws://localhost:' + port);
ws.on('message', function(data, flags) {
data.should.eql('hello!');
ws.on('message', function(message, flags) {
ws.send(message);
});
});
wss.on('connection', function(client) {
client.on('message', function(message) {
message.should.eql(data);
wss.close();
done();
});
client.send(data);
});
wss.on('connection', function(client) {
client.send('hello!');
});
});
});
});

@@ -689,4 +729,6 @@ });

it('verifyClient gets client origin', function(done) {
var verifyClientCalled = false;
var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
info.origin.should.eql('http://foobarbaz.com');
verifyClientCalled = true;
return false;

@@ -709,2 +751,3 @@ }}, function() {

req.on('response', function(res) {
verifyClientCalled.should.be.ok;
wss.close();

@@ -717,2 +760,32 @@ done();

it('verifyClient gets original request', function(done) {
var verifyClientCalled = false;
var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
info.req.headers['sec-websocket-key1'].should.eql('3e6b263 4 17 80');
verifyClientCalled = true;
return false;
}}, function() {
var options = {
port: port,
host: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'WebSocket',
'Origin': 'http://foobarbaz.com',
'Sec-WebSocket-Key1': '3e6b263 4 17 80',
'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90'
}
};
var req = http.request(options);
req.write('WjN}|M(6');
req.end();
req.on('response', function(res) {
verifyClientCalled.should.be.ok;
wss.close();
done();
});
});
wss.on('error', function() {});
});
it('handles messages passed along with the upgrade request (upgrade head)', function(done) {

@@ -743,3 +816,3 @@ var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {

wss.close();
done();
done();
});

@@ -749,3 +822,2 @@ });

});
});

@@ -752,0 +824,0 @@ });

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