mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-11 07:58:13 -05:00
Compare commits
202 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41b9a7e45d | ||
|
|
e4d61b1be6 | ||
|
|
ed74dee3b0 | ||
|
|
9ad1fd2771 | ||
|
|
d25c5484c3 | ||
|
|
fea676b90e | ||
|
|
386d2a9c0c | ||
|
|
8b47789414 | ||
|
|
47b06c0fcf | ||
|
|
9823325a1f | ||
|
|
a47d76b990 | ||
|
|
db3ac4b415 | ||
|
|
b9a2804b1a | ||
|
|
b4182a5d42 | ||
|
|
5120a706f2 | ||
|
|
ee078cb124 | ||
|
|
64d8f572aa | ||
|
|
4e1ba9f872 | ||
|
|
5d93af994a | ||
|
|
6e25c802cc | ||
|
|
37690f78d7 | ||
|
|
3cbd00ca70 | ||
|
|
b2a8ed1421 | ||
|
|
0d3313f536 | ||
|
|
3b7224c7e0 | ||
|
|
2030cf1432 | ||
|
|
de9e8dffe1 | ||
|
|
3a3044ebba | ||
|
|
d10b4dd1bd | ||
|
|
12beee2d63 | ||
|
|
875f14d16b | ||
|
|
8ca8990a0c | ||
|
|
c218468f67 | ||
|
|
4164e3bd7e | ||
|
|
46227e7ac9 | ||
|
|
d723d363b2 | ||
|
|
fa1c1b2ada | ||
|
|
d32a848c3f | ||
|
|
48ad0d3d1d | ||
|
|
281a467960 | ||
|
|
1fa74a46a3 | ||
|
|
ca4e3f32a3 | ||
|
|
9dd8134e6a | ||
|
|
180f1c91b9 | ||
|
|
bddf652c25 | ||
|
|
c795e4cf1a | ||
|
|
6afbb34581 | ||
|
|
ac39dbc721 | ||
|
|
a5c5c20438 | ||
|
|
f48b40e134 | ||
|
|
1679fd564c | ||
|
|
bb900d445a | ||
|
|
c6fed55f53 | ||
|
|
6adebc85fc | ||
|
|
7a087bcc94 | ||
|
|
18422183c8 | ||
|
|
aeb904f58b | ||
|
|
9c0b9de7f0 | ||
|
|
81552c11ca | ||
|
|
e1fe76aebe | ||
|
|
8197a0c854 | ||
|
|
2b91f1407f | ||
|
|
3b9715e8e7 | ||
|
|
4e13cfb03e | ||
|
|
39671e81a5 | ||
|
|
ffa8994a23 | ||
|
|
de1afe1317 | ||
|
|
aaad106b90 | ||
|
|
f850ddccd0 | ||
|
|
8d269aae4c | ||
|
|
67b4eb9abd | ||
|
|
fe6dd87443 | ||
|
|
d9aeaa494f | ||
|
|
2024d45383 | ||
|
|
e1884859bc | ||
|
|
0242a2ddf3 | ||
|
|
dbe6d5f740 | ||
|
|
e98fc7bc86 | ||
|
|
9bbf17f31e | ||
|
|
1a5a87af13 | ||
|
|
a4e53a642b | ||
|
|
6f36d8c2ff | ||
|
|
09fb16b443 | ||
|
|
330407cc9d | ||
|
|
2075307f23 | ||
|
|
d7b06edaca | ||
|
|
46fdcf00b3 | ||
|
|
147b9bb941 | ||
|
|
02a3da487c | ||
|
|
087c686ad0 | ||
|
|
16205fc522 | ||
|
|
a232159ce8 | ||
|
|
b9c3255b7c | ||
|
|
d80010dcf0 | ||
|
|
00694a8a98 | ||
|
|
da95094998 | ||
|
|
e7d7582f84 | ||
|
|
df5f23d309 | ||
|
|
e018ba91eb | ||
|
|
c59aa6ff2c | ||
|
|
9431709298 | ||
|
|
a29525e043 | ||
|
|
5312e154b3 | ||
|
|
480b86f382 | ||
|
|
c0e2c3012f | ||
|
|
97b04c4152 | ||
|
|
c8306e207d | ||
|
|
de5c0b3554 | ||
|
|
57a0b24060 | ||
|
|
204576c006 | ||
|
|
66ac425bf7 | ||
|
|
a01e7e2256 | ||
|
|
47cfa5aadf | ||
|
|
ddd7f804af | ||
|
|
8c1c7a24ef | ||
|
|
09b130f4cf | ||
|
|
b662704b0b | ||
|
|
304a4285ff | ||
|
|
6074795b19 | ||
|
|
a139809a97 | ||
|
|
8ff2edd79c | ||
|
|
ebd25676ee | ||
|
|
d9d529cb17 | ||
|
|
b37666a8e8 | ||
|
|
cc2270bb90 | ||
|
|
36fc7b07ea | ||
|
|
8eab3a87e7 | ||
|
|
94d513c85a | ||
|
|
70abe7aada | ||
|
|
9a8c1c4ae7 | ||
|
|
c110036f75 | ||
|
|
d5ab46d662 | ||
|
|
eeaca6d9ac | ||
|
|
a7f45fe6c0 | ||
|
|
b59fd61d56 | ||
|
|
7948619609 | ||
|
|
6e8166d039 | ||
|
|
8fc3e37ca1 | ||
|
|
17d0f4d489 | ||
|
|
61e7e8955a | ||
|
|
4c17f7f83b | ||
|
|
0f29d786b2 | ||
|
|
5ee6b43921 | ||
|
|
f211f78019 | ||
|
|
eeb2a73f16 | ||
|
|
3887633e35 | ||
|
|
db8cf7673b | ||
|
|
dfb852151b | ||
|
|
7b6c85030e | ||
|
|
2d5dcc1a8a | ||
|
|
2b28c46400 | ||
|
|
27714d7286 | ||
|
|
ffef944dd5 | ||
|
|
f4b434a6a5 | ||
|
|
e4a9342e8b | ||
|
|
3ed6b79781 | ||
|
|
6f2270add6 | ||
|
|
220f8d5bf5 | ||
|
|
946418e70e | ||
|
|
2bb60ac40b | ||
|
|
e20777d21d | ||
|
|
311ef7e7e7 | ||
|
|
9e92075cbb | ||
|
|
63043b3d5d | ||
|
|
92a3cce272 | ||
|
|
8339c96e84 | ||
|
|
a125fcb1a4 | ||
|
|
97f634f18f | ||
|
|
82266cf202 | ||
|
|
be94641651 | ||
|
|
703d1d778e | ||
|
|
70c61fa84d | ||
|
|
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 | ||
|
|
d9049f69c1 | ||
|
|
10ffbd59e9 | ||
|
|
a51fe07420 |
6
.travis.yml
Normal file
6
.travis.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
|
||||
notifications:
|
||||
irc: "irc.freenode.org#socket.io"
|
||||
164
History.md
164
History.md
@@ -1,4 +1,168 @@
|
||||
|
||||
0.9.19 / 2017-05-16
|
||||
===================
|
||||
|
||||
* Properly require EventEmitter
|
||||
|
||||
0.9.18 / 2017-05-07
|
||||
===================
|
||||
|
||||
* Remove process.EventEmitter usage for Node 7.x
|
||||
|
||||
0.9.17 / 2014-05-22
|
||||
===================
|
||||
|
||||
* use static channels for remote syncing instead of subscribing/unsubscribing 5 channels for every connection
|
||||
* Use destroy buffer size on websocket transport method as well
|
||||
* http-polling : adding 'X-XSS-Protection : 0;' to headers necessary not only to jsonp-polling but http-polling
|
||||
|
||||
0.9.16 / 2013-06-06
|
||||
===================
|
||||
|
||||
* transports: added tests for htmlfile escaping/unescaping
|
||||
|
||||
0.9.15 / 2013-06-06
|
||||
===================
|
||||
|
||||
* transports: added escaping to htmlfile (fixes #1251)
|
||||
|
||||
0.9.14 / 2013-03-29
|
||||
===================
|
||||
|
||||
* manager: fix memory leak with SSL [jpallen]
|
||||
|
||||
0.9.13 / 2012-12-13
|
||||
===================
|
||||
|
||||
* package: fixed `base64id` requirement
|
||||
|
||||
0.9.12 / 2012-12-13
|
||||
===================
|
||||
|
||||
* manager: fix for latest node which is returning a clone with `listeners` [viirya]
|
||||
|
||||
0.9.11 / 2012-11-02
|
||||
===================
|
||||
|
||||
* package: move redis to optionalDependenices [3rd-Eden]
|
||||
* bumped client
|
||||
|
||||
0.9.10 / 2012-08-10
|
||||
===================
|
||||
|
||||
* Don't lowercase log messages
|
||||
* Always set the HTTP response in case an error should be returned to the client
|
||||
* Create or destroy the flash policy server on configuration change
|
||||
* Honour configuration to disable flash policy server
|
||||
* Add express 3.0 instructions on Readme.md
|
||||
* Bump client
|
||||
|
||||
0.9.9 / 2012-08-01
|
||||
==================
|
||||
|
||||
* Fixed sync disconnect xhrs handling
|
||||
* Put license text in its own file (#965)
|
||||
* Add warning to .listen() to ease the migration to Express 3.x
|
||||
* Restored compatibility with node 0.4.x
|
||||
|
||||
0.9.8 / 2012-07-24
|
||||
==================
|
||||
|
||||
* Bumped client.
|
||||
|
||||
0.9.7 / 2012-07-24
|
||||
==================
|
||||
|
||||
* Prevent crash when socket leaves a room twice.
|
||||
* Corrects unsafe usage of for..in
|
||||
* Fix for node 0.8 with `gzip compression` [vadimi]
|
||||
* Update redis to support Node 0.8.x
|
||||
* Made ID generation securely random
|
||||
* Fix Redis Store race condition in manager onOpen unsubscribe callback
|
||||
* Fix for EventEmitters always reusing the same Array instance for listeners
|
||||
|
||||
0.9.6 / 2012-04-17
|
||||
==================
|
||||
|
||||
* Fixed XSS in jsonp-polling.
|
||||
|
||||
0.9.5 / 2012-04-05
|
||||
==================
|
||||
|
||||
* Added test for polling and socket close.
|
||||
* Ensure close upon request close.
|
||||
* Fix disconnection reason being lost for polling transports.
|
||||
* Ensure that polling transports work with Connection: close.
|
||||
* Log disconnection reason.
|
||||
|
||||
0.9.4 / 2012-04-01
|
||||
==================
|
||||
|
||||
* Disconnecting from namespace improvement (#795) [DanielBaulig]
|
||||
* Bumped client with polling reconnection loop (#438)
|
||||
|
||||
0.9.3 / 2012-03-28
|
||||
==================
|
||||
|
||||
* Fix "Syntax error" on FF Web Console with XHR Polling [mikito]
|
||||
|
||||
0.9.2 / 2012-03-13
|
||||
==================
|
||||
|
||||
* More sensible close `timeout default` (fixes disconnect issue)
|
||||
|
||||
0.9.1-1 / 2012-03-02
|
||||
====================
|
||||
|
||||
* Bumped client with NPM dependency fix.
|
||||
|
||||
0.9.1 / 2012-03-02
|
||||
==================
|
||||
|
||||
* Changed heartbeat timeout and interval defaults (60 and 25 seconds)
|
||||
* Make tests work both on 0.4 and 0.6
|
||||
* Updated client (improvements + bug fixes).
|
||||
|
||||
0.9.0 / 2012-02-26
|
||||
==================
|
||||
|
||||
* Make it possible to use a regexp to match the socket.io resource URL.
|
||||
We need this because we have to prefix the socket.io URL with a variable ID.
|
||||
* Supplemental fix to gavinuhma/authfix, it looks like the same Access-Control-Origin logic is needed in the http and xhr-polling transports
|
||||
* Updated express dep for windows compatibility.
|
||||
* Combine two substr calls into one in decodePayload to improve performance
|
||||
* Minor documentation fix
|
||||
* Minor. Conform to style of other files.
|
||||
* Switching setting to 'match origin protocol'
|
||||
* Revert "Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect()."
|
||||
* Revert "Handle leaked dispatch:[id] subscription."
|
||||
* Merge pull request #667 from dshaw/patch/redis-disconnect
|
||||
* Handle leaked dispatch:[id] subscription.
|
||||
* Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect().
|
||||
* Prevent memory leaking on uncompleted requests & add max post size limitation
|
||||
* Fix for testcase
|
||||
* Set Access-Control-Allow-Credentials true, regardless of cookie
|
||||
* Remove assertvarnish from package as it breaks on 0.6
|
||||
* Correct irc channel
|
||||
* Added proper return after reserved field error
|
||||
* Fixes manager.js failure to close connection after transport error has happened
|
||||
* Added implicit port 80 for origin checks. fixes #638
|
||||
* Fixed bug #432 in 0.8.7
|
||||
* Set Access-Control-Allow-Origin header to origin to enable withCredentials
|
||||
* Adding configuration variable matchOriginProtocol
|
||||
* Fixes location mismatch error in Safari.
|
||||
* Use tty to detect if we should add colors or not by default.
|
||||
* Updated the package location.
|
||||
|
||||
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
|
||||
==================
|
||||
|
||||
|
||||
22
LICENSE
Normal file
22
LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
3
Makefile
3
Makefile
@@ -6,13 +6,12 @@ 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
|
||||
|
||||
29
Readme.md
29
Readme.md
@@ -6,7 +6,9 @@ horizontal scalability, automatic JSON encoding/decoding, and more.
|
||||
|
||||
## How to Install
|
||||
|
||||
npm install socket.io
|
||||
```bash
|
||||
npm install socket.io
|
||||
```
|
||||
|
||||
## How to use
|
||||
|
||||
@@ -19,6 +21,25 @@ var io = require('socket.io');
|
||||
Next, attach it to a HTTP/HTTPS server. If you're using the fantastic `express`
|
||||
web framework:
|
||||
|
||||
#### Express 3.x
|
||||
|
||||
```js
|
||||
var app = express()
|
||||
, server = require('http').createServer(app)
|
||||
, io = io.listen(server);
|
||||
|
||||
server.listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.emit('news', { hello: 'world' });
|
||||
socket.on('my other event', function (data) {
|
||||
console.log(data);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Express 2.x
|
||||
|
||||
```js
|
||||
var app = express.createServer()
|
||||
, io = io.listen(app);
|
||||
@@ -102,10 +123,10 @@ io.sockets.on('connection', function (socket) {
|
||||
var socket = io.connect('http://localhost');
|
||||
|
||||
socket.on('connect', function () {
|
||||
socket.emit('set nickname', confirm('What is your nickname?'));
|
||||
socket.emit('set nickname', prompt('What is your nickname?'));
|
||||
socket.on('ready', function () {
|
||||
console.log('Connected !');
|
||||
socket.emit('msg', confirm('What is your message?'));
|
||||
socket.emit('msg', prompt('What is your message?'));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -131,7 +152,7 @@ The following example defines a socket that listens on '/chat' and one for
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
var chat = io
|
||||
.of('/chat');
|
||||
.of('/chat')
|
||||
.on('connection', function (socket) {
|
||||
socket.emit('a message', { that: 'only', '/chat': 'will get' });
|
||||
chat.emit('a message', { everyone: 'in', '/chat': 'will get' });
|
||||
|
||||
@@ -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.5"
|
||||
, "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;
|
||||
|
||||
@@ -39,7 +39,7 @@ var Client = irc.Client = function(host, port) {
|
||||
this.user = null;
|
||||
this.real = null;
|
||||
}
|
||||
sys.inherits(Client, process.EventEmitter);
|
||||
sys.inherits(Client, require('events').EventEmitter);
|
||||
|
||||
Client.prototype.connect = function(nick, user, real) {
|
||||
var connection = tcp.createConnection(this.port, this.host);
|
||||
|
||||
@@ -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.5"
|
||||
, "jade": "0.16.4"
|
||||
, "stylus": "0.19.0"
|
||||
, "nib": "0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
213
lib/manager.js
213
lib/manager.js
@@ -10,6 +10,8 @@
|
||||
|
||||
var fs = require('fs')
|
||||
, url = require('url')
|
||||
, tty = require('tty')
|
||||
, crypto = require('crypto')
|
||||
, util = require('./util')
|
||||
, store = require('./store')
|
||||
, client = require('socket.io-client')
|
||||
@@ -19,7 +21,7 @@ var fs = require('fs')
|
||||
, MemoryStore = require('./stores/memory')
|
||||
, SocketNamespace = require('./namespace')
|
||||
, Static = require('./static')
|
||||
, EventEmitter = process.EventEmitter;
|
||||
, EventEmitter = require('events').EventEmitter;
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
@@ -43,7 +45,8 @@ var defaultTransports = exports.defaultTransports = [
|
||||
*/
|
||||
|
||||
var parent = module.parent.exports
|
||||
, protocol = parent.protocol;
|
||||
, protocol = parent.protocol
|
||||
, jsonpolling_re = /^\d+$/;
|
||||
|
||||
/**
|
||||
* Manager constructor.
|
||||
@@ -69,14 +72,15 @@ function Manager (server, options) {
|
||||
, authorization: false
|
||||
, blacklist: ['disconnect']
|
||||
, 'log level': 3
|
||||
, 'log colors': true
|
||||
, 'close timeout': 25
|
||||
, 'heartbeat timeout': 15
|
||||
, 'heartbeat interval': 20
|
||||
, 'log colors': tty.isatty(process.stdout.fd)
|
||||
, 'close timeout': 60
|
||||
, 'heartbeat interval': 25
|
||||
, 'heartbeat timeout': 60
|
||||
, 'polling duration': 20
|
||||
, 'flash policy server': true
|
||||
, 'flash policy port': 10843
|
||||
, 'destroy upgrade': true
|
||||
, 'destroy buffer size': 10E7
|
||||
, 'browser client': true
|
||||
, 'browser client cache': true
|
||||
, 'browser client minification': false
|
||||
@@ -85,14 +89,22 @@ function Manager (server, options) {
|
||||
, 'browser client gzip': false
|
||||
, 'browser client handler': false
|
||||
, 'client store expiration': 15
|
||||
, 'match origin protocol': false
|
||||
};
|
||||
|
||||
for (var i in options) {
|
||||
this.settings[i] = options[i];
|
||||
if (options.hasOwnProperty(i)) {
|
||||
this.settings[i] = options[i];
|
||||
}
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
// default error handler
|
||||
server.on('error', function(err) {
|
||||
self.log.warn('error raised: ' + err);
|
||||
});
|
||||
|
||||
this.initStore();
|
||||
|
||||
this.on('set:store', function() {
|
||||
@@ -100,7 +112,7 @@ function Manager (server, options) {
|
||||
});
|
||||
|
||||
// reset listeners
|
||||
this.oldListeners = server.listeners('request');
|
||||
this.oldListeners = server.listeners('request').splice(0);
|
||||
server.removeAllListeners('request');
|
||||
|
||||
server.on('request', function (req, res) {
|
||||
@@ -120,11 +132,21 @@ function Manager (server, options) {
|
||||
});
|
||||
|
||||
for (var i in transports) {
|
||||
if (transports[i].init) {
|
||||
transports[i].init(this);
|
||||
if (transports.hasOwnProperty(i)) {
|
||||
if (transports[i].init) {
|
||||
transports[i].init(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// forward-compatibility with 1.0
|
||||
var self = this;
|
||||
this.sockets.on('connection', function (conn) {
|
||||
self.emit('connection', conn);
|
||||
});
|
||||
|
||||
this.sequenceNumber = Date.now() | 0;
|
||||
|
||||
this.log.info('socket.io started');
|
||||
};
|
||||
|
||||
@@ -244,7 +266,7 @@ Manager.prototype.disabled = function (key) {
|
||||
Manager.prototype.configure = function (env, fn) {
|
||||
if ('function' == typeof env) {
|
||||
env.call(this);
|
||||
} else if (env == process.env.NODE_ENV) {
|
||||
} else if (env == (process.env.NODE_ENV || 'development')) {
|
||||
fn.call(this);
|
||||
}
|
||||
|
||||
@@ -262,7 +284,6 @@ Manager.prototype.initStore = function () {
|
||||
this.connected = {};
|
||||
this.open = {};
|
||||
this.closed = {};
|
||||
this.closedA = [];
|
||||
this.rooms = {};
|
||||
this.roomClients = {};
|
||||
|
||||
@@ -299,8 +320,46 @@ Manager.prototype.initStore = function () {
|
||||
this.store.subscribe('disconnect', function (id) {
|
||||
self.onDisconnect(id);
|
||||
});
|
||||
};
|
||||
|
||||
// we need to do this in a pub/sub way since the client can POST the message
|
||||
// over a different socket (ie: different Transport instance)
|
||||
|
||||
//use persistent channel for these, don't add and remove 5 channels for every connection
|
||||
//eg. for 10,000 concurrent users this creates 50,000 channels in redis, which kind of slows things down
|
||||
//we only need 5 (extra) total channels at all times
|
||||
this.store.subscribe('message-remote',function (id, packet) {
|
||||
self.onClientMessage(id, packet);
|
||||
});
|
||||
|
||||
this.store.subscribe('disconnect-remote', function (id, reason) {
|
||||
self.onClientDisconnect(id, reason);
|
||||
});
|
||||
|
||||
this.store.subscribe('dispatch-remote', function (id, packet, volatile) {
|
||||
var transport = self.transports[id];
|
||||
if (transport) {
|
||||
transport.onDispatch(packet, volatile);
|
||||
}
|
||||
|
||||
if (!volatile) {
|
||||
self.onClientDispatch(id, packet);
|
||||
}
|
||||
});
|
||||
|
||||
this.store.subscribe('heartbeat-clear', function (id) {
|
||||
var transport = self.transports[id];
|
||||
if (transport) {
|
||||
transport.onHeartbeatClear();
|
||||
}
|
||||
});
|
||||
|
||||
this.store.subscribe('disconnect-force', function (id) {
|
||||
var transport = self.transports[id];
|
||||
if (transport) {
|
||||
transport.onForcedDisconnect();
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Called when a client handshakes.
|
||||
*
|
||||
@@ -330,15 +389,20 @@ Manager.prototype.onConnect = function (id) {
|
||||
Manager.prototype.onOpen = function (id) {
|
||||
this.open[id] = true;
|
||||
|
||||
// if we were buffering messages for the client, clear them
|
||||
if (this.closed[id]) {
|
||||
var self = this;
|
||||
|
||||
this.closedA.splice(this.closedA.indexOf(id), 1);
|
||||
var transport = self.transports[id];
|
||||
if (self.closed[id] && self.closed[id].length && transport) {
|
||||
|
||||
this.store.unsubscribe('dispatch:' + id, function () {
|
||||
delete self.closed[id];
|
||||
});
|
||||
// if we have buffered messages that accumulate between calling
|
||||
// onOpen an this async callback, send them if the transport is
|
||||
// still open, otherwise leave them buffered
|
||||
if (transport.open) {
|
||||
transport.payload(self.closed[id]);
|
||||
self.closed[id] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear the current transport
|
||||
@@ -408,7 +472,10 @@ Manager.prototype.onLeave = function (id, room) {
|
||||
if (!this.rooms[room].length) {
|
||||
delete this.rooms[room];
|
||||
}
|
||||
delete this.roomClients[id][room];
|
||||
|
||||
if (this.roomClients[id]) {
|
||||
delete this.roomClients[id][room];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -424,15 +491,8 @@ Manager.prototype.onClose = function (id) {
|
||||
}
|
||||
|
||||
this.closed[id] = [];
|
||||
this.closedA.push(id);
|
||||
|
||||
var self = this;
|
||||
|
||||
this.store.subscribe('dispatch:' + id, function (packet, volatile) {
|
||||
if (!volatile) {
|
||||
self.onClientDispatch(id, packet);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -467,8 +527,9 @@ 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);
|
||||
if (this.namespaces.hasOwnProperty(name)) {
|
||||
this.namespaces[name].handleDisconnect(id, reason, typeof this.roomClients[id] !== 'undefined' &&
|
||||
typeof this.roomClients[id][name] !== 'undefined');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +542,7 @@ Manager.prototype.onClientDisconnect = function (id, reason) {
|
||||
* @param text
|
||||
*/
|
||||
|
||||
Manager.prototype.onDisconnect = function (id, local) {
|
||||
Manager.prototype.onDisconnect = function (id) {
|
||||
delete this.handshaken[id];
|
||||
|
||||
if (this.open[id]) {
|
||||
@@ -499,24 +560,18 @@ 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]) {
|
||||
for (var room in this.roomClients[id]) {
|
||||
this.onLeave(id, room);
|
||||
if (this.roomClients[id].hasOwnProperty(room)) {
|
||||
this.onLeave(id, room);
|
||||
}
|
||||
}
|
||||
delete this.roomClients[id]
|
||||
}
|
||||
|
||||
this.store.destroyClient(id, this.get('client store expiration'));
|
||||
|
||||
this.store.unsubscribe('dispatch:' + id);
|
||||
|
||||
if (local) {
|
||||
this.store.unsubscribe('message:' + id);
|
||||
this.store.unsubscribe('disconnect:' + id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -584,6 +639,7 @@ Manager.prototype.handleUpgrade = function (req, socket, head) {
|
||||
|
||||
req.head = head;
|
||||
this.handleClient(data, req);
|
||||
req.head = null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -608,12 +664,15 @@ Manager.prototype.handleClient = function (data, req) {
|
||||
, store = this.store
|
||||
, self = this;
|
||||
|
||||
// handle sync disconnect xhrs
|
||||
if (undefined != data.query.disconnect) {
|
||||
if (this.transports[data.id] && this.transports[data.id].open) {
|
||||
this.transports[data.id].onForcedDisconnect();
|
||||
} else {
|
||||
this.store.publish('disconnect-force:' + data.id);
|
||||
this.store.publish('disconnect-force', data.id);
|
||||
}
|
||||
req.res.writeHead(200);
|
||||
req.res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -626,6 +685,11 @@ Manager.prototype.handleClient = function (data, req) {
|
||||
var transport = new transports[data.transport](this, data, req)
|
||||
, handshaken = this.handshaken[data.id];
|
||||
|
||||
if (transport.disconnected) {
|
||||
// failed during transport setup
|
||||
req.connection.end();
|
||||
return;
|
||||
}
|
||||
if (handshaken) {
|
||||
if (transport.open) {
|
||||
if (this.closed[data.id] && this.closed[data.id].length) {
|
||||
@@ -649,21 +713,15 @@ Manager.prototype.handleClient = function (data, req) {
|
||||
|
||||
// initialize the socket for all namespaces
|
||||
for (var i in this.namespaces) {
|
||||
var socket = this.namespaces[i].socket(data.id, true);
|
||||
if (this.namespaces.hasOwnProperty(i)) {
|
||||
var socket = this.namespaces[i].socket(data.id, true);
|
||||
|
||||
// echo back connect packet and fire connection event
|
||||
if (i === '') {
|
||||
this.namespaces[i].handlePacket(data.id, { type: 'connect' });
|
||||
// echo back connect packet and fire connection event
|
||||
if (i === '') {
|
||||
this.namespaces[i].handlePacket(data.id, { type: 'connect' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.store.subscribe('message:' + data.id, function (packet) {
|
||||
self.onClientMessage(data.id, packet);
|
||||
});
|
||||
|
||||
this.store.subscribe('disconnect:' + data.id, function (reason) {
|
||||
self.onClientDisconnect(data.id, reason);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (transport.open) {
|
||||
@@ -681,8 +739,22 @@ Manager.prototype.handleClient = function (data, req) {
|
||||
*/
|
||||
|
||||
Manager.prototype.generateId = function () {
|
||||
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
|
||||
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
|
||||
var rand = new Buffer(15); // multiple of 3 for base64
|
||||
if (!rand.writeInt32BE) {
|
||||
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
|
||||
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
|
||||
}
|
||||
this.sequenceNumber = (this.sequenceNumber + 1) | 0;
|
||||
rand.writeInt32BE(this.sequenceNumber, 11);
|
||||
if (crypto.randomBytes) {
|
||||
crypto.randomBytes(12).copy(rand);
|
||||
} else {
|
||||
// not secure for node 0.4
|
||||
[0, 4, 8].forEach(function(i) {
|
||||
rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i);
|
||||
});
|
||||
}
|
||||
return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -699,7 +771,7 @@ Manager.prototype.handleHandshake = function (data, req, res) {
|
||||
};
|
||||
|
||||
function writeErr (status, message) {
|
||||
if (data.query.jsonp) {
|
||||
if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) {
|
||||
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
||||
res.end('io.j[' + data.query.jsonp + '](new Error("' + message + '"));');
|
||||
} else {
|
||||
@@ -722,11 +794,8 @@ Manager.prototype.handleHandshake = function (data, req, res) {
|
||||
|
||||
if (origin) {
|
||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
||||
headers['Access-Control-Allow-Origin'] = '*';
|
||||
|
||||
if (req.headers.cookie) {
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
headers['Access-Control-Allow-Origin'] = origin;
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
|
||||
this.authorize(handshakeData, function (err, authorized, newData) {
|
||||
@@ -741,18 +810,18 @@ Manager.prototype.handleHandshake = function (data, req, res) {
|
||||
, self.transports(data).join(',')
|
||||
].join(':');
|
||||
|
||||
if (data.query.jsonp) {
|
||||
if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) {
|
||||
hs = 'io.j[' + data.query.jsonp + '](' + JSON.stringify(hs) + ');';
|
||||
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
||||
} else {
|
||||
res.writeHead(200, headers);
|
||||
}
|
||||
|
||||
res.end(hs);
|
||||
|
||||
self.onHandshake(id, newData || handshakeData);
|
||||
self.store.publish('handshake', id, newData || handshakeData);
|
||||
|
||||
res.end(hs);
|
||||
|
||||
self.log.info('handshake authorized', id);
|
||||
} else {
|
||||
writeErr(403, 'handshake unauthorized');
|
||||
@@ -776,12 +845,12 @@ Manager.prototype.handshakeData = function (data) {
|
||||
connectionAddress = {
|
||||
address: connection.remoteAddress
|
||||
, port: connection.remotePort
|
||||
};
|
||||
};
|
||||
} else if (connection.socket && connection.socket.remoteAddress) {
|
||||
connectionAddress = {
|
||||
address: connection.socket.remoteAddress
|
||||
, port: connection.socket.remotePort
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -815,6 +884,7 @@ Manager.prototype.verifyOrigin = function (request) {
|
||||
if (origin) {
|
||||
try {
|
||||
var parts = url.parse(origin);
|
||||
parts.port = parts.port || 80;
|
||||
var ok =
|
||||
~origins.indexOf(parts.hostname + ':' + parts.port) ||
|
||||
~origins.indexOf(parts.hostname + ':*') ||
|
||||
@@ -826,7 +896,7 @@ Manager.prototype.verifyOrigin = function (request) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.log.warn('origin missing from handshake, yet required by config');
|
||||
this.log.warn('origin missing from handshake, yet required by config');
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -899,8 +969,17 @@ var regexp = /^\/([^\/]+)\/?([^\/]+)?\/?([^\/]+)?\/?$/
|
||||
Manager.prototype.checkRequest = function (req) {
|
||||
var resource = this.get('resource');
|
||||
|
||||
if (req.url.substr(0, resource.length) == resource) {
|
||||
var uri = url.parse(req.url.substr(resource.length), true)
|
||||
var match;
|
||||
if (typeof resource === 'string') {
|
||||
match = req.url.substr(0, resource.length);
|
||||
if (match !== resource) match = null;
|
||||
} else {
|
||||
match = resource.exec(req.url);
|
||||
if (match) match = match[0];
|
||||
}
|
||||
|
||||
if (match) {
|
||||
var uri = url.parse(req.url.substr(match.length), true)
|
||||
, path = uri.pathname || ''
|
||||
, pieces = path.match(regexp);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
var Socket = require('./socket')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, EventEmitter = require('events').EventEmitter
|
||||
, parser = require('./parser')
|
||||
, util = require('./util');
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -234,7 +234,7 @@ exports.decodePayload = function (data) {
|
||||
|
||||
for (var i = 1, length = ''; i < data.length; i++) {
|
||||
if (data[i] == '\ufffd') {
|
||||
ret.push(exports.decodePacket(data.substr(i + 1).substr(0, length)));
|
||||
ret.push(exports.decodePacket(data.substr(i + 1, length)));
|
||||
i += Number(length) + 1;
|
||||
length = '';
|
||||
} else {
|
||||
|
||||
@@ -15,7 +15,7 @@ var client = require('socket.io-client');
|
||||
* Version.
|
||||
*/
|
||||
|
||||
exports.version = '0.8.6';
|
||||
exports.version = '0.9.16';
|
||||
|
||||
/**
|
||||
* Supported protocol version.
|
||||
@@ -39,6 +39,13 @@ exports.clientVersion = client.version;
|
||||
*/
|
||||
|
||||
exports.listen = function (server, options, fn) {
|
||||
if ('function' == typeof server) {
|
||||
console.warn('Socket.IO\'s `listen()` method expects an `http.Server` instance\n'
|
||||
+ 'as its first parameter. Are you migrating from Express 2.x to 3.x?\n'
|
||||
+ 'If so, check out the "Socket.IO compatibility" section at:\n'
|
||||
+ 'https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x');
|
||||
}
|
||||
|
||||
if ('function' == typeof options) {
|
||||
fn = options;
|
||||
options = {};
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
var parser = require('./parser')
|
||||
, util = require('./util')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, EventEmitter = require('events').EventEmitter
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
@@ -233,7 +233,7 @@ Socket.prototype.dispatch = function (packet, volatile) {
|
||||
this.manager.onClientDispatch(this.id, packet, volatile);
|
||||
}
|
||||
|
||||
this.manager.store.publish('dispatch:' + this.id, packet, volatile);
|
||||
this.manager.store.publish('dispatch-remote', this.id, packet, volatile);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -291,12 +291,19 @@ Socket.prototype.disconnect = function () {
|
||||
if (!this.disconnected) {
|
||||
this.log.info('booting client');
|
||||
|
||||
if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
|
||||
this.manager.transports[this.id].onForcedDisconnect();
|
||||
if ('' === this.namespace.name) {
|
||||
if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
|
||||
this.manager.transports[this.id].onForcedDisconnect();
|
||||
} else {
|
||||
this.manager.onClientDisconnect(this.id);
|
||||
this.manager.store.publish('disconnect-remote', this.id);
|
||||
}
|
||||
} else {
|
||||
this.manager.onClientDisconnect(this.id);
|
||||
this.manager.store.publish('disconnect:' + this.id);
|
||||
this.packet({type: 'disconnect'});
|
||||
this.manager.onLeave(this.id, this.namespace.name);
|
||||
this.$emit('disconnect', 'booted');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
@@ -178,7 +178,7 @@ Static.prototype.gzip = function (data, callback) {
|
||||
buffer.length = 0;
|
||||
});
|
||||
|
||||
gzip.on('exit', function () {
|
||||
gzip.on('close', function () {
|
||||
if (err) return callback(err);
|
||||
|
||||
var size = 0
|
||||
|
||||
@@ -15,7 +15,7 @@ exports = module.exports = Store;
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var EventEmitter = process.EventEmitter;
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
/**
|
||||
* Store interface
|
||||
|
||||
@@ -89,20 +89,6 @@ Transport.prototype.onSocketConnect = function () { };
|
||||
Transport.prototype.setHandlers = function () {
|
||||
var self = this;
|
||||
|
||||
// we need to do this in a pub/sub way since the client can POST the message
|
||||
// over a different socket (ie: different Transport instance)
|
||||
this.store.subscribe('heartbeat-clear:' + this.id, function () {
|
||||
self.onHeartbeatClear();
|
||||
});
|
||||
|
||||
this.store.subscribe('disconnect-force:' + this.id, function () {
|
||||
self.onForcedDisconnect();
|
||||
});
|
||||
|
||||
this.store.subscribe('dispatch:' + this.id, function (packet, volatile) {
|
||||
self.onDispatch(packet, volatile);
|
||||
});
|
||||
|
||||
this.bound = {
|
||||
end: this.onSocketEnd.bind(this)
|
||||
, close: this.onSocketClose.bind(this)
|
||||
@@ -126,10 +112,6 @@ Transport.prototype.setHandlers = function () {
|
||||
|
||||
Transport.prototype.clearHandlers = function () {
|
||||
if (this.handlersSet) {
|
||||
this.store.unsubscribe('disconnect-force:' + this.id);
|
||||
this.store.unsubscribe('heartbeat-clear:' + this.id);
|
||||
this.store.unsubscribe('dispatch:' + this.id);
|
||||
|
||||
this.socket.removeListener('end', this.bound.end);
|
||||
this.socket.removeListener('close', this.bound.close);
|
||||
this.socket.removeListener('error', this.bound.error);
|
||||
@@ -350,7 +332,7 @@ Transport.prototype.onMessage = function (packet) {
|
||||
if (current && current.open) {
|
||||
current.onHeartbeatClear();
|
||||
} else {
|
||||
this.store.publish('heartbeat-clear:' + this.id);
|
||||
this.store.publish('heartbeat-clear', this.id);
|
||||
}
|
||||
} else {
|
||||
if ('disconnect' == packet.type && packet.endpoint == '') {
|
||||
@@ -359,7 +341,7 @@ Transport.prototype.onMessage = function (packet) {
|
||||
if (current) {
|
||||
current.onForcedDisconnect();
|
||||
} else {
|
||||
this.store.publish('disconnect-force:' + this.id);
|
||||
this.store.publish('disconnect-force', this.id);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -378,7 +360,7 @@ Transport.prototype.onMessage = function (packet) {
|
||||
current.onDispatch(ack);
|
||||
} else {
|
||||
this.manager.onClientDispatch(this.id, ack);
|
||||
this.store.publish('dispatch:' + this.id, ack);
|
||||
this.store.publish('dispatch-remote', this.id, ack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +368,7 @@ Transport.prototype.onMessage = function (packet) {
|
||||
if (current) {
|
||||
this.manager.onClientMessage(this.id, packet);
|
||||
} else {
|
||||
this.store.publish('message:' + this.id, packet);
|
||||
this.store.publish('message-remote', this.id, packet);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -455,7 +437,7 @@ Transport.prototype.onClose = function () {
|
||||
|
||||
Transport.prototype.end = function (reason) {
|
||||
if (!this.disconnected) {
|
||||
this.log.info('transport end');
|
||||
this.log.info('transport end (' + reason + ')');
|
||||
|
||||
var local = this.manager.transports[this.id];
|
||||
|
||||
@@ -464,10 +446,10 @@ Transport.prototype.end = function (reason) {
|
||||
this.disconnected = true;
|
||||
|
||||
if (local) {
|
||||
this.manager.onClientDisconnect(this.id, reason, true);
|
||||
} else {
|
||||
this.store.publish('disconnect:' + this.id, reason);
|
||||
this.manager.onClientDisconnect(this.id, reason);
|
||||
}
|
||||
|
||||
this.store.publish('disconnect-remote', this.id, reason);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
@@ -49,13 +48,20 @@ FlashSocket.prototype.name = 'flashsocket';
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var server;
|
||||
|
||||
FlashSocket.init = function (manager) {
|
||||
var server;
|
||||
function create () {
|
||||
|
||||
// Drop out immediately if the user has
|
||||
// disabled the flash policy server
|
||||
if (!manager.get('flash policy server')) {
|
||||
return;
|
||||
}
|
||||
|
||||
server = require('policyfile').createServer({
|
||||
log: function(msg){
|
||||
manager.log.info(msg.toLowerCase());
|
||||
manager.log.info(msg);
|
||||
}
|
||||
}, manager.get('origins'));
|
||||
|
||||
@@ -80,10 +86,32 @@ 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 (~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();
|
||||
}
|
||||
});
|
||||
|
||||
if (server && server.port !== value && ~transports.indexOf('flashsocket')) {
|
||||
// destroy the server and rebuild it on a new port
|
||||
server.close();
|
||||
// create or destroy the server
|
||||
manager.on('set:flash policy server', function (value, key) {
|
||||
var transports = manager.get('transports');
|
||||
if (~transports.indexOf('flashsocket')) {
|
||||
if (server && !value) {
|
||||
// destroy the server
|
||||
try {
|
||||
server.close();
|
||||
}
|
||||
catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ }
|
||||
}
|
||||
} else if (!server && value) {
|
||||
// create the server
|
||||
create();
|
||||
}
|
||||
});
|
||||
@@ -94,7 +122,6 @@ FlashSocket.init = function (manager) {
|
||||
create();
|
||||
}
|
||||
});
|
||||
|
||||
// check if we need to initialize at start
|
||||
if (~manager.get('transports').indexOf('flashsocket')){
|
||||
create();
|
||||
|
||||
@@ -72,7 +72,8 @@ HTMLFile.prototype.handleRequest = function (req) {
|
||||
*/
|
||||
|
||||
HTMLFile.prototype.write = function (data) {
|
||||
data = '<script>_(' + JSON.stringify(data) + ');</script>';
|
||||
// escape all forward slashes. see GH-1251
|
||||
data = '<script>_(' + JSON.stringify(data).replace(/\//g, '\\/') + ');</script>';
|
||||
|
||||
if (this.response.write(data)) {
|
||||
this.drained = true;
|
||||
|
||||
@@ -43,6 +43,18 @@ HTTPPolling.prototype.__proto__ = HTTPTransport.prototype;
|
||||
|
||||
HTTPPolling.prototype.name = 'httppolling';
|
||||
|
||||
/**
|
||||
* Override setHandlers
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.setHandlers = function () {
|
||||
HTTPTransport.prototype.setHandlers.call(this);
|
||||
this.socket.removeListener('end', this.bound.end);
|
||||
this.socket.removeListener('close', this.bound.close);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes heartbeat timeouts for polling.
|
||||
*/
|
||||
@@ -128,8 +140,8 @@ HTTPPolling.prototype.write = function (data, close) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.end = function () {
|
||||
HTTPPolling.prototype.end = function (reason) {
|
||||
this.clearPollTimeout();
|
||||
return HTTPTransport.prototype.end.call(this);
|
||||
return HTTPTransport.prototype.end.call(this, reason);
|
||||
};
|
||||
|
||||
|
||||
@@ -42,15 +42,24 @@ HTTPTransport.prototype.__proto__ = Transport.prototype;
|
||||
*/
|
||||
|
||||
HTTPTransport.prototype.handleRequest = function (req) {
|
||||
|
||||
// Always set the response in case an error is returned to the client
|
||||
this.response = req.res;
|
||||
|
||||
if (req.method == 'POST') {
|
||||
var buffer = ''
|
||||
, res = req.res
|
||||
, origin = req.headers.origin
|
||||
, headers = { 'Content-Length': 1 }
|
||||
, headers = { 'Content-Length': 1, 'Content-Type': 'text/plain; charset=UTF-8' }
|
||||
, self = this;
|
||||
|
||||
req.on('data', function (data) {
|
||||
buffer += data;
|
||||
|
||||
if (Buffer.byteLength(buffer) >= self.manager.get('destroy buffer size')) {
|
||||
buffer = '';
|
||||
req.connection.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
req.on('end', function () {
|
||||
@@ -60,17 +69,19 @@ HTTPTransport.prototype.handleRequest = function (req) {
|
||||
self.onData(self.postEncoded ? qs.parse(buffer).d : buffer);
|
||||
});
|
||||
|
||||
// prevent memory leaks for uncompleted requests
|
||||
req.on('close', function () {
|
||||
buffer = '';
|
||||
self.onClose();
|
||||
});
|
||||
|
||||
if (origin) {
|
||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
||||
headers['Access-Control-Allow-Origin'] = '*';
|
||||
|
||||
if (req.headers.cookie) {
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
headers['Access-Control-Allow-Origin'] = origin;
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
headers['X-XSS-Protection'] = '0';
|
||||
}
|
||||
} else {
|
||||
this.response = req.res;
|
||||
|
||||
Transport.prototype.handleRequest.call(this, req);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
var HTTPPolling = require('./http-polling');
|
||||
var jsonpolling_re = /^\d+$/
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
@@ -29,7 +30,7 @@ function JSONPPolling (mng, data, req) {
|
||||
this.head = 'io.j[0](';
|
||||
this.foot = ');';
|
||||
|
||||
if (data.query.i) {
|
||||
if (data.query.i && jsonpolling_re.test(data.query.i)) {
|
||||
this.head = 'io.j[' + data.query.i + '](';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
@@ -10,7 +9,7 @@
|
||||
*/
|
||||
|
||||
var Transport = require('../../transport')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, EventEmitter = require('events').EventEmitter
|
||||
, crypto = require('crypto')
|
||||
, parser = require('../../parser');
|
||||
|
||||
@@ -31,7 +30,7 @@ function WebSocket (mng, data, req) {
|
||||
// parser
|
||||
var self = this;
|
||||
|
||||
this.parser = new Parser();
|
||||
this.parser = new Parser({maxBuffer: mng.get('destroy buffer size')});
|
||||
this.parser.on('data', function (packet) {
|
||||
self.log.debug(self.name + ' received data packet', packet);
|
||||
self.onMessage(parser.decodePacket(packet));
|
||||
@@ -42,6 +41,11 @@ function WebSocket (mng, data, req) {
|
||||
this.parser.on('error', function () {
|
||||
self.end();
|
||||
});
|
||||
this.parser.on('kick', function (reason) {
|
||||
self.log.warn(self.name + ' parser forced user kick: ' + reason);
|
||||
self.onMessage({type: 'disconnect', endpoint: ''});
|
||||
self.end();
|
||||
});
|
||||
|
||||
Transport.call(this, mng, data, req);
|
||||
};
|
||||
@@ -88,10 +92,15 @@ WebSocket.prototype.onSocketConnect = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
var origin = this.req.headers.origin
|
||||
, location = (this.socket.encrypted ? 'wss' : 'ws')
|
||||
+ '://' + this.req.headers.host + this.req.url
|
||||
, waitingForNonce = false;
|
||||
var origin = this.req.headers['origin']
|
||||
, waitingForNonce = false;
|
||||
if(this.manager.settings['match origin protocol']){
|
||||
location = (origin.indexOf('https')>-1 ? 'wss' : 'ws') + '://' + this.req.headers.host + this.req.url;
|
||||
}else if(this.socket.encrypted){
|
||||
location = 'wss://' + this.req.headers.host + this.req.url;
|
||||
}else{
|
||||
location = 'ws://' + this.req.headers.host + this.req.url;
|
||||
}
|
||||
|
||||
if (this.req.headers['sec-websocket-key1']) {
|
||||
// If we don't have the nonce yet, wait for it (HAProxy compatibility).
|
||||
@@ -289,7 +298,9 @@ WebSocket.prototype.doClose = function () {
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Parser () {
|
||||
function Parser (opts) {
|
||||
this._maxBuffer = (opts && opts.maxBuffer) || 10E7;
|
||||
this._dataLength = 0;
|
||||
this.buffer = '';
|
||||
this.i = 0;
|
||||
};
|
||||
@@ -307,6 +318,13 @@ Parser.prototype.__proto__ = EventEmitter.prototype;
|
||||
*/
|
||||
|
||||
Parser.prototype.add = function (data) {
|
||||
this._dataLength += data.length;
|
||||
if(this._dataLength > this._maxBuffer) {
|
||||
this.buffer = ''; //Clear buffer
|
||||
this.emit('kick', 'max buffer size reached');
|
||||
return;
|
||||
}
|
||||
|
||||
this.buffer += data;
|
||||
this.parse();
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
var Transport = require('../../transport')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, EventEmitter = require('events').EventEmitter
|
||||
, crypto = require('crypto')
|
||||
, url = require('url')
|
||||
, parser = require('../../parser')
|
||||
@@ -35,7 +35,7 @@ function WebSocket (mng, data, req) {
|
||||
var self = this;
|
||||
|
||||
this.manager = mng;
|
||||
this.parser = new Parser();
|
||||
this.parser = new Parser({maxBuffer: mng.get('destroy buffer size')});
|
||||
this.parser.on('data', function (packet) {
|
||||
self.onMessage(parser.decodePacket(packet));
|
||||
});
|
||||
@@ -56,6 +56,11 @@ function WebSocket (mng, data, req) {
|
||||
self.log.warn(self.name + ' parser error: ' + reason);
|
||||
self.end();
|
||||
});
|
||||
this.parser.on('kick', function (reason) {
|
||||
self.log.warn(self.name + ' parser forced user kick: ' + reason);
|
||||
self.onMessage({type: 'disconnect', endpoint: ''});
|
||||
self.end();
|
||||
});
|
||||
|
||||
Transport.call(this, mng, data, req);
|
||||
};
|
||||
@@ -91,14 +96,17 @@ WebSocket.prototype.protocolVersion = '07-12';
|
||||
WebSocket.prototype.onSocketConnect = function () {
|
||||
var self = this;
|
||||
|
||||
if (this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
if (typeof this.req.headers.upgrade === 'undefined' ||
|
||||
this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
this.log.warn(this.name + ' connection invalid');
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
var origin = this.req.headers['sec-websocket-origin']
|
||||
, location = (this.socket.encrypted ? 'wss' : 'ws')
|
||||
, location = ((this.manager.settings['match origin protocol'] ?
|
||||
origin.match(/^https/) : this.socket.encrypted) ?
|
||||
'wss' : 'ws')
|
||||
+ '://' + this.req.headers.host + this.req.url;
|
||||
|
||||
if (!this.verifyOrigin(origin)) {
|
||||
@@ -158,6 +166,7 @@ WebSocket.prototype.verifyOrigin = function (origin) {
|
||||
if (origin) {
|
||||
try {
|
||||
var parts = url.parse(origin);
|
||||
parts.port = parts.port || 80;
|
||||
var ok =
|
||||
~origins.indexOf(parts.hostname + ':' + parts.port) ||
|
||||
~origins.indexOf(parts.hostname + ':*') ||
|
||||
@@ -262,7 +271,7 @@ WebSocket.prototype.doClose = function () {
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Parser () {
|
||||
function Parser (opts) {
|
||||
this.state = {
|
||||
activeFragmentedOperation: null,
|
||||
lastFragment: false,
|
||||
@@ -274,6 +283,8 @@ function Parser () {
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
this.currentMessage = '';
|
||||
this._maxBuffer = (opts && opts.maxBuffer) || 10E7;
|
||||
this._dataLength = 0;
|
||||
|
||||
var self = this;
|
||||
this.opcodeHandlers = {
|
||||
@@ -444,6 +455,15 @@ Parser.prototype.__proto__ = EventEmitter.prototype;
|
||||
*/
|
||||
|
||||
Parser.prototype.add = function(data) {
|
||||
this._dataLength += data.length;
|
||||
if (this._dataLength > this._maxBuffer) {
|
||||
// Clear data
|
||||
this.overflow = null;
|
||||
this.expectBuffer = null;
|
||||
// Kick client
|
||||
this.emit('kick', 'max buffer size reached');
|
||||
return;
|
||||
}
|
||||
if (this.expectBuffer == null) {
|
||||
this.addToOverflow(data);
|
||||
return;
|
||||
@@ -487,6 +507,10 @@ Parser.prototype.addToOverflow = function(data) {
|
||||
*/
|
||||
|
||||
Parser.prototype.expect = function(what, length, handler) {
|
||||
if (length > this._maxBuffer) {
|
||||
this.emit('kick', 'expected input larger than max buffer');
|
||||
return;
|
||||
}
|
||||
this.expectBuffer = new Buffer(length);
|
||||
this.expectOffset = 0;
|
||||
this.expectHandler = handler;
|
||||
@@ -504,7 +528,9 @@ Parser.prototype.expect = function(what, length, handler) {
|
||||
*/
|
||||
|
||||
Parser.prototype.processPacket = function (data) {
|
||||
if ((data[0] & 0x70) != 0) this.error('reserved fields must be empty');
|
||||
if ((data[0] & 0x70) != 0) {
|
||||
this.error('reserved fields must be empty');
|
||||
}
|
||||
this.state.lastFragment = (data[0] & 0x80) == 0x80;
|
||||
this.state.masked = (data[1] & 0x80) == 0x80;
|
||||
var opcode = data[0] & 0xf;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
@@ -10,7 +9,7 @@
|
||||
*/
|
||||
|
||||
var Transport = require('../../transport')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, EventEmitter = require('events').EventEmitter
|
||||
, crypto = require('crypto')
|
||||
, url = require('url')
|
||||
, parser = require('../../parser')
|
||||
@@ -35,7 +34,7 @@ function WebSocket (mng, data, req) {
|
||||
var self = this;
|
||||
|
||||
this.manager = mng;
|
||||
this.parser = new Parser();
|
||||
this.parser = new Parser({maxBuffer: mng.get('destroy buffer size')});
|
||||
this.parser.on('data', function (packet) {
|
||||
self.onMessage(parser.decodePacket(packet));
|
||||
});
|
||||
@@ -56,6 +55,11 @@ function WebSocket (mng, data, req) {
|
||||
self.log.warn(self.name + ' parser error: ' + reason);
|
||||
self.end();
|
||||
});
|
||||
this.parser.on('kick', function (reason) {
|
||||
self.log.warn(self.name + ' parser forced user kick: ' + reason);
|
||||
self.onMessage({type: 'disconnect', endpoint: ''});
|
||||
self.end();
|
||||
});
|
||||
|
||||
Transport.call(this, mng, data, req);
|
||||
};
|
||||
@@ -91,14 +95,17 @@ WebSocket.prototype.protocolVersion = '16';
|
||||
WebSocket.prototype.onSocketConnect = function () {
|
||||
var self = this;
|
||||
|
||||
if (this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
if (typeof this.req.headers.upgrade === 'undefined' ||
|
||||
this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
this.log.warn(this.name + ' connection invalid');
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
var origin = this.req.headers['origin']
|
||||
, location = (this.socket.encrypted ? 'wss' : 'ws')
|
||||
var origin = this.req.headers['origin'] || ''
|
||||
, location = ((this.manager.settings['match origin protocol'] ?
|
||||
origin.match(/^https/) : this.socket.encrypted) ?
|
||||
'wss' : 'ws')
|
||||
+ '://' + this.req.headers.host + this.req.url;
|
||||
|
||||
if (!this.verifyOrigin(origin)) {
|
||||
@@ -158,6 +165,7 @@ WebSocket.prototype.verifyOrigin = function (origin) {
|
||||
if (origin) {
|
||||
try {
|
||||
var parts = url.parse(origin);
|
||||
parts.port = parts.port || 80;
|
||||
var ok =
|
||||
~origins.indexOf(parts.hostname + ':' + parts.port) ||
|
||||
~origins.indexOf(parts.hostname + ':*') ||
|
||||
@@ -262,7 +270,7 @@ WebSocket.prototype.doClose = function () {
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Parser () {
|
||||
function Parser (opts) {
|
||||
this.state = {
|
||||
activeFragmentedOperation: null,
|
||||
lastFragment: false,
|
||||
@@ -274,6 +282,8 @@ function Parser () {
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
this.currentMessage = '';
|
||||
this._maxBuffer = (opts && opts.maxBuffer) || 10E7;
|
||||
this._dataLength = 0;
|
||||
|
||||
var self = this;
|
||||
this.opcodeHandlers = {
|
||||
@@ -444,6 +454,15 @@ Parser.prototype.__proto__ = EventEmitter.prototype;
|
||||
*/
|
||||
|
||||
Parser.prototype.add = function(data) {
|
||||
this._dataLength += data.length;
|
||||
if (this._dataLength > this._maxBuffer) {
|
||||
// Clear data
|
||||
this.overflow = null;
|
||||
this.expectBuffer = null;
|
||||
// Kick client
|
||||
this.emit('kick', 'max buffer size reached');
|
||||
return;
|
||||
}
|
||||
if (this.expectBuffer == null) {
|
||||
this.addToOverflow(data);
|
||||
return;
|
||||
@@ -487,6 +506,10 @@ Parser.prototype.addToOverflow = function(data) {
|
||||
*/
|
||||
|
||||
Parser.prototype.expect = function(what, length, handler) {
|
||||
if (length > this._maxBuffer) {
|
||||
this.emit('kick', 'expected input larger than max buffer');
|
||||
return;
|
||||
}
|
||||
this.expectBuffer = new Buffer(length);
|
||||
this.expectOffset = 0;
|
||||
this.expectHandler = handler;
|
||||
@@ -504,7 +527,10 @@ Parser.prototype.expect = function(what, length, handler) {
|
||||
*/
|
||||
|
||||
Parser.prototype.processPacket = function (data) {
|
||||
if ((data[0] & 0x70) != 0) this.error('reserved fields must be empty');
|
||||
if ((data[0] & 0x70) != 0) {
|
||||
this.error('reserved fields must be empty');
|
||||
return;
|
||||
}
|
||||
this.state.lastFragment = (data[0] & 0x80) == 0x80;
|
||||
this.state.masked = (data[1] & 0x80) == 0x80;
|
||||
var opcode = data[0] & 0xf;
|
||||
|
||||
@@ -59,11 +59,8 @@ XHRPolling.prototype.doWrite = function (data) {
|
||||
|
||||
if (origin) {
|
||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
||||
headers['Access-Control-Allow-Origin'] = '*';
|
||||
|
||||
if (this.req.headers.cookie) {
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
headers['Access-Control-Allow-Origin'] = origin;
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
|
||||
this.response.writeHead(200, headers);
|
||||
|
||||
19
package.json
19
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "socket.io"
|
||||
, "version": "0.8.6"
|
||||
, "version": "0.9.19"
|
||||
, "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,18 +16,23 @@
|
||||
, "url": "https://github.com/LearnBoost/socket.io.git"
|
||||
}
|
||||
, "dependencies": {
|
||||
"socket.io-client": "0.8.6"
|
||||
"socket.io-client": "0.9.16"
|
||||
, "policyfile": "0.0.4"
|
||||
, "redis": "0.6.7"
|
||||
, "base64id": "0.1.0"
|
||||
}
|
||||
, "devDependencies": {
|
||||
"expresso": "0.7.7"
|
||||
, "should": "0.0.4"
|
||||
, "assertvanish": "0.0.3-1"
|
||||
"expresso": "0.9.2"
|
||||
, "should": "*"
|
||||
, "benchmark": "0.2.2"
|
||||
, "microtime": "0.1.3-1"
|
||||
, "microtime": "2.1.3"
|
||||
, "colors": "0.5.1"
|
||||
}
|
||||
, "optionalDependencies": {
|
||||
"redis": "0.7.3"
|
||||
}
|
||||
, "main": "index"
|
||||
, "engines": { "node": ">= 0.4.0" }
|
||||
, "scripts": {
|
||||
"test": "make test"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,29 +468,45 @@ 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) {
|
||||
@@ -554,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);
|
||||
|
||||
@@ -582,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();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var io = require('socket.io')
|
||||
var io = require('../')
|
||||
, parser = io.parser
|
||||
, http = require('http')
|
||||
, https = require('https')
|
||||
@@ -91,8 +91,25 @@ 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) {
|
||||
if (self.agent.sockets[socket][i]._handle.socket) {
|
||||
self.agent.sockets[socket][i]._handle.socket.end();
|
||||
} else {
|
||||
self.agent.sockets[socket][i]._handle.owner.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -214,7 +231,7 @@ function WSClient (port, sid, transport) {
|
||||
this.transportName = transport || 'websocket';
|
||||
WebSocket.call(
|
||||
this
|
||||
, 'ws://localhost:' + port + '/socket.io/'
|
||||
, 'ws://localhost:' + port + '/socket.io/'
|
||||
+ io.protocol + '/' + this.transportName + '/' + sid
|
||||
);
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ mask = function(buf, maskString) {
|
||||
if (typeof buf == 'string') buf = new Buffer(buf);
|
||||
var mask = getBufferFromHexString(maskString || '34 83 a8 68');
|
||||
for (var i = 0; i < buf.length; ++i) {
|
||||
buf[i] ^= mask[i % 4];
|
||||
buf[i] ^= mask[i % 4];
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@@ -51,20 +51,20 @@ mask = function(buf, maskString) {
|
||||
/**
|
||||
* Returns a hex string representing the length of a message
|
||||
*/
|
||||
|
||||
getHybiLengthAsHexString = function(len, masked) {
|
||||
|
||||
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);
|
||||
@@ -94,6 +94,6 @@ pack = function(length, number) {
|
||||
* Left pads the string 's' to a total length of 'n' with char 'c'.
|
||||
*/
|
||||
|
||||
padl = function(s, n, c) {
|
||||
padl = function(s, n, c) {
|
||||
return new Array(1 + n - s.length).join(c) + s;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, fs = require('fs')
|
||||
, http = require('http')
|
||||
, https = require('https')
|
||||
@@ -116,10 +116,10 @@ module.exports = {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
done();
|
||||
} catch (e) {
|
||||
e.should.match(/EACCES/);
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, http = require('http')
|
||||
, should = require('./common')
|
||||
, ports = 15100;
|
||||
@@ -117,6 +117,7 @@ module.exports = {
|
||||
io.disable('foo');
|
||||
|
||||
calls.should.eql(3);
|
||||
|
||||
done();
|
||||
},
|
||||
|
||||
@@ -276,6 +277,23 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
'test that a referer with implicit port 80 is accepted for foo.bar.com:80 origin': function (done) {
|
||||
var port = ++ports
|
||||
, io = sio.listen(port)
|
||||
, cl = client(port);
|
||||
|
||||
io.configure(function () {
|
||||
io.set('origins', 'foo.bar.com:80');
|
||||
});
|
||||
|
||||
cl.get('/socket.io/{protocol}', { headers: { referer: 'http://foo.bar.com/something' } }, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
'test that erroneous referer is denied for addr:* origin': function (done) {
|
||||
var port = ++ports
|
||||
, io = sio.listen(port)
|
||||
@@ -338,7 +356,7 @@ module.exports = {
|
||||
|
||||
cl.get('/socket.io/{protocol}/', { headers:headers }, function (res, data) {
|
||||
res.statusCode.should.eql(200);
|
||||
res.headers['access-control-allow-origin'].should.eql('*');
|
||||
res.headers['access-control-allow-origin'].should.eql('http://example.org:1337');
|
||||
res.headers['access-control-allow-credentials'].should.eql('true');
|
||||
|
||||
cl.end();
|
||||
@@ -426,8 +444,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 +464,8 @@ module.exports = {
|
||||
|
||||
socket.on('disconnect', function (reason) {
|
||||
beat.should.be.false;
|
||||
|
||||
cl.end();
|
||||
ws.finishClose();
|
||||
cl.end();
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
@@ -505,8 +522,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,8 +534,10 @@ 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) {
|
||||
@@ -535,8 +556,10 @@ module.exports = {
|
||||
console.log = _console;
|
||||
calls.should.equal(0);
|
||||
|
||||
io.server.close();
|
||||
done();
|
||||
process.nextTick(function() {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
'test disabling logging with colors': function (done) {
|
||||
@@ -558,7 +581,9 @@ module.exports = {
|
||||
console.log = _console;
|
||||
calls.should.equal(2);
|
||||
|
||||
io.server.close();
|
||||
done();
|
||||
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'
|
||||
});
|
||||
})
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
@@ -282,5 +282,46 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
'disconnecting from namespace only': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, ws1
|
||||
, ws2;
|
||||
|
||||
io.of('/foo').on('connection', function (socket) {
|
||||
socket.disconnect();
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
ws1 = websocket(cl, sid);
|
||||
ws1.on('open', function () {
|
||||
ws1.packet({
|
||||
type: 'connect'
|
||||
, endpoint: '/bar'
|
||||
});
|
||||
cl.handshake(function (sid) {
|
||||
ws2 = websocket(cl, sid);
|
||||
ws2.on('open', function () {
|
||||
ws2.packet({
|
||||
type: 'connect'
|
||||
, endpoint: '/foo'
|
||||
});
|
||||
});
|
||||
ws2.on('message', function (data) {
|
||||
if ('disconnect' === data.type) {
|
||||
cl.end();
|
||||
ws1.finishClose();
|
||||
ws2.finishClose();
|
||||
io.server.close();
|
||||
|
||||
data.endpoint.should.eql('/foo');
|
||||
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var parser = require('socket.io').parser
|
||||
var parser = require('../').parser
|
||||
, decode = parser.decode
|
||||
, should = require('./common');
|
||||
|
||||
@@ -95,7 +95,7 @@ module.exports = {
|
||||
'decoding json packet with message id and ack data': function () {
|
||||
parser.decodePacket('4:1+::{"a":"b"}').should.eql({
|
||||
type: 'json'
|
||||
, id: 1
|
||||
, id: '1'
|
||||
, ack: 'data'
|
||||
, endpoint: ''
|
||||
, data: { a: 'b' }
|
||||
@@ -114,7 +114,7 @@ module.exports = {
|
||||
'decoding an event packet with message id and ack': function () {
|
||||
parser.decodePacket('5:1+::{"name":"tobi"}').should.eql({
|
||||
type: 'event'
|
||||
, id: 1
|
||||
, id: '1'
|
||||
, ack: 'data'
|
||||
, endpoint: ''
|
||||
, name: 'tobi'
|
||||
@@ -143,7 +143,7 @@ module.exports = {
|
||||
'decoding a message packet with id and endpoint': function () {
|
||||
parser.decodePacket('3:5:/tobi').should.eql({
|
||||
type: 'message'
|
||||
, id: 5
|
||||
, id: '5'
|
||||
, ack: true
|
||||
, endpoint: '/tobi'
|
||||
, data: ''
|
||||
@@ -245,7 +245,7 @@ module.exports = {
|
||||
'encoding json packet with message id and ack data': function () {
|
||||
parser.encodePacket({
|
||||
type: 'json'
|
||||
, id: 1
|
||||
, id: '1'
|
||||
, ack: 'data'
|
||||
, endpoint: ''
|
||||
, data: { a: 'b' }
|
||||
@@ -264,7 +264,7 @@ module.exports = {
|
||||
'encoding an event packet with message id and ack': function () {
|
||||
parser.encodePacket({
|
||||
type: 'event'
|
||||
, id: 1
|
||||
, id: '1'
|
||||
, ack: 'data'
|
||||
, endpoint: ''
|
||||
, name: 'tobi'
|
||||
@@ -292,7 +292,7 @@ module.exports = {
|
||||
'encoding a message packet with id and endpoint': function () {
|
||||
parser.encodePacket({
|
||||
type: 'message'
|
||||
, id: 5
|
||||
, id: '5'
|
||||
, ack: true
|
||||
, endpoint: '/tobi'
|
||||
, data: ''
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
/**
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
, should = require('./common');
|
||||
|
||||
/**
|
||||
* Test.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
|
||||
};
|
||||
@@ -9,7 +9,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, should = require('./common')
|
||||
, ports = 15400;
|
||||
|
||||
@@ -30,8 +30,10 @@ module.exports = {
|
||||
(!!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) {
|
||||
@@ -41,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) {
|
||||
@@ -90,7 +94,7 @@ module.exports = {
|
||||
|
||||
'test that the client is build with the enabled transports': function (done) {
|
||||
var port = ++ports
|
||||
, io = sio.listen(port)
|
||||
, io = sio.listen(port)
|
||||
, cl = client(port);
|
||||
|
||||
io.set('transports', ['websocket']);
|
||||
@@ -448,7 +452,7 @@ module.exports = {
|
||||
|
||||
cl.get('/socket.io/socket.io.js', function (res, data) {
|
||||
res.headers['content-type'].should.eql('application/javascript');
|
||||
res.headers['content-length'].should.eql(13);
|
||||
res.headers['content-length'].should.eql('13');
|
||||
res.headers.etag.should.eql('1.0');
|
||||
|
||||
data.should.eql('custom_client');
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, should = require('should')
|
||||
, MemoryStore = sio.MemoryStore;
|
||||
|
||||
@@ -45,7 +45,7 @@ module.exports = {
|
||||
|
||||
client.set('b', 'c', function (err) {
|
||||
should.strictEqual(err, null);
|
||||
|
||||
|
||||
client.set('c', 'd', function (err) {
|
||||
should.strictEqual(err, null);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, redis = require('redis')
|
||||
, should = require('should')
|
||||
, RedisStore = sio.RedisStore;
|
||||
@@ -95,7 +95,7 @@ module.exports = {
|
||||
|
||||
client.set('b', 'c', function (err) {
|
||||
should.strictEqual(err, null);
|
||||
|
||||
|
||||
client.set('c', 'd', function (err) {
|
||||
should.strictEqual(err, null);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, net = require('net')
|
||||
, http = require('http')
|
||||
, should = require('./common')
|
||||
@@ -30,7 +30,7 @@ function FlashSocket (port, sid) {
|
||||
|
||||
WebSocket.call(
|
||||
this
|
||||
, 'ws://localhost:' + port + '/socket.io/'
|
||||
, 'ws://localhost:' + port + '/socket.io/'
|
||||
+ sio.protocol + '/flashsocket/' + sid
|
||||
);
|
||||
};
|
||||
@@ -104,7 +104,7 @@ module.exports = {
|
||||
netConnection(port, function (err, data){
|
||||
should.strictEqual(err, null);
|
||||
|
||||
data.toString().should.include.string('<cross-domain-policy>');
|
||||
data.toString().should.match(/<cross-domain-policy>/);
|
||||
|
||||
this.destroy();
|
||||
io.flashPolicyServer.close();
|
||||
@@ -133,7 +133,7 @@ module.exports = {
|
||||
netConnection(next, function (err, data){
|
||||
should.strictEqual(err, null);
|
||||
|
||||
data.toString().should.include.string('<cross-domain-policy>');
|
||||
data.toString().should.match(/<cross-domain-policy>/);
|
||||
|
||||
this.destroy();
|
||||
io.flashPolicyServer.close();
|
||||
@@ -159,7 +159,7 @@ module.exports = {
|
||||
server.origins.should.not.contain('google.com:80');
|
||||
server.origins.should.contain('foo.bar:80');
|
||||
server.origins.should.contain('socket.io:1337');
|
||||
server.buffer.toString('utf8').should.include.string('socket.io');
|
||||
server.buffer.toString('utf8').should.match(/socket\.io/);
|
||||
|
||||
io.flashPolicyServer.close();
|
||||
done();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, should = require('./common')
|
||||
, HTTPClient = should.HTTPClient
|
||||
, parser = sio.parser
|
||||
@@ -77,10 +77,14 @@ HTMLFile.prototype.data = function (path, opts, fn) {
|
||||
|
||||
case 2:
|
||||
if (buf.indexOf(foot) != -1) {
|
||||
var data = buf.slice(0, buf.indexOf(foot))
|
||||
, obj = JSON.parse(data);
|
||||
var data = buf.slice(0, buf.indexOf(foot));
|
||||
|
||||
fn(obj === '' ? obj : parser.decodePayload(obj), ++messages);
|
||||
if (false === opts.parse) {
|
||||
fn(data, ++messages);
|
||||
} else {
|
||||
var obj = JSON.parse(data);
|
||||
fn(obj === '' ? obj : parser.decodePayload(obj), ++messages);
|
||||
}
|
||||
|
||||
buf = buf.substr(data.length + foot.length);
|
||||
state = 1;
|
||||
@@ -453,6 +457,78 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
'test escaping for security': function (done) {
|
||||
var port = ++ports
|
||||
, cl = client(port)
|
||||
, io = create(cl)
|
||||
, messaged = false;
|
||||
|
||||
io.configure(function () {
|
||||
io.set('close timeout', 0);
|
||||
});
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.emit('</script> woot');
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
cl.data('/socket.io/{protocol}/htmlfile/' + sid, { parse: false }, function (msg, i) {
|
||||
switch (i) {
|
||||
case 2:
|
||||
msg.should.not.include('</script');
|
||||
cl.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
'test that unescaping works': function(done){
|
||||
var port = ++ports
|
||||
, cl = client(port)
|
||||
, io = create(cl)
|
||||
, messaged = false;
|
||||
|
||||
io.configure(function () {
|
||||
io.set('close timeout', 0);
|
||||
});
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.emit('woot </script> <//script>', '</script><script>');
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
io.server.close();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs, i) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
msgs.should.have.length(1);
|
||||
msgs[0].type.should.eql('connect');
|
||||
msgs[0].endpoint.should.eql('');
|
||||
break;
|
||||
|
||||
case 2:
|
||||
msgs.should.have.length(1);
|
||||
msgs[0].should.eql({
|
||||
type: 'event'
|
||||
, name: 'woot </script> <//script>'
|
||||
, endpoint: ''
|
||||
, args: ['</script><script>']
|
||||
});
|
||||
cl.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, should = require('./common')
|
||||
, qs = require('querystring')
|
||||
, HTTPClient = should.HTTPClient
|
||||
@@ -250,15 +250,14 @@ 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
|
||||
, sid;
|
||||
|
||||
io.configure(function () {
|
||||
io.set('close timeout', .05);
|
||||
io.set('close timeout', .1);
|
||||
});
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -621,7 +625,7 @@ module.exports = {
|
||||
|
||||
io.configure(function () {
|
||||
io.set('polling duration', .2);
|
||||
io.set('close timeout', .2);
|
||||
io.set('close timeout', .5);
|
||||
});
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var assert = require('assert');
|
||||
var assert = require('assert');
|
||||
var Parser = require('../lib/transports/websocket/hybi-07-12.js').Parser;
|
||||
require('./hybi-common');
|
||||
|
||||
@@ -14,38 +14,38 @@ module.exports = {
|
||||
'can parse unmasked text message': function() {
|
||||
var p = new Parser();
|
||||
var packet = '81 05 48 65 6c 6c 6f';
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
assert.equal('Hello', data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
'can parse close message': function() {
|
||||
var p = new Parser();
|
||||
var packet = '88 00';
|
||||
|
||||
|
||||
var gotClose = false;
|
||||
p.on('close', function(data) {
|
||||
gotClose = true;
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotClose);
|
||||
},
|
||||
'can parse masked text message': function() {
|
||||
var p = new Parser();
|
||||
var packet = '81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5';
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
assert.equal('5:::{"name":"echo"}', data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -54,13 +54,13 @@ module.exports = {
|
||||
var message = 'A';
|
||||
for (var i = 0; i < 300; ++i) message += (i % 5).toString();
|
||||
var packet = '81 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -75,7 +75,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -87,13 +87,13 @@ module.exports = {
|
||||
var msgpiece2 = message.substr(150);
|
||||
var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68'));
|
||||
var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
gotData = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet1));
|
||||
p.add(getBufferFromHexString(packet2));
|
||||
assert.ok(gotData);
|
||||
@@ -102,25 +102,25 @@ module.exports = {
|
||||
var p = new Parser();
|
||||
var message = 'Hello';
|
||||
var packet = '89 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotPing = false;
|
||||
p.on('ping', function(data) {
|
||||
gotPing = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotPing);
|
||||
},
|
||||
'can parse a ping with no data': function() {
|
||||
var p = new Parser();
|
||||
var packet = '89 00';
|
||||
|
||||
|
||||
var gotPing = false;
|
||||
p.on('ping', function(data) {
|
||||
gotPing = true;
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotPing);
|
||||
},
|
||||
@@ -128,16 +128,16 @@ module.exports = {
|
||||
var p = new Parser();
|
||||
var message = 'A';
|
||||
for (var i = 0; i < 300; ++i) message += (i % 5).toString();
|
||||
|
||||
|
||||
var msgpiece1 = message.substr(0, 150);
|
||||
var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68'));
|
||||
|
||||
|
||||
var pingMessage = 'Hello';
|
||||
var pingPacket = '89 FE ' + pack(4, pingMessage.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68'));
|
||||
|
||||
|
||||
var msgpiece2 = message.substr(150);
|
||||
var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
@@ -148,7 +148,7 @@ module.exports = {
|
||||
gotPing = true;
|
||||
assert.equal(pingMessage, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet1));
|
||||
p.add(getBufferFromHexString(pingPacket));
|
||||
p.add(getBufferFromHexString(packet2));
|
||||
@@ -159,16 +159,16 @@ module.exports = {
|
||||
var p = new Parser();
|
||||
var message = 'A';
|
||||
for (var i = 0; i < 300; ++i) message += (i % 5).toString();
|
||||
|
||||
|
||||
var msgpiece1 = message.substr(0, 150);
|
||||
var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68'));
|
||||
|
||||
|
||||
var pingMessage = 'Hello';
|
||||
var pingPacket = '89 FE ' + pack(4, pingMessage.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68'));
|
||||
|
||||
|
||||
var msgpiece2 = message.substr(150);
|
||||
var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
@@ -179,7 +179,7 @@ module.exports = {
|
||||
gotPing = true;
|
||||
assert.equal(pingMessage, data);
|
||||
});
|
||||
|
||||
|
||||
var buffers = [];
|
||||
buffers = buffers.concat(splitBuffer(getBufferFromHexString(packet1)));
|
||||
buffers = buffers.concat(splitBuffer(getBufferFromHexString(pingPacket)));
|
||||
@@ -195,7 +195,7 @@ module.exports = {
|
||||
var length = 100;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
var gotData = false;
|
||||
@@ -203,7 +203,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -212,7 +212,7 @@ module.exports = {
|
||||
var length = 256;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
var gotData = false;
|
||||
@@ -220,7 +220,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -229,7 +229,7 @@ module.exports = {
|
||||
var length = 200 * 1024;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
var gotData = false;
|
||||
@@ -237,7 +237,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -246,7 +246,7 @@ module.exports = {
|
||||
var length = 200 * 1024;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, false) + ' ' + getHexStringFromBuffer(message);
|
||||
|
||||
var gotData = false;
|
||||
@@ -254,7 +254,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var assert = require('assert');
|
||||
var assert = require('assert');
|
||||
var Parser = require('../lib/transports/websocket/hybi-16.js').Parser;
|
||||
require('./hybi-common');
|
||||
|
||||
@@ -14,38 +14,38 @@ module.exports = {
|
||||
'can parse unmasked text message': function() {
|
||||
var p = new Parser();
|
||||
var packet = '81 05 48 65 6c 6c 6f';
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
assert.equal('Hello', data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
'can parse close message': function() {
|
||||
var p = new Parser();
|
||||
var packet = '88 00';
|
||||
|
||||
|
||||
var gotClose = false;
|
||||
p.on('close', function(data) {
|
||||
gotClose = true;
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotClose);
|
||||
},
|
||||
'can parse masked text message': function() {
|
||||
var p = new Parser();
|
||||
var packet = '81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5';
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
assert.equal('5:::{"name":"echo"}', data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -54,13 +54,13 @@ module.exports = {
|
||||
var message = 'A';
|
||||
for (var i = 0; i < 300; ++i) message += (i % 5).toString();
|
||||
var packet = '81 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -75,7 +75,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -87,13 +87,13 @@ module.exports = {
|
||||
var msgpiece2 = message.substr(150);
|
||||
var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68'));
|
||||
var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
gotData = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet1));
|
||||
p.add(getBufferFromHexString(packet2));
|
||||
assert.ok(gotData);
|
||||
@@ -102,25 +102,25 @@ module.exports = {
|
||||
var p = new Parser();
|
||||
var message = 'Hello';
|
||||
var packet = '89 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotPing = false;
|
||||
p.on('ping', function(data) {
|
||||
gotPing = true;
|
||||
assert.equal(message, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotPing);
|
||||
},
|
||||
'can parse a ping with no data': function() {
|
||||
var p = new Parser();
|
||||
var packet = '89 00';
|
||||
|
||||
|
||||
var gotPing = false;
|
||||
p.on('ping', function(data) {
|
||||
gotPing = true;
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotPing);
|
||||
},
|
||||
@@ -128,16 +128,16 @@ module.exports = {
|
||||
var p = new Parser();
|
||||
var message = 'A';
|
||||
for (var i = 0; i < 300; ++i) message += (i % 5).toString();
|
||||
|
||||
|
||||
var msgpiece1 = message.substr(0, 150);
|
||||
var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68'));
|
||||
|
||||
|
||||
var pingMessage = 'Hello';
|
||||
var pingPacket = '89 FE ' + pack(4, pingMessage.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68'));
|
||||
|
||||
|
||||
var msgpiece2 = message.substr(150);
|
||||
var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
@@ -148,7 +148,7 @@ module.exports = {
|
||||
gotPing = true;
|
||||
assert.equal(pingMessage, data);
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet1));
|
||||
p.add(getBufferFromHexString(pingPacket));
|
||||
p.add(getBufferFromHexString(packet2));
|
||||
@@ -159,16 +159,16 @@ module.exports = {
|
||||
var p = new Parser();
|
||||
var message = 'A';
|
||||
for (var i = 0; i < 300; ++i) message += (i % 5).toString();
|
||||
|
||||
|
||||
var msgpiece1 = message.substr(0, 150);
|
||||
var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68'));
|
||||
|
||||
|
||||
var pingMessage = 'Hello';
|
||||
var pingPacket = '89 FE ' + pack(4, pingMessage.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68'));
|
||||
|
||||
|
||||
var msgpiece2 = message.substr(150);
|
||||
var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68'));
|
||||
|
||||
|
||||
var gotData = false;
|
||||
p.on('data', function(data) {
|
||||
gotData = true;
|
||||
@@ -179,7 +179,7 @@ module.exports = {
|
||||
gotPing = true;
|
||||
assert.equal(pingMessage, data);
|
||||
});
|
||||
|
||||
|
||||
var buffers = [];
|
||||
buffers = buffers.concat(splitBuffer(getBufferFromHexString(packet1)));
|
||||
buffers = buffers.concat(splitBuffer(getBufferFromHexString(pingPacket)));
|
||||
@@ -195,7 +195,7 @@ module.exports = {
|
||||
var length = 100;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
var gotData = false;
|
||||
@@ -203,7 +203,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -212,7 +212,7 @@ module.exports = {
|
||||
var length = 256;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
var gotData = false;
|
||||
@@ -220,7 +220,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -229,7 +229,7 @@ module.exports = {
|
||||
var length = 200 * 1024;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68'));
|
||||
|
||||
var gotData = false;
|
||||
@@ -237,7 +237,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
@@ -246,7 +246,7 @@ module.exports = {
|
||||
var length = 200 * 1024;
|
||||
var message = new Buffer(length);
|
||||
for (var i = 0; i < length; ++i) message[i] = i % 256;
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var originalMessage = getHexStringFromBuffer(message);
|
||||
var packet = '82 ' + getHybiLengthAsHexString(length, false) + ' ' + getHexStringFromBuffer(message);
|
||||
|
||||
var gotData = false;
|
||||
@@ -254,7 +254,7 @@ module.exports = {
|
||||
gotData = true;
|
||||
assert.equal(originalMessage, getHexStringFromBuffer(data));
|
||||
});
|
||||
|
||||
|
||||
p.add(getBufferFromHexString(packet));
|
||||
assert.ok(gotData);
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
* Test dependencies.
|
||||
*/
|
||||
|
||||
var sio = require('socket.io')
|
||||
var sio = require('../')
|
||||
, should = require('./common')
|
||||
, HTTPClient = should.HTTPClient
|
||||
, parser = sio.parser
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -284,6 +289,40 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
'test that connection close does not mean disconnect': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, sid
|
||||
, end
|
||||
, disconnected = false
|
||||
|
||||
io.configure(function () {
|
||||
io.set('polling duration', .2);
|
||||
io.set('close timeout', .5);
|
||||
});
|
||||
|
||||
io.sockets.on('connection', function (client) {
|
||||
end = function () {
|
||||
cl.end();
|
||||
console.log('ending');
|
||||
client.on('disconnect', function () {
|
||||
disconnected = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
cl.handshake(function (sid) {
|
||||
cl.get('/socket.io/{protocol}/xhr-polling/' + sid);
|
||||
setTimeout(end, 30);
|
||||
setTimeout(function () {
|
||||
console.log('finished');
|
||||
disconnected.should.be.false;
|
||||
io.server.close();
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
},
|
||||
|
||||
'test sending back data': function (done) {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl);
|
||||
@@ -763,7 +802,7 @@ module.exports = {
|
||||
var cl = client(++ports)
|
||||
, io = create(cl)
|
||||
, messages = 0;
|
||||
|
||||
|
||||
io.configure(function () {
|
||||
io.set('polling duration', 0);
|
||||
io.set('close timeout', .1);
|
||||
@@ -1312,7 +1351,7 @@ module.exports = {
|
||||
msgs.should.have.length(1);
|
||||
msgs[0].should.eql({
|
||||
type: 'ack'
|
||||
, ackId: 1
|
||||
, ackId: '1'
|
||||
, endpoint: ''
|
||||
, args: []
|
||||
});
|
||||
@@ -2647,8 +2686,8 @@ module.exports = {
|
||||
}, function (res, packs) {
|
||||
var headers = res.headers;
|
||||
|
||||
headers['access-control-allow-origin'].should.equal('*');
|
||||
should.strictEqual(headers['access-control-allow-credentials'], undefined);
|
||||
headers['access-control-allow-origin'].should.equal('http://localhost:3500');
|
||||
headers['access-control-allow-credentials'].should.equal('true');
|
||||
|
||||
packs.should.have.length(1);
|
||||
packs[0].type.should.eql('message');
|
||||
@@ -2664,7 +2703,7 @@ module.exports = {
|
||||
}
|
||||
}, function (res, data) {
|
||||
var headers = res.headers;
|
||||
headers['access-control-allow-origin'].should.equal('*');
|
||||
headers['access-control-allow-origin'].should.equal('http://localhost:3500');
|
||||
headers['access-control-allow-credentials'].should.equal('true');
|
||||
|
||||
data.should.equal('1');
|
||||
@@ -2746,7 +2785,7 @@ module.exports = {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user