From 5573f7fcdfa18d1833e01a90c5502fb2132ad5f7 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Wed, 5 Oct 2011 20:16:20 +0200 Subject: [PATCH 1/4] First stab of adding Expires + cache control headers for #558 --- lib/manager.js | 1 + lib/static.js | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/manager.js b/lib/manager.js index e3e91b557a..2b0b755df2 100644 --- a/lib/manager.js +++ b/lib/manager.js @@ -79,6 +79,7 @@ function Manager (server, options) { , 'browser client cache': true , 'browser client minification': false , 'browser client etag': false + , 'browser client expires': 315360000 , 'browser client gzip': false , 'browser client handler': false , 'client store expiration': 15 diff --git a/lib/static.js b/lib/static.js index 03505ddd40..820a32fa61 100644 --- a/lib/static.js +++ b/lib/static.js @@ -42,7 +42,8 @@ var mime = { * @api private */ -var bundle = /\+((?:\+)?[\w\-]+)*(?:\.js)$/g; +var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/g + , versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/; /** * Export the constructor @@ -291,15 +292,23 @@ Static.prototype.write = function (path, req, res) { var accept = req.headers['accept-encoding'] || '' , gzip = !!~accept.toLowerCase().indexOf('gzip') , mime = reply.mime + , versioned = reply.versioned , headers = { 'Content-Type': mime.type }; // check if we can add a etag - if (self.manager.enabled('browser client etag') && reply.etag) { + if (self.manager.enabled('browser client etag') && reply.etag && !versioned) { headers['Etag'] = reply.etag; } + // see if we need to set Expire headers because the path is versioned + if (versioned) { + var expires = self.manager.get('browser client expires') + headers['Cache-Control'] = 'public, max-age=' + expires; + headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString(); + } + // check if we can send gzip data if (gzip && reply.gzip) { headers['Content-Length'] = reply.gzip.length; @@ -342,6 +351,7 @@ Static.prototype.write = function (path, req, res) { , length: content.length , mime: details.mime , etag: etag || client.version + , versioned: versioning.test(path) }; // check if gzip is enabled From 8107c1a1e206ba746dbef1f88930e85300a5d7d6 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sat, 8 Oct 2011 15:46:23 +0200 Subject: [PATCH 2/4] Added support for HEAD requests, closes #557 --- lib/static.js | 10 ++++++++-- test/common.js | 18 ++++++++++++++++++ test/static.test.js | 18 +++++++++++++++++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/lib/static.js b/lib/static.js index 820a32fa61..3b62090a37 100644 --- a/lib/static.js +++ b/lib/static.js @@ -272,7 +272,13 @@ Static.prototype.write = function (path, req, res) { function write (status, headers, content, encoding) { try { res.writeHead(status, headers || undefined); - res.end(content || '', encoding || undefined); + + // only write content if it's not a HEAD request and we actually have + // some content to write (304's doesn't have content). + res.end( + req.method !== 'HEAD' && content ? content : '' + , encoding || undefined + ); } catch (e) {} } @@ -306,10 +312,10 @@ Static.prototype.write = function (path, req, res) { if (versioned) { var expires = self.manager.get('browser client expires') headers['Cache-Control'] = 'public, max-age=' + expires; + headers['Date'] = new Date().toUTCString(); headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString(); } - // check if we can send gzip data if (gzip && reply.gzip) { headers['Content-Length'] = reply.gzip.length; headers['Content-Encoding'] = 'gzip'; diff --git a/test/common.js b/test/common.js index 425651d058..a30ab78436 100644 --- a/test/common.js +++ b/test/common.js @@ -147,6 +147,24 @@ HTTPClient.prototype.post = function (path, data, opts, fn) { return this.request(path, opts, fn); }; +/** + * Issue a HEAD request + * + * @api private + */ + +HTTPClient.prototype.head = function (path, opts, fn) { + if ('function' == typeof opts) { + fn = opts; + opts = {}; + } + + opts = opts || {}; + opts.method = 'HEAD'; + + return this.request(path, opts, fn); +}; + /** * Performs a handshake (GET) request * diff --git a/test/static.test.js b/test/static.test.js index 06ca98e05b..058024662c 100644 --- a/test/static.test.js +++ b/test/static.test.js @@ -455,6 +455,22 @@ module.exports = { io.server.close(); done(); }); - } + }, + + 'test that HEAD requests work': function (done) { + var port = ++ports + , io = sio.listen(port) + , cl = client(port); + + cl.head('/socket.io/socket.io.js', function (res, data) { + res.headers['content-type'].should.eql('application/javascript'); + res.headers['content-length'].should.match(/([0-9]+)/); + data.should.eql(''); + + cl.end(); + io.server.close() + done(); + }); + } }; From 763fdd1c4e9d25e6aaa5a0496e0eb961ca157099 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 10 Oct 2011 20:01:28 +0200 Subject: [PATCH 3/4] Added more hardcore caching fixes #558 Added tests against it Added vary header for gzip --- lib/static.js | 15 +- test/static.test.js | 49 +- test/transports.websocket.test.js.orig | 1935 ++++++++++++++++++++++++ 3 files changed, 1993 insertions(+), 6 deletions(-) create mode 100644 test/transports.websocket.test.js.orig diff --git a/lib/static.js b/lib/static.js index 3b62090a37..e3117eda84 100644 --- a/lib/static.js +++ b/lib/static.js @@ -42,7 +42,7 @@ var mime = { * @api private */ -var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/g +var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/ , versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/; /** @@ -121,10 +121,14 @@ Static.prototype.init = function () { build(self.manager.get('transports'), callback); }); + this.add('/socket.io.v', { mime: mime.js }, function (path, callback) { + build(self.manager.get('transports'), callback); + }); + // allow custom builds based on url paths this.add('/socket.io+', { mime: mime.js }, function (path, callback) { var available = self.manager.get('transports') - , matches = bundle.exec(path) + , matches = path.match(bundle) , transports = []; if (!matches) return callback('No valid transports'); @@ -218,7 +222,7 @@ Static.prototype.has = function (path) { , i = keys.length; while (i--) { - if (!!~path.indexOf(keys[i])) return this.paths[keys[i]]; + if (-~path.indexOf(keys[i])) return this.paths[keys[i]]; } return false; @@ -310,8 +314,8 @@ Static.prototype.write = function (path, req, res) { // see if we need to set Expire headers because the path is versioned if (versioned) { - var expires = self.manager.get('browser client expires') - headers['Cache-Control'] = 'public, max-age=' + expires; + var expires = self.manager.get('browser client expires'); + headers['Cache-Control'] = 'private, x-gzip-ok="", max-age=' + expires; headers['Date'] = new Date().toUTCString(); headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString(); } @@ -319,6 +323,7 @@ Static.prototype.write = function (path, req, res) { if (gzip && reply.gzip) { headers['Content-Length'] = reply.gzip.length; headers['Content-Encoding'] = 'gzip'; + headers['Vary'] = 'Accept-Encoding'; write(200, headers, reply.gzip.content, mime.encoding); } else { headers['Content-Length'] = reply.length; diff --git a/test/static.test.js b/test/static.test.js index 058024662c..6feed80b58 100644 --- a/test/static.test.js +++ b/test/static.test.js @@ -24,7 +24,9 @@ module.exports = { , io = sio.listen(port); (!!io.static.has('/socket.io.js')).should.be.true; - (!!io.static.has('/socket.io+')).should.be.true; + (!!io.static.has('/socket.io.v1.0.0.js')).should.be.true; + (!!io.static.has('/socket.io+xhr-polling.js')).should.be.true; + (!!io.static.has('/socket.io+xhr-polling.v1.0.0.js')).should.be.true; (!!io.static.has('/static/flashsocket/WebSocketMain.swf')).should.be.true; (!!io.static.has('/static/flashsocket/WebSocketMainInsecure.swf')).should.be.true; @@ -472,5 +474,50 @@ module.exports = { io.server.close() done(); }); + }, + + 'test that a versioned client is served': function (done) { + var port = ++ports + , io = sio.listen(port) + , cl = client(port); + + cl.get('/socket.io/socket.io.v0.8.9.js', function (res, data) { + res.headers['content-type'].should.eql('application/javascript'); + res.headers['content-length'].should.match(/([0-9]+)/); + res.headers['cache-control'] + .indexOf(io.get('browser client expires')).should.be.above(-1); + + data.should.match(/XMLHttpRequest/); + + cl.end(); + io.server.close(); + done(); + }); + }, + + 'test that a custom versioned build client is served': function (done) { + var port = ++ports + , io = sio.listen(port) + , cl = client(port); + + io.set('browser client expires', 1337); + + cl.get('/socket.io/socket.io+websocket.v0.8.10.js', function (res, data) { + res.headers['content-type'].should.eql('application/javascript'); + res.headers['content-length'].should.match(/([0-9]+)/); + res.headers['cache-control'] + .indexOf(io.get('browser client expires')).should.be.above(-1); + + data.should.match(/XMLHttpRequest/); + data.should.match(/WS\.prototype\.name/); + data.should.not.match(/Flashsocket\.prototype\.name/); + data.should.not.match(/HTMLFile\.prototype\.name/); + data.should.not.match(/JSONPPolling\.prototype\.name/); + data.should.not.match(/XHRPolling\.prototype\.name/); + + cl.end(); + io.server.close(); + done(); + }); } }; diff --git a/test/transports.websocket.test.js.orig b/test/transports.websocket.test.js.orig new file mode 100644 index 0000000000..5592aae7e2 --- /dev/null +++ b/test/transports.websocket.test.js.orig @@ -0,0 +1,1935 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Test dependencies. + */ + +var sio = require('socket.io') + , should = require('./common') + , parser = sio.parser + , ports = 15800; + +/** + * Tests. + */ + +module.exports = { + 'websocket identifies as websocket': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + io.set('transports', ['websocket']); + io.sockets.on('connection', function (socket) { + socket.manager.transports[socket.id].name.should.equal('websocket'); + done(); + }); + cl.handshake(function (sid) { + ws = websocket(cl, sid); + }); + }, + + 'default websocket draft parser is used for unknown sec-websocket-version': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + io.set('transports', ['websocket']); + io.sockets.on('connection', function (socket) { + socket.manager.transports[socket.id].protocolVersion.should.equal('hixie-76'); + done(); + }); + cl.handshake(function (sid) { + ws = websocket(cl, sid); + }); + }, + + 'hybi-07-12 websocket draft parser is used for sec-websocket-version: 8': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + io.set('transports', ['websocket']); + io.sockets.on('connection', function (socket) { + socket.manager.transports[socket.id].protocolVersion.should.equal('07-12'); + done(); + }); + var headers = { + 'sec-websocket-version': 8, + 'upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' + } + cl.get('/socket.io/{protocol}', {}, function (res, data) { + var sid = data.split(':')[0]; + var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; + cl.get(url, {headers: headers}, function (res, data) {}); + }); + }, + + 'hybi-16 websocket draft parser is used for sec-websocket-version: 13': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + io.set('transports', ['websocket']); + io.sockets.on('connection', function (socket) { + socket.manager.transports[socket.id].protocolVersion.should.equal('16'); + done(); + }); + var headers = { + 'sec-websocket-version': 13, + 'upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' + } + cl.get('/socket.io/{protocol}', {}, function (res, data) { + var sid = data.split(':')[0]; + var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; + cl.get(url, {headers: headers}, function (res, data) {}); + }); + }, + + 'hybi-07-12 origin filter blocks access for mismatched sec-websocket-origin': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + io.set('transports', ['websocket']); + io.set('origins', 'foo.bar.com:*'); + + var headers = { + 'sec-websocket-version': 8, + 'upgrade': 'websocket', + 'Sec-WebSocket-Origin': 'http://baz.bar.com', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' + } + // handshake uses correct origin -- we want to block the actuall websocket call + cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) { + var sid = data.split(':')[0]; + var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; + cl.get(url, {headers: headers}, function (res, data) {}); + res.client.onend = function() { + done(); + } + }); + }, + + 'hybi-16 origin filter blocks access for mismatched sec-websocket-origin': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + io.set('transports', ['websocket']); + io.set('origins', 'foo.bar.com:*'); + + var headers = { + 'sec-websocket-version': 13, + 'upgrade': 'websocket', + 'origin': 'http://baz.bar.com', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' + } + // handshake uses correct origin -- we want to block the actuall websocket call + cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) { + var sid = data.split(':')[0]; + var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; + cl.get(url, {headers: headers}, function (res, data) {}); + res.client.onend = function() { + done(); + } + }); + }, + + 'test that not responding to a heartbeat drops client': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function (reason) { + beat.should.be.true; + reason.should.eql('heartbeat timeout'); + + cl.end(); + ws.finishClose(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (packet) { + if (++messages == 1) { + packet.type.should.eql('connect'); + } else { + packet.type.should.eql('heartbeat'); + beat = true; + } + }); + }); + }, + + 'test that responding to a heartbeat maintains session': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , heartbeats = 0 + , ws; + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function (reason) { + heartbeats.should.eql(2); + reason.should.eql('heartbeat timeout'); + + cl.end(); + ws.finishClose(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (packet) { + if (++messages == 1) { + packet.type.should.eql('connect'); + } else { + packet.type.should.eql('heartbeat'); + heartbeats++; + + if (heartbeats == 1) { + ws.packet({ type: 'heartbeat' }); + } + } + }); + }); + }, + + 'test sending undeliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + msg.type.should.eql('connect'); + ws.finishClose(); + + setTimeout(function () { + s.volatile.send('ah wha wha'); + + ws = websocket(cl, sid); + ws.on('message', function () { + messaged = true; + }); + + setTimeout(function () { + ws.finishClose(); + }, 10); + }, 10); + }); + }); + }, + + 'test sending undeliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function () { + ws.finishClose(); + + setTimeout(function () { + s.volatile.json.send({ a: 'b' }); + + ws = websocket(cl, sid); + ws.on('message', function () { + messaged = true; + }); + + setTimeout(function () { + ws.finishClose(); + }, 10); + }, 10); + }); + }); + }, + + 'test sending undeliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function () { + ws.finishClose(); + + setTimeout(function () { + s.volatile.emit({ a: 'b' }); + + ws = websocket(cl, sid); + ws.on('message', function () { + messaged = true; + }); + + setTimeout(function () { + ws.finishClose(); + }, 10); + }, 10); + }); + }); + }, + + 'test sending deliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , messaged = false; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.send('tobi'); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (++messages == 1) { + msg.type.should.eql('connect'); + } else { + msg.should.eql({ + type: 'message' + , data: 'tobi' + , endpoint: '' + }); + messaged = true; + ws.finishClose(); + } + }); + }); + }, + + 'test sending deliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.json.send([1, 2, 3]); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: [1, 2, 3] + , endpoint: '' + }); + messaged = true; + ws.finishClose(); + } + }); + }); + }, + + 'test sending deliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.emit('tobi'); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'tobi' + , endpoint: '' + , args: [] + }); + messaged = true; + ws.finishClose(); + } + }); + }); + }, + + 'test sending to all clients in a namespace': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 2) { + io.sockets.send('yup'); + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 2) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'yup' + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'yup' + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + }, + + 'test sending json to all clients in a namespace': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 2) { + io.sockets.json.send({ a: 'b' }); + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 2) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: { a: 'b' } + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: { a: 'b' } + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + }, + + 'test emitting to all clients in a namespace': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 2) { + io.sockets.emit('tobi', 'rapture'); + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 2) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'tobi' + , args: ['rapture'] + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'tobi' + , args: ['rapture'] + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + }, + + 'test sending to all clients in a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , joins = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections != 3) { + socket.join('woot'); + joins++; + + if (joins == 2) { + setTimeout(function () { + connections.should.eql(3); + io.sockets.in('woot').send('hahaha'); + }, 20); + } + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'hahaha' + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws1.finishClose(); + }, 50); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'hahaha' + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws2.finishClose(); + }, 50); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'hahaha' + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + }, + + 'test sending json to all clients in a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , joins = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections != 3) { + socket.join('woot'); + joins++; + + if (joins == 2) { + setTimeout(function () { + connections.should.eql(3); + io.sockets.in('woot').json.send(123); + }, 20); + } + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: 123 + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws1.finishClose(); + }, 50); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: 123 + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws2.finishClose(); + }, 50); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: 123 + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + }, + + 'test emitting to all clients in a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , joins = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections != 3) { + socket.join('woot'); + joins++; + + if (joins == 2) { + setTimeout(function () { + connections.should.eql(3); + io.sockets.in('woot').emit('locki'); + }, 20); + } + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'locki' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws1.finishClose(); + }, 50); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'locki' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws2.finishClose(); + }, 50); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'locki' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + }, + + 'test leaving a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , joins = 0 + , disconnects = 0; + + io.set('close timeout', 0); + + io.sockets.on('connection', function (socket) { + socket.join('foo'); + io.sockets.clients('foo').should.have.length(++joins); + + socket.on('disconnect', function () { + socket.leave('foo'); + socket.leave('foo'); + socket.leave('foo'); + + io.sockets.clients('foo').should.have.length(--joins); + + if (++disconnects == 2) { + io.server.close(); + cl1.end(); + cl2.end(); + done(); + } + }) + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + ws2.finishClose(); + } + }); + }); + }, +<<<<<<< HEAD + + 'test room lookup': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , joins = 0 + , disconnects = 0; + + io.set('close timeout', 0); + + io.sockets.on('connection', function (socket) { + socket.join('foo'); + socket.join('bar'); + + console.log(socket.rooms); + socket.rooms.indexOf('foo').should.be.above(-1); + socket.rooms.indexOf('bar').should.be.above(-1); + socket.rooms.indexOf('baz').should.eql(-1); + + socket.on('disconnect', function () { + io.server.close(); + cl.end(); + done(); + }) + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + ws.finishClose(); + } + }); + }); + }, + +======= + +>>>>>>> 1d743cfc841875a299884e034fcc86a7c7a2736a + 'test message with broadcast flag': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('trigger broadcast', function () { + socket.broadcast.send('boom'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'boom' + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'boom' + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }, + + 'test json with broadcast flag': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('trigger broadcast', function () { + socket.broadcast.json.send([1, 2, 3]); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: [1, 2, 3] + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: [1, 2, 3] + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }, + + 'test event with broadcast flag': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('trigger broadcast', function () { + socket.broadcast.emit('hey', 'arnold'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'hey' + , args: ['arnold'] + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'hey' + , args: ['arnold'] + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }, + + 'test message with broadcast flag and to()': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 1) { + socket.join('losers'); + } + + socket.on('trigger broadcast', function () { + socket.broadcast.to('losers').send('boom'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(1); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'boom' + , endpoint: '' + }); + + messages++; + } + }); + + ws1.on('open', function () { + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + throw new Error('This socket shouldnt get a message'); + } + }); + + ws2.on('open', function () { + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws1.finishClose(); + ws2.finishClose(); + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }); + }); + }); + }); + }, + + 'test json with broadcast flag and to()': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 1) { + socket.join('losers'); + } + + socket.on('trigger broadcast', function () { + socket.broadcast.json.to('losers').send({ hello: 'world' }); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(1); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: { hello: 'world' } + , endpoint: '' + }); + + messages++; + } + }); + + ws1.on('open', function () { + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + throw new Error('This socket shouldnt get a message'); + } + }); + + ws2.on('open', function () { + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws1.finishClose(); + ws2.finishClose(); + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }); + }); + }); + }); + }, + + 'test event with broadcast flag and to()': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 1) { + socket.join('losers'); + } + + socket.on('trigger broadcast', function () { + socket.broadcast.to('losers').emit('victory'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(1); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'victory' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + ws1.on('open', function () { + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + throw new Error('This socket shouldnt get a message'); + }; + }); + + ws2.on('open', function () { + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws1.finishClose(); + ws2.finishClose(); + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }); + }); + }); + }); + }, + + 'test accessing handshake data from sockets': function (done) { + var cl = client(++ports) + , io = create(cl) + , ws; + + io.sockets.on('connection', function (socket) { + (!!socket.handshake.address.address).should.be.true; + (!!socket.handshake.address.port).should.be.true; + socket.handshake.headers.host.should.equal('localhost'); + socket.handshake.headers.connection.should.equal('keep-alive'); + socket.handshake.time.should.match(/GMT/); + + socket.on('disconnect', function () { + setTimeout(function () { + ws.finishClose(); + cl.end(); + io.server.close(); + done(); + }, 10); + }); + + socket.disconnect(); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } + }); + }); + }, + + 'test accessing the array of clients': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , total = 2 + , ws1, ws2; + + io.sockets.on('connection', function (socket) { + socket.on('join ferrets', function () { + socket.join('ferrets'); + socket.send('done'); + }); + }); + + function check() { + io.sockets.clients('ferrets').should.have.length(1); + io.sockets.clients('ferrets')[0].should.be.an.instanceof(sio.Socket); + io.sockets.clients('ferrets')[0].id.should.equal(ws1.sid); + io.sockets.clients().should.have.length(2); + io.sockets.clients()[0].should.be.an.instanceof(sio.Socket); + io.sockets.clients()[0].id.should.equal(ws1.sid); + io.sockets.clients()[1].should.be.an.instanceof(sio.Socket); + io.sockets.clients()[1].id.should.equal(ws2.sid); + + ws1.finishClose(); + ws2.finishClose(); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + }; + + cl1.handshake(function (sid) { + ws1 = websocket(cl1, sid); + ws1.sid = sid; + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + ws1.packet({ + type: 'event' + , name: 'join ferrets' + , endpoint: '' + }); + } else { + cl2.handshake(function (sid) { + ws2 = websocket(cl2, sid); + ws2.sid = sid; + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + check(); + } + }); + }); + } + }); + }); + }, + + 'test accessing handshake data from sockets on disconnect': function (done) { + var cl = client(++ports) + , io = create(cl) + , ws; + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + + (!!socket.handshake.address.address).should.be.true; + (!!socket.handshake.address.port).should.be.true; + socket.handshake.headers.host.should.equal('localhost'); + socket.handshake.headers.connection.should.equal('keep-alive'); + socket.handshake.time.should.match(/GMT/); + + setTimeout(function () { + ws.finishClose(); + cl.end(); + io.server.close(); + done(); + }, 10); + }); + + socket.disconnect(); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } + }); + }); + }, + + 'test for intentional and unintentional disconnects': function (done) { + var cl = client(++ports) + , io = create(cl) + , calls = 0 + , ws; + + function close () { + cl.end(); + io.server.close(); + ws.finishClose(); + done(); + } + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.of('/foo').on('connection', function (socket) { + socket.on('disconnect', function (reason) { + reason.should.equal('packet'); + + if (++calls == 2) close(); + }); + }); + + io.of('/bar').on('connection', function (socket) { + socket.on('disconnect', function (reason) { + reason.should.equal('socket end'); + + if (++calls == 2) close(); + }); + }); + + cl.handshake(function (sid) { + var messages = 0; + ws = websocket(cl, sid); + ws.on('open', function () { + ws.packet({ + type: 'connect' + , endpoint: '/foo' + }); + ws.packet({ + type: 'connect' + , endpoint: '/bar' + }); + }); + + ws.on('message', function (packet) { + if (packet.type == 'connect') { + if (++messages === 3) { + ws.packet({ type: 'disconnect', endpoint:'/foo' }); + ws.finishClose(); + } + } + }); + }); + }, + + 'test socket clean up': function (done) { + var cl = client(++ports) + , io = create(cl) + , ws; + + io.sockets.on('connection', function (socket) { + var self = this + , id = socket.id; + + socket.on('disconnect', function () { + setTimeout(function () { + var available = !!self.sockets[id]; + + available.should.be.false; + ws.finishClose(); + cl.end(); + io.server.close(); + done(); + }, 10); + }); + + socket.disconnect(); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } + }); + }); + }, + +}; From 0e3bbd0e16e489469da2e56cef1526df24dcf314 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 10 Oct 2011 20:02:37 +0200 Subject: [PATCH 4/4] Whoops --- test/transports.websocket.test.js.orig | 1935 ------------------------ 1 file changed, 1935 deletions(-) delete mode 100644 test/transports.websocket.test.js.orig diff --git a/test/transports.websocket.test.js.orig b/test/transports.websocket.test.js.orig deleted file mode 100644 index 5592aae7e2..0000000000 --- a/test/transports.websocket.test.js.orig +++ /dev/null @@ -1,1935 +0,0 @@ - -/*! - * socket.io-node - * Copyright(c) 2011 LearnBoost - * MIT Licensed - */ - -/** - * Test dependencies. - */ - -var sio = require('socket.io') - , should = require('./common') - , parser = sio.parser - , ports = 15800; - -/** - * Tests. - */ - -module.exports = { - 'websocket identifies as websocket': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , ws; - io.set('transports', ['websocket']); - io.sockets.on('connection', function (socket) { - socket.manager.transports[socket.id].name.should.equal('websocket'); - done(); - }); - cl.handshake(function (sid) { - ws = websocket(cl, sid); - }); - }, - - 'default websocket draft parser is used for unknown sec-websocket-version': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , ws; - io.set('transports', ['websocket']); - io.sockets.on('connection', function (socket) { - socket.manager.transports[socket.id].protocolVersion.should.equal('hixie-76'); - done(); - }); - cl.handshake(function (sid) { - ws = websocket(cl, sid); - }); - }, - - 'hybi-07-12 websocket draft parser is used for sec-websocket-version: 8': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , ws; - io.set('transports', ['websocket']); - io.sockets.on('connection', function (socket) { - socket.manager.transports[socket.id].protocolVersion.should.equal('07-12'); - done(); - }); - var headers = { - 'sec-websocket-version': 8, - 'upgrade': 'websocket', - 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' - } - cl.get('/socket.io/{protocol}', {}, function (res, data) { - var sid = data.split(':')[0]; - var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; - cl.get(url, {headers: headers}, function (res, data) {}); - }); - }, - - 'hybi-16 websocket draft parser is used for sec-websocket-version: 13': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , ws; - io.set('transports', ['websocket']); - io.sockets.on('connection', function (socket) { - socket.manager.transports[socket.id].protocolVersion.should.equal('16'); - done(); - }); - var headers = { - 'sec-websocket-version': 13, - 'upgrade': 'websocket', - 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' - } - cl.get('/socket.io/{protocol}', {}, function (res, data) { - var sid = data.split(':')[0]; - var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; - cl.get(url, {headers: headers}, function (res, data) {}); - }); - }, - - 'hybi-07-12 origin filter blocks access for mismatched sec-websocket-origin': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , ws; - io.set('transports', ['websocket']); - io.set('origins', 'foo.bar.com:*'); - - var headers = { - 'sec-websocket-version': 8, - 'upgrade': 'websocket', - 'Sec-WebSocket-Origin': 'http://baz.bar.com', - 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' - } - // handshake uses correct origin -- we want to block the actuall websocket call - cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) { - var sid = data.split(':')[0]; - var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; - cl.get(url, {headers: headers}, function (res, data) {}); - res.client.onend = function() { - done(); - } - }); - }, - - 'hybi-16 origin filter blocks access for mismatched sec-websocket-origin': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , ws; - io.set('transports', ['websocket']); - io.set('origins', 'foo.bar.com:*'); - - var headers = { - 'sec-websocket-version': 13, - 'upgrade': 'websocket', - 'origin': 'http://baz.bar.com', - 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' - } - // handshake uses correct origin -- we want to block the actuall websocket call - cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) { - var sid = data.split(':')[0]; - var url = '/socket.io/' + sio.protocol + '/websocket/' + sid; - cl.get(url, {headers: headers}, function (res, data) {}); - res.client.onend = function() { - done(); - } - }); - }, - - 'test that not responding to a heartbeat drops client': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , ws; - - io.configure(function () { - io.set('heartbeat interval', .05); - io.set('heartbeat timeout', .05); - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - socket.on('disconnect', function (reason) { - beat.should.be.true; - reason.should.eql('heartbeat timeout'); - - cl.end(); - ws.finishClose(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - ws = websocket(cl, sid); - ws.on('message', function (packet) { - if (++messages == 1) { - packet.type.should.eql('connect'); - } else { - packet.type.should.eql('heartbeat'); - beat = true; - } - }); - }); - }, - - 'test that responding to a heartbeat maintains session': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , heartbeats = 0 - , ws; - - io.configure(function () { - io.set('heartbeat interval', .05); - io.set('heartbeat timeout', .05); - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - socket.on('disconnect', function (reason) { - heartbeats.should.eql(2); - reason.should.eql('heartbeat timeout'); - - cl.end(); - ws.finishClose(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - ws = websocket(cl, sid); - ws.on('message', function (packet) { - if (++messages == 1) { - packet.type.should.eql('connect'); - } else { - packet.type.should.eql('heartbeat'); - heartbeats++; - - if (heartbeats == 1) { - ws.packet({ type: 'heartbeat' }); - } - } - }); - }); - }, - - 'test sending undeliverable volatile messages': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , messaged = false - , s; - - io.configure(function () { - io.set('close timeout', .05); - }); - - io.sockets.on('connection', function (socket) { - s = socket; - - socket.on('disconnect', function () { - messaged.should.be.false; - cl.end(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - var ws = websocket(cl, sid); - ws.on('message', function (msg) { - msg.type.should.eql('connect'); - ws.finishClose(); - - setTimeout(function () { - s.volatile.send('ah wha wha'); - - ws = websocket(cl, sid); - ws.on('message', function () { - messaged = true; - }); - - setTimeout(function () { - ws.finishClose(); - }, 10); - }, 10); - }); - }); - }, - - 'test sending undeliverable volatile json': function (done) { - var cl = client(++ports) - , io = create(cl) - , messaged = false - , s; - - io.configure(function () { - io.set('close timeout', .05); - }); - - io.sockets.on('connection', function (socket) { - s = socket; - - socket.on('disconnect', function () { - messaged.should.be.false; - cl.end(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - var ws = websocket(cl, sid); - ws.on('message', function () { - ws.finishClose(); - - setTimeout(function () { - s.volatile.json.send({ a: 'b' }); - - ws = websocket(cl, sid); - ws.on('message', function () { - messaged = true; - }); - - setTimeout(function () { - ws.finishClose(); - }, 10); - }, 10); - }); - }); - }, - - 'test sending undeliverable volatile events': function (done) { - var cl = client(++ports) - , io = create(cl) - , messaged = false - , s; - - io.configure(function () { - io.set('close timeout', .05); - }); - - io.sockets.on('connection', function (socket) { - s = socket; - - socket.on('disconnect', function () { - messaged.should.be.false; - cl.end(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - var ws = websocket(cl, sid); - ws.on('message', function () { - ws.finishClose(); - - setTimeout(function () { - s.volatile.emit({ a: 'b' }); - - ws = websocket(cl, sid); - ws.on('message', function () { - messaged = true; - }); - - setTimeout(function () { - ws.finishClose(); - }, 10); - }, 10); - }); - }); - }, - - 'test sending deliverable volatile messages': function (done) { - var cl = client(++ports) - , io = create(cl) - , messages = 0 - , messaged = false; - - io.configure(function () { - io.set('close timeout', .05); - }); - - io.sockets.on('connection', function (socket) { - socket.volatile.send('tobi'); - - socket.on('disconnect', function () { - messaged.should.be.true; - cl.end(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - var ws = websocket(cl, sid); - ws.on('message', function (msg) { - if (++messages == 1) { - msg.type.should.eql('connect'); - } else { - msg.should.eql({ - type: 'message' - , data: 'tobi' - , endpoint: '' - }); - messaged = true; - ws.finishClose(); - } - }); - }); - }, - - 'test sending deliverable volatile json': function (done) { - var cl = client(++ports) - , io = create(cl) - , messaged = false; - - io.configure(function () { - io.set('close timeout', .05); - }); - - io.sockets.on('connection', function (socket) { - socket.volatile.json.send([1, 2, 3]); - - socket.on('disconnect', function () { - messaged.should.be.true; - cl.end(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - var ws = websocket(cl, sid); - ws.on('message', function (msg) { - if (!ws.connected) { - msg.type.should.eql('connect'); - ws.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: [1, 2, 3] - , endpoint: '' - }); - messaged = true; - ws.finishClose(); - } - }); - }); - }, - - 'test sending deliverable volatile events': function (done) { - var cl = client(++ports) - , io = create(cl) - , messaged = false; - - io.configure(function () { - io.set('close timeout', .05); - }); - - io.sockets.on('connection', function (socket) { - socket.volatile.emit('tobi'); - - socket.on('disconnect', function () { - messaged.should.be.true; - cl.end(); - io.server.close(); - done(); - }); - }); - - cl.handshake(function (sid) { - var ws = websocket(cl, sid); - ws.on('message', function (msg) { - if (!ws.connected) { - msg.type.should.eql('connect'); - ws.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'tobi' - , endpoint: '' - , args: [] - }); - messaged = true; - ws.finishClose(); - } - }); - }); - }, - - 'test sending to all clients in a namespace': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , io = create(cl1) - , messages = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections == 2) { - io.sockets.send('yup'); - } - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 2) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'yup' - , endpoint: '' - }); - - messages++; - ws1.finishClose(); - } - }); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'yup' - , endpoint: '' - }); - - messages++; - ws2.finishClose(); - } - }); - }); - }, - - 'test sending json to all clients in a namespace': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , io = create(cl1) - , messages = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections == 2) { - io.sockets.json.send({ a: 'b' }); - } - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 2) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: { a: 'b' } - , endpoint: '' - }); - - messages++; - ws1.finishClose(); - } - }); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: { a: 'b' } - , endpoint: '' - }); - - messages++; - ws2.finishClose(); - } - }); - }); - }, - - 'test emitting to all clients in a namespace': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , io = create(cl1) - , messages = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections == 2) { - io.sockets.emit('tobi', 'rapture'); - } - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 2) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'tobi' - , args: ['rapture'] - , endpoint: '' - }); - - messages++; - ws1.finishClose(); - } - }); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'tobi' - , args: ['rapture'] - , endpoint: '' - }); - - messages++; - ws2.finishClose(); - } - }); - }); - }, - - 'test sending to all clients in a room': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , joins = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections != 3) { - socket.join('woot'); - joins++; - - if (joins == 2) { - setTimeout(function () { - connections.should.eql(3); - io.sockets.in('woot').send('hahaha'); - }, 20); - } - } - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'hahaha' - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws1.finishClose(); - }, 50); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'hahaha' - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws2.finishClose(); - }, 50); - }); - - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'hahaha' - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws3.finishClose(); - }, 50); - }); - }, - - 'test sending json to all clients in a room': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , joins = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections != 3) { - socket.join('woot'); - joins++; - - if (joins == 2) { - setTimeout(function () { - connections.should.eql(3); - io.sockets.in('woot').json.send(123); - }, 20); - } - } - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: 123 - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws1.finishClose(); - }, 50); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: 123 - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws2.finishClose(); - }, 50); - }); - - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: 123 - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws3.finishClose(); - }, 50); - }); - }, - - 'test emitting to all clients in a room': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , joins = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections != 3) { - socket.join('woot'); - joins++; - - if (joins == 2) { - setTimeout(function () { - connections.should.eql(3); - io.sockets.in('woot').emit('locki'); - }, 20); - } - } - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'locki' - , args: [] - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws1.finishClose(); - }, 50); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'locki' - , args: [] - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws2.finishClose(); - }, 50); - }); - - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'locki' - , args: [] - , endpoint: '' - }); - - messages++; - } - }); - - setTimeout(function () { - ws3.finishClose(); - }, 50); - }); - }, - - 'test leaving a room': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , io = create(cl1) - , joins = 0 - , disconnects = 0; - - io.set('close timeout', 0); - - io.sockets.on('connection', function (socket) { - socket.join('foo'); - io.sockets.clients('foo').should.have.length(++joins); - - socket.on('disconnect', function () { - socket.leave('foo'); - socket.leave('foo'); - socket.leave('foo'); - - io.sockets.clients('foo').should.have.length(--joins); - - if (++disconnects == 2) { - io.server.close(); - cl1.end(); - cl2.end(); - done(); - } - }) - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - ws1.finishClose(); - } - }); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - ws2.finishClose(); - } - }); - }); - }, -<<<<<<< HEAD - - 'test room lookup': function (done) { - var port = ++ports - , cl = client(port) - , io = create(cl) - , joins = 0 - , disconnects = 0; - - io.set('close timeout', 0); - - io.sockets.on('connection', function (socket) { - socket.join('foo'); - socket.join('bar'); - - console.log(socket.rooms); - socket.rooms.indexOf('foo').should.be.above(-1); - socket.rooms.indexOf('bar').should.be.above(-1); - socket.rooms.indexOf('baz').should.eql(-1); - - socket.on('disconnect', function () { - io.server.close(); - cl.end(); - done(); - }) - }); - - cl.handshake(function (sid) { - var ws = websocket(cl, sid); - ws.on('message', function (msg) { - if (!ws.connected) { - msg.type.should.eql('connect'); - ws.connected = true; - ws.finishClose(); - } - }); - }); - }, - -======= - ->>>>>>> 1d743cfc841875a299884e034fcc86a7c7a2736a - 'test message with broadcast flag': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - socket.on('trigger broadcast', function () { - socket.broadcast.send('boom'); - }); - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'boom' - , endpoint: '' - }); - - messages++; - ws1.finishClose(); - } - }); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'boom' - , endpoint: '' - }); - - messages++; - ws2.finishClose(); - } - }); - }); - - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('open', function () { - ws3.packet({ - type: 'event' - , name: 'trigger broadcast' - , endpoint: '' - }); - - setTimeout(function () { - ws3.finishClose(); - }, 50); - }); - - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - throw new Error('we shouldnt get a message here'); - } - }); - }); - }, - - 'test json with broadcast flag': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - socket.on('trigger broadcast', function () { - socket.broadcast.json.send([1, 2, 3]); - }); - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: [1, 2, 3] - , endpoint: '' - }); - - messages++; - ws1.finishClose(); - } - }); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: [1, 2, 3] - , endpoint: '' - }); - - messages++; - ws2.finishClose(); - } - }); - }); - - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('open', function () { - ws3.packet({ - type: 'event' - , name: 'trigger broadcast' - , endpoint: '' - }); - - setTimeout(function () { - ws3.finishClose(); - }, 50); - }); - - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - throw new Error('we shouldnt get a message here'); - } - }); - }); - }, - - 'test event with broadcast flag': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - socket.on('trigger broadcast', function () { - socket.broadcast.emit('hey', 'arnold'); - }); - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(2); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'hey' - , args: ['arnold'] - , endpoint: '' - }); - - messages++; - ws1.finishClose(); - } - }); - }); - - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'hey' - , args: ['arnold'] - , endpoint: '' - }); - - messages++; - ws2.finishClose(); - } - }); - }); - - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('open', function () { - ws3.packet({ - type: 'event' - , name: 'trigger broadcast' - , endpoint: '' - }); - - setTimeout(function () { - ws3.finishClose(); - }, 50); - }); - - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - throw new Error('we shouldnt get a message here'); - } - }); - }); - }, - - 'test message with broadcast flag and to()': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections == 1) { - socket.join('losers'); - } - - socket.on('trigger broadcast', function () { - socket.broadcast.to('losers').send('boom'); - }); - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(1); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'message' - , data: 'boom' - , endpoint: '' - }); - - messages++; - } - }); - - ws1.on('open', function () { - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - throw new Error('This socket shouldnt get a message'); - } - }); - - ws2.on('open', function () { - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('open', function () { - ws3.packet({ - type: 'event' - , name: 'trigger broadcast' - , endpoint: '' - }); - - setTimeout(function () { - ws1.finishClose(); - ws2.finishClose(); - ws3.finishClose(); - }, 50); - }); - - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - throw new Error('we shouldnt get a message here'); - } - }); - }); - }); - }); - }); - }); - }, - - 'test json with broadcast flag and to()': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections == 1) { - socket.join('losers'); - } - - socket.on('trigger broadcast', function () { - socket.broadcast.json.to('losers').send({ hello: 'world' }); - }); - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(1); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'json' - , data: { hello: 'world' } - , endpoint: '' - }); - - messages++; - } - }); - - ws1.on('open', function () { - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - throw new Error('This socket shouldnt get a message'); - } - }); - - ws2.on('open', function () { - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('open', function () { - ws3.packet({ - type: 'event' - , name: 'trigger broadcast' - , endpoint: '' - }); - - setTimeout(function () { - ws1.finishClose(); - ws2.finishClose(); - ws3.finishClose(); - }, 50); - }); - - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - throw new Error('we shouldnt get a message here'); - } - }); - }); - }); - }); - }); - }); - }, - - 'test event with broadcast flag and to()': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , cl3 = client(port) - , io = create(cl1) - , messages = 0 - , connections = 0 - , disconnections = 0; - - io.configure(function () { - io.set('close timeout', 0); - }); - - io.sockets.on('connection', function (socket) { - connections++; - - if (connections == 1) { - socket.join('losers'); - } - - socket.on('trigger broadcast', function () { - socket.broadcast.to('losers').emit('victory'); - }); - - socket.on('disconnect', function () { - disconnections++; - - if (disconnections == 3) { - messages.should.eql(1); - cl1.end(); - cl2.end(); - cl3.end(); - io.server.close(); - done(); - } - }); - }); - - cl1.handshake(function (sid) { - var ws1 = websocket(cl1, sid); - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - } else { - msg.should.eql({ - type: 'event' - , name: 'victory' - , args: [] - , endpoint: '' - }); - - messages++; - } - }); - - ws1.on('open', function () { - cl2.handshake(function (sid) { - var ws2 = websocket(cl2, sid); - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - } else { - throw new Error('This socket shouldnt get a message'); - }; - }); - - ws2.on('open', function () { - cl3.handshake(function (sid) { - var ws3 = websocket(cl3, sid); - ws3.on('open', function () { - ws3.packet({ - type: 'event' - , name: 'trigger broadcast' - , endpoint: '' - }); - - setTimeout(function () { - ws1.finishClose(); - ws2.finishClose(); - ws3.finishClose(); - }, 50); - }); - - ws3.on('message', function (msg) { - if (!ws3.connected) { - msg.type.should.eql('connect'); - ws3.connected = true; - } else { - throw new Error('we shouldnt get a message here'); - } - }); - }); - }); - }); - }); - }); - }, - - 'test accessing handshake data from sockets': function (done) { - var cl = client(++ports) - , io = create(cl) - , ws; - - io.sockets.on('connection', function (socket) { - (!!socket.handshake.address.address).should.be.true; - (!!socket.handshake.address.port).should.be.true; - socket.handshake.headers.host.should.equal('localhost'); - socket.handshake.headers.connection.should.equal('keep-alive'); - socket.handshake.time.should.match(/GMT/); - - socket.on('disconnect', function () { - setTimeout(function () { - ws.finishClose(); - cl.end(); - io.server.close(); - done(); - }, 10); - }); - - socket.disconnect(); - }); - - cl.handshake(function (sid) { - ws = websocket(cl, sid); - ws.on('message', function (msg) { - if (!ws.connected) { - msg.type.should.eql('connect'); - ws.connected = true; - } - }); - }); - }, - - 'test accessing the array of clients': function (done) { - var port = ++ports - , cl1 = client(port) - , cl2 = client(port) - , io = create(cl1) - , total = 2 - , ws1, ws2; - - io.sockets.on('connection', function (socket) { - socket.on('join ferrets', function () { - socket.join('ferrets'); - socket.send('done'); - }); - }); - - function check() { - io.sockets.clients('ferrets').should.have.length(1); - io.sockets.clients('ferrets')[0].should.be.an.instanceof(sio.Socket); - io.sockets.clients('ferrets')[0].id.should.equal(ws1.sid); - io.sockets.clients().should.have.length(2); - io.sockets.clients()[0].should.be.an.instanceof(sio.Socket); - io.sockets.clients()[0].id.should.equal(ws1.sid); - io.sockets.clients()[1].should.be.an.instanceof(sio.Socket); - io.sockets.clients()[1].id.should.equal(ws2.sid); - - ws1.finishClose(); - ws2.finishClose(); - cl1.end(); - cl2.end(); - io.server.close(); - done(); - }; - - cl1.handshake(function (sid) { - ws1 = websocket(cl1, sid); - ws1.sid = sid; - ws1.on('message', function (msg) { - if (!ws1.connected) { - msg.type.should.eql('connect'); - ws1.connected = true; - ws1.packet({ - type: 'event' - , name: 'join ferrets' - , endpoint: '' - }); - } else { - cl2.handshake(function (sid) { - ws2 = websocket(cl2, sid); - ws2.sid = sid; - ws2.on('message', function (msg) { - if (!ws2.connected) { - msg.type.should.eql('connect'); - ws2.connected = true; - check(); - } - }); - }); - } - }); - }); - }, - - 'test accessing handshake data from sockets on disconnect': function (done) { - var cl = client(++ports) - , io = create(cl) - , ws; - - io.sockets.on('connection', function (socket) { - socket.on('disconnect', function () { - - (!!socket.handshake.address.address).should.be.true; - (!!socket.handshake.address.port).should.be.true; - socket.handshake.headers.host.should.equal('localhost'); - socket.handshake.headers.connection.should.equal('keep-alive'); - socket.handshake.time.should.match(/GMT/); - - setTimeout(function () { - ws.finishClose(); - cl.end(); - io.server.close(); - done(); - }, 10); - }); - - socket.disconnect(); - }); - - cl.handshake(function (sid) { - ws = websocket(cl, sid); - ws.on('message', function (msg) { - if (!ws.connected) { - msg.type.should.eql('connect'); - ws.connected = true; - } - }); - }); - }, - - 'test for intentional and unintentional disconnects': function (done) { - var cl = client(++ports) - , io = create(cl) - , calls = 0 - , ws; - - function close () { - cl.end(); - io.server.close(); - ws.finishClose(); - done(); - } - - io.configure(function () { - io.set('heartbeat interval', .05); - io.set('heartbeat timeout', .05); - io.set('close timeout', 0); - }); - - io.of('/foo').on('connection', function (socket) { - socket.on('disconnect', function (reason) { - reason.should.equal('packet'); - - if (++calls == 2) close(); - }); - }); - - io.of('/bar').on('connection', function (socket) { - socket.on('disconnect', function (reason) { - reason.should.equal('socket end'); - - if (++calls == 2) close(); - }); - }); - - cl.handshake(function (sid) { - var messages = 0; - ws = websocket(cl, sid); - ws.on('open', function () { - ws.packet({ - type: 'connect' - , endpoint: '/foo' - }); - ws.packet({ - type: 'connect' - , endpoint: '/bar' - }); - }); - - ws.on('message', function (packet) { - if (packet.type == 'connect') { - if (++messages === 3) { - ws.packet({ type: 'disconnect', endpoint:'/foo' }); - ws.finishClose(); - } - } - }); - }); - }, - - 'test socket clean up': function (done) { - var cl = client(++ports) - , io = create(cl) - , ws; - - io.sockets.on('connection', function (socket) { - var self = this - , id = socket.id; - - socket.on('disconnect', function () { - setTimeout(function () { - var available = !!self.sockets[id]; - - available.should.be.false; - ws.finishClose(); - cl.end(); - io.server.close(); - done(); - }, 10); - }); - - socket.disconnect(); - }); - - cl.handshake(function (sid) { - ws = websocket(cl, sid); - ws.on('message', function (msg) { - if (!ws.connected) { - msg.type.should.eql('connect'); - ws.connected = true; - } - }); - }); - }, - -};