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

websocket

Package Overview
Dependencies
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

websocket - npm Package Compare versions

Comparing version 0.0.20 to 1.0.0

2

lib/websocket.js

@@ -8,3 +8,3 @@ module.exports = {

"connection" : require('./WebSocketConnection'),
"version" : "0.0.20"
"version" : "1.0.0"
};

@@ -33,2 +33,4 @@ /************************************************************************

this.remoteAddress = socket.remoteAddress;
this.closeReasonCode = -1;
this.closeDescription = null;

@@ -84,3 +86,17 @@ // We have to mask outgoing packets if we're acting as a WebSocket client.

if (this.config.keepalive) {
this._pingIntervalID = setInterval(this.ping.bind(this), this.config.keepaliveInterval);
if (typeof(this.config.keepaliveInterval) !== 'number') {
throw new Error("keepaliveInterval must be specified and numeric " +
"if keepalive is true.");
}
this._keepaliveTimerHandler = this.handleKeepaliveTimer.bind(this);
this.setKeepaliveTimer();
if (this.config.dropConnectionOnKeepaliveTimeout) {
if (typeof(this.config.keepaliveGracePeriod) !== 'number') {
throw new Error("keepaliveGracePeriod must be specified and " +
"numeric if dropConnectionOnKeepaliveTimeout " +
"is true.")
}
this._gracePeriodTimerHandler = this.handleGracePeriodTimer.bind(this);
}
}

@@ -93,9 +109,73 @@ };

WebSocketConnection.CLOSE_REASON_UNPROCESSABLE_INPUT = 1003;
WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_LARGE = 1004;
WebSocketConnection.CLOSE_REASON_NOT_PROVIDED = 1005; // Reserved value, not to be used
WebSocketConnection.CLOSE_REASON_ABNORMAL = 1006; // Reserved value, not to be used
WebSocketConnection.CLOSE_REASON_RESERVED = 1004; // Reserved value. Undefined meaning.
WebSocketConnection.CLOSE_REASON_NOT_PROVIDED = 1005; // Not to be used on the wire
WebSocketConnection.CLOSE_REASON_ABNORMAL = 1006; // Not to be used on the wire
WebSocketConnection.CLOSE_REASON_INVALID_DATA = 1007;
WebSocketConnection.CLOSE_REASON_POLICY_VIOLATION = 1008;
WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_BIG = 1009;
WebSocketConnection.CLOSE_REASON_EXTENSION_REQUIRED = 1010;
WebSocketConnection.CLOSE_DESCRIPTIONS = {
1000: "Normal connection closure",
1001: "Remote peer is going away",
1002: "Protocol error",
1003: "Unprocessable input",
1004: "Reserved",
1005: "Reason not provided",
1006: "Abnormal closure, no further detail available",
1007: "Invalid data received",
1008: "Policy violation",
1009: "Message too big",
1010: "Extension requested by client is required"
};
util.inherits(WebSocketConnection, EventEmitter);
// set or reset the keepalive timer when data is received.
WebSocketConnection.prototype.setKeepaliveTimer = function() {
if (!this.config.keepalive) { return; }
if (this._keepaliveTimeoutID) {
clearTimeout(this._keepaliveTimeoutID);
}
if (this._gracePeriodTimeoutID) {
clearTimeout(this._gracePeriodTimeoutID);
}
this._keepaliveTimeoutID = setTimeout(this._keepaliveTimerHandler, this.config.keepaliveInterval);
};
// No data has been received within config.keepaliveTimeout ms.
WebSocketConnection.prototype.handleKeepaliveTimer = function() {
this._keepaliveTimeoutID = null;
this.ping();
// If we are configured to drop connections if the client doesn't respond
// then set the grace period timer.
if (this.config.dropConnectionOnKeepaliveTimeout) {
this.setGracePeriodTimer();
}
else {
// Otherwise reset the keepalive timer to send the next ping.
this.setKeepaliveTimer();
}
};
WebSocketConnection.prototype.setGracePeriodTimer = function() {
if (this._gracePeriodTimeoutID) {
clearTimeout(this._gracePeriodTimeoutID);
}
this._gracePeriodTimeoutID = setTimeout(this._gracePeriodTimerHandler, this.config.keepaliveGracePeriod);
};
WebSocketConnection.prototype.handleGracePeriodTimer = function() {
// If this is called, the client has not responded and is assumed dead.
this._gracePeriodTimeoutID = null;
this.drop(WebSocketConnection.CLOSE_REASON_ABNORMAL, "Peer not responding.", true);
};
WebSocketConnection.prototype.handleSocketData = function(data) {
// Reset the keepalive timer when receiving data of any kind.
this.setKeepaliveTimer();
// Add received data to our bufferList, which efficiently holds received
// data chunks in a linked list of Buffer objects.
this.bufferList.write(data);

@@ -115,3 +195,3 @@

else if (this.currentFrame.frameTooLarge) {
this.drop(WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_LARGE, this.currentFrame.dropReason);
this.drop(WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_BIG, this.currentFrame.dropReason);
return;

@@ -155,11 +235,17 @@ }

this.connected = false;
this.state = "closed";
this.state = STATE_CLOSED;
// If closeReasonCode is still set to -1 at this point then we must
// not have received a close frame!!
if (this.closeReasonCode === -1) {
this.closeReasonCode = WebSocketConnection.CLOSE_REASON_ABNORMAL;
this.closeDescription = "Connection dropped by remote peer.";
}
if (!this.closeEventEmitted) {
this.closeEventEmitted = true;
// console.log((new Date()) + " - Emitting WebSocketConnection close event");
this.emit('close', this);
this.emit('close', this.closeReasonCode, this.closeDescription);
}
this.clearCloseTimer();
if (this.config.keepalive) {
clearInterval(this._pingIntervalID);
if (this._keepaliveTimeoutID) {
clearTimeout(this._keepaliveTimeoutID);
}

@@ -176,5 +262,7 @@ };

if (this.connected) {
this.closeReasonCode = WebSocketConnection.CLOSE_REASON_NORMAL;
this.closeDescription = WebSocketConnection.CLOSE_DESCRIPTIONS[this.closeReasonCode];
this.setCloseTimer();
this.sendCloseFrame();
this.state = "closing";
this.state = STATE_CLOSING;
this.connected = false;

@@ -184,17 +272,30 @@ }

WebSocketConnection.prototype.drop = function(closeReason, reasonText) {
if (typeof(closeReason) !== 'number') {
closeReason = WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR;
WebSocketConnection.prototype.drop = function(reasonCode, description, skipCloseFrame) {
if (typeof(reasonCode) !== 'number') {
reasonCode = WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR;
}
var logText = "WebSocket: Dropping Connection. Code: " + closeReason.toString(10);
if (reasonText) {
logText += (" - " + reasonText);
var logText = "WebSocket: Dropping Connection. Code: " + reasonCode.toString(10);
if (typeof(description) !== 'string') {
// If no description is provided, try to look one up based on the
// specified reasonCode.
description = WebSocketConnection.CLOSE_DESCRIPTIONS[reasonCode];
}
if (description) {
logText += (" - " + description);
}
console.error((new Date()) + " " + logText);
this.closeReasonCode = reasonCode;
this.closeDescription = description;
this.outgoingFrameQueue = [];
this.frameQueue = []
this.fragmentationSize = 0;
this.sendCloseFrame(closeReason, reasonText, true);
if (!skipCloseFrame) {
this.sendCloseFrame(reasonCode, description, true);
}
this.connected = false;
this.state = "closed";
this.state = STATE_CLOSED;
this.closeEventEmitted = true;
this.emit('close', reasonCode, description);
this.socket.destroy();

@@ -285,3 +386,3 @@ };

if (this.fragmentationSize > this.maxReceivedMessageSize) {
this.drop(WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR,
this.drop(WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_BIG,
"Maximum message size exceeded.");

@@ -341,3 +442,3 @@ return;

this.waitingForCloseResponse = false;
this.state = "closed";
this.state = STATE_CLOSED;
this.socket.end();

@@ -348,31 +449,13 @@ }

// Send back acknowledgement and then hang up.
this.state = "closing";
if (frame.closeStatus !== WebSocketConnection.CLOSE_REASON_NORMAL) {
var logCloseError;
switch(frame.closeStatus) {
case WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR:
logCloseError = "Remote peer closed connection: Protocol Error";
break;
case WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_LARGE:
logCloseError = "Remote peer closed connection: Received Message Too Large";
break;
case WebSocketConnection.CLOSE_REASON_UNPROCESSABLE_INPUT:
logCloseError = "Remote peer closed connection: Unprocessable Input";
break;
case WebSocketConnection.CLOSE_REASON_GOING_AWAY:
logCloseError = "Remote peer closed connection: Going Away";
break;
default:
logCloseError = "Remote peer closed connection: Status code " + frame.closeStatus.toString(10);
break;
}
if (frame.binaryPayload) {
logCloseError += (" - Description Provided: " + frame.binaryPayload.toString('utf8'));
}
// console.error((new Date()) + " " + logCloseError);
this.state = STATE_CLOSING;
this.closeReasonCode = frame.closeStatus;
if (frame.binaryPayload.length > 0) {
this.closeDescription = frame.binaryPayload.toString('utf8');
}
else {
// console.log((new Date()) + " - Remote peer " + this.remoteAddress + " requested disconnect");
this.closeDescription = WebSocketConnection.CLOSE_DESCRIPTIONS[this.closeReasonCode];
}
// console.log((new Date()) + " - Sending close frame in response and closing the socket.");
// console.log((new Date()) + " Remote peer " + this.remoteAddress +
// " requested disconnect, code: " + this.closeReasonCode + " - " + this.closeDescription +
// " - close frame payload length: " + frame.length);
this.sendCloseFrame(WebSocketConnection.CLOSE_REASON_NORMAL);

@@ -389,2 +472,14 @@ this.socket.end();

WebSocketConnection.prototype.send = function(data) {
if (Buffer.isBuffer(data)) {
this.sendBytes(data);
}
else if (typeof(data['toString']) === 'function') {
this.sendUTF(data);
}
else {
throw new Error("Data provided must either be a Node Buffer or implement toString()")
}
};
WebSocketConnection.prototype.sendUTF = function(data) {

@@ -407,9 +502,19 @@ var frame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);

WebSocketConnection.prototype.ping = function() {
WebSocketConnection.prototype.ping = function(data) {
var frame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
frame.opcode = 0x09; // WebSocketOpcode.PING
frame.fin = true;
if (data) {
if (!Buffer.isBuffer(data)) {
data = new Buffer(data.toString(), 'utf8')
}
if (data.length > 125) {
console.warn("WebSocket: Data for ping is longer than 125 bytes. Truncating.");
data = data.slice(0,124);
}
frame.binaryPayload = data;
}
this.sendFrame(frame);
};
// Pong frames have to echo back the contents of the data portion of the

@@ -420,2 +525,6 @@ // ping frame exactly, byte for byte.

frame.opcode = 0x0A; // WebSocketOpcode.PONG
if (Buffer.isBuffer(binaryPayload) && binaryPayload.length > 125) {
console.warn("WebSocket: Data for pong is longer than 125 bytes. Truncating.");
binaryPayload = binaryPayload.slice(0,124);
}
frame.binaryPayload = binaryPayload;

@@ -487,3 +596,3 @@ frame.fin = true;

WebSocketConnection.prototype.processOutgoingFrameQueue = function() {
if (this.outputPaused) { return; }
if (this.outputPaused || !this.connected) { return; }
if (this.outgoingFrameQueue.length > 0) {

@@ -495,3 +604,3 @@ var buffer = this.outgoingFrameQueue.pop();

catch(e) {
console.error("Error while writing to socket: " + e.toString());
console.warn("Error while writing to socket: " + e.toString());
return;

@@ -498,0 +607,0 @@ }

@@ -131,2 +131,6 @@ /************************************************************************

this.binaryPayload = new Buffer(0);
if (this.opcode === 0x08) { // WebSocketOpcode.CONNECTION_CLOSE
// The remote peer didn't include a close status
this.closeStatus = 1005; // WebSocketConnection.CLOSE_REASON_NOT_PROVIDED
}
this.parseState = COMPLETE;

@@ -143,4 +147,10 @@ return true;

if (this.opcode === 0x08) { // WebSocketOpcode.CONNECTION_CLOSE
this.closeStatus = ctio.ruint16(this.binaryPayload, 'big', 0);
this.binaryPayload = this.binaryPayload.slice(2);
if (this.length >= 2) {
this.closeStatus = ctio.ruint16(this.binaryPayload, 'big', 0);
this.binaryPayload = this.binaryPayload.slice(2);
}
else {
// The remote peer didn't include a close status
this.closeStatus = 1005; // WebSocketConnection.CLOSE_REASON_NOT_PROVIDED
}
}

@@ -147,0 +157,0 @@

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

requestAccepted: this.handleRequestAccepted.bind(this),
connectionClose: this.handleConnectionClose.bind(this)
};

@@ -58,8 +57,21 @@ this.connections = [];

// If true, the server will automatically send a ping to all
// clients every 'keepaliveInterval' milliseconds.
// clients every 'keepaliveInterval' milliseconds. The timer is
// reset on any received data from the client.
keepalive: true,
// The interval to send keepalive pings to connected clients.
// The interval to send keepalive pings to connected clients if the
// connection is idle. Any received data will reset the counter.
keepaliveInterval: 20000,
// If true, the server will consider any connection that has not
// received any data within the amount of time specified by
// 'keepaliveGracePeriod' after a keepalive ping has been sent.
// Ignored if keepalive is false.
dropConnectionOnKeepaliveTimeout: true,
// The amount of time to wait after sending a keepalive ping before
// closing the connection if the connected peer does not respond.
// Ignored if keepalive is false.
keepaliveGracePeriod: 10000,
// If true, fragmented messages will be automatically assembled

@@ -168,7 +180,11 @@ // and the full message will be emitted via a 'message' event.

WebSocketServer.prototype.handleRequestAccepted = function(connection) {
connection.once('close', this._handlers.connectionClose);
var self = this;
connection.once('close', function(closeReason, description) {
self.handleConnectionClose(connection, closeReason, description);
});
this.connections.push(connection);
this.emit('connect', connection);
};
WebSocketServer.prototype.handleConnectionClose = function(connection) {
WebSocketServer.prototype.handleConnectionClose = function(connection, closeReason, description) {
var index = this.connections.indexOf(connection);

@@ -178,5 +194,5 @@ if (index !== -1) {

}
this.emit('close', connection);
this.emit('close', connection, closeReason, description);
};
module.exports = WebSocketServer;

@@ -6,3 +6,3 @@ {

"author": "Brian McKelvey <brian@worlize.com>",
"version": "0.0.20",
"version": "1.0.0",
"repository": {

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

@@ -129,3 +129,3 @@ WebSocket Client & Server Implementation for Node

});
connection.on('close', function(connection) {
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + " Peer " + connection.remoteAddress + " disconnected.");

@@ -132,0 +132,0 @@ });

@@ -61,3 +61,4 @@ #!/usr/bin/env node

wsServer.on('connect', function(connection) {
console.log((new Date()) + " Connection accepted.");
console.log((new Date()) + " Connection accepted" +
" - Protocol Version " + connection.websocketVersion);
connection.on('message', function(message) {

@@ -73,5 +74,5 @@ if (message.type === 'utf8') {

});
connection.on('close', function(connection) {
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + " Peer " + connection.remoteAddress + " disconnected.");
});
});

@@ -63,3 +63,3 @@ #!/usr/bin/env node

var radius = Math.round(Math.random() * 30);
connection.sendUTF("c #" + color.toString(16) + " " + x + " " + y + " " + radius + ";");
connection.send("c #" + color.toString(16) + " " + x + " " + y + " " + radius + ";");
setTimeout(spamCircles, 10);

@@ -66,0 +66,0 @@ }

@@ -106,3 +106,3 @@ #!/usr/bin/env node

connection.sendUTF(historyString);
connection.send(historyString);
}

@@ -126,3 +126,3 @@

mirrorConnections.forEach(function (outputConnection) {
outputConnection.sendUTF(message.utf8Data);
outputConnection.send(message.utf8Data);
});

@@ -132,6 +132,6 @@ }

connection.on('close', function(connection) {
connection.on('close', function(closeReason, description) {
var index = mirrorConnections.indexOf(connection);
if (index !== -1) {
console.log((new Date()) + " lws-mirror-protocol peer " + connection.remoteAddress + " disconnected.");
console.log((new Date()) + " lws-mirror-protocol peer " + connection.remoteAddress + " disconnected, code: " + closeReason + ".");
mirrorConnections.splice(index, 1);

@@ -155,3 +155,3 @@ }

connection.timerInterval = setInterval(function() {
connection.sendUTF((number++).toString(10));
connection.send((number++).toString(10));
}, 50);

@@ -169,4 +169,4 @@ connection.on('close', function() {

});
connection.on('close', function(connection) {
console.log((new Date()) + " dumb-increment-protocol peer " + connection.remoteAddress + " disconnected");
connection.on('close', function(closeReason, description) {
console.log((new Date()) + " dumb-increment-protocol peer " + connection.remoteAddress + " disconnected, code: " + closeReason + ".");
});

@@ -173,0 +173,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