Compare commits

...

5 Commits
0.3.7 ... 0.4.1

Author SHA1 Message Date
Guillermo Rauch
8bf30afda2 Proper support for draft 76 2010-06-29 21:23:59 -07:00
Oliver Morgan
b971a18e5b Fixed WebSockets to follow latest 76 draft.
TODO: Implement the closing handshake, specified in draft-76
2010-06-27 13:57:44 -07:00
Guillermo Rauch
57c8d37d47 Implemented heartbeats 2010-06-26 15:04:55 -07:00
Guillermo Rauch
5e329229b4 Fix for flush in htmlfile 2010-06-25 14:57:57 -07:00
Guillermo Rauch
ea36d24d9e Updated Socket.IO client 2010-06-18 03:02:51 -03:00
3 changed files with 75 additions and 41 deletions

View File

@@ -17,11 +17,11 @@ exports.htmlfile = Client.extend({
'Transfer-Encoding': 'chunked'
});
this.response.write('<html><body>' + new Array(244).join(' '));
this.response.flush();
if ('flush' in this.response) this.response.flush();
this._payload();
this._heartbeatInterval = setInterval(function(){
self.response.write('<!-- heartbeat -->');
self.response.flush();
if ('flush' in self.response) self.response.flush();
}, this.options.heartbeatInterval);
break;
@@ -44,7 +44,7 @@ exports.htmlfile = Client.extend({
_write: function(message){
this.response.write('<script>parent.s._('+ message +', document);</script>');
this.response.flush();
if ('flush' in this.response) this.response.flush();
}
});

View File

@@ -1,47 +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 || '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
];
try {
this.connection.write(headers.concat('', '').join('\r\n'));
} catch(e){
this._onClose();
}
}
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;
@@ -60,34 +87,41 @@ 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'];
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');
try {
this.connection.write(headers.concat('', '').join('\r\n') + md5.digest('binary'), 'binary');
} catch(e){
this._onClose();
}
}
return true;
},
@@ -100,7 +134,7 @@ exports.websocket = Client.extend({
this._onClose();
}
}
});
exports.websocket.httpUpgrade = true;