Permalink
Browse files

Fixed WebSockets to follow latest 76 draft.

TODO: Implement the closing handshake, specified in draft-76
  • Loading branch information...
1 parent 57c8d37 commit b971a18e5be19849abac956dd2d2dd1fa85e6c82 Oliver Morgan committed Jun 27, 2010
Showing with 57 additions and 39 deletions.
  1. +57 −39 lib/socket.io/transports/websocket.js
@@ -1,56 +1,74 @@
-var Client = require('../client').Client,
+var Client = require('../client').Client,
url = require('url'),
Buffer = require('buffer').Buffer,
crypto = require('crypto');
exports.websocket = Client.extend({
-
+
_onConnect: function(req, socket){
var self = this, headers = [];
this.request = req;
this.connection = socket;
this.data = '';
-
+
if (this.request.headers.upgrade !== 'WebSocket' || !this._verifyOrigin(this.request.headers.origin)){
this.listener.options.log('WebSocket connection invalid');
this.connection.end();
}
-
+
this.connection.setTimeout(0);
this.connection.setEncoding('utf8');
this.connection.setNoDelay(true);
-
- headers = [
- 'HTTP/1.1 101 Web Socket Protocol Handshake',
- 'Upgrade: WebSocket',
- 'Connection: Upgrade',
- 'WebSocket-Origin: ' + this.request.headers.origin,
- 'WebSocket-Location: ws://' + this.request.headers.host + this.request.url
- ];
-
- if ('sec-websocket-key1' in this.request.headers){
- headers.push(
- 'Sec-WebSocket-Origin: ' + this.request.headers.origin,
- 'Sec-WebSocket-Location: ws://' + this.request.headers.host + this.request.url);
+
+ if ('sec-websocket-key1' in this.request.headers) {
+ this.draft = 76;
+ }
+
+ if (this.draft == 76) {
+
+ var origin = this.request.headers.origin;
+
+ headers = [
+ 'HTTP/1.1 101 WebSocket Protocol Handshake',
+ 'Upgrade: WebSocket',
+ 'Connection: Upgrade',
+ 'Sec-WebSocket-Origin: ' + origin ? origin : "null",
+ 'Sec-WebSocket-Location: ws://' + this.request.headers.host + this.request.url
+ ];
+
+ if ('sec-websocket-protocol' in this.request.headers) {
+ headers.push('Sec-WebSocket-Protocol: ' + this.request.headers['sec-websocket-protocol']);
+ }
+ }
+ else {
+
+ headers = [
+ 'HTTP/1.1 101 Web Socket Protocol Handshake',
+ 'Upgrade: WebSocket',
+ 'Connection: Upgrade',
+ 'WebSocket-Origin: ' + this.request.headers.origin,
+ 'WebSocket-Location: ws://' + this.request.headers.host + this.request.url
+ ];
+
+ this.connection.write(headers.concat('', '').join('\r\n'));
}
- this.connection.write(headers.concat('', '').join('\r\n'));
- this.connection.addListener('end', function(){ self._onClose(); });
- this.connection.addListener('data', function(data){ self._handle(data); });
-
- if (this._proveReception()){
+ this.connection.addListener('end', function(){self._onClose();});
+ this.connection.addListener('data', function(data){self._handle(data);});
+
+ if (this._proveReception(headers)){
this._payload();
}
-
+
setInterval(function(){
self._write(JSON.stringify({heartbeat: '1'}));
}, 10000);
},
-
+
_handle: function(data){
var chunk, chunks, chunk_count;
this.data += data;
- chunks = this.data.split('\ufffd');
+ chunks = this.data.split(this.draft == 76 ? '\ufffd' : '\u00ff');
chunk_count = chunks.length - 1;
for (var i = 0; i < chunk_count; i++) {
chunk = chunks[i];
@@ -65,33 +83,33 @@ exports.websocket = Client.extend({
},
// http://www.whatwg.org/specs/web-apps/current-work/complete/network.html#opening-handshake
- _proveReception: function(){
+ _proveReception: function(headers){
var k1 = this.request.headers['sec-websocket-key1'],
k2 = this.request.headers['sec-websocket-key2'];
if (k1 && k2) {
var md5 = crypto.createHash('md5');
[k1, k2].forEach(function(k) {
- var n = k.replace(/[^\d]/g, ''),
- spaces = k.replace(/[^ ]/g, '').length,
- buf = new Buffer(4);
- if (spaces === 0) {
+ var n = parseInt(k.replace(/[^\d]/g, '')),
+ spaces = k.replace(/[^ ]/g, '').length;
+
+ if (spaces === 0 || n % spaces !== 0) {
this.listener.options.log('Invalid WebSocket key: "' + k + '". Dropping connection');
this.connection.destroy();
return false;
}
n /= spaces;
- buf[3] = n & 0xff;
- buf[2] = (n >>= 8) & 0xff;
- buf[1] = (n >>= 8) & 0xff;
- buf[0] = (n >>= 8) & 0xff;
-
- md5.update(buf.toString('binary'));
+
+ md5.update(String.fromCharCode(
+ n >> 24 & 0xFF,
+ n >> 16 & 0xFF,
+ n >> 8 & 0xFF,
+ n & 0xFF));
});
-
+
md5.update(this.upgradeHead.toString('binary'));
- this.connection.write(md5.digest('binary'), 'binary');
+ this.connection.write(headers.concat('', '').join('\r\n') + md5.digest('binary'), 'binary');
}
return true;
},
@@ -105,7 +123,7 @@ exports.websocket = Client.extend({
this._onClose();
}
}
-
+
});
exports.websocket.httpUpgrade = true;

0 comments on commit b971a18

Please sign in to comment.