Comparing version
@@ -0,1 +1,8 @@ | ||
v0.4.12 - Mar 30th 2012 | ||
===================== | ||
* various memory leak / possible memory leak cleanups [einaros] | ||
* api documentation [nicokaiser] | ||
* add option to disable client tracking [nicokaiser] | ||
v0.4.11 - Mar 24th 2012 | ||
@@ -2,0 +9,0 @@ ===================== |
@@ -8,5 +8,5 @@ /*! | ||
/** | ||
* Windows Compatibility | ||
* Windows Compatibility | ||
*/ | ||
module.exports.BufferUtil = { | ||
@@ -25,8 +25,10 @@ merge: function(mergedBuffer, buffers) { | ||
for (; i < length - 3; i += 4) { | ||
output.writeUInt32LE(maskNum ^ source.readUInt32LE(i, true), offset + i, true); | ||
var num = maskNum ^ source.readUInt32LE(i, true); | ||
if (num < 0) num = 4294967296 + num; | ||
output.writeUInt32LE(num, offset + i, true); | ||
} | ||
switch (length % 4) { | ||
case 3: output[offset + i + 2] = source[i + 2] ^ mask[2]; | ||
case 2: output[offset + i + 1] = source[i + 1] ^ mask[1]; | ||
case 1: output[offset + i] = source[i] ^ mask[0]; | ||
case 3: output[offset + i + 2] = source[i + 2] ^ mask[2]; | ||
case 2: output[offset + i + 1] = source[i + 1] ^ mask[1]; | ||
case 1: output[offset + i] = source[i] ^ mask[0]; | ||
case 0:; | ||
@@ -37,6 +39,16 @@ } | ||
var maskNum = mask.readUInt32LE(0, true); | ||
for (var i = 0, ll = data.length; i < ll; i += 4) { | ||
data.writeUInt32LE(maskNum ^ data.readUInt32LE(i, true), i, true); | ||
var length = data.length; | ||
var i = 0; | ||
for (; i < length - 3; i += 4) { | ||
var num = maskNum ^ data.readUInt32LE(i, true); | ||
if (num < 0) num = 4294967296 + num; | ||
data.writeUInt32LE(num, i, true); | ||
} | ||
switch (length % 4) { | ||
case 3: data[i + 2] = data[i + 2] ^ mask[2]; | ||
case 2: data[i + 1] = data[i + 1] ^ mask[1]; | ||
case 1: data[i] = data[i] ^ mask[0]; | ||
case 0:; | ||
} | ||
} | ||
} | ||
} |
@@ -27,2 +27,3 @@ /*! | ||
this.spanLength = 0; | ||
this.dead = false; | ||
} | ||
@@ -71,2 +72,14 @@ | ||
/** | ||
* Releases all resources used by the receiver. | ||
* | ||
* @api public | ||
*/ | ||
Receiver.prototype.cleanup = function() { | ||
this.dead = true; | ||
this.state = EMPTY; | ||
this.buffers = []; | ||
} | ||
/** | ||
* Process buffered data. | ||
@@ -115,2 +128,3 @@ * | ||
Receiver.prototype.reset = function (reason) { | ||
if (this.dead) return; | ||
this.state = EMPTY; | ||
@@ -117,0 +131,0 @@ this.buffers = []; |
@@ -60,2 +60,3 @@ /*! | ||
this.expectHeader(2, this.processPacket); | ||
this.dead = false; | ||
}; | ||
@@ -88,3 +89,3 @@ | ||
if (toRead < dataLength) { | ||
this.overflow.push(data.slice(toRead, dataLength)); | ||
this.overflow.push(data.slice(toRead)); | ||
} | ||
@@ -100,2 +101,20 @@ while (this.expectBuffer && this.expectOffset == this.expectBuffer.length) { | ||
/** | ||
* Releases all resources used by the receiver. | ||
* | ||
* @api public | ||
*/ | ||
Receiver.prototype.cleanup = function() { | ||
this.dead = true; | ||
this.overflow = null; | ||
this.headerBuffer = null; | ||
this.expectBuffer = null; | ||
this.expectHandler = null; | ||
this.unfragmentedBufferPool = null; | ||
this.fragmentedBufferPool = null; | ||
this.state = null; | ||
this.currentMessage = null; | ||
} | ||
/** | ||
* Waits for a certain amount of header bytes to be available, then fires a callback. | ||
@@ -111,3 +130,3 @@ * | ||
} | ||
this.expectBuffer = this.headerBuffer.slice(this.expectOffset, length); | ||
this.expectBuffer = this.headerBuffer.slice(this.expectOffset, this.expectOffset + length); | ||
this.expectHandler = handler; | ||
@@ -230,2 +249,3 @@ var toRead = length; | ||
Receiver.prototype.reset = function() { | ||
if (this.dead) return; | ||
this.state = { | ||
@@ -283,3 +303,3 @@ activeFragmentedOperation: null, | ||
return this; | ||
}; | ||
} | ||
@@ -286,0 +306,0 @@ /** |
@@ -29,2 +29,8 @@ /*! | ||
/** | ||
* Node version 0.4 and 0.6 compatibility | ||
*/ | ||
var isNodeV4 = /^v0\.4/.test(process.version); | ||
/** | ||
* WebSocket implementation | ||
@@ -269,4 +275,4 @@ */ | ||
if (this._socket) { | ||
this._socket.end(); | ||
this._socket = null; | ||
try { this._socket.end(); } | ||
catch (e) { this._socket.destroy(); } | ||
} | ||
@@ -424,5 +430,4 @@ else if (this.readyState == WebSocket.CONNECTING) { | ||
// node<=v0.4.x compatibility | ||
var isNodeV4 = false; | ||
var agent; | ||
if (/^v0\.4/.test(process.version)) { | ||
if (isNodeV4) { | ||
isNodeV4 = true; | ||
@@ -463,7 +468,9 @@ agent = new httpObj.Agent({ | ||
}); | ||
(isNodeV4 ? agent : req).on('upgrade', function(res, socket, upgradeHead) { | ||
(isNodeV4 ? agent : req).once('upgrade', function(res, socket, upgradeHead) { | ||
if (self.readyState == WebSocket.CLOSED) { | ||
// client closed before server accepted connection | ||
self.emit('close'); | ||
socket.end(); | ||
removeAllListeners(self); | ||
try { socket.end(); } | ||
catch (e) { socket.destroy(); } | ||
return; | ||
@@ -474,3 +481,5 @@ } | ||
self.emit('error', 'invalid server key'); | ||
socket.end(); | ||
removeAllListeners(self); | ||
try { socket.end(); } | ||
catch (e) { socket.destroy(); } | ||
return; | ||
@@ -480,2 +489,7 @@ } | ||
establishConnection.call(self, Receiver, Sender, socket, upgradeHead); | ||
// cleanup | ||
removeAllListeners(isNodeV4 ? agent : req); | ||
req = null; | ||
agent = null; | ||
}); | ||
@@ -492,2 +506,3 @@ | ||
var self = this; | ||
var receiver = new ReceiverClass(); | ||
@@ -498,12 +513,20 @@ // socket cleanup handlers | ||
self._readyState = WebSocket.CLOSED; | ||
if (self._socket) { | ||
self._socket.removeAllListeners(); | ||
self._socket.end(); | ||
if (socket) { | ||
removeAllListeners(socket); | ||
try { socket.end(); } | ||
catch (e) { socket.destroy(); } | ||
self._socket = null; | ||
socket = null; | ||
} | ||
if (self._sender) { | ||
self._sender.removeAllListeners(); | ||
self._sender = null; | ||
removeAllListeners(self._sender); | ||
delete self._sender; | ||
} | ||
if (receiver) { | ||
removeAllListeners(receiver); | ||
receiver.cleanup(); | ||
receiver = null; | ||
} | ||
self.emit('close', self._closeCode || 1000, self._closeMessage || ''); | ||
removeAllListeners(self); | ||
} | ||
@@ -513,3 +536,2 @@ socket.on('end', closeSocket); | ||
var receiver = new ReceiverClass(); | ||
// ensure that the upgradeHead is added to the receiver | ||
@@ -574,3 +596,3 @@ function firstHandler(data) { | ||
// finalize the client | ||
Object.defineProperty(this, '_sender', { value: new SenderClass(socket) }); | ||
Object.defineProperty(this, '_sender', { value: new SenderClass(socket), configurable: true }); | ||
this._sender.on('error', function(error) { | ||
@@ -617,1 +639,10 @@ self.emit('error', error); | ||
} | ||
function removeAllListeners(instance) { | ||
if (isNodeV4) { | ||
// node v4 doesn't *actually* remove all listeners globally, | ||
// so we do that instead | ||
instance._events = {}; | ||
} | ||
else instance.removeAllListeners(); | ||
} |
@@ -29,3 +29,4 @@ /*! | ||
noServer: false, | ||
disableHixie: false | ||
disableHixie: false, | ||
clientTracking: true | ||
}).merge(options); | ||
@@ -232,10 +233,13 @@ if (!options.value.port && !options.value.server && !options.value.noServer) { | ||
}); | ||
this._clients.push(client); | ||
var self = this; | ||
client.on('close', function() { | ||
var index = self._clients.indexOf(client); | ||
if (index != -1) { | ||
self._clients.splice(index, 1); | ||
} | ||
}); | ||
if (this.options.clientTracking) { | ||
this._clients.push(client); | ||
var self = this; | ||
client.on('close', function() { | ||
var index = self._clients.indexOf(client); | ||
if (index != -1) { | ||
self._clients.splice(index, 1); | ||
} | ||
}); | ||
} | ||
cb(client); | ||
@@ -307,9 +311,11 @@ } | ||
}); | ||
self._clients.push(client); | ||
client.on('close', function() { | ||
var index = self._clients.indexOf(client); | ||
if (index != -1) { | ||
self._clients.splice(index, 1); | ||
} | ||
}); | ||
if (this.options.clientTracking) { | ||
self._clients.push(client); | ||
client.on('close', function() { | ||
var index = self._clients.indexOf(client); | ||
if (index != -1) { | ||
self._clients.splice(index, 1); | ||
} | ||
}); | ||
} | ||
cb(client); | ||
@@ -344,3 +350,3 @@ } | ||
socket.on('data', handler); | ||
} | ||
} | ||
} | ||
@@ -347,0 +353,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.11", | ||
"version": "0.4.12", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "type": "git", |
@@ -108,18 +108,5 @@ [](http://travis-ci.org/einaros/ws) | ||
_Note: This api documentation is currently incomplete. For a better understanding of the api, see the test set._ | ||
See the doc/ directory for Node.js-like docs for the ws classes. | ||
### WebSocket | ||
`supports.binary` | ||
> Returns true or false based on whether the underlying protocol (hixie, hybi, etc) has binary support. | ||
Example: | ||
```js | ||
var wss = new WebSocketServer({port: 8080}); | ||
wss.on('connection', function(client) { | ||
if (client.supports.binary) ... | ||
}); | ||
``` | ||
## Todos ## | ||
@@ -126,0 +113,0 @@ |
@@ -197,2 +197,14 @@ var http = require('http') | ||
it('can be disabled', function(done) { | ||
var wss = new WebSocketServer({port: ++port, clientTracking: false}, function() { | ||
wss.clients.length.should.eql(0); | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
}); | ||
wss.on('connection', function(client) { | ||
wss.clients.length.should.eql(0); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
it('is updated when client terminates the connection', function(done) { | ||
@@ -199,0 +211,0 @@ var ws; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
221324
3.05%56
1.82%5675
1.5%142
-8.39%