Compare commits

..

4 Commits
0.3.1 ... 0.3.3

Author SHA1 Message Date
Virtuo
dd3d829173 Correct bug due to variable name clash.
IMO: this kind of code should be put in an external lib and 100% tested.
2010-05-21 13:09:14 +02:00
Guillermo Rauch
fbce6379a5 Note about submodules 2010-05-13 22:05:31 -03:00
Guillermo Rauch
0459c95848 Added support for Node 0.1.94
Close timeout for transports with keep-alive / websocket set to 0
Close timeout for xhr-polling reduced from 8 seconds to 5 seconds
Now you can pass options to specific transports from io.listen()
Some cleanup
2010-05-12 12:16:44 -03:00
Guillermo Rauch
67815ec15d http > git in gitmodules 2010-05-11 19:34:25 -03:00
8 changed files with 66 additions and 49 deletions

2
.gitmodules vendored
View File

@@ -3,4 +3,4 @@
url = git://github.com/visionmedia/js-oo.git
[submodule "test/client"]
path = test/client
url = http://github.com/LearnBoost/Socket.IO.git
url = git://github.com/LearnBoost/Socket.IO.git

View File

@@ -11,7 +11,7 @@ The `Socket.IO` server provides seamless supports for a variety of transports in
Requirements
------------
- Node v0.1.93+
- Node v0.1.94+
- [Socket.IO client](http://github.com/LearnBoost/Socket.IO) to connect from the browser
How to use
@@ -36,12 +36,15 @@ By default, the server will intercept requests that contain `socket.io` in the p
On the client side, you should use the [Socket.IO client](https://github.com/LearnBoost/Socket.IO) to connect.
## Checking out
## Notes
After cloning the repository, remember to run
IMPORTANT! When checking out the git repo, make sure to include the submodules. One way to do it is:
git submodule init
git submodule update
git clone [repo] --recursive
Another, once cloned
git submodule update --init --recursive
## Demo
@@ -105,11 +108,9 @@ Options:
A list of the accepted transports.
- *timeout*
8000
Time it has to pass without a reconnection to consider a client disconnected. Applies to all transports.
- *transportOptions*
An object of options to pass to each transport. For example `{ websocket: { closeTimeout: 8000 }}`
- *log*
@@ -171,7 +172,7 @@ One of the design goals is that you should be able to implement whatever protoco
The concept of session also benefits naturally full-duplex WebSocket, in the event of an accidental disconnection and a quick reconnection. Messages that the server intends to deliver to the client are cached temporarily until the reconnection.
The implementation of reconnection logic (potentially with retries) is left for the user.
The implementation of reconnection logic (potentially with retries) is left for the user. By default, transports that are keep-alive or open all the time (like WebSocket) have a timeout of 0 if a disconnection is detected.
* Message batching

View File

@@ -1,9 +1,16 @@
var sys = require('sys');
var Options = require('./util/options').Options;
this.Client = Class({
include: [Options],
options: {
closeTimeout: 0
},
init: function(listener, req, res){
this.listener = listener;
init: function(listener, req, res, options){
this.listener = listener;
this.setOptions(options);
this.connections = 0;
this.connected = false;
this._onConnect(req, res);
@@ -66,7 +73,7 @@ this.Client = Class({
this.connected = false;
this._disconnectTimeout = setTimeout(function(){
self._onDisconnect();
}, this.listener.options.timeout);
}, this.options.closeTimeout);
},
_onDisconnect: function(){

View File

@@ -1,9 +1,10 @@
var url = require('url'),
sys = require('sys'),
Options = require('./util/options').Options,
Options = require('./util/options').Options,
Client = require('./client').Client,
Transports = {},
Transports = {};
Listener = this.Listener = Class({
include: [process.EventEmitter.prototype, Options],
@@ -12,17 +13,17 @@ Listener = this.Listener = Class({
origins: '*:*',
resource: 'socket.io',
transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling'],
timeout: 8000,
transportOptions: {},
log: function(message){
sys.log(message);
}
},
init: function(server, options){
var self = this;
process.EventEmitter.call(this);
this.server = server;
this.setOptions(options);
this.server = server;
this.setOptions(options);
this.clients = [];
this.clientsIndex = {};
@@ -30,15 +31,20 @@ Listener = this.Listener = Class({
? this.server._events['request'][0]
: this.server._events['request'];
if (listener){
var self = this;
this.server._events['request'] = function(req, res){
if (self.check(req, res)) return;
listener(req, res);
listener(req, res);
};
} else {
throw new Error('Couldn\'t find the `request` event in the HTTP server.');
}
this.server.addListener('upgrade', function(req, socket, head){
if (!self.check(req, socket, true)){
socket.destroy();
}
});
this.options.transports.forEach(function(t){
if (!(t in Transports)){
Transports[t] = require('./transports/' + t)[t];
@@ -53,13 +59,13 @@ Listener = this.Listener = Class({
for (var i = 0, l = this.clients.length; i < l; i++){
if (this.clients[i] && (!except || [].concat(except).indexOf(this.clients[i].sessionId) == -1)){
this.clients[i].send(message);
}
}
}
return this;
},
check: function(req, res){
var path = url.parse(req.url).pathname, parts, cn;
check: function(req, res, httpUpgrade){
var path = url.parse(req.url).pathname, parts, cn;
if (path.indexOf('/' + this.options.resource) === 0){
parts = path.substr(1).split('/');
if (parts[2]){
@@ -71,10 +77,10 @@ Listener = this.Listener = Class({
sys.log('Couldnt find client with session id "' + parts[2] + '"');
}
} else {
this._onConnection(parts[1], req, res);
}
this._onConnection(parts[1], req, res, httpUpgrade);
}
return true;
}
}
return false;
},
@@ -105,13 +111,13 @@ Listener = this.Listener = Class({
},
// new connections (no session id)
_onConnection: function(transport, req, res){
if (this.options.transports.indexOf(transport) === -1){
req.connection.end();
_onConnection: function(transport, req, res, httpUpgrade){
if (this.options.transports.indexOf(transport) === -1 || (httpUpgrade && !Transports[transport].httpUpgrade)){
httpUpgrade ? res.destroy() : req.connection.destroy();
return sys.log('Illegal transport "'+ transport +'"');
}
sys.log('Initializing client with transport "'+ transport +'"');
new Transports[transport](this, req, res);
new Transports[transport](this, req, res, this.options.transportOptions[transport]);
}
});

View File

@@ -3,7 +3,7 @@ var websocket = require('./websocket').websocket,
listeners = [];
this.flashsocket = websocket.extend({});
this.flashsocket.httpUpgrade = true;
this.flashsocket.init = function(listener){
listeners.push(listener);
};

View File

@@ -3,15 +3,15 @@ var Client = require('../client').Client,
this.websocket = Client.extend({
_onConnect: function(req, res){
_onConnect: function(req, socket){
var self = this;
this.__super__(req, res);
this.request = req;
this.connection = socket;
this.data = '';
if (!this.request.upgrade || this.request.headers['upgrade'] !== 'WebSocket' || !this._verifyOrigin(this.request.headers['origin'])){
if (this.request.headers['upgrade'] !== 'WebSocket' || !this._verifyOrigin(this.request.headers['origin'])){
this.listener.options.log('WebSocket connection invalid');
this.connection.end();
return;
}
this.connection.setTimeout(0);
@@ -60,4 +60,6 @@ this.websocket = Client.extend({
this.connection.write('\uffff', 'binary');
}
});
});
this.websocket.httpUpgrade = true;

View File

@@ -5,6 +5,7 @@ var Client = require('../client').Client,
this['xhr-polling'] = Client.extend({
options: {
closeTimeout: 5000,
duration: 20000
},

View File

@@ -2,15 +2,15 @@
// Copyright (c) 2006-2009 Valerio Proietti, <http://mad4milk.net/>
var clone = this.clone = function(item){
var clone;
var cloned;
if (item instanceof Array){
clone = [];
for (var i = 0; i < item.length; i++) clone[i] = clone(item[i]);
return clone;
cloned = [];
for (var i = 0; i < item.length; i++) cloned[i] = clone(item[i]);
return cloned;
} else if (typeof item == 'object') {
clone = {};
for (var key in object) clone[key] = clone(object[key]);
return clone;
cloned = {};
for (var key in object) cloned[key] = clone(object[key]);
return cloned;
} else {
return item;
}
@@ -35,4 +35,4 @@ this.merge = function(source, k, v){
for (var key in object) mergeOne(source, key, object[key]);
}
return source;
};
};