Socket
Socket
Sign inDemoInstall

ws

Package Overview
Dependencies
Maintainers
2
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.32 to 0.5.0

wscat/bin/wscat

10

History.md

@@ -0,1 +1,11 @@

v0.5 - November 20th 2013
=====================
* Fixed a file descriptor leak.
* Removed wscat as cli client from ws and released as separate module (wscat)
* Fixed memory leak caused by EventEmitters.
* Protocol errors now return a 401 error instead of 404 which is more suitable.
* Code refactor to support strict mode.
* Updated dependencies to latest versions
v0.4.31 - September 23th, 2013

@@ -2,0 +12,0 @@ =====================

47

index.js

@@ -0,1 +1,3 @@

'use strict';
/*!

@@ -7,21 +9,42 @@ * ws: a node.js websocket client

module.exports = require('./lib/WebSocket');
module.exports.Server = require('./lib/WebSocketServer');
module.exports.Sender = require('./lib/Sender');
module.exports.Receiver = require('./lib/Receiver');
var WS = module.exports = require('./lib/WebSocket');
module.exports.createServer = function (options, connectionListener) {
var server = new module.exports.Server(options);
if (typeof connectionListener === 'function') {
server.on('connection', connectionListener);
WS.Server = require('./lib/WebSocketServer');
WS.Sender = require('./lib/Sender');
WS.Receiver = require('./lib/Receiver');
/**
* Create a new WebSocket server.
*
* @param {Object} options Server options
* @param {Function} fn Optional connection listener.
* @returns {WS.Server}
* @api public
*/
WS.createServer = function createServer(options, fn) {
var server = new WS.Server(options);
if (typeof fn === 'function') {
server.on('connection', fn);
}
return server;
};
module.exports.connect = module.exports.createConnection = function (address, openListener) {
var client = new module.exports(address);
if (typeof openListener === 'function') {
client.on('open', openListener);
/**
* Create a new WebSocket connection.
*
* @param {String} address The URL/address we need to connect to.
* @param {Function} fn Open listener.
* @returns {WS}
* @api public
*/
WS.connect = WS.createConnection = function connect(address, fn) {
var client = new WS(address);
if (typeof fn === 'function') {
client.on('open', fn);
}
return client;
};

@@ -16,2 +16,4 @@ /*!

function Sender(socket) {
events.EventEmitter.call(this);
this.socket = socket;

@@ -18,0 +20,0 @@ this.continuationFrame = false;

@@ -18,2 +18,4 @@ /*!

function Sender(socket) {
events.EventEmitter.call(this);
this._socket = socket;

@@ -20,0 +22,0 @@ this.firstFragment = true;

@@ -0,1 +1,3 @@

'use strict';
/*!

@@ -7,9 +9,9 @@ * ws: a node.js websocket client

var util = require('util')
, events = require('events')
var url = require('url')
, util = require('util')
, http = require('http')
, https = require('https')
, crypto = require('crypto')
, url = require('url')
, stream = require('stream')
, Ultron = require('ultron')
, Options = require('options')

@@ -19,3 +21,4 @@ , Sender = require('./Sender')

, SenderHixie = require('./Sender.hixie')
, ReceiverHixie = require('./Receiver.hixie');
, ReceiverHixie = require('./Receiver.hixie')
, EventEmitter = require('events').EventEmitter;

@@ -32,11 +35,17 @@ /**

var closeTimeout = 30000; // Allow 5 seconds to terminate the connection cleanly
var closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly
/**
* WebSocket implementation
*
* @constructor
* @param {String} address Connection address.
* @param {String|Array} protocols WebSocket protocols.
* @param {Object} options Additional connection options.
* @api public
*/
function WebSocket(address, protocols, options) {
EventEmitter.call(this);
if (protocols && !Array.isArray(protocols) && 'object' == typeof protocols) {
if (protocols && !Array.isArray(protocols) && 'object' === typeof protocols) {
// accept the "options" Object as the 2nd argument

@@ -46,11 +55,15 @@ options = protocols;

}
if ('string' == typeof protocols) {
if ('string' === typeof protocols) {
protocols = [ protocols ];
}
if (!Array.isArray(protocols)) {
protocols = [];
}
// TODO: actually handle the `Sub-Protocols` part of the WebSocket client
this._socket = null;
this._ultron = null;
this.bytesReceived = 0;

@@ -70,10 +83,8 @@ this.readyState = null;

*/
util.inherits(WebSocket, EventEmitter);
util.inherits(WebSocket, events.EventEmitter);
/**
* Ready States
*/
["CONNECTING", "OPEN", "CLOSING", "CLOSED"].forEach(function (state, index) {
["CONNECTING", "OPEN", "CLOSING", "CLOSED"].forEach(function each(state, index) {
WebSocket.prototype[state] = WebSocket[state] = index;

@@ -88,9 +99,13 @@ });

*/
WebSocket.prototype.close = function close(code, data) {
if (
this.readyState === WebSocket.CLOSING
|| this.readyState === WebSocket.CLOSED
) return;
WebSocket.prototype.close = function(code, data) {
if (this.readyState == WebSocket.CLOSING || this.readyState == WebSocket.CLOSED) return;
if (this.readyState == WebSocket.CONNECTING) {
if (this.readyState === WebSocket.CONNECTING) {
this.readyState = WebSocket.CLOSED;
return;
}
try {

@@ -102,10 +117,8 @@ this.readyState = WebSocket.CLOSING;

this._sender.close(code, data, mask);
}
catch (e) {
} catch (e) {
this.emit('error', e);
}
finally {
} finally {
this.terminate();
}
}
};

@@ -117,7 +130,7 @@ /**

*/
WebSocket.prototype.pause = function pauser() {
if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
WebSocket.prototype.pause = function() {
if (this.readyState != WebSocket.OPEN) throw new Error('not opened');
return this._socket.pause();
}
};

@@ -132,12 +145,14 @@ /**

*/
WebSocket.prototype.ping = function(data, options, dontFailWhenClosed) {
if (this.readyState != WebSocket.OPEN) {
WebSocket.prototype.ping = function ping(data, options, dontFailWhenClosed) {
if (this.readyState !== WebSocket.OPEN) {
if (dontFailWhenClosed === true) return;
throw new Error('not opened');
}
options = options || {};
if (typeof options.mask == 'undefined') options.mask = !this._isServer;
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
this._sender.ping(data, options);
}
};

@@ -152,12 +167,14 @@ /**

*/
WebSocket.prototype.pong = function(data, options, dontFailWhenClosed) {
if (this.readyState != WebSocket.OPEN) {
if (this.readyState !== WebSocket.OPEN) {
if (dontFailWhenClosed === true) return;
throw new Error('not opened');
}
options = options || {};
if (typeof options.mask == 'undefined') options.mask = !this._isServer;
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
this._sender.pong(data, options);
}
};

@@ -169,7 +186,7 @@ /**

*/
WebSocket.prototype.resume = function resume() {
if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
WebSocket.prototype.resume = function() {
if (this.readyState != WebSocket.OPEN) throw new Error('not opened');
return this._socket.resume();
}
};

@@ -185,12 +202,14 @@ /**

WebSocket.prototype.send = function(data, options, cb) {
if (typeof options == 'function') {
WebSocket.prototype.send = function send(data, options, cb) {
if (typeof options === 'function') {
cb = options;
options = {};
}
if (this.readyState != WebSocket.OPEN) {
if (typeof cb == 'function') cb(new Error('not opened'));
if (this.readyState !== WebSocket.OPEN) {
if (typeof cb === 'function') cb(new Error('not opened'));
else throw new Error('not opened');
return;
}
if (!data) data = '';

@@ -202,5 +221,7 @@ if (this._queue) {

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

@@ -216,14 +237,24 @@ data instanceof Uint8Array ||

}
if (typeof options.mask == 'undefined') options.mask = !this._isServer;
var readable = typeof stream.Readable == 'function' ? stream.Readable : stream.Stream;
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
var readable = typeof stream.Readable === 'function'
? stream.Readable
: stream.Stream;
if (data instanceof readable) {
startQueue(this);
var self = this;
sendStream(this, data, options, function(error) {
process.nextTick(function() { executeQueueSends(self); });
if (typeof cb == 'function') cb(error);
sendStream(this, data, options, function send(error) {
process.nextTick(function tock() {
executeQueueSends(self);
});
if (typeof cb === 'function') cb(error);
});
} else {
this._sender.send(data, options, cb);
}
else this._sender.send(data, options, cb);
}
};

@@ -237,25 +268,32 @@ /**

*/
WebSocket.prototype.stream = function(options, cb) {
if (typeof options == 'function') {
WebSocket.prototype.stream = function stream(options, cb) {
if (typeof options === 'function') {
cb = options;
options = {};
}
var self = this;
if (typeof cb != 'function') throw new Error('callback must be provided');
if (this.readyState != WebSocket.OPEN) {
if (typeof cb == 'function') cb(new Error('not opened'));
if (typeof cb !== 'function') throw new Error('callback must be provided');
if (this.readyState !== WebSocket.OPEN) {
if (typeof cb === 'function') cb(new Error('not opened'));
else throw new Error('not opened');
return;
}
if (this._queue) {
this._queue.push(function() { self.stream(options, cb); });
this._queue.push(function () { self.stream(options, cb); });
return;
}
options = options || {};
if (typeof options.mask == 'undefined') options.mask = !this._isServer;
if (typeof options.mask === 'undefined') options.mask = !this._isServer;
startQueue(this);
var send = function(data, final) {
function send(data, final) {
try {
if (self.readyState != WebSocket.OPEN) throw new Error('not opened');
if (self.readyState !== WebSocket.OPEN) throw new Error('not opened');
options.fin = final === true;

@@ -265,5 +303,4 @@ self._sender.send(data, options);

else executeQueueSends(self);
}
catch (e) {
if (typeof cb == 'function') cb(e);
} catch (e) {
if (typeof cb === 'function') cb(e);
else {

@@ -275,4 +312,5 @@ delete self._queue;

}
process.nextTick(cb.bind(null, null, send));
}
};

@@ -284,10 +322,8 @@ /**

*/
WebSocket.prototype.terminate = function terminate() {
if (this.readyState === WebSocket.CLOSED) return;
WebSocket.prototype.terminate = function() {
if (this.readyState == WebSocket.CLOSED) return;
if (this._socket) {
try {
// End the connection
this._socket.end();
}
// End the connection
try { this._socket.end(); }
catch (e) {

@@ -303,4 +339,3 @@ // Socket error during end() call, so just destroy it right now

this._closeTimer = setTimeout(cleanupWebsocketResources.bind(this, true), closeTimeout);
}
else if (this.readyState == WebSocket.CONNECTING) {
} else if (this.readyState === WebSocket.CONNECTING) {
cleanupWebsocketResources.call(this, true);

@@ -315,3 +350,2 @@ }

*/
Object.defineProperty(WebSocket.prototype, 'bufferedAmount', {

@@ -333,3 +367,2 @@ get: function get() {

*/
['open', 'error', 'close', 'message'].forEach(function(method) {

@@ -343,3 +376,2 @@ Object.defineProperty(WebSocket.prototype, 'on' + method, {

*/
get: function get() {

@@ -357,3 +389,2 @@ var listener = this.listeners(method)[0];

*/
set: function set(listener) {

@@ -375,30 +406,39 @@ this.removeAllListeners(method);

var target = this;
function onMessage (data, flags) {
listener.call(target, new MessageEvent(data, flags.binary ? 'Binary' : 'Text', target));
}
function onClose (code, message) {
listener.call(target, new CloseEvent(code, message, target));
}
function onError (event) {
event.target = target;
listener.call(target, event);
}
function onOpen () {
listener.call(target, new OpenEvent(target));
}
if (typeof listener === 'function') {
if (method === 'message') {
function onMessage (data, flags) {
listener.call(this, new MessageEvent(data, flags.binary ? 'Binary' : 'Text', target));
}
// store a reference so we can return the original function from the addEventListener hook
// store a reference so we can return the original function from the
// addEventListener hook
onMessage._listener = listener;
this.on(method, onMessage);
} else if (method === 'close') {
function onClose (code, message) {
listener.call(this, new CloseEvent(code, message, target));
}
// store a reference so we can return the original function from the addEventListener hook
// store a reference so we can return the original function from the
// addEventListener hook
onClose._listener = listener;
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
// 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
// store a reference so we can return the original function from the
// addEventListener hook
onOpen._listener = listener;

@@ -410,3 +450,3 @@ this.on(method, onOpen);

}
}
};

@@ -419,5 +459,5 @@ module.exports = WebSocket;

* @see http://www.w3.org/TR/html5/comms.html
* @constructor
* @api private
*/
function MessageEvent(dataArg, typeArg, target) {

@@ -433,7 +473,7 @@ this.data = dataArg;

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

@@ -448,5 +488,5 @@ this.reason = reason;

* @see http://www.w3.org/TR/html5/comms.html
* @constructor
* @api private
*/
function OpenEvent(target) {

@@ -460,3 +500,2 @@ this.target = target;

*/
function initAsServerClient(req, socket, upgradeHead, options) {

@@ -471,3 +510,3 @@ options = new Options({

this.protocolVersion = options.value.protocolVersion;
this.supports.binary = (this.protocolVersion != 'hixie-76');
this.supports.binary = (this.protocolVersion !== 'hixie-76');
this.upgradeReq = req;

@@ -478,4 +517,7 @@ this.readyState = WebSocket.CONNECTING;

// establish connection
if (options.value.protocolVersion == 'hixie-76') establishConnection.call(this, ReceiverHixie, SenderHixie, socket, upgradeHead);
else establishConnection.call(this, Receiver, Sender, socket, upgradeHead);
if (options.value.protocolVersion === 'hixie-76') {
establishConnection.call(this, ReceiverHixie, SenderHixie, socket, upgradeHead);
} else {
establishConnection.call(this, Receiver, Sender, socket, upgradeHead);
}
}

@@ -501,7 +543,8 @@

}).merge(options);
if (options.value.protocolVersion != 8 && options.value.protocolVersion != 13) {
if (options.value.protocolVersion !== 8 && options.value.protocolVersion !== 13) {
throw new Error('unsupported protocol version');
}
// verify url and establish http class
// verify URL and establish http class
var serverUrl = url.parse(address);

@@ -519,3 +562,3 @@ var isUnixSocket = serverUrl.protocol === 'ws+unix:';

this.protocolVersion = options.value.protocolVersion;
this.supports.binary = (this.protocolVersion != 'hixie-76');
this.supports.binary = (this.protocolVersion !== 'hixie-76');

@@ -531,5 +574,6 @@ // begin handshake

var headerHost = serverUrl.hostname;
// Append port number to Host and Origin header, only if specified in the url and non-default
if(serverUrl.port) {
if((isSecure && (port != 443)) || (!isSecure && (port != 80))){
// Append port number to Host and Origin header, only if specified in the url
// and non-default
if (serverUrl.port) {
if ((isSecure && (port !== 443)) || (!isSecure && (port !== 80))){
headerHost = headerHost + ':' + port;

@@ -554,3 +598,3 @@ }

if (auth) {
requestOptions.headers['Authorization'] = 'Basic ' + new Buffer(auth).toString('base64');
requestOptions.headers.Authorization = 'Basic ' + new Buffer(auth).toString('base64');
}

@@ -563,3 +607,3 @@

if (options.value.host) {
requestOptions.headers['Host'] = options.value.host;
requestOptions.headers.Host = options.value.host;
}

@@ -608,3 +652,3 @@

if (options.value.protocolVersion < 13) requestOptions.headers['Sec-WebSocket-Origin'] = options.value.origin;
else requestOptions.headers['Origin'] = options.value.origin;
else requestOptions.headers.Origin = options.value.origin;
}

@@ -615,3 +659,3 @@

req.on('error', function(error) {
req.on('error', function onerror(error) {
self.emit('error', error);

@@ -621,13 +665,16 @@ cleanupWebsocketResources.call(this, error);

req.once('response', function(res) {
req.once('response', function response(res) {
var error;
if (!self.emit('unexpected-response', req, res)) {
var error = new Error('unexpected server response (' + res.statusCode + ')');
error = new Error('unexpected server response (' + res.statusCode + ')');
req.abort();
self.emit('error', error);
}
cleanupWebsocketResources.call(this, error);
});
req.once('upgrade', function(res, socket, upgradeHead) {
if (self.readyState == WebSocket.CLOSED) {
req.once('upgrade', function upgrade(res, socket, upgradeHead) {
if (self.readyState === WebSocket.CLOSED) {
// client closed before server accepted connection

@@ -639,4 +686,5 @@ self.emit('close');

}
var serverKey = res.headers['sec-websocket-accept'];
if (typeof serverKey == 'undefined' || serverKey !== expectedServerKey) {
if (typeof serverKey === 'undefined' || serverKey !== expectedServerKey) {
self.emit('error', 'invalid server key');

@@ -651,16 +699,18 @@ self.removeAllListeners();

var protError = null;
if (!options.value.protocol && serverProt) {
protError = 'server sent a subprotocol even though none requested';
protError = 'server sent a subprotocol even though none requested';
} else if (options.value.protocol && !serverProt) {
protError = 'server sent no subprotocol even though requested';
protError = 'server sent no subprotocol even though requested';
} else if (serverProt && protList.indexOf(serverProt) === -1) {
protError = 'server responded with an invalid protocol';
protError = 'server responded with an invalid protocol';
}
if (protError) {
self.emit('error', protError);
self.removeAllListeners();
socket.end();
return;
self.emit('error', protError);
self.removeAllListeners();
socket.end();
return;
} else if (serverProt) {
self.protocol = serverProt;
self.protocol = serverProt;
}

@@ -681,3 +731,5 @@

function establishConnection(ReceiverClass, SenderClass, socket, upgradeHead) {
var ultron = this._ultron = new Ultron(socket);
this._socket = socket;
socket.setTimeout(0);

@@ -689,9 +741,10 @@ socket.setNoDelay(true);

// socket cleanup handlers
socket.on('end', cleanupWebsocketResources.bind(this));
socket.on('close', cleanupWebsocketResources.bind(this));
socket.on('error', cleanupWebsocketResources.bind(this));
ultron.on('end', cleanupWebsocketResources.bind(this));
ultron.on('close', cleanupWebsocketResources.bind(this));
ultron.on('error', cleanupWebsocketResources.bind(this));
// ensure that the upgradeHead is added to the receiver
function firstHandler(data) {
if (self.readyState != WebSocket.OPEN) return;
if (self.readyState !== WebSocket.OPEN) return;
if (upgradeHead && upgradeHead.length > 0) {

@@ -703,3 +756,5 @@ self.bytesReceived += upgradeHead.length;

}
dataHandler = realHandler;
if (data) {

@@ -710,2 +765,3 @@ self.bytesReceived += data.length;

}
// subsequent packets are pushed straight to the receiver

@@ -716,3 +772,5 @@ function realHandler(data) {

}
var dataHandler = firstHandler;
// if data was passed along with the http upgrade,

@@ -726,26 +784,39 @@ // this will schedule a push of that on to the receiver.

// receiver event handlers
self._receiver.ontext = function (data, flags) {
self._receiver.ontext = function ontext(data, flags) {
flags = flags || {};
self.emit('message', data, flags);
};
self._receiver.onbinary = function (data, flags) {
self._receiver.onbinary = function onbinary(data, flags) {
flags = flags || {};
flags.binary = true;
self.emit('message', data, flags);
};
self._receiver.onping = function(data, flags) {
self._receiver.onping = function onping(data, flags) {
flags = flags || {};
self.pong(data, {mask: !self._isServer, binary: flags.binary === true}, true);
self.pong(data, {
mask: !self._isServer,
binary: flags.binary === true
}, true);
self.emit('ping', data, flags);
};
self._receiver.onpong = function(data, flags) {
self.emit('pong', data, flags);
self._receiver.onpong = function onpong(data, flags) {
self.emit('pong', data, flags || {});
};
self._receiver.onclose = function(code, data, flags) {
self._receiver.onclose = function onclose(code, data, flags) {
flags = flags || {};
self.close(code, data);
};
self._receiver.onerror = function(reason, errorCode) {
self._receiver.onerror = function onerror(reason, errorCode) {
// close the connection when the receiver reports a HyBi error code
self.close(typeof errorCode != 'undefined' ? errorCode : 1002, '');
self.close(typeof errorCode !== 'undefined' ? errorCode : 1002, '');
self.emit('error', reason, errorCode);

@@ -756,10 +827,11 @@ };

this._sender = new SenderClass(socket);
this._sender.on('error', function(error) {
this._sender.on('error', function onerror(error) {
self.close(1002, '');
self.emit('error', error);
});
this.readyState = WebSocket.OPEN;
this.emit('open');
socket.on('data', dataHandler);
ultron.on('data', dataHandler);
}

@@ -773,3 +845,4 @@

var queue = instance._queue;
if (typeof queue == 'undefined') return;
if (typeof queue === 'undefined') return;
delete instance._queue;

@@ -782,5 +855,5 @@ for (var i = 0, l = queue.length; i < l; ++i) {

function sendStream(instance, stream, options, cb) {
stream.on('data', function(data) {
if (instance.readyState != WebSocket.OPEN) {
if (typeof cb == 'function') cb(new Error('not opened'));
stream.on('data', function incoming(data) {
if (instance.readyState !== WebSocket.OPEN) {
if (typeof cb === 'function') cb(new Error('not opened'));
else {

@@ -792,8 +865,10 @@ delete instance._queue;

}
options.fin = false;
instance._sender.send(data, options);
});
stream.on('end', function() {
if (instance.readyState != WebSocket.OPEN) {
if (typeof cb == 'function') cb(new Error('not opened'));
stream.on('end', function end() {
if (instance.readyState !== WebSocket.OPEN) {
if (typeof cb === 'function') cb(new Error('not opened'));
else {

@@ -805,5 +880,7 @@ delete instance._queue;

}
options.fin = true;
instance._sender.send(null, options);
if (typeof cb == 'function') cb(null);
if (typeof cb === 'function') cb(null);
});

@@ -813,4 +890,5 @@ }

function cleanupWebsocketResources(error) {
if (this.readyState == WebSocket.CLOSED) return;
var emitClose = this.readyState != WebSocket.CONNECTING;
if (this.readyState === WebSocket.CLOSED) return;
var emitClose = this.readyState !== WebSocket.CONNECTING;
this.readyState = WebSocket.CLOSED;

@@ -820,18 +898,23 @@

this._closeTimer = null;
if (emitClose) this.emit('close', this._closeCode || 1000, this._closeMessage || '');
if (emitClose) {
this.emit('close', this._closeCode || 1000, this._closeMessage || '');
}
if (this._socket) {
this._socket.removeAllListeners();
// catch all socket error after removing all standard handlers
var socket = this._socket;
this._socket.on('error', function() {
try { socket.destroy(); } catch (e) {}
if (this._ultron) this._ultron.destroy();
this._socket.on('error', function onerror() {
try { this.destroy(); }
catch (e) {}
});
try {
if (!error) this._socket.end();
else this._socket.destroy();
}
catch (e) { /* Ignore termination errors */ }
} catch (e) { /* Ignore termination errors */ }
this._socket = null;
this._ultron = null;
}
if (this._sender) {

@@ -841,2 +924,3 @@ this._sender.removeAllListeners();

}
if (this._receiver) {

@@ -846,5 +930,6 @@ this._receiver.cleanup();

}
this.removeAllListeners();
this.on('error', function() {}); // catch all errors after this
this.on('error', function onerror() {}); // catch all errors after this
delete this._queue;
}

@@ -21,2 +21,4 @@ /*!

function WebSocketServer(options, callback) {
events.EventEmitter.call(this);
options = new Options({

@@ -250,3 +252,3 @@ host: '0.0.0.0',

callbackCalled = true;
if (!result) abortConnection(socket, 404, 'Unauthorized')
if (!result) abortConnection(socket, 401, 'Unauthorized');
else completeHybiUpgrade2(protocol);

@@ -253,0 +255,0 @@ });

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

"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.32",
"version": "0.5.0",
"license": "MIT",
"keywords": [

@@ -20,5 +21,2 @@ "Hixie",

},
"bin": {
"wscat": "./bin/wscat"
},
"scripts": {

@@ -28,17 +26,14 @@ "test": "make test",

},
"engines": {
"node": ">=0.4.0"
},
"dependencies": {
"commander": "~2.1.0",
"nan": "~1.0.0",
"tinycolor": "0.x",
"options": ">=0.0.5"
"nan": "1.4.x",
"options": ">=0.0.5",
"ultron": "1.0.x"
},
"devDependencies": {
"mocha": "1.12.0",
"should": "1.2.x",
"expect.js": "0.2.x",
"ansi": "0.3.x",
"benchmark": "0.3.x",
"ansi": "latest"
"expect.js": "0.3.x",
"mocha": "2.0.x",
"should": "4.3.x",
"tinycolor": "0.0.x"
},

@@ -45,0 +40,0 @@ "browser": "./lib/browser.js",

@@ -1,40 +0,42 @@

[![Build Status](https://secure.travis-ci.org/einaros/ws.png)](http://travis-ci.org/einaros/ws)
# ws: a node.js websocket library
# ws: a node.js websocket library #
[![Build Status](https://travis-ci.org/einaros/ws.svg?branch=master)](https://travis-ci.org/einaros/ws)
`ws` is a simple to use websocket implementation, up-to-date against RFC-6455, and [probably the fastest WebSocket library for node.js](http://web.archive.org/web/20130314230536/http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs).
`ws` is a simple to use WebSocket implementation, up-to-date against RFC-6455,
and [probably the fastest WebSocket library for node.js][archive].
Passes the quite extensive Autobahn test suite. See http://einaros.github.com/ws for the full reports.
Passes the quite extensive Autobahn test suite. See http://einaros.github.com/ws
for the full reports.
Comes with a command line utility, `wscat`, which can either act as a server (--listen), or client (--connect); Use it to debug simple websocket services.
## Protocol support
## Protocol support ##
* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera.
Added to ws version 0.4.2, but server only. Can be disabled by setting the
`disableHixie` option to true.)
* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)
* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`)
* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera. Added to ws version 0.4.2, but server only. Can be disabled by setting the `disableHixie` option to true.)
* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`, or argument `-p 8` for wscat)
* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`, or argument `-p 13` for wscat)
### Installing
_See the echo.websocket.org example below for how to use the `protocolVersion` option._
```
npm install ---save ws
```
## Usage ##
### Sending and receiving text data
### Installing ###
`npm install ws`
### Sending and receiving text data ###
```js
var WebSocket = require('ws');
var ws = new WebSocket('ws://www.host.com/path');
ws.on('open', function() {
ws.send('something');
ws.on('open', function open() {
ws.send('something');
});
ws.on('message', function(data, flags) {
// flags.binary will be set if a binary data is received
// flags.masked will be set if the data was masked
// flags.binary will be set if a binary data is received.
// flags.masked will be set if the data was masked.
});
```
### Sending binary data ###
### Sending binary data

@@ -44,37 +46,47 @@ ```js

var ws = new WebSocket('ws://www.host.com/path');
ws.on('open', function() {
var array = new Float32Array(5);
for (var i = 0; i < array.length; ++i) array[i] = i / 2;
ws.send(array, {binary: true, mask: true});
ws.on('open', function open() {
var array = new Float32Array(5);
for (var i = 0; i < array.length; ++i) {
array[i] = i / 2;
}
ws.send(array, { binary: true, mask: true });
});
```
Setting `mask`, as done for the send options above, will cause the data to be masked according to the websocket protocol. The same option applies for text data.
Setting `mask`, as done for the send options above, will cause the data to be
masked according to the WebSocket protocol. The same option applies for text
data.
### Server example ###
### Server example
```js
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 8080});
wss.on('connection', function(ws) {
ws.on('message', function(message) {
console.log('received: %s', message);
});
ws.send('something');
, wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
```
### Server sending broadcast data ###
### Server sending broadcast data
```js
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 8080});
wss.broadcast = function(data) {
for(var i in this.clients)
this.clients[i].send(data);
, wss = new WebSocketServer({ port: 8080 });
wss.broadcast = function broadcast(data) {
for(var i in this.clients) {
this.clients[i].send(data);
}
};
```
### Error handling best practices ###
### Error handling best practices

@@ -85,67 +97,65 @@ ```js

// Errors (both immediate and async write errors) can be detected in an optional callback.
// The callback is also the only way of being notified that data has actually been sent.
ws.send('something', function(error) {
// if error is null, the send has been completed,
// otherwise the error object will indicate what failed.
// Errors (both immediate and async write errors) can be detected in an optional
// callback. The callback is also the only way of being notified that data has
// actually been sent.
ws.send('something', function ack(error) {
// if error is null, the send has been completed,
// otherwise the error object will indicate what failed.
});
// Immediate errors can also be handled with try/catch-blocks, but **note**
// that since sends are inherently asynchronous, socket write failures will *not*
// be captured when this technique is used.
try {
ws.send('something');
}
catch (e) {
// handle error
}
// Immediate errors can also be handled with try/catch-blocks, but **note** that
// since sends are inherently asynchronous, socket write failures will *not* be
// captured when this technique is used.
try { ws.send('something'); }
catch (e) { /* handle error */ }
```
### echo.websocket.org demo ###
### echo.websocket.org demo
```js
var WebSocket = require('ws');
var ws = new WebSocket('ws://echo.websocket.org/', {protocolVersion: 8, origin: 'http://websocket.org'});
ws.on('open', function() {
console.log('connected');
ws.send(Date.now().toString(), {mask: true});
var ws = new WebSocket('ws://echo.websocket.org/', {
protocolVersion: 8,
origin: 'http://websocket.org'
});
ws.on('close', function() {
console.log('disconnected');
ws.on('open', function open() {
console.log('connected');
ws.send(Date.now().toString(), {mask: true});
});
ws.on('message', function(data, flags) {
console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags);
setTimeout(function() {
ws.send(Date.now().toString(), {mask: true});
}, 500);
ws.on('close', function close() {
console.log('disconnected');
});
```
### wscat against echo.websocket.org ###
ws.on('message', function message(data, flags) {
console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags);
$ npm install -g ws
$ wscat -c ws://echo.websocket.org
connected (press CTRL+C to quit)
> hi there
< hi there
> are you a happy parrot?
< are you a happy parrot?
setTimeout(function timeout() {
ws.send(Date.now().toString(), {mask: true});
}, 500);
});
```
### Other examples ###
### Other examples
For a full example with a browser client communicating with a ws server, see the examples folder.
For a full example with a browser client communicating with a ws server, see the
examples folder.
Note that the usage together with Express 3.0 is quite different from Express 2.x. The difference is expressed in the two different serverstats-examples.
Note that the usage together with Express 3.0 is quite different from Express
2.x. The difference is expressed in the two different serverstats-examples.
Otherwise, see the test cases.
### Running the tests ###
### Running the tests
`make test`
```
make test
```
## API Docs ##
## API Docs
See the doc/ directory for Node.js-like docs for the ws classes.
## License ##
## License

@@ -174,1 +184,3 @@ (The MIT License)

SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[archive]: http://web.archive.org/web/20130314230536/http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs

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
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc