mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-11 16:08:24 -05:00
Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ed6b79781 | ||
|
|
946418e70e | ||
|
|
2bb60ac40b | ||
|
|
e20777d21d | ||
|
|
311ef7e7e7 | ||
|
|
9e92075cbb | ||
|
|
63043b3d5d | ||
|
|
92a3cce272 | ||
|
|
8339c96e84 | ||
|
|
a125fcb1a4 | ||
|
|
97f634f18f | ||
|
|
82266cf202 | ||
|
|
be94641651 | ||
|
|
703d1d778e | ||
|
|
70c61fa84d | ||
|
|
abd0326b06 | ||
|
|
3e0b4488f8 | ||
|
|
86908c3b4d | ||
|
|
5491c2798e | ||
|
|
a9def6e209 | ||
|
|
c7a2dc45c8 | ||
|
|
cf76b13145 | ||
|
|
db2a17f279 | ||
|
|
3a07cc29bd | ||
|
|
89a5134b66 | ||
|
|
6ca42fdc8f | ||
|
|
a9f81a59c2 | ||
|
|
8a90bf5234 | ||
|
|
357a9cb870 | ||
|
|
8253ed573a | ||
|
|
3f55d82bf7 | ||
|
|
08467d4e12 | ||
|
|
cb70f7873f | ||
|
|
57b0ce73c7 | ||
|
|
25f97431d4 | ||
|
|
f931af5758 | ||
|
|
c88ea9ed61 | ||
|
|
2bdee1b28f | ||
|
|
a1f0b6c361 | ||
|
|
c1e64b90a4 | ||
|
|
79c3d84a98 | ||
|
|
f6c376d087 | ||
|
|
bc15077ecc | ||
|
|
28bf55e572 | ||
|
|
f213d69e17 | ||
|
|
aa6f228ccf | ||
|
|
553b9e9d68 | ||
|
|
ec6e43d7ee | ||
|
|
48140cf8a0 | ||
|
|
796bc9e95b | ||
|
|
67495ad8a9 | ||
|
|
bee1efb11c | ||
|
|
120924f626 | ||
|
|
acdbacb25e | ||
|
|
cde6a38218 | ||
|
|
e69c185e17 | ||
|
|
8cab86af1c | ||
|
|
00557f663a | ||
|
|
54c22aea96 | ||
|
|
a9929c916f | ||
|
|
1d66b6b5da | ||
|
|
a75670c1c2 | ||
|
|
373c729e66 | ||
|
|
7800003c5e | ||
|
|
b662f2e14e | ||
|
|
709c172444 | ||
|
|
6d5ffa0d33 | ||
|
|
f8c7ff2782 | ||
|
|
175fe8573b | ||
|
|
0224e4ac5f | ||
|
|
ecd20b0e1f | ||
|
|
b8f6dc7810 | ||
|
|
0339e745fd | ||
|
|
b3740e9ab6 | ||
|
|
0b7ed64082 | ||
|
|
07b84f4400 | ||
|
|
59e4c3b46c | ||
|
|
0e3bbd0e16 | ||
|
|
763fdd1c4e | ||
|
|
61bd23f0f9 | ||
|
|
8107c1a1e2 | ||
|
|
fa5b518110 | ||
|
|
b3df2836e9 | ||
|
|
08568ee49e | ||
|
|
aba2d5e0ef | ||
|
|
5573f7fcdf |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,4 +6,5 @@ lib-cov
|
||||
*.dat
|
||||
*.out
|
||||
*.pid
|
||||
benchmarks/*.png
|
||||
node_modules
|
||||
|
||||
26
History.md
26
History.md
@@ -1,4 +1,30 @@
|
||||
|
||||
0.8.7 / 2011-11-05
|
||||
==================
|
||||
|
||||
* Fixed memory leaks in closed clients.
|
||||
* Fixed memory leaks in namespaces.
|
||||
* Fixed websocket handling for malformed requests from proxies. [einaros]
|
||||
* Node 0.6 compatibility. [einaros] [3rd-Eden]
|
||||
* Adapted tests and examples.
|
||||
|
||||
0.8.6 / 2011-10-27
|
||||
==================
|
||||
|
||||
* Added JSON decoding on jsonp-polling transport.
|
||||
* Fixed README example.
|
||||
* Major speed optimizations [3rd-Eden] [einaros] [visionmedia]
|
||||
* Added decode/encode benchmarks [visionmedia]
|
||||
* Added support for black-listing client sent events.
|
||||
* Fixed logging options, closes #540 [3rd-Eden]
|
||||
* Added vary header for gzip [3rd-Eden]
|
||||
* Properly cleaned up async websocket / flashsocket tests, after patching node-websocket-client
|
||||
* Patched to properly shut down when a finishClose call is made during connection establishment
|
||||
* Added support for socket.io version on url and far-future Expires [3rd-Eden] [getify]
|
||||
* Began IE10 compatibility [einaros] [tbranyen]
|
||||
* Misc WebSocket fixes [einaros]
|
||||
* Added UTF8 to respone headers for htmlfile [3rd-Eden]
|
||||
|
||||
0.8.5 / 2011-10-07
|
||||
==================
|
||||
|
||||
|
||||
15
Makefile
15
Makefile
@@ -1,17 +1,17 @@
|
||||
|
||||
ALL_TESTS = $(shell find test/ -name '*.test.js')
|
||||
ALL_BENCH = $(shell find benchmarks -name '*.bench.js')
|
||||
|
||||
run-tests:
|
||||
@./node_modules/.bin/expresso \
|
||||
-t 3000 \
|
||||
-I support \
|
||||
-I lib \
|
||||
--serial \
|
||||
$(TESTFLAGS) \
|
||||
$(TESTS)
|
||||
|
||||
test:
|
||||
@$(MAKE) TESTS="$(ALL_TESTS)" run-tests
|
||||
@$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests
|
||||
|
||||
test-cov:
|
||||
@TESTFLAGS=--cov $(MAKE) test
|
||||
@@ -19,4 +19,13 @@ test-cov:
|
||||
test-leaks:
|
||||
@ls test/leaks/* | xargs node --expose_debug_as=debug --expose_gc
|
||||
|
||||
.PHONY: test
|
||||
run-bench:
|
||||
@node $(PROFILEFLAGS) benchmarks/runner.js
|
||||
|
||||
bench:
|
||||
@$(MAKE) BENCHMARKS="$(ALL_BENCH)" run-bench
|
||||
|
||||
profile:
|
||||
@PROFILEFLAGS='--prof --trace-opt --trace-bailout --trace-deopt' $(MAKE) bench
|
||||
|
||||
.PHONY: test bench profile
|
||||
|
||||
@@ -67,7 +67,7 @@ io.sockets.on('connection', function (socket) {
|
||||
});
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
sockets.emit('user disconnected');
|
||||
io.sockets.emit('user disconnected');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
64
benchmarks/decode.bench.js
Normal file
64
benchmarks/decode.bench.js
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var benchmark = require('benchmark')
|
||||
, colors = require('colors')
|
||||
, io = require('../')
|
||||
, parser = io.parser
|
||||
, suite = new benchmark.Suite('Decode packet');
|
||||
|
||||
suite.add('string', function () {
|
||||
parser.decodePacket('4:::"2"');
|
||||
});
|
||||
|
||||
suite.add('event', function () {
|
||||
parser.decodePacket('5:::{"name":"woot"}');
|
||||
});
|
||||
|
||||
suite.add('event+ack', function () {
|
||||
parser.decodePacket('5:1+::{"name":"tobi"}');
|
||||
});
|
||||
|
||||
suite.add('event+data', function () {
|
||||
parser.decodePacket('5:::{"name":"edwald","args":[{"a": "b"},2,"3"]}');
|
||||
});
|
||||
|
||||
suite.add('heartbeat', function () {
|
||||
parser.decodePacket('2:::');
|
||||
});
|
||||
|
||||
suite.add('error', function () {
|
||||
parser.decodePacket('7:::2+0');
|
||||
});
|
||||
|
||||
var payload = parser.encodePayload([
|
||||
parser.encodePacket({ type: 'message', data: '5', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: '53d', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
]);
|
||||
|
||||
suite.add('payload', function () {
|
||||
parser.decodePayload(payload);
|
||||
});
|
||||
|
||||
suite.on('cycle', function (bench, details) {
|
||||
console.log('\n' + suite.name.grey, details.name.white.bold);
|
||||
console.log([
|
||||
details.hz.toFixed(2).cyan + ' ops/sec'.grey
|
||||
, details.count.toString().white + ' times executed'.grey
|
||||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey
|
||||
,
|
||||
].join(', '.grey));
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
suite.run();
|
||||
} else {
|
||||
module.exports = suite;
|
||||
}
|
||||
90
benchmarks/encode.bench.js
Normal file
90
benchmarks/encode.bench.js
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var benchmark = require('benchmark')
|
||||
, colors = require('colors')
|
||||
, io = require('../')
|
||||
, parser = io.parser
|
||||
, suite = new benchmark.Suite('Encode packet');
|
||||
|
||||
suite.add('string', function () {
|
||||
parser.encodePacket({
|
||||
type: 'json'
|
||||
, endpoint: ''
|
||||
, data: '2'
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('event', function () {
|
||||
parser.encodePacket({
|
||||
type: 'event'
|
||||
, name: 'woot'
|
||||
, endpoint: ''
|
||||
, args: []
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('event+ack', function () {
|
||||
parser.encodePacket({
|
||||
type: 'json'
|
||||
, id: 1
|
||||
, ack: 'data'
|
||||
, endpoint: ''
|
||||
, data: { a: 'b' }
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('event+data', function () {
|
||||
parser.encodePacket({
|
||||
type: 'event'
|
||||
, name: 'edwald'
|
||||
, endpoint: ''
|
||||
, args: [{a: 'b'}, 2, '3']
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('heartbeat', function () {
|
||||
parser.encodePacket({
|
||||
type: 'heartbeat'
|
||||
, endpoint: ''
|
||||
})
|
||||
});
|
||||
|
||||
suite.add('error', function () {
|
||||
parser.encodePacket({
|
||||
type: 'error'
|
||||
, reason: 'unauthorized'
|
||||
, advice: 'reconnect'
|
||||
, endpoint: ''
|
||||
})
|
||||
})
|
||||
|
||||
suite.add('payload', function () {
|
||||
parser.encodePayload([
|
||||
parser.encodePacket({ type: 'message', data: '5', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: '53d', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
]);
|
||||
});
|
||||
|
||||
suite.on('cycle', function (bench, details) {
|
||||
console.log('\n' + suite.name.grey, details.name.white.bold);
|
||||
console.log([
|
||||
details.hz.toFixed(2).cyan + ' ops/sec'.grey
|
||||
, details.count.toString().white + ' times executed'.grey
|
||||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey
|
||||
,
|
||||
].join(', '.grey));
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
suite.run();
|
||||
} else {
|
||||
module.exports = suite;
|
||||
}
|
||||
55
benchmarks/runner.js
Normal file
55
benchmarks/runner.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Benchmark runner dependencies
|
||||
*/
|
||||
|
||||
var colors = require('colors')
|
||||
, path = require('path');
|
||||
|
||||
/**
|
||||
* Find all the benchmarks
|
||||
*/
|
||||
|
||||
var benchmarks_files = process.env.BENCHMARKS.split(' ')
|
||||
, all = [].concat(benchmarks_files)
|
||||
, first = all.shift()
|
||||
, benchmarks = {};
|
||||
|
||||
// find the benchmarks and load them all in our obj
|
||||
benchmarks_files.forEach(function (file) {
|
||||
benchmarks[file] = require(path.join(__dirname, '..', file));
|
||||
});
|
||||
|
||||
// setup the complete listeners
|
||||
benchmarks_files.forEach(function (file) {
|
||||
var benchmark = benchmarks[file]
|
||||
, next_file = all.shift()
|
||||
, next = benchmarks[next_file];
|
||||
|
||||
/**
|
||||
* Generate a oncomplete function for the tests, either we are done or we
|
||||
* have more benchmarks to process.
|
||||
*/
|
||||
|
||||
function complete () {
|
||||
if (!next) {
|
||||
console.log(
|
||||
'\n\nBenchmark completed in'.grey
|
||||
, (Date.now() - start).toString().green + ' ms'.grey
|
||||
);
|
||||
} else {
|
||||
console.log('\nStarting benchmark '.grey + next_file.yellow);
|
||||
next.run();
|
||||
}
|
||||
}
|
||||
|
||||
// attach the listener
|
||||
benchmark.on('complete', complete);
|
||||
});
|
||||
|
||||
/**
|
||||
* Start the benchmark
|
||||
*/
|
||||
|
||||
var start = Date.now();
|
||||
console.log('Starting benchmark '.grey + first.yellow);
|
||||
benchmarks[first].run();
|
||||
@@ -1,10 +1,3 @@
|
||||
|
||||
/**
|
||||
* Bootstrap app.
|
||||
*/
|
||||
|
||||
require.paths.unshift(__dirname + '/../../lib/');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
@@ -12,7 +5,7 @@ require.paths.unshift(__dirname + '/../../lib/');
|
||||
var express = require('express')
|
||||
, stylus = require('stylus')
|
||||
, nib = require('nib')
|
||||
, sio = require('socket.io');
|
||||
, sio = require('../../lib/socket.io');
|
||||
|
||||
/**
|
||||
* App.
|
||||
@@ -25,7 +18,7 @@ var app = express.createServer();
|
||||
*/
|
||||
|
||||
app.configure(function () {
|
||||
app.use(stylus.middleware({ src: __dirname + '/public', compile: compile }))
|
||||
app.use(stylus.middleware({ src: __dirname + '/public', compile: compile }));
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
app.set('views', __dirname);
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
, "description": "example chat application with socket.io"
|
||||
, "version": "0.0.1"
|
||||
, "dependencies": {
|
||||
"express": "2.3.11"
|
||||
, "jade": "0.12.1"
|
||||
, "stylus": "0.13.3"
|
||||
, "nib": "0.0.8"
|
||||
"express": "2.5.0"
|
||||
, "jade": "0.16.4"
|
||||
, "stylus": "0.19.0"
|
||||
, "nib": "0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
|
||||
/**
|
||||
* Bootstrap app.
|
||||
*/
|
||||
|
||||
require.paths.unshift(__dirname + '/../../lib/');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
@@ -12,7 +5,7 @@ require.paths.unshift(__dirname + '/../../lib/');
|
||||
var express = require('express')
|
||||
, stylus = require('stylus')
|
||||
, nib = require('nib')
|
||||
, sio = require('socket.io')
|
||||
, sio = require('../../lib/socket.io')
|
||||
, irc = require('./irc');
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* From https://github.com/felixge/nodelog/
|
||||
*/
|
||||
|
||||
var sys = require('sys');
|
||||
var sys = require('util');
|
||||
var tcp = require('net');
|
||||
var irc = exports;
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"name": "socket.io-irc"
|
||||
, "version": "0.0.1"
|
||||
, "dependencies": {
|
||||
"express": "2.3.11"
|
||||
, "jade": "0.12.1"
|
||||
, "stylus": "0.13.3"
|
||||
, "nib": "0.0.8"
|
||||
"express": "2.5.0"
|
||||
, "jade": "0.16.4"
|
||||
, "stylus": "0.19.0"
|
||||
, "nib": "0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ var Logger = module.exports = function (opts) {
|
||||
opts = opts || {}
|
||||
this.colors = false !== opts.colors;
|
||||
this.level = 3;
|
||||
this.enabled = true;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -71,7 +72,7 @@ var Logger = module.exports = function (opts) {
|
||||
Logger.prototype.log = function (type) {
|
||||
var index = levels.indexOf(type);
|
||||
|
||||
if (index > this.level)
|
||||
if (index > this.level || !this.enabled)
|
||||
return this;
|
||||
|
||||
console.log.apply(
|
||||
|
||||
@@ -67,7 +67,9 @@ function Manager (server, options) {
|
||||
, resource: '/socket.io'
|
||||
, transports: defaultTransports
|
||||
, authorization: false
|
||||
, blacklist: ['disconnect']
|
||||
, 'log level': 3
|
||||
, 'log colors': true
|
||||
, 'close timeout': 25
|
||||
, 'heartbeat timeout': 15
|
||||
, 'heartbeat interval': 20
|
||||
@@ -79,6 +81,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
|
||||
@@ -90,6 +93,11 @@ function Manager (server, options) {
|
||||
|
||||
var self = this;
|
||||
|
||||
// default error handler
|
||||
server.on('error', function(err) {
|
||||
self.log.warn('error raised: ' + err);
|
||||
});
|
||||
|
||||
this.initStore();
|
||||
|
||||
this.on('set:store', function() {
|
||||
@@ -146,10 +154,11 @@ Manager.prototype.__defineGetter__('store', function () {
|
||||
*/
|
||||
|
||||
Manager.prototype.__defineGetter__('log', function () {
|
||||
if (this.disabled('log')) return;
|
||||
|
||||
var logger = this.get('logger');
|
||||
|
||||
logger.level = this.get('log level') || -1;
|
||||
logger.colors = this.get('log colors');
|
||||
logger.enabled = this.enabled('log');
|
||||
|
||||
return logger;
|
||||
});
|
||||
@@ -258,7 +267,6 @@ Manager.prototype.initStore = function () {
|
||||
this.connected = {};
|
||||
this.open = {};
|
||||
this.closed = {};
|
||||
this.closedA = [];
|
||||
this.rooms = {};
|
||||
this.roomClients = {};
|
||||
|
||||
@@ -330,8 +338,6 @@ Manager.prototype.onOpen = function (id) {
|
||||
if (this.closed[id]) {
|
||||
var self = this;
|
||||
|
||||
this.closedA.splice(this.closedA.indexOf(id), 1);
|
||||
|
||||
this.store.unsubscribe('dispatch:' + id, function () {
|
||||
delete self.closed[id];
|
||||
});
|
||||
@@ -420,7 +426,6 @@ Manager.prototype.onClose = function (id) {
|
||||
}
|
||||
|
||||
this.closed[id] = [];
|
||||
this.closedA.push(id);
|
||||
|
||||
var self = this;
|
||||
|
||||
@@ -463,9 +468,7 @@ Manager.prototype.onClientMessage = function (id, packet) {
|
||||
|
||||
Manager.prototype.onClientDisconnect = function (id, reason) {
|
||||
for (var name in this.namespaces) {
|
||||
if (this.roomClients[id][name]) {
|
||||
this.namespaces[name].handleDisconnect(id, reason);
|
||||
}
|
||||
this.namespaces[name].handleDisconnect(id, reason, typeof this.roomClients[id][name] !== 'undefined');
|
||||
}
|
||||
|
||||
this.onDisconnect(id);
|
||||
@@ -495,7 +498,6 @@ Manager.prototype.onDisconnect = function (id, local) {
|
||||
|
||||
if (this.closed[id]) {
|
||||
delete this.closed[id];
|
||||
this.closedA.splice(this.closedA.indexOf(id), 1);
|
||||
}
|
||||
|
||||
if (this.roomClients[id]) {
|
||||
|
||||
@@ -34,7 +34,7 @@ function SocketNamespace (mgr, name) {
|
||||
SocketNamespace.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Copies emit since we override it
|
||||
* Copies emit since we override it.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
@@ -103,7 +103,7 @@ SocketNamespace.prototype.__defineGetter__('volatile', function () {
|
||||
});
|
||||
|
||||
/**
|
||||
* Overrides the room to relay messages to (flag)
|
||||
* Overrides the room to relay messages to (flag).
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
@@ -114,7 +114,7 @@ SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a session id we should prevent relaying messages to (flag)
|
||||
* Adds a session id we should prevent relaying messages to (flag).
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
@@ -139,7 +139,7 @@ SocketNamespace.prototype.setFlags = function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends out a packet
|
||||
* Sends out a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
@@ -175,9 +175,9 @@ SocketNamespace.prototype.send = function (data) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Emits to everyone (override)
|
||||
* Emits to everyone (override).
|
||||
*
|
||||
* @api private
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.emit = function (name) {
|
||||
@@ -196,7 +196,7 @@ SocketNamespace.prototype.emit = function (name) {
|
||||
* Retrieves or creates a write-only socket for a client, unless specified.
|
||||
*
|
||||
* @param {Boolean} whether the socket will be readable when initialized
|
||||
* @api private
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.socket = function (sid, readable) {
|
||||
@@ -208,7 +208,7 @@ SocketNamespace.prototype.socket = function (sid, readable) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets authorization for this namespace
|
||||
* Sets authorization for this namespace.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
@@ -224,9 +224,9 @@ SocketNamespace.prototype.authorization = function (fn) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.handleDisconnect = function (sid, reason) {
|
||||
SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) {
|
||||
if (this.sockets[sid] && this.sockets[sid].readable) {
|
||||
this.sockets[sid].onDisconnect(reason);
|
||||
if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason);
|
||||
delete this.sockets[sid];
|
||||
}
|
||||
};
|
||||
@@ -264,6 +264,7 @@ SocketNamespace.prototype.authorize = function (data, fn) {
|
||||
SocketNamespace.prototype.handlePacket = function (sessid, packet) {
|
||||
var socket = this.socket(sessid)
|
||||
, dataAck = packet.ack == 'data'
|
||||
, manager = this.manager
|
||||
, self = this;
|
||||
|
||||
function ack () {
|
||||
@@ -296,8 +297,7 @@ SocketNamespace.prototype.handlePacket = function (sessid, packet) {
|
||||
if (packet.endpoint == '') {
|
||||
connect();
|
||||
} else {
|
||||
var manager = this.manager
|
||||
, handshakeData = manager.handshaken[sessid];
|
||||
var handshakeData = manager.handshaken[sessid];
|
||||
|
||||
this.authorize(handshakeData, function (err, authorized, newData) {
|
||||
if (err) return error(err);
|
||||
@@ -322,13 +322,18 @@ SocketNamespace.prototype.handlePacket = function (sessid, packet) {
|
||||
break;
|
||||
|
||||
case 'event':
|
||||
var params = [packet.name].concat(packet.args);
|
||||
// check if the emitted event is not blacklisted
|
||||
if (-~manager.get('blacklist').indexOf(packet.name)) {
|
||||
this.log.debug('ignoring blacklisted event `' + packet.name + '`');
|
||||
} else {
|
||||
var params = [packet.name].concat(packet.args);
|
||||
|
||||
if (dataAck) {
|
||||
params.push(ack);
|
||||
if (dataAck) {
|
||||
params.push(ack);
|
||||
}
|
||||
|
||||
socket.$emit.apply(socket, params);
|
||||
}
|
||||
|
||||
socket.$emit.apply(socket, params);
|
||||
break;
|
||||
|
||||
case 'disconnect':
|
||||
|
||||
130
lib/parser.js
130
lib/parser.js
@@ -13,35 +13,38 @@
|
||||
* Packet types.
|
||||
*/
|
||||
|
||||
var packets = exports.packets = [
|
||||
'disconnect'
|
||||
, 'connect'
|
||||
, 'heartbeat'
|
||||
, 'message'
|
||||
, 'json'
|
||||
, 'event'
|
||||
, 'ack'
|
||||
, 'error'
|
||||
, 'noop'
|
||||
];
|
||||
var packets = exports.packets = {
|
||||
'disconnect': 0
|
||||
, 'connect': 1
|
||||
, 'heartbeat': 2
|
||||
, 'message': 3
|
||||
, 'json': 4
|
||||
, 'event': 5
|
||||
, 'ack': 6
|
||||
, 'error': 7
|
||||
, 'noop': 8
|
||||
}
|
||||
, packetslist = Object.keys(packets);
|
||||
|
||||
/**
|
||||
* Errors reasons.
|
||||
*/
|
||||
|
||||
var reasons = exports.reasons = [
|
||||
'transport not supported'
|
||||
, 'client not handshaken'
|
||||
, 'unauthorized'
|
||||
];
|
||||
var reasons = exports.reasons = {
|
||||
'transport not supported': 0
|
||||
, 'client not handshaken': 1
|
||||
, 'unauthorized': 2
|
||||
}
|
||||
, reasonslist = Object.keys(reasons);
|
||||
|
||||
/**
|
||||
* Errors advice.
|
||||
*/
|
||||
|
||||
var advice = exports.advice = [
|
||||
'reconnect'
|
||||
];
|
||||
var advice = exports.advice = {
|
||||
'reconnect': 0
|
||||
}
|
||||
, advicelist = Object.keys(advice);
|
||||
|
||||
/**
|
||||
* Encodes a packet.
|
||||
@@ -50,22 +53,13 @@ var advice = exports.advice = [
|
||||
*/
|
||||
|
||||
exports.encodePacket = function (packet) {
|
||||
var type = packets.indexOf(packet.type)
|
||||
var type = packets[packet.type]
|
||||
, id = packet.id || ''
|
||||
, endpoint = packet.endpoint || ''
|
||||
, ack = packet.ack
|
||||
, data = null;
|
||||
|
||||
switch (packet.type) {
|
||||
case 'error':
|
||||
var reason = packet.reason ? reasons.indexOf(packet.reason) : ''
|
||||
, adv = packet.advice ? advice.indexOf(packet.advice) : ''
|
||||
|
||||
if (reason !== '' || adv !== '')
|
||||
data = reason + (adv !== '' ? ('+' + adv) : '')
|
||||
|
||||
break;
|
||||
|
||||
case 'message':
|
||||
if (packet.data !== '')
|
||||
data = packet.data;
|
||||
@@ -85,30 +79,35 @@ exports.encodePacket = function (packet) {
|
||||
data = JSON.stringify(packet.data);
|
||||
break;
|
||||
|
||||
case 'connect':
|
||||
if (packet.qs)
|
||||
data = packet.qs;
|
||||
break;
|
||||
|
||||
case 'ack':
|
||||
data = packet.ackId
|
||||
+ (packet.args && packet.args.length
|
||||
? '+' + JSON.stringify(packet.args) : '');
|
||||
break;
|
||||
|
||||
case 'connect':
|
||||
if (packet.qs)
|
||||
data = packet.qs;
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
var reason = packet.reason ? reasons[packet.reason] : ''
|
||||
, adv = packet.advice ? advice[packet.advice] : ''
|
||||
|
||||
if (reason !== '' || adv !== '')
|
||||
data = reason + (adv !== '' ? ('+' + adv) : '')
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// construct packet with required fragments
|
||||
var encoded = [
|
||||
type
|
||||
, id + (ack == 'data' ? '+' : '')
|
||||
, endpoint
|
||||
];
|
||||
var encoded = type + ':' + id + (ack == 'data' ? '+' : '') + ':' + endpoint;
|
||||
|
||||
// data fragment is optional
|
||||
if (data !== null && data !== undefined)
|
||||
encoded.push(data);
|
||||
encoded += ':' + data;
|
||||
|
||||
return encoded.join(':');
|
||||
return encoded;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -140,6 +139,18 @@ exports.encodePayload = function (packets) {
|
||||
|
||||
var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
|
||||
|
||||
/**
|
||||
* Wrap the JSON.parse in a seperate function the crankshaft optimizer will
|
||||
* only punish this function for the usage for try catch
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parse (data) {
|
||||
try { return JSON.parse(data) }
|
||||
catch (e) { return false }
|
||||
}
|
||||
|
||||
exports.decodePacket = function (data) {
|
||||
var pieces = data.match(regexp);
|
||||
|
||||
@@ -148,7 +159,7 @@ exports.decodePacket = function (data) {
|
||||
var id = pieces[2] || ''
|
||||
, data = pieces[5] || ''
|
||||
, packet = {
|
||||
type: packets[pieces[1]]
|
||||
type: packetslist[pieces[1]]
|
||||
, endpoint: pieces[4] || ''
|
||||
};
|
||||
|
||||
@@ -163,30 +174,22 @@ exports.decodePacket = function (data) {
|
||||
|
||||
// handle different packet types
|
||||
switch (packet.type) {
|
||||
case 'error':
|
||||
var pieces = data.split('+');
|
||||
packet.reason = reasons[pieces[0]] || '';
|
||||
packet.advice = advice[pieces[1]] || '';
|
||||
break;
|
||||
|
||||
case 'message':
|
||||
packet.data = data || '';
|
||||
break;
|
||||
|
||||
case 'event':
|
||||
try {
|
||||
var opts = JSON.parse(data);
|
||||
packet.name = opts.name;
|
||||
packet.args = opts.args;
|
||||
} catch (e) { }
|
||||
pieces = parse(data);
|
||||
if (pieces) {
|
||||
packet.name = pieces.name;
|
||||
packet.args = pieces.args;
|
||||
}
|
||||
|
||||
packet.args = packet.args || [];
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
try {
|
||||
packet.data = JSON.parse(data);
|
||||
} catch (e) { }
|
||||
packet.data = parse(data);
|
||||
break;
|
||||
|
||||
case 'connect':
|
||||
@@ -194,23 +197,22 @@ exports.decodePacket = function (data) {
|
||||
break;
|
||||
|
||||
case 'ack':
|
||||
var pieces = data.match(/^([0-9]+)(\+)?(.*)/);
|
||||
pieces = data.match(/^([0-9]+)(\+)?(.*)/);
|
||||
if (pieces) {
|
||||
packet.ackId = pieces[1];
|
||||
packet.args = [];
|
||||
|
||||
if (pieces[3]) {
|
||||
try {
|
||||
packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];
|
||||
} catch (e) { }
|
||||
packet.args = parse(pieces[3]) || [];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'disconnect':
|
||||
case 'heartbeat':
|
||||
break;
|
||||
};
|
||||
case 'error':
|
||||
pieces = data.split('+');
|
||||
packet.reason = reasonslist[pieces[0]] || '';
|
||||
packet.advice = advicelist[pieces[1]] || '';
|
||||
}
|
||||
|
||||
return packet;
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ var client = require('socket.io-client');
|
||||
* Version.
|
||||
*/
|
||||
|
||||
exports.version = '0.8.5';
|
||||
exports.version = '0.8.7';
|
||||
|
||||
/**
|
||||
* Supported protocol version.
|
||||
|
||||
@@ -42,7 +42,8 @@ var mime = {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var bundle = /\+((?:\+)?[\w\-]+)*(?:\.js)$/g;
|
||||
var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/
|
||||
, versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/;
|
||||
|
||||
/**
|
||||
* Export the constructor
|
||||
@@ -120,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');
|
||||
@@ -217,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;
|
||||
@@ -271,7 +276,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) {}
|
||||
}
|
||||
|
||||
@@ -291,19 +302,28 @@ 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;
|
||||
}
|
||||
|
||||
// check if we can send gzip data
|
||||
// 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'] = 'private, x-gzip-ok="", max-age=' + expires;
|
||||
headers['Date'] = new Date().toUTCString();
|
||||
headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString();
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -342,6 +362,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
|
||||
|
||||
@@ -84,6 +84,9 @@ function Redis (opts) {
|
||||
}
|
||||
|
||||
Store.call(this, opts);
|
||||
|
||||
this.sub.setMaxListeners(0);
|
||||
this.setMaxListeners(0);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,9 +49,9 @@ FlashSocket.prototype.name = 'flashsocket';
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var server;
|
||||
|
||||
FlashSocket.init = function (manager) {
|
||||
var server;
|
||||
function create () {
|
||||
server = require('policyfile').createServer({
|
||||
log: function(msg){
|
||||
@@ -80,10 +80,15 @@ FlashSocket.init = function (manager) {
|
||||
// destory the server and create a new server
|
||||
manager.on('set:flash policy port', function (value, key) {
|
||||
var transports = manager.get('transports');
|
||||
|
||||
if (server && server.port !== value && ~transports.indexOf('flashsocket')) {
|
||||
// destroy the server and rebuild it on a new port
|
||||
server.close();
|
||||
if (~transports.indexOf('flashsocket')) {
|
||||
if (server) {
|
||||
if (server.port === value) return;
|
||||
// destroy the server and rebuild it on a new port
|
||||
try {
|
||||
server.close();
|
||||
}
|
||||
catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ }
|
||||
}
|
||||
create();
|
||||
}
|
||||
});
|
||||
@@ -94,7 +99,6 @@ FlashSocket.init = function (manager) {
|
||||
create();
|
||||
}
|
||||
});
|
||||
|
||||
// check if we need to initialize at start
|
||||
if (~manager.get('transports').indexOf('flashsocket')){
|
||||
create();
|
||||
|
||||
@@ -52,7 +52,7 @@ HTMLFile.prototype.handleRequest = function (req) {
|
||||
|
||||
if (req.method == 'GET') {
|
||||
req.res.writeHead(200, {
|
||||
'Content-Type': 'text/html'
|
||||
'Content-Type': 'text/html; charset=UTF-8'
|
||||
, 'Connection': 'keep-alive'
|
||||
, 'Transfer-Encoding': 'chunked'
|
||||
});
|
||||
|
||||
@@ -54,6 +54,24 @@ JSONPPolling.prototype.name = 'jsonppolling';
|
||||
|
||||
JSONPPolling.prototype.postEncoded = true;
|
||||
|
||||
/**
|
||||
* Handles incoming data.
|
||||
* Due to a bug in \n handling by browsers, we expect a JSONified string.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
JSONPPolling.prototype.onData = function (data) {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {
|
||||
this.error('parse', 'reconnect');
|
||||
return;
|
||||
}
|
||||
|
||||
HTTPPolling.prototype.onData.call(this, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the write.
|
||||
*
|
||||
|
||||
@@ -41,7 +41,13 @@ function WebSocket (mng, data, req) {
|
||||
});
|
||||
this.parser.on('ping', function () {
|
||||
// version 8 ping => pong
|
||||
self.socket.write('\u008a\u0000');
|
||||
try {
|
||||
self.socket.write('\u008a\u0000');
|
||||
}
|
||||
catch (e) {
|
||||
self.end();
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.parser.on('close', function () {
|
||||
self.end();
|
||||
@@ -85,7 +91,8 @@ WebSocket.prototype.protocolVersion = '07-12';
|
||||
WebSocket.prototype.onSocketConnect = function () {
|
||||
var self = this;
|
||||
|
||||
if (this.req.headers.upgrade !== 'websocket') {
|
||||
if (typeof this.req.headers.upgrade === 'undefined' ||
|
||||
this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
this.log.warn(this.name + ' connection invalid');
|
||||
this.end();
|
||||
return;
|
||||
@@ -177,7 +184,13 @@ WebSocket.prototype.verifyOrigin = function (origin) {
|
||||
WebSocket.prototype.write = function (data) {
|
||||
if (this.open) {
|
||||
var buf = this.frame(0x81, data);
|
||||
this.socket.write(buf, 'binary');
|
||||
try {
|
||||
this.socket.write(buf, 'binary');
|
||||
}
|
||||
catch (e) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,7 +41,13 @@ function WebSocket (mng, data, req) {
|
||||
});
|
||||
this.parser.on('ping', function () {
|
||||
// version 8 ping => pong
|
||||
self.socket.write('\u008a\u0000');
|
||||
try {
|
||||
self.socket.write('\u008a\u0000');
|
||||
}
|
||||
catch (e) {
|
||||
self.end();
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.parser.on('close', function () {
|
||||
self.end();
|
||||
@@ -85,7 +91,8 @@ WebSocket.prototype.protocolVersion = '16';
|
||||
WebSocket.prototype.onSocketConnect = function () {
|
||||
var self = this;
|
||||
|
||||
if (this.req.headers.upgrade !== 'websocket') {
|
||||
if (typeof this.req.headers.upgrade === 'undefined' ||
|
||||
this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
this.log.warn(this.name + ' connection invalid');
|
||||
this.end();
|
||||
return;
|
||||
@@ -177,7 +184,13 @@ WebSocket.prototype.verifyOrigin = function (origin) {
|
||||
WebSocket.prototype.write = function (data) {
|
||||
if (this.open) {
|
||||
var buf = this.frame(0x81, data);
|
||||
this.socket.write(buf, 'binary');
|
||||
try {
|
||||
this.socket.write(buf, 'binary');
|
||||
}
|
||||
catch (e) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
}
|
||||
};
|
||||
|
||||
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "socket.io"
|
||||
, "version": "0.8.5"
|
||||
, "version": "0.8.7"
|
||||
, "description": "Real-time apps made cross-browser & easy with a WebSocket-like API"
|
||||
, "homepage": "http://socket.io"
|
||||
, "keywords": ["websocket", "socket", "realtime", "socket.io", "comet", "ajax"]
|
||||
@@ -16,14 +16,17 @@
|
||||
, "url": "https://github.com/LearnBoost/socket.io.git"
|
||||
}
|
||||
, "dependencies": {
|
||||
"socket.io-client": "0.8.5"
|
||||
"socket.io-client": "0.8.7"
|
||||
, "policyfile": "0.0.4"
|
||||
, "redis": "0.6.6"
|
||||
, "redis": "0.6.7"
|
||||
}
|
||||
, "devDependencies": {
|
||||
"expresso": "0.7.7"
|
||||
"expresso": "0.9.2"
|
||||
, "should": "0.0.4"
|
||||
, "assertvanish": "0.0.3-1"
|
||||
, "benchmark": "0.2.2"
|
||||
, "microtime": "0.1.3-1"
|
||||
, "colors": "0.5.1"
|
||||
}
|
||||
, "main": "index"
|
||||
, "engines": { "node": ">= 0.4.0" }
|
||||
|
||||
@@ -5,7 +5,7 @@ var events = require('events');
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
var urllib = require('url');
|
||||
var sys = require('sys');
|
||||
var sys = require('util');
|
||||
|
||||
var FRAME_NO = 0;
|
||||
var FRAME_LO = 1;
|
||||
@@ -347,7 +347,6 @@ var WebSocket = function(url, proto, opts) {
|
||||
// that we've closed.
|
||||
var finishClose = self.finishClose = function() {
|
||||
readyState = CLOSED;
|
||||
|
||||
if (stream) {
|
||||
stream.end();
|
||||
stream.destroy();
|
||||
@@ -469,31 +468,54 @@ var WebSocket = function(url, proto, opts) {
|
||||
// that http.Client passes its constructor arguments through,
|
||||
// un-inspected to net.Stream.connect(). The latter accepts a
|
||||
// string as its first argument to connect to a UNIX socket.
|
||||
var httpClient = undefined;
|
||||
var opt = {};
|
||||
var agent = null;
|
||||
switch (getUrlScheme(url)) {
|
||||
case 'ws':
|
||||
var u = urllib.parse(url);
|
||||
httpClient = http.createClient(u.port || 80, u.hostname);
|
||||
httpPath = (u.pathname || '/') + (u.search || '');
|
||||
httpHeaders.Host = u.hostname + (u.port ? (":" + u.port) : "");
|
||||
agent = new http.Agent({
|
||||
host: u.hostname,
|
||||
port: u.port || 80
|
||||
});
|
||||
opt.agent = agent;
|
||||
opt.host = u.hostname;
|
||||
opt.port = u.port || 80;
|
||||
opt.path = (u.pathname || '/') + (u.search || '');
|
||||
opt.headers = httpHeaders;
|
||||
break;
|
||||
|
||||
case 'ws+unix':
|
||||
var sockPath = url.substring('ws+unix://'.length, url.length);
|
||||
httpClient = http.createClient(sockPath);
|
||||
httpHeaders.Host = 'localhost';
|
||||
var u = urllib.parse(url);
|
||||
agent = new http.Agent({
|
||||
host: 'localhost',
|
||||
port: sockPath
|
||||
});
|
||||
opt.agent = agent;
|
||||
opt.host = 'localhost';
|
||||
opt.path = sockPath;
|
||||
opt.headers = httpHeaders;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('Invalid URL scheme \'' + urlScheme + '\' specified.');
|
||||
}
|
||||
|
||||
httpClient.on('upgrade', (function() {
|
||||
var httpReq = http.request(opt, function() { });
|
||||
var upgradeHandler = (function() {
|
||||
var data = undefined;
|
||||
|
||||
return function(req, s, head) {
|
||||
req.socket.setNoDelay(true);
|
||||
stream = s;
|
||||
|
||||
if (readyState == CLOSED) {
|
||||
stream.end();
|
||||
stream.destroy();
|
||||
stream = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
stream.on('data', function(d) {
|
||||
if (d.length <= 0) {
|
||||
return;
|
||||
@@ -547,7 +569,7 @@ var WebSocket = function(url, proto, opts) {
|
||||
//
|
||||
// XXX: This is lame. We should only remove the listeners
|
||||
// that we added.
|
||||
httpClient.removeAllListeners('upgrade');
|
||||
httpReq.removeAllListeners('upgrade');
|
||||
stream.removeAllListeners('data');
|
||||
stream.on('data', dataListener);
|
||||
|
||||
@@ -575,13 +597,9 @@ var WebSocket = function(url, proto, opts) {
|
||||
|
||||
stream.emit('data', head);
|
||||
};
|
||||
})());
|
||||
httpClient.on('error', function(e) {
|
||||
httpClient.end();
|
||||
errorListener(e);
|
||||
});
|
||||
|
||||
var httpReq = httpClient.request(httpPath, httpHeaders);
|
||||
})();
|
||||
agent.on('upgrade', upgradeHandler); // node v0.4
|
||||
httpReq.on('upgrade', upgradeHandler); // node v0.5+
|
||||
|
||||
httpReq.write(challenge, 'binary');
|
||||
httpReq.end();
|
||||
|
||||
@@ -91,8 +91,21 @@ HTTPClient.prototype.request = function (path, opts, fn) {
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.end = function () {
|
||||
this.agent.sockets.forEach(function (socket) {
|
||||
socket.end();
|
||||
// node <v0.5 compat
|
||||
if (this.agent.sockets.forEach) {
|
||||
this.agent.sockets.forEach(function (socket) {
|
||||
if (socket.end) socket.end();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// node >=v0.5 compat
|
||||
var self = this;
|
||||
Object.keys(this.agent.sockets).forEach(function (socket) {
|
||||
for (var i = 0, l = self.agent.sockets[socket].length; i < l; ++i) {
|
||||
if (self.agent.sockets[socket][i]._handle) {
|
||||
self.agent.sockets[socket][i]._handle.socket.end();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -147,6 +160,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
|
||||
*
|
||||
@@ -179,7 +210,6 @@ client = function (port) {
|
||||
*/
|
||||
|
||||
create = function (cl) {
|
||||
console.log('');
|
||||
var manager = io.listen(cl.port);
|
||||
manager.set('client store expiration', 0);
|
||||
return manager;
|
||||
|
||||
@@ -55,16 +55,16 @@ mask = function(buf, maskString) {
|
||||
getHybiLengthAsHexString = function(len, masked) {
|
||||
if (len < 126) {
|
||||
var buf = new Buffer(1);
|
||||
buf[0] = (masked ? 0x80 : 0) | len;
|
||||
buf[0] = (masked ? 0x80 : 0) | len;
|
||||
}
|
||||
else if (len < 65536) {
|
||||
var buf = new Buffer(3);
|
||||
buf[0] = (masked ? 0x80 : 0) | 126;
|
||||
buf[0] = (masked ? 0x80 : 0) | 126;
|
||||
getBufferFromHexString(pack(4, len)).copy(buf, 1);
|
||||
}
|
||||
else {
|
||||
var buf = new Buffer(9);
|
||||
buf[0] = (masked ? 0x80 : 0) | 127;
|
||||
buf[0] = (masked ? 0x80 : 0) | 127;
|
||||
getBufferFromHexString(pack(16, len)).copy(buf, 1);
|
||||
}
|
||||
return getHexStringFromBuffer(buf);
|
||||
|
||||
@@ -116,10 +116,10 @@ module.exports = {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
done();
|
||||
} catch (e) {
|
||||
e.should.match(/EACCES/);
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -117,6 +117,7 @@ module.exports = {
|
||||
io.disable('foo');
|
||||
|
||||
calls.should.eql(3);
|
||||
|
||||
done();
|
||||
},
|
||||
|
||||
@@ -426,8 +427,8 @@ module.exports = {
|
||||
|
||||
'test disabling heartbeats': function (done) {
|
||||
var port = ++ports
|
||||
, io = sio.listen(port)
|
||||
, cl = client(port)
|
||||
, io = create(cl)
|
||||
, messages = 0
|
||||
, beat = false
|
||||
, ws;
|
||||
@@ -446,9 +447,8 @@ module.exports = {
|
||||
|
||||
socket.on('disconnect', function (reason) {
|
||||
beat.should.be.false;
|
||||
|
||||
cl.end();
|
||||
ws.finishClose();
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
@@ -505,8 +505,10 @@ module.exports = {
|
||||
io.rooms.foo.length.should.equal(2);
|
||||
io.rooms.bar.length.should.equal(2);
|
||||
|
||||
io.server.close();
|
||||
done();
|
||||
process.nextTick(function() {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
'test passing options directly to the Manager through listen': function (done) {
|
||||
@@ -515,7 +517,56 @@ module.exports = {
|
||||
|
||||
io.get('resource').should.equal('/my resource');
|
||||
io.get('custom').should.equal('opt');
|
||||
io.server.close();
|
||||
done();
|
||||
process.nextTick(function() {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
'test disabling the log': function (done) {
|
||||
var port = ++ports
|
||||
, io = sio.listen(port, { log: false })
|
||||
, _console = console.log
|
||||
, calls = 0;
|
||||
|
||||
// the logger uses console.log to output data, override it to see if get's
|
||||
// used
|
||||
console.log = function () { ++calls };
|
||||
|
||||
io.log.debug('test');
|
||||
io.log.log('testing');
|
||||
|
||||
console.log = _console;
|
||||
calls.should.equal(0);
|
||||
|
||||
process.nextTick(function() {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
'test disabling logging with colors': function (done) {
|
||||
var port = ++ports
|
||||
, io = sio.listen(port, { 'log colors': false })
|
||||
, _console = console.log
|
||||
, calls = 0;
|
||||
|
||||
// the logger uses console.log to output data, override it to see if get's
|
||||
// used
|
||||
console.log = function (data) {
|
||||
++calls;
|
||||
data.indexOf('\033').should.equal(-1);
|
||||
};
|
||||
|
||||
io.log.debug('test');
|
||||
io.log.log('testing');
|
||||
|
||||
console.log = _console;
|
||||
calls.should.equal(2);
|
||||
|
||||
process.nextTick(function() {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -131,7 +131,7 @@ module.exports = {
|
||||
if (data.endpoint == '/a') {
|
||||
data.type.should.eql('error');
|
||||
data.reason.should.eql('unauthorized')
|
||||
|
||||
|
||||
cl.end();
|
||||
ws.finishClose();
|
||||
io.server.close()
|
||||
@@ -154,6 +154,9 @@ module.exports = {
|
||||
|
||||
io.of('a')
|
||||
.on('connection', function (socket){
|
||||
if (connect < 2) {
|
||||
return;
|
||||
}
|
||||
socket.broadcast.emit('b', 'test');
|
||||
socket.broadcast.json.emit('json', {foo:'bar'});
|
||||
socket.broadcast.send('foo');
|
||||
@@ -163,7 +166,6 @@ module.exports = {
|
||||
connect.should.equal(2);
|
||||
message.should.equal(1);
|
||||
events.should.equal(2);
|
||||
|
||||
cl.end();
|
||||
ws1.finishClose();
|
||||
ws2.finishClose();
|
||||
@@ -173,16 +175,19 @@ module.exports = {
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
ws1 = websocket(cl, sid);
|
||||
|
||||
ws1.on('open', function() {
|
||||
ws1.packet({
|
||||
type: 'connect'
|
||||
, endpoint: 'a'
|
||||
});
|
||||
});
|
||||
|
||||
ws1.on('message', function (data) {
|
||||
if (data.type === 'connect') {
|
||||
if (connect == 0) {
|
||||
cl.handshake(function (sid) {
|
||||
ws2 = websocket(cl, sid);
|
||||
ws2.on('open', function () {
|
||||
ws2.packet({
|
||||
type: 'connect'
|
||||
, endpoint: 'a'
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
++connect;
|
||||
if (++calls === expected) finish();
|
||||
}
|
||||
@@ -197,17 +202,12 @@ module.exports = {
|
||||
if (++calls === expected) finish();
|
||||
}
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
ws2 = websocket(cl, sid);
|
||||
|
||||
ws2.on('open', function () {
|
||||
ws2.packet({
|
||||
type: 'connect'
|
||||
, endpoint: 'a'
|
||||
});
|
||||
ws1.on('open', function() {
|
||||
ws1.packet({
|
||||
type: 'connect'
|
||||
, endpoint: 'a'
|
||||
});
|
||||
})
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
@@ -243,5 +243,44 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
'ignoring blacklisted events': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, calls = 0
|
||||
, ws;
|
||||
|
||||
io.set('heartbeat interval', 1);
|
||||
io.set('blacklist', ['foobar']);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.on('foobar', function () {
|
||||
calls++;
|
||||
});
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
ws = websocket(cl, sid);
|
||||
|
||||
ws.on('open', function (){
|
||||
ws.packet({
|
||||
type: 'event'
|
||||
, name: 'foobar'
|
||||
, endpoint: ''
|
||||
});
|
||||
});
|
||||
|
||||
ws.on('message', function (data) {
|
||||
if (data.type === 'heartbeat') {
|
||||
cl.end();
|
||||
ws.finishClose();
|
||||
io.server.close();
|
||||
|
||||
calls.should.equal(0);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
/**
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
, should = require('./common');
|
||||
|
||||
/**
|
||||
* Test.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
|
||||
};
|
||||
@@ -24,12 +24,16 @@ 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;
|
||||
|
||||
io.server.close();
|
||||
done();
|
||||
process.nextTick(function() {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
'test that static files are correctly looked up': function (done) {
|
||||
@@ -39,8 +43,10 @@ module.exports = {
|
||||
(!!io.static.has('/socket.io.js')).should.be.true;
|
||||
(!!io.static.has('/invalidfilehereplease.js')).should.be.false;
|
||||
|
||||
io.server.close();
|
||||
done();
|
||||
process.nextTick(function() {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
'test that the client is served': function (done) {
|
||||
@@ -455,6 +461,89 @@ 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();
|
||||
});
|
||||
},
|
||||
|
||||
'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();
|
||||
});
|
||||
},
|
||||
|
||||
'test that etags are ignored for versioned requests': function (done) {
|
||||
var port = ++ports
|
||||
, io = sio.listen(port)
|
||||
, cl = client(port);
|
||||
|
||||
io.enable('browser client etag');
|
||||
|
||||
cl.get('/socket.io/socket.io.v0.8.9.js', function (res, data) {
|
||||
should.strictEqual(res.headers.etag, undefined);
|
||||
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();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -168,13 +168,18 @@ module.exports = {
|
||||
'flashsocket identifies as flashsocket': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, messages = 0
|
||||
, ws;
|
||||
|
||||
io.set('transports', ['flashsocket']);
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.manager.transports[socket.id].name.should.equal('flashsocket');
|
||||
ws.finishClose();
|
||||
cl.end();
|
||||
io.flashPolicyServer.close();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
ws = websocket(cl, sid, 'flashsocket');
|
||||
});
|
||||
|
||||
@@ -250,8 +250,7 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
'test the disconnection event when the client sends ?disconnect req':
|
||||
function (done) {
|
||||
'test the disconnection event when the client sends ?disconnect req': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, disconnected = false
|
||||
@@ -279,12 +278,17 @@ module.exports = {
|
||||
msgs.should.have.length(1);
|
||||
msgs[0].should.eql({ type: 'disconnect', endpoint: '' });
|
||||
disconnected.should.be.true;
|
||||
cl.end();
|
||||
io.server.close();
|
||||
cl.end();
|
||||
done();
|
||||
});
|
||||
|
||||
cl.get('/socket.io/{protocol}/jsonp-polling/' + sid + '/?disconnect');
|
||||
// with the new http bits in node 0.5, there's no guarantee that
|
||||
// the previous request is actually dispatched (and received) before the following
|
||||
// reset call is sent. to not waste more time on a workaround, a timeout is added.
|
||||
setTimeout(function() {
|
||||
cl.get('/socket.io/{protocol}/jsonp-polling/' + sid + '/?disconnect');
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -323,7 +327,7 @@ module.exports = {
|
||||
io.sockets.on('connection', function (client) {
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'disconnect' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'disconnect' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -390,11 +394,11 @@ module.exports = {
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePayload([
|
||||
, JSON.stringify(parser.encodePayload([
|
||||
parser.encodePacket({ type: 'message', data: 'a' })
|
||||
, parser.encodePacket({ type: 'message', data: 'b' })
|
||||
, parser.encodePacket({ type: 'disconnect' })
|
||||
])
|
||||
]))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -504,7 +508,7 @@ module.exports = {
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'connect', endpoint: '/woot' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'connect', endpoint: '/woot' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -585,21 +589,21 @@ module.exports = {
|
||||
cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function () {
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'connect', endpoint: '/woot' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'connect', endpoint: '/woot' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'disconnect', endpoint: '/woot' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'disconnect', endpoint: '/woot' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'message', data: 'ferret' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'message', data: 'ferret' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -656,7 +660,7 @@ module.exports = {
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'connect', endpoint: '/a' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'connect', endpoint: '/a' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -665,7 +669,7 @@ module.exports = {
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'connect', endpoint: '/b' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'connect', endpoint: '/b' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -721,7 +725,7 @@ module.exports = {
|
||||
cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, data) {
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'message', data: '' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'message', data: '' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -730,14 +734,14 @@ module.exports = {
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'connect', endpoint: '/a' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'connect', endpoint: '/a' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'message', endpoint: '/a', data: 'a' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'message', endpoint: '/a', data: 'a' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
@@ -748,14 +752,14 @@ module.exports = {
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'connect', endpoint: '/b' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'connect', endpoint: '/b' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
|
||||
cl.post(
|
||||
'/socket.io/{protocol}/jsonp-polling/' + sid
|
||||
, parser.encodePacket({ type: 'message', endpoint: '/b', data: 'b' })
|
||||
, JSON.stringify(parser.encodePacket({ type: 'message', endpoint: '/b', data: 'b' }))
|
||||
, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
data.should.eql('1');
|
||||
|
||||
@@ -19,7 +19,24 @@ var sio = require('socket.io')
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
|
||||
'websocket identifies as websocket': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, ws;
|
||||
|
||||
io.set('transports', ['websocket']);
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.manager.transports[socket.id].name.should.equal('websocket');
|
||||
ws.finishClose();
|
||||
cl.end();
|
||||
io.server.close();
|
||||
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)
|
||||
@@ -28,17 +45,10 @@ module.exports = {
|
||||
io.set('transports', ['websocket']);
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.manager.transports[socket.id].protocolVersion.should.equal('hixie-76');
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
setTimeout(function () {
|
||||
ws.finishClose();
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
}, 10);
|
||||
});
|
||||
|
||||
socket.disconnect();
|
||||
ws.finishClose();
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
@@ -48,22 +58,14 @@ module.exports = {
|
||||
|
||||
'hybi-07-12 websocket draft parser is used for sec-websocket-version: 8': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, ws;
|
||||
, io = create(cl);
|
||||
|
||||
io.set('transports', ['websocket']);
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.manager.transports[socket.id].protocolVersion.should.equal('07-12');
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
setTimeout(function () {
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
}, 10);
|
||||
});
|
||||
|
||||
socket.disconnect();
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
|
||||
var headers = {
|
||||
@@ -87,16 +89,9 @@ module.exports = {
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.manager.transports[socket.id].protocolVersion.should.equal('16');
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
setTimeout(function () {
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
}, 10);
|
||||
});
|
||||
|
||||
socket.disconnect();
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
|
||||
var headers = {
|
||||
@@ -131,10 +126,9 @@ module.exports = {
|
||||
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() {
|
||||
io.server.close();
|
||||
done();
|
||||
}
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -157,10 +151,9 @@ module.exports = {
|
||||
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() {
|
||||
io.server.close();
|
||||
done();
|
||||
}
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -243,140 +236,12 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
'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);
|
||||
});
|
||||
|
||||
@@ -220,7 +220,12 @@ module.exports = {
|
||||
done();
|
||||
});
|
||||
|
||||
cl.get('/socket.io/{protocol}/xhr-polling/' + sid + '/?disconnect');
|
||||
// with the new http bits in node 0.5, there's no guarantee that
|
||||
// the previous request is actually dispatched (and received) before the following
|
||||
// reset call is sent. to not waste more time on a workaround, a timeout is added.
|
||||
setTimeout(function() {
|
||||
cl.get('/socket.io/{protocol}/xhr-polling/' + sid + '/?disconnect');
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user