Comparing version 0.4.11 to 0.4.12
@@ -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 @@ [![Build Status](https://secure.travis-ci.org/einaros/ws.png)](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
221324
56
5675
142