Compare commits

...

18 Commits
0.3.2 ... 0.3.7

Author SHA1 Message Date
Guillermo Rauch
d79de5aa56 Multipart fix for Node 0.1.98 2010-06-18 02:38:08 -03:00
Guillermo Rauch
06769c4ca7 Object fixes 2010-06-01 16:19:29 -03:00
Christiaan
df876e37df New changes passing JSlint as much as possible again 2010-06-01 21:05:20 +02:00
Christiaan
31d119740c Merge branch 'master' of http://github.com/LearnBoost/Socket.IO-node
Conflicts:
	lib/socket.io/client.js
	lib/socket.io/listener.js
	lib/socket.io/transports/websocket.js
	lib/socket.io/transports/xhr-multipart.js
	lib/socket.io/transports/xhr-polling.js

Conflicts Resolved
2010-06-01 20:54:13 +02:00
Guillermo Rauch
f3c28e298a Cross domain support:
XHR-Polling
 XHR-Multipart
WebSocket support for Webkit nightly / Chromium nightly
Added heartbeats to multipart
2010-06-01 08:01:11 -03:00
Brian
71d80181fa Fixed multipart streaming so that it works properly again (especially for cross-domain requests). Tested on Firefox 3.6.4. 2010-05-30 22:52:28 -07:00
Brian
0e483a05a5 Moved the cross-site origin checking to the client class, added cross-domain support to xhr-* transports, added ping functionality for the xhr-multipart transport, and fixed the listener class where the log function that can be overridden was not being referenced everywhere. 2010-05-30 22:52:16 -07:00
Christiaan
c1fca0c520 Almost fully passing JSlint 2010-05-29 15:21:46 +02:00
Visnu Pitiyanuvath
1918b75360 implement the sec-websocket-key handshake for latest chrome and webkit builds
http://www.whatwg.org/specs/web-apps/current-work/complete/network.html#opening-handshake
2010-05-28 11:15:55 -07:00
Christiaan
5e255ccdf9 Use exports instead of this as exports is the official way according to the commonjs spec 2010-05-28 19:37:46 +02:00
Christiaan
9a306fddab variables which are no constructor shouldn't start with a uppercase letter 2010-05-28 19:24:38 +02:00
Christiaan
dc593e9972 Use EventEmitter public API instead of the private _events array 2010-05-28 19:22:54 +02:00
Guillermo Rauch
7f5228abc3 Fixed syntax error -.- 2010-05-28 06:12:31 -03:00
Guillermo Rauch
0ad237ddf5 Fix for stream not writable problems 2010-05-28 05:28:25 -03:00
Guillermo Rauch
3134940ed6 Updated io.Socket initialization to work on hosts other than localhost
Updated client
2010-05-27 21:45:01 -03:00
Guillermo Rauch
0f783bc06a Fixed htmlfile
- end > close for detecting closed connections
 - Added hearbeats
 - added flush() in write
2010-05-27 21:33:07 -03:00
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
14 changed files with 279 additions and 143 deletions

View File

@@ -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

View File

@@ -1,29 +1,37 @@
var Options = require('./util/options').Options;
var options = require('./util/options').options, urlparse = require('url').parse;
this.Client = Class({
exports.Client = Class({
include: [Options],
include: [options],
options: {
closeTimeout: 0
closeTimeout: 0,
heartbeatInterval: 5000
},
init: function(listener, req, res, options){
init: function(listener, req, res, options, head){
this.listener = listener;
this.setOptions(options);
this.connections = 0;
this.connected = false;
this.upgradeHead = head;
this._onConnect(req, res);
},
send: function(message){
if (!this.connected || !(this.connection.readyState == 'open' || this.connection.readyState == 'writeOnly')) return this._queue(message);
if (!this.connected || !(this.connection.readyState === 'open' ||
this.connection.readyState === 'writeOnly')) {
return this._queue(message);
}
this._write(JSON.stringify({messages: [message]}));
return this;
},
broadcast: function(message){
if (!('sessionId' in this)) return this;
if (!('sessionId' in this)) {
return this;
}
this.listener.broadcast(message, this.sessionId);
return this;
},
@@ -44,7 +52,9 @@ this.Client = Class({
this.request = req;
this.response = res;
this.connection = this.request.connection;
if (this._disconnectTimeout) clearTimeout(this._disconnectTimeout);
if (this._disconnectTimeout) {
clearTimeout(this._disconnectTimeout);
}
},
_payload: function(){
@@ -64,12 +74,19 @@ this.Client = Class({
payload = payload.concat(this._writeQueue || []);
this._writeQueue = [];
if (payload.length) this._write(JSON.stringify({messages: payload}));
if (this.connections == 1) this.listener._onClientConnect(this);
if (payload.length) {
this._write(JSON.stringify({messages: payload}));
}
if (this.connections === 1) {
this.listener._onClientConnect(this);
}
},
_onClose: function(){
var self = this;
if (this._heartbeatInterval) {
clearInterval(this._heartbeatInterval);
}
this.connected = false;
this._disconnectTimeout = setTimeout(function(){
self._onDisconnect();
@@ -81,20 +98,34 @@ this.Client = Class({
this._writeQueue = [];
this.connected = false;
this.finalized = true;
if (this.handshaked) this.listener._onClientDisconnect(this);
if (this.handshaked) {
this.listener._onClientDisconnect(this);
}
}
},
_queue: function(message){
if (!('_writeQueue' in this)) this._writeQueue = [];
if (!('_writeQueue' in this)) {
this._writeQueue = [];
}
this._writeQueue.push(message);
return this;
},
_generateSessionId: function(){
if (this.sessionId) return this.listener.options.log('This client already has a session id');
if (this.sessionId) {
return this.listener.options.log('This client already has a session id');
}
this.sessionId = Math.random().toString().substr(2);
return this;
},
_verifyOrigin: function(origin){
var parts = urlparse(origin), origins = this.listener.options.origins;
return origins.indexOf('*:*') !== -1 ||
origins.indexOf(parts.host + ':' + parts.port) !== -1 ||
origins.indexOf(parts.host + ':*') !== -1 ||
origins.indexOf('*:' + parts.port) !== -1;
}
});

View File

@@ -1,13 +1,11 @@
var url = require('url'),
sys = require('sys'),
Options = require('./util/options').Options,
Client = require('./client').Client,
options = require('./util/options').options,
Client = require('./client').Client,
transports = {};
Transports = {};
Listener = this.Listener = Class({
var Listener = exports.Listener = Class({
include: [process.EventEmitter.prototype, Options],
include: [process.EventEmitter.prototype, options],
options: {
origins: '*:*',
@@ -15,7 +13,7 @@ Listener = this.Listener = Class({
transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling'],
transportOptions: {},
log: function(message){
sys.log(message);
require('sys').log(message);
}
},
@@ -27,28 +25,26 @@ Listener = this.Listener = Class({
this.clients = [];
this.clientsIndex = {};
var listener = (this.server._events['request'] instanceof Array)
? this.server._events['request'][0]
: this.server._events['request'];
if (listener){
this.server._events['request'] = function(req, res){
if (self.check(req, res)) return;
listener(req, res);
};
} else {
throw new Error('Couldn\'t find the `request` event in the HTTP server.');
}
var listeners = this.server.listeners('request');
this.server.removeAllListeners('request');
this.server.addListener('request', function(req, res){
if (self.check(req, res)) return;
for (var i = 0; i < listeners.length; i++) {
listeners[i].call(this, req, res);
}
});
this.server.addListener('upgrade', function(req, socket, head){
if (!self.check(req, socket, true)){
if (!self.check(req, socket, true, head)){
socket.destroy();
}
});
this.options.transports.forEach(function(t){
if (!(t in Transports)){
Transports[t] = require('./transports/' + t)[t];
if (Transports[t].init) Transports[t].init(this);
if (!(t in transports)){
transports[t] = require('./transports/' + t)[t];
if (transports[t].init) transports[t].init(this);
}
}, this);
@@ -64,7 +60,7 @@ Listener = this.Listener = Class({
return this;
},
check: function(req, res, httpUpgrade){
check: function(req, res, httpUpgrade, head){
var path = url.parse(req.url).pathname, parts, cn;
if (path.indexOf('/' + this.options.resource) === 0){
parts = path.substr(1).split('/');
@@ -74,10 +70,10 @@ Listener = this.Listener = Class({
cn._onConnect(req, res);
} else {
req.connection.end();
sys.log('Couldnt find client with session id "' + parts[2] + '"');
this.options.log('Couldnt find client with session id "' + parts[2] + '"');
}
} else {
this._onConnection(parts[1], req, res, httpUpgrade);
this._onConnection(parts[1], req, res, httpUpgrade, head);
}
return true;
}
@@ -90,12 +86,12 @@ Listener = this.Listener = Class({
_onClientConnect: function(client){
if (!(client instanceof Client) || !client.sessionId){
return sys.log('Invalid client');
return this.options.log('Invalid client');
}
client.i = this.clients.length;
this.clients.push(client);
this.clientsIndex[client.sessionId] = client;
sys.log('Client '+ client.sessionId +' connected');
this.options.log('Client '+ client.sessionId +' connected');
this.emit('clientConnect', client);
},
@@ -106,18 +102,18 @@ Listener = this.Listener = Class({
_onClientDisconnect: function(client){
this.clientsIndex[client.sessionId] = null;
this.clients[client.i] = null;
sys.log('Client '+ client.sessionId +' disconnected');
this.options.log('Client '+ client.sessionId +' disconnected');
this.emit('clientDisconnect', client);
},
// new connections (no session id)
_onConnection: function(transport, req, res, httpUpgrade){
if (this.options.transports.indexOf(transport) === -1 || (httpUpgrade && !Transports[transport].httpUpgrade)){
_onConnection: function(transport, req, res, httpUpgrade, head){
if (this.options.transports.indexOf(transport) === -1 || (httpUpgrade && !transports[transport].httpUpgrade)){
httpUpgrade ? res.destroy() : req.connection.destroy();
return sys.log('Illegal transport "'+ transport +'"');
return this.options.log('Illegal transport "'+ transport +'"');
}
sys.log('Initializing client with transport "'+ transport +'"');
new Transports[transport](this, req, res, this.options.transportOptions[transport]);
this.options.log('Initializing client with transport "'+ transport +'"');
new transports[transport](this, req, res, this.options.transportOptions[transport], head);
}
});
});

View File

@@ -2,9 +2,9 @@ var websocket = require('./websocket').websocket,
net = require('net'),
listeners = [];
this.flashsocket = websocket.extend({});
this.flashsocket.httpUpgrade = true;
this.flashsocket.init = function(listener){
exports.flashsocket = websocket.extend({});
exports.flashsocket.httpUpgrade = true;
exports.flashsocket.init = function(listener){
listeners.push(listener);
};
@@ -22,4 +22,4 @@ net.createServer(function(socket){
socket.write('</cross-domain-policy>\n');
socket.end();
}).listen(843);
}).listen(843);

View File

@@ -1,19 +1,28 @@
var Client = require('../client').Client,
qs = require('querystring');
this['htmlfile'] = Client.extend({
exports.htmlfile = Client.extend({
_onConnect: function(req, res){
var self = this, body = '';
switch (req.method){
case 'GET':
this.__super__(req, res);
this.request.connection.addListener('end', function(){ self._onClose(); });
this.response.useChunkedEncodingByDefault = false;
this.request.connection.addListener('close', function(){ self._onClose(); });
this.response.useChunkedEncodingByDefault = true;
this.response.shouldKeepAlive = true;
this.response.writeHead(200, { 'Content-type': 'text/html' });
this.response.writeHead(200, {
'Content-Type': 'text/html',
'Connection': 'keep-alive',
'Transfer-Encoding': 'chunked'
});
this.response.write('<html><body>' + new Array(244).join(' '));
this.response.flush();
this._payload();
this._heartbeatInterval = setInterval(function(){
self.response.write('<!-- heartbeat -->');
self.response.flush();
}, this.options.heartbeatInterval);
break;
case 'POST':
@@ -24,7 +33,7 @@ this['htmlfile'] = Client.extend({
try {
var msg = qs.parse(body);
self._onMessage(msg.data);
} catch(e){}
} catch(e){}
res.writeHead(200);
res.write('ok');
res.end();
@@ -34,8 +43,8 @@ this['htmlfile'] = Client.extend({
},
_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();
}
});

View File

@@ -1,15 +1,17 @@
var Client = require('../client').Client,
url = require('url');
url = require('url'),
Buffer = require('buffer').Buffer,
crypto = require('crypto');
this.websocket = Client.extend({
exports.websocket = Client.extend({
_onConnect: function(req, socket){
var self = this;
var self = this, headers = [];
this.request = req;
this.connection = socket;
this.data = '';
if (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();
}
@@ -17,26 +19,37 @@ this.websocket = Client.extend({
this.connection.setTimeout(0);
this.connection.setEncoding('utf8');
this.connection.setNoDelay(true);
this.connection.write([
headers = [
'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'));
'WebSocket-Location: ws://' + this.request.headers.host + this.request.url
];
if ('sec-websocket-key1' in this.request.headers){
headers.push(
'Sec-WebSocket-Origin: ' + this.request.headers.origin,
'Sec-WebSocket-Location: ws://' + this.request.headers.host + this.request.url);
}
this.connection.write(headers.concat('', '').join('\r\n'));
this.connection.addListener('end', function(){ self._onClose(); });
this.connection.addListener('data', function(data){ self._handle(data); });
this._payload();
if (this._proveReception()) {
this._payload();
}
},
_handle: function(data){
var chunk, chunks, chunk_count;
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') {
if (chunk[0] !== '\u0000') {
this.listener.options.log('Data incorrectly framed by UA. Dropping connection');
this.connection.destroy();
return false;
@@ -45,21 +58,49 @@ this.websocket = Client.extend({
}
this.data = chunks[chunks.length - 1];
},
_verifyOrigin: function(origin){
var parts = url.parse(origin);
return this.listener.options.origins.indexOf('*:*') !== -1
|| this.listener.options.origins.indexOf(parts.host + ':' + parts.port) !== -1
|| this.listener.options.origins.indexOf(parts.host + ':*') !== -1
|| this.listener.options.origins.indexOf('*:' + parts.port) !== -1;
// http://www.whatwg.org/specs/web-apps/current-work/complete/network.html#opening-handshake
_proveReception: function(){
var k1 = this.request.headers['sec-websocket-key1'],
k2 = this.request.headers['sec-websocket-key2'];
if (k1 && k2) {
var md5 = crypto.createHash('md5');
[k1, k2].forEach(function(k) {
var n = k.replace(/[^\d]/g, ''),
spaces = k.replace(/[^ ]/g, '').length,
buf = new Buffer(4);
if (spaces === 0) {
this.listener.options.log('Invalid WebSocket key: "' + k + '". Dropping connection');
this.connection.destroy();
return false;
}
n /= spaces;
buf[3] = n & 0xff;
buf[2] = (n >>= 8) & 0xff;
buf[1] = (n >>= 8) & 0xff;
buf[0] = (n >>= 8) & 0xff;
md5.update(buf.toString('binary'));
});
md5.update(this.upgradeHead.toString('binary'));
this.connection.write(md5.digest('binary'), 'binary');
}
return true;
},
_write: function(message){
this.connection.write('\u0000', 'binary');
this.connection.write(message, 'utf8');
this.connection.write('\uffff', 'binary');
try {
this.connection.write('\u0000', 'binary');
this.connection.write(message, 'utf8');
this.connection.write('\uffff', 'binary');
} catch(e){
this._onClose();
}
}
});
this.websocket.httpUpgrade = true;
exports.websocket.httpUpgrade = true;

View File

@@ -1,48 +1,69 @@
var Client = require('../client').Client,
qs = require('querystring');
qs = require('querystring');
this['xhr-multipart'] = Client.extend({
exports['xhr-multipart'] = Client.extend({
options: {
pingInterval: 7000
},
_pingInterval: null,
_onConnect: function(req, res){
var self = this, body = '';
var self = this, body = '', headers = {};
// https://developer.mozilla.org/En/HTTP_Access_Control
if (req.headers.origin && this._verifyOrigin(req.headers.origin)) {
headers['Access-Control-Allow-Origin'] = req.headers.origin;
headers['Access-Control-Allow-Credentials'] = 'true';
}
if (typeof req.headers['access-control-request-method'] !== 'undefined') {
// CORS preflight message
headers['Access-Control-Allow-Methods'] = req.headers['access-control-request-method'];
res.writeHead(200, headers);
res.write('ok');
res.end();
return;
}
switch (req.method){
case 'GET':
var self = this;
this.__super__(req, res);
headers['Content-Type'] = 'multipart/x-mixed-replace;boundary="socketio"';
headers['Connection'] = 'keep-alive';
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.writeHead(200, headers);
this.response.write("--socketio\n");
this.response.flush();
if ('flush' in this.response) this.response.flush();
this._payload();
this._heartbeatInterval = setInterval(function(){
self._write(String.fromCharCode(6));
}, this.options.heartbeatInterval);
break;
case 'POST':
req.addListener('data', function(message){
body += message;
body += message.toString();
});
req.addListener('end', function(){
try {
var msg = qs.parse(body);
self._onMessage(msg.data);
} catch(e){}
res.writeHead(200);
} catch(e){}
res.writeHead(200, headers);
res.write('ok');
res.end();
body = '';
});
break;
}
},
_write: function(message){
this.response.write("Content-Type: text/plain\n\n");
this.response.write("Content-Type: text/plain" + (message.length === 1 && message.charCodeAt(0) === 6 ? "; charset=us-ascii" : "") + "\n\n");
this.response.write(message + "\n");
this.response.write("--socketio\n");
this.response.flush();
if ('flush' in this.response) this.response.flush();
}
});

View File

@@ -1,8 +1,7 @@
var Client = require('../client').Client,
qs = require('querystring'),
sys = require('sys');
qs = require('querystring');
this['xhr-polling'] = Client.extend({
exports['xhr-polling'] = Client.extend({
options: {
closeTimeout: 5000,
@@ -13,10 +12,10 @@ this['xhr-polling'] = Client.extend({
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;
@@ -28,7 +27,7 @@ this['xhr-polling'] = Client.extend({
try {
var msg = qs.parse(body);
self._onMessage(msg.data);
} catch(e){}
} catch(e){}
res.writeHead(200);
res.write('ok');
res.end();
@@ -38,8 +37,18 @@ this['xhr-polling'] = Client.extend({
},
_write: function(message){
if (this._closeTimeout) clearTimeout(this._closeTimeout);
this.response.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': message.length});
if (this._closeTimeout) {
clearTimeout(this._closeTimeout);
}
var headers = {'Content-Type': 'text/plain', 'Content-Length': message.length};
// https://developer.mozilla.org/En/HTTP_Access_Control
if (this.request.headers.origin && this._verifyOrigin(this.request.headers.origin)) {
headers['Access-Control-Allow-Origin'] = this.request.headersorigin;
if (this.request.headers.cookie) {
headers['Access-Control-Allow-Credentials'] = 'true';
}
}
this.response.writeHead(200, headers);
this.response.write(message);
this.response.end();
this._onClose();

View File

@@ -1,16 +1,20 @@
// Based on Mixin.js from MooTools (MIT)
// Copyright (c) 2006-2009 Valerio Proietti, <http://mad4milk.net/>
this.flatten = function(arr){
exports.flatten = function(arr){
var array = [];
for (var i = 0, l = arr.length; i < l; i++){
var item = arr[i];
if (item != null) array = array.concat(item instanceof Array ? array.flatten(item) : item);
if (item !== null) {
array = array.concat(item instanceof Array ? array.flatten(item) : item);
}
}
return array;
};
this.include = function(arr, item){
if (arr.indexOf(item) == -1) arr.push(item);
exports.include = function(arr, item){
if (arr.indexOf(item) === -1) {
arr.push(item);
}
return arr;
};

View File

@@ -1,38 +1,51 @@
// Based on Mixin.js from MooTools (MIT)
// Copyright (c) 2006-2009 Valerio Proietti, <http://mad4milk.net/>
var clone = this.clone = function(item){
var clone;
exports.clone = function(item) {
var cloned;
if (item instanceof Array){
clone = [];
for (var i = 0; i < item.length; i++) clone[i] = clone(item[i]);
return clone;
} else if (typeof item == 'object') {
clone = {};
for (var key in object) clone[key] = clone(object[key]);
return clone;
} else {
return item;
cloned = [];
for (var i = 0; i < item.length; i++) {
cloned[i] = exports.clone(item[i]);
}
return cloned;
}
},
if (typeof item === 'object') {
cloned = {};
for (var key in item) {
cloned[key] = exports.clone(item[key]);
}
return cloned;
}
return item;
};
mergeOne = function(source, key, current){
var mergeOne = function(source, key, current){
if (current instanceof Array){
source[key] = clone(current);
} else if (typeof current == 'object'){
if (typeof source[key] == 'object') object.merge(source[key], current);
else source[key] = clone(current);
source[key] = exports.clone(current);
} else if (typeof current === 'object'){
if (typeof source[key] === 'object') {
exports.merge(source[key], current);
} else {
source[key] = exports.clone(current);
}
} else {
source[key] = current;
}
return source;
};
this.merge = function(source, k, v){
if (typeof k == 'string') return mergeOne(source, k, v);
exports.merge = function(source, k, v){
if (typeof k === 'string') {
return mergeOne(source, k, v);
}
for (var i = 1, l = arguments.length; i < l; i++){
var object = arguments[i];
for (var key in object) mergeOne(source, key, object[key]);
for (var key in object) {
mergeOne(source, key, object[key]);
}
}
return source;
};
};

View File

@@ -2,7 +2,7 @@
// Copyright (c) 2006-2009 Valerio Proietti, <http://mad4milk.net/>
var object = require('./object'), sys = require('sys');
this.Options = {
exports.options = {
options: {},
@@ -12,13 +12,20 @@ this.Options = {
},
setOptions: function(options){
for (var key in options) this.setOption(key, options[key]);
for (var key in options) {
this.setOption(key, options[key]);
}
if (this.addListener){
var first_lower = function(full, first){
return first.toLowerCase();
};
// Automagically register callbacks if the varname starts with on
for (var i in this.options){
if (!(/^on[A-Z]/).test(i) || typeof this.options[i] != 'function') continue;
this.addListener(i.replace(/^on([A-Z])/, function(full, first){
return first.toLowerCase();
}), this.options[i]);
if (!(/^on[A-Z]/).test(i) || typeof this.options[i] !== 'function') {
continue;
}
this.addListener(i.replace(/^on([A-Z])/, first_lower), this.options[i]);
this.options[i] = null;
}
}

View File

@@ -25,7 +25,7 @@
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 = JSON.parse(data);

View File

@@ -23,8 +23,8 @@ server = http.createServer(function(req, res){
default:
if (/\.(js|html|swf)$/.test(path)){
try {
var swf = path.substr(-4) == '.swf';
res.writeHead(200, {'Content-Type': swf ? 'application/x-shockwave-flash' : ('text/' + (path.substr(-3) == '.js' ? 'javascript' : 'html'))});
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.end();
} catch(e){
@@ -58,7 +58,9 @@ io.listen(server, {
onClientMessage: function(message, client){
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
if (buffer.length > 15) {
buffer.shift();
}
client.broadcast(json(msg));
}