Socket
Socket
Sign inDemoInstall

ws

Package Overview
Dependencies
71
Maintainers
1
Versions
168
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.4.25 to 0.4.27

examples/ssl.js

19

doc/ws.md

@@ -22,3 +22,5 @@ # ws

Either `port` or `server` must be provided, otherwise you might enable `noServer` if you want to pass the requests directly.
Either `port` or `server` must be provided, otherwise you might enable
`noServer` if you want to pass the requests directly. Please note that the
`callback` is only used when you supply the a `port` number in the options.

@@ -60,2 +62,17 @@ ### server.close([code], [data])

* `address` String|Array
* `options` Object
* `protocol` String
* `protocolVersion` Number|String
-- the following only apply if `address` is a String
* `host` String
* `origin` String
* `pfx` String|Buffer
* `key` String|Buffer
* `passphrase` String
* `cert` String|Buffer
* `ca` Array
* `ciphers` String
* `rejectUnauthorized` Boolean
Instantiating with an `address` creates a new WebSocket client object. If `address` is an Array (request, socket, rest), it is instantiated as a Server client (e.g. called from the `ws.Server`).

@@ -62,0 +79,0 @@

2

examples/serverstats-express_3/server.js

@@ -20,3 +20,3 @@ var WebSocketServer = require('../../').Server

clearInterval(id);
})
});
});

@@ -1,2 +0,2 @@

v0.4.24 - December 6th, 2012
v0.4.25 - December 17th, 2012
=====================

@@ -3,0 +3,0 @@ * Removed install.js. [shtylman]

@@ -106,3 +106,7 @@ /*!

canModifyData = true;
data = (data && typeof data.buffer !== 'undefined') ? getArrayBuffer(data.buffer) : new Buffer(data);
if (data && (typeof data.byteLength !== 'undefined' || typeof data.buffer !== 'undefined')) {
data = getArrayBuffer(data);
} else {
data = new Buffer(data);
}
}

@@ -205,4 +209,6 @@

function getArrayBuffer(array) {
var l = array.byteLength
function getArrayBuffer(data) {
// data is either an ArrayBuffer or ArrayBufferView.
var array = data.buffer || data
, l = data.byteLength || data.length
, buffer = new Buffer(l);

@@ -209,0 +215,0 @@ for (var i = 0; i < l; ++i) {

@@ -66,6 +66,5 @@ /*!

WebSocket.CONNECTING = 0;
WebSocket.OPEN = 1;
WebSocket.CLOSING = 2;
WebSocket.CLOSED = 3;
["CONNECTING", "OPEN", "CLOSING", "CLOSED"].forEach(function (state, index) {
WebSocket.prototype[state] = WebSocket[state] = index;
});

@@ -187,2 +186,5 @@ /**

options.fin = true;
if (typeof options.binary == 'undefined') {
options.binary = (data instanceof ArrayBuffer || data instanceof Buffer);
}
if (typeof options.mask == 'undefined') options.mask = !this._isServer;

@@ -277,2 +279,14 @@ if (data instanceof fs.ReadStream) {

/**
* Expose bufferedAmount
*
* @api public
*/
Object.defineProperty(WebSocket.prototype, 'bufferedAmount', {
get: function get() {
return this._socket ? this._socket.bufferSize : 0;
}
});
/**
* Emulates the W3C Browser based WebSocket interface using function members.

@@ -321,6 +335,7 @@ *

WebSocket.prototype.addEventListener = function(method, listener) {
var target = this;
if (typeof listener === 'function') {
if (method === 'message') {
function onMessage (data) {
listener.call(this, new MessageEvent(data));
function onMessage (data, flags) {
listener.call(this, new MessageEvent(data, flags.binary ? 'Binary' : 'Text', target));
}

@@ -330,6 +345,5 @@ // store a reference so we can return the original function from the addEventListener hook

this.on(method, onMessage);
}
else if (method === 'close') {
} else if (method === 'close') {
function onClose (code, message) {
listener.call(this, new CloseEvent(code, message));
listener.call(this, new CloseEvent(code, message, target));
}

@@ -339,2 +353,17 @@ // store a reference so we can return the original function from the addEventListener hook

this.on(method, onClose);
} else if (method === 'error') {
function onError (event) {
event.target = target;
listener.call(this, event);
}
// store a reference so we can return the original function from the addEventListener hook
onError._listener = listener;
this.on(method, onError);
} else if (method === 'open') {
function onOpen () {
listener.call(this, new OpenEvent(target));
}
// store a reference so we can return the original function from the addEventListener hook
onOpen._listener = listener;
this.on(method, onOpen);
} else {

@@ -355,5 +384,6 @@ this.on(method, listener);

function MessageEvent(dataArg) {
// Currently only the data attribute is implemented. More can be added later if needed.
function MessageEvent(dataArg, typeArg, target) {
this.data = dataArg;
this.type = typeArg;
this.target = target;
}

@@ -368,9 +398,21 @@

function CloseEvent(code, reason) {
function CloseEvent(code, reason, target) {
this.wasClean = (typeof code == 'undefined' || code == 1000);
this.code = code;
this.reason = reason;
this.target = target;
}
/**
* W3C OpenEvent
*
* @see http://www.w3.org/TR/html5/comms.html
* @api private
*/
function OpenEvent(target) {
this.target = target;
}
/**
* Entirely private apis,

@@ -380,3 +422,3 @@ * which may or may not be bound to a sepcific WebSocket instance.

function initAsServerClient(req, socket, upgradeHead, options) {
function initAsServerClient(req, socket, upgradeHead, options) {
options = new Options({

@@ -405,3 +447,12 @@ protocolVersion: protocolVersion,

host: null,
protocol: null
protocol: null,
// ssl-related options
pfx: null,
key: null,
passphrase: null,
cert: null,
ca: null,
ciphers: null,
rejectUnauthorized: null
}).merge(options);

@@ -418,2 +469,3 @@ if (options.value.protocolVersion != 8 && options.value.protocolVersion != 13) {

var httpObj = isSecure ? https : http;
var port = serverUrl.port || (isSecure ? 443 : 80);

@@ -438,8 +490,9 @@ // expose state properties

host: serverUrl.hostname,
port: serverUrl.port || (isSecure ? 443 : 80)
port: port
});
}
var headerHost = serverUrl.hostname + ':' + port;
var requestOptions = {
port: serverUrl.port || (isSecure ? 443 : 80),
port: port,
host: serverUrl.hostname,

@@ -449,2 +502,4 @@ headers: {

'Upgrade': 'websocket',
'Host': headerHost,
'Origin': headerHost,
'Sec-WebSocket-Version': options.value.protocolVersion,

@@ -461,7 +516,35 @@ 'Sec-WebSocket-Key': key

if (options.isDefinedAndNonNull('pfx')
|| options.isDefinedAndNonNull('key')
|| options.isDefinedAndNonNull('passphrase')
|| options.isDefinedAndNonNull('cert')
|| options.isDefinedAndNonNull('ca')
|| options.isDefinedAndNonNull('ciphers')
|| options.isDefinedAndNonNull('rejectUnauthorized')) {
if (isNodeV4) {
throw new Error('Client side certificates are not supported on Node 0.4.x');
}
if (options.isDefinedAndNonNull('pfx')) requestOptions.pfx = options.value.pfx;
if (options.isDefinedAndNonNull('key')) requestOptions.key = options.value.key;
if (options.isDefinedAndNonNull('passphrase')) requestOptions.passphrase = options.value.passphrase;
if (options.isDefinedAndNonNull('cert')) requestOptions.cert = options.value.cert;
if (options.isDefinedAndNonNull('ca')) requestOptions.ca = options.value.ca;
if (options.isDefinedAndNonNull('ciphers')) requestOptions.ciphers = options.value.ciphers;
if (options.isDefinedAndNonNull('rejectUnauthorized')) requestOptions.rejectUnauthorized = options.value.rejectUnauthorized;
// global agent ignores client side certificates
agent = new httpObj.Agent(requestOptions);
}
if (isNodeV4) {
requestOptions.path = (serverUrl.pathname || '/') + (serverUrl.search || '');
}
else requestOptions.path = serverUrl.path || '/';
if (agent) {
requestOptions.agent = agent;
}
else requestOptions.path = serverUrl.path || '/';
if (isUnixSocket) {

@@ -477,2 +560,3 @@ requestOptions.socketPath = serverUrl.pathname;

var req = httpObj.request(requestOptions);
(isNodeV4 ? agent : req).on('error', function(error) {

@@ -503,2 +587,21 @@ self.emit('error', error);

var serverProt = res.headers['sec-websocket-protocol'];
var protList = (options.value.protocol || "").split(/, */);
var protError = null;
if (!options.value.protocol && serverProt) {
protError = 'server sent a subprotocol even though none requested';
} else if (options.value.protocol && !serverProt) {
protError = 'server sent no subprotocol even though requested';
} else if (serverProt && protList.indexOf(serverProt) === -1) {
protError = 'server responded with an invalid protocol';
}
if (protError) {
self.emit('error', protError);
removeAllListeners(self);
socket.end();
return;
} else if (serverProt) {
self.protocol = serverProt;
}
establishConnection.call(self, Receiver, Sender, socket, upgradeHead);

@@ -642,2 +745,4 @@

clearTimeout(this._closeTimer);
this._closeTimer = null;
if (emitClose) this.emit('close', this._closeCode || 1000, this._closeMessage || '');

@@ -653,3 +758,3 @@ if (this._socket) {

if (!error) this._socket.end();
else this._socket.terminate();
else this._socket.destroy();
}

@@ -667,3 +772,2 @@ catch (e) { /* Ignore termination errors */ }

}
if (emitClose) this.emit('close', this._closeCode || 1000, this._closeMessage || '');
removeAllListeners(this);

@@ -670,0 +774,0 @@ this.on('error', function() {}); // catch all errors after this

@@ -27,2 +27,3 @@ /*!

verifyClient: null,
handleProtocols: null,
path: null,

@@ -33,3 +34,4 @@ noServer: false,

}).merge(options);
if (!options.value.port && !options.value.server && !options.value.noServer) {
if (!options.isDefinedAndNonNull('port') && !options.isDefinedAndNonNull('server') && !options.value.noServer) {
throw new TypeError('`port` or a `server` must be provided');

@@ -40,3 +42,3 @@ }

if (options.value.port) {
if (options.isDefinedAndNonNull('port')) {
this._server = http.createServer(function (req, res) {

@@ -70,3 +72,7 @@ res.writeHead(200, {'Content-Type': 'text/plain'});

this._server.on('upgrade', function(req, socket, upgradeHead) {
self.handleUpgrade(req, socket, upgradeHead, function(client) {
//copy upgradeHead to avoid retention of large slab buffers used in node core
var head = new Buffer(upgradeHead.length);
upgradeHead.copy(head);
self.handleUpgrade(req, socket, head, function(client) {
self.emit('connection'+req.url, client);

@@ -176,2 +182,5 @@ self.emit('connection', client);

// verify protocol
var protocols = req.headers['sec-websocket-protocol'];
// verify client

@@ -184,4 +193,3 @@ var origin = version < 13 ?

var self = this;
var completeHybiUpgrade = function() {
var protocol = req.headers['sec-websocket-protocol'];
var completeHybiUpgrade2 = function(protocol) {

@@ -239,2 +247,29 @@ // calc key

// optionally call external protocol selection handler before
// calling completeHybiUpgrade2
var completeHybiUpgrade1 = function() {
// choose from the sub-protocols
if (typeof self.options.handleProtocols == 'function') {
var protList = (protocols || "").split(/, */);
var callbackCalled = false;
var res = self.options.handleProtocols(protList, function(result, protocol) {
callbackCalled = true;
if (!result) abortConnection(socket, 404, 'Unauthorized')
else completeHybiUpgrade2(protocol);
});
if (!callbackCalled) {
// the handleProtocols handler never called our callback
abortConnection(socket, 501, 'Could not process protocols');
}
return;
} else {
if (typeof protocols !== 'undefined') {
completeHybiUpgrade2(protocols.split(/, */)[0]);
}
else {
completeHybiUpgrade2();
}
}
}
// optionally call external client verification handler

@@ -250,3 +285,3 @@ if (typeof this.options.verifyClient == 'function') {

if (!result) abortConnection(socket, 401, 'Unauthorized')
else completeHybiUpgrade();
else completeHybiUpgrade1();
});

@@ -261,3 +296,3 @@ return;

completeHybiUpgrade();
completeHybiUpgrade1();
}

@@ -264,0 +299,0 @@

@@ -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.25",
"version": "0.4.27",
"repository": {

@@ -24,3 +24,3 @@ "type": "git",

"tinycolor": "0.x",
"options": "latest"
"options": ">=0.0.5"
},

@@ -34,5 +34,3 @@ "devDependencies": {

},
"browser": {
"./index.js": "./lib/browser.js"
}
"browser": "./lib/browser.js"
}

@@ -83,2 +83,34 @@ var assert = require('assert')

describe('#bufferedAmount', function() {
it('defaults to zero', function(done) {
server.createServer(++port, function(srv) {
var url = 'ws://localhost:' + port;
var ws = new WebSocket(url);
assert.equal(0, ws.bufferedAmount);
ws.terminate();
ws.on('close', function() {
srv.close();
done();
});
});
});
it('stress kernel write buffer', function(done) {
var wss = new WebSocketServer({port: ++port}, function() {
var ws = new WebSocket('ws://localhost:' + port);
});
wss.on('connection', function(ws) {
while (true) {
if (ws.bufferedAmount > 0) break;
ws.send((new Array(10000)).join('hello'));
}
ws.terminate();
ws.on('close', function() {
wss.close();
done();
});
});
});
});
describe('#readyState', function() {

@@ -150,3 +182,3 @@ it('defaults to connecting', function(done) {

describe('.' + state, function() {
it('is enumerable property', function() {
it('is enumerable property of class', function() {
var propertyDescripter = Object.getOwnPropertyDescriptor(WebSocket, state)

@@ -158,2 +190,13 @@ assert.equal(readyStates[state], propertyDescripter.value);

});
server.createServer(++port, function(srv) {
var ws = new WebSocket('ws://localhost:' + port);
Object.keys(readyStates).forEach(function(state) {
describe('.' + state, function() {
it('is property of instance', function() {
assert.equal(readyStates[state], ws[state]);
});
});
});
});
});

@@ -504,2 +547,37 @@

it('ArrayBuffer is auto-detected without binary flag', function(done) {
server.createServer(++port, function(srv) {
var ws = new WebSocket('ws://localhost:' + port);
var array = new Float32Array(5);
for (var i = 0; i < array.length; ++i) array[i] = i / 2;
ws.on('open', function() {
ws.send(array.buffer);
});
ws.onmessage = function (event) {
assert.ok(event.type = 'Binary');
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(event.data))));
ws.terminate();
srv.close();
done();
};
});
});
it('Buffer is auto-detected without binary flag', function(done) {
server.createServer(++port, function(srv) {
var ws = new WebSocket('ws://localhost:' + port);
var buf = new Buffer('foobar');
ws.on('open', function() {
ws.send(buf);
});
ws.onmessage = function (event) {
assert.ok(event.type = 'Binary');
assert.ok(areArraysEqual(event.data, buf));
ws.terminate();
srv.close();
done();
};
});
});
it('before connect should fail', function(done) {

@@ -1312,3 +1390,3 @@ server.createServer(++port, function(srv) {

it('should receive vaild CloseEvent when server closes with code 1001', function(done) {
it('should receive valid CloseEvent when server closes with code 1001', function(done) {
var wss = new WebSocketServer({port: ++port}, function() {

@@ -1329,2 +1407,28 @@ var ws = new WebSocket('ws://localhost:' + port);

});
it('should have target set on Events', function(done) {
var wss = new WebSocketServer({port: ++port}, function() {
var ws = new WebSocket('ws://localhost:' + port);
ws.addEventListener('open', function(openEvent) {
assert.equal(ws, openEvent.target);
});
ws.addEventListener('message', function(messageEvent) {
assert.equal(ws, messageEvent.target);
wss.close();
});
ws.addEventListener('close', function(closeEvent) {
assert.equal(ws, closeEvent.target);
ws.emit('error', new Error('forced'));
});
ws.addEventListener('error', function(errorEvent) {
assert.equal(errorEvent.message, 'forced');
assert.equal(ws, errorEvent.target);
ws.terminate();
done();
});
});
wss.on('connection', function(client) {
client.send('hi')
});
});
});

@@ -1353,2 +1457,37 @@

});
it('can connect to secure websocket server with client side certificate', function(done) {
var options = {
key: fs.readFileSync('test/fixtures/key.pem'),
cert: fs.readFileSync('test/fixtures/certificate.pem'),
ca: [fs.readFileSync('test/fixtures/ca1-cert.pem')],
requestCert: true
};
var clientOptions = {
key: fs.readFileSync('test/fixtures/agent1-key.pem'),
cert: fs.readFileSync('test/fixtures/agent1-cert.pem')
};
var app = https.createServer(options, function (req, res) {
res.writeHead(200);
res.end();
});
var success = false;
var wss = new WebSocketServer({
server: app,
verifyClient: function(info) {
success = !!info.req.client.authorized;
return true;
}
});
app.listen(++port, function() {
var ws = new WebSocket('wss://localhost:' + port, clientOptions);
});
wss.on('connection', function(ws) {
app.close();
ws.terminate();
wss.close();
success.should.be.ok;
done();
});
});

@@ -1355,0 +1494,0 @@ it('cannot connect to secure websocket server via ws://', function(done) {

@@ -8,3 +8,3 @@ var http = require('http')

var port = 20000;
var port = 8000;

@@ -637,2 +637,94 @@ function getArrayBuffer(buf) {

});
it('selects the first protocol by default', function(done) {
var wss = new WebSocketServer({port: ++port}, function() {
var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
ws.on('open', function(client) {
ws.protocol.should.eql('prot1');
wss.close();
done();
});
});
});
it('selects the last protocol via protocol handler', function(done) {
var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
cb(true, ps[ps.length-1]); }}, function() {
var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
ws.on('open', function(client) {
ws.protocol.should.eql('prot2');
wss.close();
done();
});
});
});
it('client detects invalid server protocol', function(done) {
var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
cb(true, 'prot3'); }}, function() {
var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
ws.on('open', function(client) {
done(new Error('connection must not be established'));
});
ws.on('error', function() {
done();
});
});
});
it('client detects no server protocol', function(done) {
var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
cb(true); }}, function() {
var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
ws.on('open', function(client) {
done(new Error('connection must not be established'));
});
ws.on('error', function() {
done();
});
});
});
it('client refuses server protocols', function(done) {
var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
cb(false); }}, function() {
var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
ws.on('open', function(client) {
done(new Error('connection must not be established'));
});
ws.on('error', function() {
done();
});
});
});
it('server detects invalid protocol handler', function(done) {
var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
// not calling callback is an error and shouldn't timeout
}}, function() {
var options = {
port: port,
host: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket',
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
'Sec-WebSocket-Version': 13,
'Sec-WebSocket-Origin': 'http://foobar.com'
}
};
options.port = port;
var req = http.request(options);
req.end();
req.on('response', function(res) {
res.statusCode.should.eql(501);
wss.close();
done();
});
});
wss.on('connection', function(ws) {
done(new Error('connection must not be established'));
});
wss.on('error', function() {});
});
});

@@ -639,0 +731,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc