mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-11 16:08:24 -05:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ad237ddf5 | ||
|
|
3134940ed6 | ||
|
|
0f783bc06a | ||
|
|
dd3d829173 | ||
|
|
fbce6379a5 | ||
|
|
0459c95848 | ||
|
|
67815ec15d | ||
|
|
87f62373c5 | ||
|
|
a557bd6acb | ||
|
|
ae9e550c26 | ||
|
|
b19bac2d33 | ||
|
|
a977ecd65b | ||
|
|
c4cf1b28f2 | ||
|
|
f5796c630c | ||
|
|
6ce8c52c4d | ||
|
|
408b2c73f8 | ||
|
|
16b5de7b4f | ||
|
|
b65e6fa611 | ||
|
|
ddfc39826f | ||
|
|
1745e89936 | ||
|
|
10e6b66a97 | ||
|
|
bf9ba8c08b | ||
|
|
4e58204b83 | ||
|
|
4308ba8f14 | ||
|
|
0e5fb040a9 | ||
|
|
e62370161d | ||
|
|
5c5b7ee0ba |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -3,4 +3,4 @@
|
||||
url = git://github.com/visionmedia/js-oo.git
|
||||
[submodule "test/client"]
|
||||
path = test/client
|
||||
url = git@github.com:RosePad/Socket.IO.git
|
||||
url = git://github.com/LearnBoost/Socket.IO.git
|
||||
|
||||
43
README.md
43
README.md
@@ -4,7 +4,6 @@ Socket.IO Server: Sockets for the rest of us
|
||||
The `Socket.IO` server provides seamless supports for a variety of transports intended for realtime communication
|
||||
|
||||
- WebSocket (with Flash policy support)
|
||||
- Server-Sent Events
|
||||
- XHR Polling
|
||||
- XHR Multipart Streaming
|
||||
- Forever Iframe
|
||||
@@ -12,8 +11,8 @@ The `Socket.IO` server provides seamless supports for a variety of transports in
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- Node v0.1.32+
|
||||
- [Socket.IO client](http://github.com/RosePad/Socket.IO) to connect from the browser
|
||||
- Node v0.1.94+
|
||||
- [Socket.IO client](http://github.com/LearnBoost/Socket.IO) to connect from the browser
|
||||
|
||||
How to use
|
||||
----------
|
||||
@@ -35,23 +34,17 @@ By default, the server will intercept requests that contain `socket.io` in the p
|
||||
// socket.io, I choose you
|
||||
io.listen(server);
|
||||
|
||||
Due to a lack of flexibility in the current Node HTTP server implementation, you'll have to patch Node before using `socket.io`.
|
||||
In the node directory run:
|
||||
|
||||
patch -p1 < {../directory/to/socket.io-node}/patch/{node version}.patch
|
||||
./configure
|
||||
make
|
||||
make test
|
||||
sudo make install
|
||||
|
||||
On the client side, you should use the [Socket.IO client](https://github.com/RosePad/Socket.IO) to connect.
|
||||
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
|
||||
|
||||
@@ -115,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*
|
||||
|
||||
@@ -181,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
|
||||
|
||||
@@ -191,15 +182,13 @@ Despite this extra layer, your messages are delivered unaltered to the different
|
||||
|
||||
## Credits
|
||||
|
||||
Guillermo Rauch [guillermo@rosepad.com]
|
||||
|
||||
Special thanks to [Jonas Pfenniger](http://github.com/zimbatm) for his workaround patch to keep the HTTPConnection open after the request is successful.
|
||||
Guillermo Rauch <guillermo@learnboost.com>
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2009 RosePad <dev@rosepad.com>
|
||||
Copyright (c) 2010 LearnBoost <dev@learnboost.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -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);
|
||||
@@ -22,18 +29,22 @@ this.Client = Class({
|
||||
},
|
||||
|
||||
_onMessage: function(data){
|
||||
var messages = JSON.parse(data);
|
||||
try {
|
||||
var messages = JSON.parse(data);
|
||||
} catch(e){
|
||||
return this.listener.options.log('Bad message received from client ' + this.sessionId);
|
||||
}
|
||||
for (var i = 0, l = messages.length; i < l; i++){
|
||||
this.listener._onClientMessage(messages[i], this);
|
||||
}
|
||||
},
|
||||
|
||||
_onConnect: function(req, res){
|
||||
var self = this;
|
||||
var self = this;
|
||||
this.request = req;
|
||||
this.response = res;
|
||||
this.connection = this.request.connection;
|
||||
if (this._disconnectTimeout) clearTimeout(this._disconnectTimeout);
|
||||
this.connection = this.request.connection;
|
||||
if (this._disconnectTimeout) clearTimeout(this._disconnectTimeout);
|
||||
},
|
||||
|
||||
_payload: function(){
|
||||
@@ -62,7 +73,7 @@ this.Client = Class({
|
||||
this.connected = false;
|
||||
this._disconnectTimeout = setTimeout(function(){
|
||||
self._onDisconnect();
|
||||
}, this.listener.options.timeout);
|
||||
}, this.options.closeTimeout);
|
||||
},
|
||||
|
||||
_onDisconnect: function(){
|
||||
|
||||
@@ -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],
|
||||
@@ -11,18 +12,18 @@ Listener = this.Listener = Class({
|
||||
options: {
|
||||
origins: '*:*',
|
||||
resource: 'socket.io',
|
||||
transports: ['websocket', 'server-events', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling'],
|
||||
timeout: 8000,
|
||||
transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling'],
|
||||
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]){
|
||||
@@ -67,14 +73,14 @@ Listener = this.Listener = Class({
|
||||
if (cn){
|
||||
cn._onConnect(req, res);
|
||||
} else {
|
||||
req.connection.close();
|
||||
req.connection.end();
|
||||
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.close();
|
||||
_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]);
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,14 +1,14 @@
|
||||
var websocket = require('./websocket').websocket,
|
||||
tcp = require('tcp'),
|
||||
net = require('net'),
|
||||
listeners = [];
|
||||
|
||||
this.flashsocket = websocket.extend({});
|
||||
|
||||
this.flashsocket.httpUpgrade = true;
|
||||
this.flashsocket.init = function(listener){
|
||||
listeners.push(listener);
|
||||
};
|
||||
|
||||
tcp.createServer(function(socket){
|
||||
net.createServer(function(socket){
|
||||
socket.write('<?xml version="1.0"?>\n');
|
||||
socket.write('<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">\n');
|
||||
socket.write('<cross-domain-policy>\n');
|
||||
@@ -21,5 +21,5 @@ tcp.createServer(function(socket){
|
||||
});
|
||||
|
||||
socket.write('</cross-domain-policy>\n');
|
||||
socket.close();
|
||||
socket.end();
|
||||
}).listen(843);
|
||||
@@ -4,43 +4,47 @@ var Client = require('../client').Client,
|
||||
this['htmlfile'] = Client.extend({
|
||||
|
||||
_onConnect: function(req, res){
|
||||
var self = this, body = '';
|
||||
switch (req.method){
|
||||
case 'GET':
|
||||
var self = this;
|
||||
this.__super__(req, res);
|
||||
this.request.addListener('end', function(){
|
||||
if (!('hijack' in self.connection)){
|
||||
throw new Error('You have to patch Node! Please refer to the README');
|
||||
}
|
||||
|
||||
self.connection.addListener('end', function(){ self._onClose(); });
|
||||
self.connection.hijack();
|
||||
self.connection.setTimeout(0);
|
||||
this.__super__(req, res);
|
||||
this.request.connection.addListener('close', function(){ self._onClose(); });
|
||||
this.response.useChunkedEncodingByDefault = true;
|
||||
this.response.shouldKeepAlive = true;
|
||||
this.response.writeHead(200, {
|
||||
'Content-Type': 'text/html',
|
||||
'Connection': 'keep-alive',
|
||||
'Transfer-Encoding': 'chunked'
|
||||
});
|
||||
|
||||
this.response.writeHead(200, { 'Content-type': 'text/html' });
|
||||
this.response.write('<html><body>' + new Array(244).join(' '));
|
||||
this.response.flush();
|
||||
|
||||
this._payload();
|
||||
setInterval(function(){
|
||||
self.response.write('<!-- heartbeat -->');
|
||||
self.response.flush();
|
||||
}, 1000);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
req.addListener('data', function(message){
|
||||
body += message;
|
||||
});
|
||||
req.addListener('end', function(){
|
||||
try {
|
||||
var msg = qs.parse(message);
|
||||
var msg = qs.parse(body);
|
||||
self._onMessage(msg.data);
|
||||
} catch(e){}
|
||||
} catch(e){}
|
||||
res.writeHead(200);
|
||||
res.write('ok');
|
||||
res.close();
|
||||
res.end();
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_write: function(message){
|
||||
// not sure if this is enough escaping. looks lousy
|
||||
this.response.write("<script>parent.callback('"+ message.replace(/'/, "\'") +"')</script>");
|
||||
this.response.write('<script>parent.s._('+ message +', document);</script>');
|
||||
this.response.flush();
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,46 +0,0 @@
|
||||
var Client = require('../client').Client,
|
||||
qs = require('querystring');
|
||||
|
||||
this['server-events'] = Client.extend({
|
||||
|
||||
_onConnect: function(req, res){
|
||||
switch (req.method){
|
||||
case 'GET':
|
||||
var self = this;
|
||||
this.__super__(req, res);
|
||||
this.request.addListener('end', function(){
|
||||
if (!('hijack' in self.connection)){
|
||||
throw new Error('You have to patch Node! Please refer to the README');
|
||||
}
|
||||
|
||||
self.connection.addListener('end', function(){ self._onClose(); });
|
||||
self.connection.hijack();
|
||||
self.connection.setTimeout(0);
|
||||
});
|
||||
|
||||
this.response.writeHead(200, { 'Content-type': 'application/x-dom-event-stream' });
|
||||
this.response.flush();
|
||||
|
||||
this._payload();
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
req.addListener('data', function(message){
|
||||
try {
|
||||
var msg = qs.parse(message);
|
||||
self._onMessage(msg.data);
|
||||
} catch(e){}
|
||||
res.writeHead(200);
|
||||
res.write('ok');
|
||||
res.close();
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_write: function(message){
|
||||
this.response.write("Event: socket.io");
|
||||
this.response.write("data: " + message);
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,51 +1,51 @@
|
||||
var Client = require('../client').Client,
|
||||
url = require('url'),
|
||||
sys = require('sys');
|
||||
url = require('url');
|
||||
|
||||
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.headers['connection'] !== '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.close();
|
||||
return;
|
||||
this.connection.end();
|
||||
}
|
||||
|
||||
this.request.addListener('end', function(){
|
||||
if (!('hijack' in self.connection)){
|
||||
throw new Error('You have to patch Node! Please refer to the README');
|
||||
}
|
||||
|
||||
self.connection.hijack();
|
||||
self.connection.setTimeout(0);
|
||||
self.connection.setNoDelay(true);
|
||||
self.connection.addListener('end', function(){ self._onClose(); });
|
||||
self.connection.addListener('data', function(data){
|
||||
if (data[0] !== '\u0000' && data[data.length - 1] !== '\ufffd'){
|
||||
self.connection.close();
|
||||
} else {
|
||||
self._onMessage(data.substr(1, data.length - 2));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.response.use_chunked_encoding_by_default = false;
|
||||
this.response.writeHeader(101, 'Web Socket Protocol Handshake', {
|
||||
'Upgrade': 'WebSocket',
|
||||
'Connection': 'Upgrade',
|
||||
'WebSocket-Origin': this.request.headers.origin,
|
||||
'WebSocket-Location': 'ws://' + this.request.headers.host + this.request.url
|
||||
});
|
||||
this.response.flush();
|
||||
|
||||
this.connection.setTimeout(0);
|
||||
this.connection.setEncoding('utf8');
|
||||
this.connection.setNoDelay(true);
|
||||
this.connection.write([
|
||||
'HTTP/1.1 101 Web Socket Protocol Handshake',
|
||||
'Upgrade: WebSocket',
|
||||
'Connection: Upgrade',
|
||||
'WebSocket-Origin: ' + this.request.headers.origin,
|
||||
'WebSocket-Location: ws://' + this.request.headers.host + this.request.url,
|
||||
'', ''
|
||||
].join('\r\n'));
|
||||
this.connection.addListener('end', function(){ self._onClose(); });
|
||||
this.connection.addListener('data', function(data){ self._handle(data); });
|
||||
this._payload();
|
||||
},
|
||||
|
||||
_handle: function(data){
|
||||
this.data += data;
|
||||
chunks = this.data.split('\ufffd');
|
||||
chunk_count = chunks.length - 1;
|
||||
for (var i = 0; i < chunk_count; i++) {
|
||||
chunk = chunks[i];
|
||||
if (chunk[0] != '\u0000') {
|
||||
this.listener.options.log('Data incorrectly framed by UA. Dropping connection');
|
||||
this.connection.destroy();
|
||||
return false;
|
||||
}
|
||||
this._onMessage(chunk.slice(1));
|
||||
}
|
||||
this.data = chunks[chunks.length - 1];
|
||||
},
|
||||
|
||||
_verifyOrigin: function(origin){
|
||||
var parts = url.parse(origin);
|
||||
return this.listener.options.origins.indexOf('*:*') !== -1
|
||||
@@ -55,7 +55,15 @@ this.websocket = Client.extend({
|
||||
},
|
||||
|
||||
_write: function(message){
|
||||
this.connection.write('\u0000' + message + '\uffff');
|
||||
try {
|
||||
this.connection.write('\u0000', 'binary');
|
||||
this.connection.write(message, 'utf8');
|
||||
this.connection.write('\uffff', 'binary');
|
||||
} catch(){
|
||||
this._onClose();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
this.websocket.httpUpgrade = true;
|
||||
@@ -4,41 +4,35 @@ var Client = require('../client').Client,
|
||||
this['xhr-multipart'] = Client.extend({
|
||||
|
||||
_onConnect: function(req, res){
|
||||
var self = this;
|
||||
var self = this, body = '';
|
||||
switch (req.method){
|
||||
case 'GET':
|
||||
var self = this;
|
||||
this.__super__(req, res);
|
||||
this.request.addListener('end', function(){
|
||||
if (!('hijack' in self.connection)){
|
||||
throw new Error('You have to patch Node! Please refer to the README');
|
||||
}
|
||||
|
||||
self.connection.addListener('end', function(){ self._onClose(); });
|
||||
self.connection.hijack();
|
||||
self.connection.setTimeout(0);
|
||||
});
|
||||
|
||||
this.response.use_chunked_encoding_by_default = false;
|
||||
this.request.connection.addListener('end', function(){ self._onClose(); });
|
||||
this.response.useChunkedEncodingByDefault = false;
|
||||
this.response.shouldKeepAlive = true;
|
||||
this.response.writeHead(200, {
|
||||
'Content-Type': 'multipart/x-mixed-replace;boundary=socketio',
|
||||
'Connection': 'keep-alive'
|
||||
});
|
||||
this.response.write("--socketio\n");
|
||||
this.response.flush();
|
||||
|
||||
this._payload();
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
req.addListener('data', function(message){
|
||||
body += message;
|
||||
});
|
||||
req.addListener('end', function(){
|
||||
try {
|
||||
var msg = qs.parse(message);
|
||||
var msg = qs.parse(body);
|
||||
self._onMessage(msg.data);
|
||||
} catch(e){}
|
||||
res.writeHead(200);
|
||||
res.write('ok');
|
||||
res.close();
|
||||
res.end();
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5,29 +5,33 @@ var Client = require('../client').Client,
|
||||
this['xhr-polling'] = Client.extend({
|
||||
|
||||
options: {
|
||||
closeTimeout: 5000,
|
||||
duration: 20000
|
||||
},
|
||||
|
||||
_onConnect: function(req, res){
|
||||
var self = this;
|
||||
var self = this, body = '';
|
||||
switch (req.method){
|
||||
case 'GET':
|
||||
this.__super__(req, res);
|
||||
this.__super__(req, res);
|
||||
this._closeTimeout = setTimeout(function(){
|
||||
self._write('');
|
||||
}, this.options.duration);
|
||||
}, this.options.duration);
|
||||
this._payload();
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
req.addListener('data', function(message){
|
||||
body += message;
|
||||
});
|
||||
req.addListener('end', function(){
|
||||
try {
|
||||
var msg = qs.parse(message);
|
||||
var msg = qs.parse(body);
|
||||
self._onMessage(msg.data);
|
||||
} catch(e){}
|
||||
res.writeHead(200);
|
||||
res.write('ok');
|
||||
res.close();
|
||||
res.end();
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -37,7 +41,7 @@ this['xhr-polling'] = Client.extend({
|
||||
if (this._closeTimeout) clearTimeout(this._closeTimeout);
|
||||
this.response.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': message.length});
|
||||
this.response.write(message);
|
||||
this.response.close();
|
||||
this.response.end();
|
||||
this._onClose();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
diff -rup node-v0.1.32-orig/src/node_http.cc node-v0.1.32/src/node_http.cc
|
||||
--- node-v0.1.32-orig/src/node_http.cc 2010-03-13 13:14:00.000000000 -0800
|
||||
+++ node-v0.1.32/src/node_http.cc 2010-03-13 13:23:48.000000000 -0800
|
||||
@@ -57,6 +57,7 @@ HTTPConnection::Initialize (Handle<Objec
|
||||
client_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
client_constructor_template->SetClassName(String::NewSymbol("Client"));
|
||||
NODE_SET_PROTOTYPE_METHOD(client_constructor_template, "resetParser", ResetParser);
|
||||
+ NODE_SET_PROTOTYPE_METHOD(client_constructor_template, "hijack", Hijack);
|
||||
target->Set(String::NewSymbol("Client"), client_constructor_template->GetFunction());
|
||||
|
||||
t = FunctionTemplate::New(NewServer);
|
||||
@@ -64,6 +65,7 @@ HTTPConnection::Initialize (Handle<Objec
|
||||
server_constructor_template->Inherit(Connection::constructor_template);
|
||||
server_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
NODE_SET_PROTOTYPE_METHOD(server_constructor_template, "resetParser", ResetParser);
|
||||
+ NODE_SET_PROTOTYPE_METHOD(server_constructor_template, "hijack", Hijack);
|
||||
server_constructor_template->SetClassName(String::NewSymbol("ServerSideConnection"));
|
||||
|
||||
end_symbol = NODE_PSYMBOL("end");
|
||||
@@ -101,6 +103,14 @@ Handle<Value> HTTPConnection::ResetParse
|
||||
}
|
||||
|
||||
|
||||
+Handle<Value> HTTPConnection::Hijack(const Arguments& args) {
|
||||
+ HandleScope scope;
|
||||
+ HTTPConnection *connection = ObjectWrap::Unwrap<HTTPConnection>(args.Holder());
|
||||
+ connection->Hijack();
|
||||
+ return Undefined();
|
||||
+}
|
||||
+
|
||||
+
|
||||
void
|
||||
HTTPConnection::OnReceive (const void *buf, size_t len)
|
||||
{
|
||||
@@ -109,6 +119,11 @@ HTTPConnection::OnReceive (const void *b
|
||||
assert(refs_);
|
||||
size_t nparsed;
|
||||
|
||||
+ if (hijacked) {
|
||||
+ Connection::OnReceive(buf, len);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
nparsed = http_parser_execute(&parser_, static_cast<const char*>(buf), len);
|
||||
|
||||
if (nparsed != len) {
|
||||
diff -rup node-v0.1.32-orig/src/node_http.h node-v0.1.32/src/node_http.h
|
||||
--- node-v0.1.32-orig/src/node_http.h 2010-03-13 13:14:00.000000000 -0800
|
||||
+++ node-v0.1.32/src/node_http.h 2010-03-13 13:25:05.000000000 -0800
|
||||
@@ -12,17 +12,21 @@ public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
static v8::Persistent<v8::FunctionTemplate> client_constructor_template;
|
||||
- static v8::Persistent<v8::FunctionTemplate> server_constructor_template;
|
||||
+ static v8::Persistent<v8::FunctionTemplate> server_constructor_template;
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> NewClient (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> NewServer (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ResetParser(const v8::Arguments& args);
|
||||
+ static v8::Handle<v8::Value> Hijack(const v8::Arguments& args);
|
||||
+
|
||||
+ bool hijacked;
|
||||
|
||||
HTTPConnection (enum http_parser_type t)
|
||||
: Connection()
|
||||
{
|
||||
type_ = t;
|
||||
+ hijacked = false;
|
||||
ResetParser();
|
||||
}
|
||||
|
||||
@@ -41,6 +45,10 @@ protected:
|
||||
parser_.data = this;
|
||||
}
|
||||
|
||||
+ void Hijack() {
|
||||
+ hijacked = true;
|
||||
+ }
|
||||
+
|
||||
void OnReceive (const void *buf, size_t len);
|
||||
void OnEOF ();
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
diff -rup node-v0.1.32-orig/src/node_http.cc node-v0.1.32/src/node_http.cc
|
||||
--- node-v0.1.32-orig/src/node_http.cc 2010-03-13 13:14:00.000000000 -0800
|
||||
+++ node-v0.1.32/src/node_http.cc 2010-03-13 13:23:48.000000000 -0800
|
||||
@@ -57,6 +57,7 @@ HTTPConnection::Initialize (Handle<Objec
|
||||
client_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
client_constructor_template->SetClassName(String::NewSymbol("Client"));
|
||||
NODE_SET_PROTOTYPE_METHOD(client_constructor_template, "resetParser", ResetParser);
|
||||
+ NODE_SET_PROTOTYPE_METHOD(client_constructor_template, "hijack", Hijack);
|
||||
target->Set(String::NewSymbol("Client"), client_constructor_template->GetFunction());
|
||||
|
||||
t = FunctionTemplate::New(NewServer);
|
||||
@@ -64,6 +65,7 @@ HTTPConnection::Initialize (Handle<Objec
|
||||
server_constructor_template->Inherit(Connection::constructor_template);
|
||||
server_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
NODE_SET_PROTOTYPE_METHOD(server_constructor_template, "resetParser", ResetParser);
|
||||
+ NODE_SET_PROTOTYPE_METHOD(server_constructor_template, "hijack", Hijack);
|
||||
server_constructor_template->SetClassName(String::NewSymbol("ServerSideConnection"));
|
||||
|
||||
end_symbol = NODE_PSYMBOL("end");
|
||||
@@ -101,6 +103,14 @@ Handle<Value> HTTPConnection::ResetParse
|
||||
}
|
||||
|
||||
|
||||
+Handle<Value> HTTPConnection::Hijack(const Arguments& args) {
|
||||
+ HandleScope scope;
|
||||
+ HTTPConnection *connection = ObjectWrap::Unwrap<HTTPConnection>(args.Holder());
|
||||
+ connection->Hijack();
|
||||
+ return Undefined();
|
||||
+}
|
||||
+
|
||||
+
|
||||
void
|
||||
HTTPConnection::OnReceive (const void *buf, size_t len)
|
||||
{
|
||||
@@ -109,6 +119,11 @@ HTTPConnection::OnReceive (const void *b
|
||||
assert(refs_);
|
||||
size_t nparsed;
|
||||
|
||||
+ if (hijacked) {
|
||||
+ Connection::OnReceive(buf, len);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
nparsed = http_parser_execute(&parser_, static_cast<const char*>(buf), len);
|
||||
|
||||
if (nparsed != len) {
|
||||
diff -rup node-v0.1.32-orig/src/node_http.h node-v0.1.32/src/node_http.h
|
||||
--- node-v0.1.32-orig/src/node_http.h 2010-03-13 13:14:00.000000000 -0800
|
||||
+++ node-v0.1.32/src/node_http.h 2010-03-13 13:25:05.000000000 -0800
|
||||
@@ -12,17 +12,21 @@ public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
static v8::Persistent<v8::FunctionTemplate> client_constructor_template;
|
||||
- static v8::Persistent<v8::FunctionTemplate> server_constructor_template;
|
||||
+ static v8::Persistent<v8::FunctionTemplate> server_constructor_template;
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> NewClient (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> NewServer (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ResetParser(const v8::Arguments& args);
|
||||
+ static v8::Handle<v8::Value> Hijack(const v8::Arguments& args);
|
||||
+
|
||||
+ bool hijacked;
|
||||
|
||||
HTTPConnection (enum http_parser_type t)
|
||||
: Connection()
|
||||
{
|
||||
type_ = t;
|
||||
+ hijacked = false;
|
||||
ResetParser();
|
||||
}
|
||||
|
||||
@@ -41,6 +45,10 @@ protected:
|
||||
parser_.data = this;
|
||||
}
|
||||
|
||||
+ void Hijack() {
|
||||
+ hijacked = true;
|
||||
+ }
|
||||
+
|
||||
void OnReceive (const void *buf, size_t len);
|
||||
void OnEOF ();
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
document.getElementById('text').value = '';
|
||||
}
|
||||
|
||||
var socket = new io.Socket('localhost', {rememberTransport: false, port: 8080});
|
||||
var socket = new io.Socket(null, {rememberTransport: false, port: 8080});
|
||||
socket.connect();
|
||||
socket.addEvent('message', function(data){
|
||||
var obj = io.util.JSON.decode(data);
|
||||
var obj = JSON.parse(data);
|
||||
|
||||
if ('buffer' in obj){
|
||||
document.getElementById('form').style.display='block';
|
||||
|
||||
Submodule test/client updated: 5cebe02f5d...d643e6029c
@@ -7,7 +7,7 @@ var http = require('http'),
|
||||
send404 = function(res){
|
||||
res.writeHead(404);
|
||||
res.write('404');
|
||||
res.close();
|
||||
res.end();
|
||||
},
|
||||
|
||||
server = http.createServer(function(req, res){
|
||||
@@ -17,7 +17,7 @@ server = http.createServer(function(req, res){
|
||||
case '/':
|
||||
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||
res.write('<h1>Welcome. Try the <a href="/chat.html">chat</a> example.</h1>');
|
||||
res.close();
|
||||
res.end();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -26,7 +26,7 @@ server = http.createServer(function(req, res){
|
||||
var swf = path.substr(-4) == '.swf';
|
||||
res.writeHead(200, {'Content-Type': swf ? 'application/x-shockwave-flash' : ('text/' + (path.substr(-3) == '.js' ? 'javascript' : 'html'))});
|
||||
res.write(fs.readFileSync(__dirname + path, swf ? 'binary' : 'utf8'), swf ? 'binary' : 'utf8');
|
||||
res.close();
|
||||
res.end();
|
||||
} catch(e){
|
||||
send404(res);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user