ws
Advanced tools
Comparing version 0.4.16 to 0.4.17
@@ -0,1 +1,9 @@ | ||
v0.4.17 - June 13th 2012 | ||
===================== | ||
* Improve error handling during connection handshaking [einaros] | ||
* Ensure that errors are caught also after connection teardown [nicokaiser] | ||
* Update 'mocha' version to 1.1.0. [einaros] | ||
* Stop showing 'undefined' for some error logs. [tricknotes] | ||
* Update 'should' version to 0.6.3 [tricknotes] | ||
v0.4.16 - June 1st 2012 | ||
@@ -2,0 +10,0 @@ ===================== |
@@ -596,2 +596,7 @@ /*! | ||
removeAllListeners(this._socket); | ||
// catch all socket error after removing all standard handlers | ||
var socket = this._socket; | ||
this._socket.on('error', function() { | ||
try { socket.destroy(); } catch (e) {} | ||
}); | ||
try { | ||
@@ -598,0 +603,0 @@ if (!error) this._socket.end(); |
@@ -18,3 +18,3 @@ /*! | ||
/** | ||
* WebSocket implementation | ||
* WebSocket Server implementation | ||
*/ | ||
@@ -154,2 +154,8 @@ | ||
function handleHybiUpgrade(req, socket, upgradeHead, cb) { | ||
// handle premature socket errors | ||
var errorHandler = function() { | ||
try { socket.destroy(); } catch (e) {} | ||
} | ||
socket.on('error', errorHandler); | ||
// verify key presence | ||
@@ -173,3 +179,56 @@ if (!req.headers['sec-websocket-key']) { | ||
var args = [req, socket, upgradeHead, version, cb]; | ||
// handler to call when the connection sequence completes | ||
var self = this; | ||
var completeHybiUpgrade = function() { | ||
var protocol = req.headers['sec-websocket-protocol']; | ||
// calc key | ||
var key = req.headers['sec-websocket-key']; | ||
var shasum = crypto.createHash('sha1'); | ||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); | ||
key = shasum.digest('base64'); | ||
var headers = [ | ||
'HTTP/1.1 101 Switching Protocols' | ||
, 'Upgrade: websocket' | ||
, 'Connection: Upgrade' | ||
, 'Sec-WebSocket-Accept: ' + key | ||
]; | ||
if (typeof protocol != 'undefined') { | ||
headers['Sec-WebSocket-Protocol'] = protocol; | ||
} | ||
try { | ||
socket.write(headers.concat('', '').join('\r\n')); | ||
} | ||
catch (e) { | ||
// if the upgrade write fails, shut the connection down hard | ||
try { socket.destroy(); } catch (e) {} | ||
return; | ||
} | ||
socket.setTimeout(0); | ||
socket.setNoDelay(true); | ||
var client = new WebSocket([req, socket, upgradeHead], { | ||
protocolVersion: version, | ||
protocol: protocol | ||
}); | ||
if (self.options.clientTracking) { | ||
self.clients.push(client); | ||
client.on('close', function() { | ||
var index = self.clients.indexOf(client); | ||
if (index != -1) { | ||
self.clients.splice(index, 1); | ||
} | ||
}); | ||
} | ||
// signal upgrade complete | ||
socket.removeListener('error', errorHandler); | ||
cb(client); | ||
} | ||
// optionally call external client verification handler | ||
if (typeof this.options.verifyClient == 'function') { | ||
@@ -182,6 +241,5 @@ var info = { | ||
if (this.options.verifyClient.length == 2) { | ||
var self = this; | ||
this.options.verifyClient(info, function(result) { | ||
if (!result) abortConnection(socket, 401, 'Unauthorized') | ||
else completeUpgrade.apply(self, args); | ||
else completeHybiUpgrade(); | ||
}); | ||
@@ -196,52 +254,13 @@ return; | ||
completeUpgrade.apply(this, args); | ||
completeHybiUpgrade(); | ||
} | ||
function completeUpgrade(req, socket, upgradeHead, version, cb) { | ||
var protocol = req.headers['sec-websocket-protocol']; | ||
// calc key | ||
var key = req.headers['sec-websocket-key']; | ||
var shasum = crypto.createHash('sha1'); | ||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); | ||
key = shasum.digest('base64'); | ||
var headers = [ | ||
'HTTP/1.1 101 Switching Protocols' | ||
, 'Upgrade: websocket' | ||
, 'Connection: Upgrade' | ||
, 'Sec-WebSocket-Accept: ' + key | ||
]; | ||
if (typeof protocol != 'undefined') { | ||
headers['Sec-WebSocket-Protocol'] = protocol; | ||
} | ||
try { | ||
socket.write(headers.concat('', '').join('\r\n')); | ||
} | ||
catch (e) { | ||
// if the upgrade write fails, shut the connection down hard | ||
function handleHixieUpgrade(req, socket, upgradeHead, cb) { | ||
// handle premature socket errors | ||
var errorHandler = function() { | ||
try { socket.destroy(); } catch (e) {} | ||
return; | ||
} | ||
socket.setTimeout(0); | ||
socket.setNoDelay(true); | ||
var client = new WebSocket([req, socket, upgradeHead], { | ||
protocolVersion: version, | ||
protocol: protocol | ||
}); | ||
socket.on('error', errorHandler); | ||
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); | ||
} | ||
function handleHixieUpgrade(req, socket, upgradeHead, cb) { | ||
// bail if options prevent hixie | ||
if (this.options.disableHixie) { | ||
@@ -258,6 +277,9 @@ abortConnection(socket, 401, 'Hixie support disabled'); | ||
var origin = req.headers['origin'] | ||
, self = this; | ||
// setup handshake completion to run after client has been verified | ||
var self = this; | ||
var onClientVerified = function() { | ||
var protocol = req.headers['sec-websocket-protocol']; | ||
var location = ((req.headers['x-forwarded-proto'] === 'https' || socket.encrypted) ? 'wss' : 'ws') + '://' + req.headers.host + req.url | ||
, protocol = req.headers['sec-websocket-protocol']; | ||
@@ -270,2 +292,3 @@ // handshake completion code to run once nonce has been successfully retrieved | ||
, md5 = crypto.createHash('md5'); | ||
[k1, k2].forEach(function (k) { | ||
@@ -280,6 +303,6 @@ var n = parseInt(k.replace(/[^\d]/g, '')) | ||
md5.update(String.fromCharCode( | ||
n >> 24 & 0xFF, | ||
n >> 16 & 0xFF, | ||
n >> 8 & 0xFF, | ||
n & 0xFF)); | ||
n >> 24 & 0xFF, | ||
n >> 16 & 0xFF, | ||
n >> 8 & 0xFF, | ||
n & 0xFF)); | ||
}); | ||
@@ -300,4 +323,30 @@ md5.update(nonce.toString('binary')); | ||
try { | ||
socket.write(headers.concat('', '').join('\r\n')); | ||
socket.write(md5.digest('binary'), 'binary'); | ||
// merge header and hash buffer | ||
var headerBuffer = new Buffer(headers.concat('', '').join('\r\n')); | ||
var hashBuffer = new Buffer(md5.digest('binary')); | ||
var handshakeBuffer = new Buffer(headerBuffer.length + hashBuffer.length); | ||
headerBuffer.copy(handshakeBuffer, 0); | ||
hashBuffer.copy(handshakeBuffer, headerBuffer.length); | ||
// do a single write, which - upon success - causes a new client websocket to be setup | ||
socket.write(handshakeBuffer, 'binary', function(err) { | ||
if (err) return; // do not create client if an error happens | ||
var client = new WebSocket([req, socket, rest], { | ||
protocolVersion: 'hixie-76', | ||
protocol: protocol | ||
}); | ||
if (self.options.clientTracking) { | ||
self.clients.push(client); | ||
client.on('close', function() { | ||
var index = self.clients.indexOf(client); | ||
if (index != -1) { | ||
self.clients.splice(index, 1); | ||
} | ||
}); | ||
} | ||
// signal upgrade complete | ||
socket.removeListener('error', errorHandler); | ||
cb(client); | ||
}); | ||
} | ||
@@ -308,17 +357,2 @@ catch (e) { | ||
} | ||
var client = new WebSocket([req, socket, rest], { | ||
protocolVersion: 'hixie-76', | ||
protocol: protocol | ||
}); | ||
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); | ||
} | ||
@@ -356,4 +390,2 @@ | ||
// verify client | ||
var location = ((req.headers['x-forwarded-proto'] === 'https' || socket.encrypted) ? 'wss' : 'ws') + '://' + req.headers.host + req.url | ||
, origin = req.headers['origin']; | ||
if (typeof this.options.verifyClient == 'function') { | ||
@@ -378,2 +410,3 @@ var info = { | ||
} | ||
// no client verification required | ||
@@ -380,0 +413,0 @@ onClientVerified(); |
@@ -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.16", | ||
"version": "0.4.17", | ||
"repository": { | ||
@@ -29,5 +29,5 @@ "type": "git", | ||
"devDependencies": { | ||
"mocha": "0.8.x", | ||
"should": "0.4.2", | ||
"expect.js": "0.1.2", | ||
"mocha": "1.1.x", | ||
"should": "0.6.x", | ||
"expect.js": "0.1.x", | ||
"benchmark": "0.3.x", | ||
@@ -34,0 +34,0 @@ "tinycolor": "0.x", |
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
Sorry, the diff of this file is not supported yet
227444
5798