mirror of
https://github.com/logsol/chuck.js.git
synced 2026-05-11 10:37:34 +00:00
added networking tests
This commit is contained in:
parent
bcde1d3171
commit
620f2626a3
506 changed files with 228337 additions and 0 deletions
94
networking/app.js
Normal file
94
networking/app.js
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
var http = require('http'),
|
||||
io = require('socket.io'),
|
||||
fs = require('fs'),
|
||||
Box2D = require('./box2d.js');
|
||||
|
||||
eval(fs.readFileSync('common.js') + '');
|
||||
|
||||
var clients = [];
|
||||
|
||||
function update() {
|
||||
world.Step(1 / 60, 10, 10);
|
||||
world.ClearForces();
|
||||
}
|
||||
|
||||
setInterval(update, 1000 / 60);
|
||||
setInterval(updateClients, 500);
|
||||
|
||||
function updateClients() {
|
||||
var body = world.GetBodyList();
|
||||
var update = {};
|
||||
|
||||
do {
|
||||
var userData = body.GetUserData();
|
||||
|
||||
if(userData && userData.bodyId){
|
||||
update[userData.bodyId] = {
|
||||
p: body.GetPosition(),
|
||||
a: body.GetAngle(),
|
||||
v: body.GetLinearVelocity(),
|
||||
};
|
||||
}
|
||||
} while (body = body.GetNext());
|
||||
|
||||
sendToClients('world-update', update);
|
||||
}
|
||||
|
||||
function sendToClients(message, data) {
|
||||
var packet = {
|
||||
m: message,
|
||||
d: data
|
||||
}
|
||||
//console.log(JSON.stringify(packet));
|
||||
for (var i = 0; i < clients.length; i++) {
|
||||
clients[i].send(JSON.stringify(packet));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
setupWorld();
|
||||
//update();
|
||||
|
||||
// SOCKETS
|
||||
|
||||
var server = http.createServer(
|
||||
function(req, res){
|
||||
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||
res.end('<h1>Hello world</h1>');
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
server.listen(xport, xhost);
|
||||
console.log('port', xport);
|
||||
var socket = io.listen(server);
|
||||
|
||||
socket.configure('development', function(){
|
||||
socket.set('log level', 0);
|
||||
});
|
||||
|
||||
socket.on('connection', function(client) {
|
||||
clients.push(client);
|
||||
console.log("Total clients: " + clients.length);
|
||||
|
||||
client.send(JSON.stringify({"startId" : clients.length}));
|
||||
|
||||
client.on('message', function(data){
|
||||
data = JSON.parse(data);
|
||||
|
||||
if(data && data.m){
|
||||
switch(data.m){
|
||||
case 'jump':
|
||||
jump();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.on('disconnect', function(){
|
||||
console.log("disconnect");
|
||||
});
|
||||
});
|
||||
94
networking/app.js~
Normal file
94
networking/app.js~
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
var http = require('http'),
|
||||
io = require('socket.io'),
|
||||
fs = require('fs'),
|
||||
Box2D = require('./box2d.js');
|
||||
|
||||
eval(fs.readFileSync('common.js') + '');
|
||||
|
||||
var clients = [];
|
||||
|
||||
function update() {
|
||||
world.Step(1 / 60, 10, 10);
|
||||
world.ClearForces();
|
||||
}
|
||||
|
||||
setInterval(update, 1000 / 60);
|
||||
setInterval(updateClients, 500);
|
||||
|
||||
function updateClients() {
|
||||
var body = world.GetBodyList();
|
||||
var update = {};
|
||||
|
||||
do {
|
||||
var userData = body.GetUserData();
|
||||
|
||||
if(userData && userData.bodyId){
|
||||
update[userData.bodyId] = {
|
||||
p: body.GetPosition(),
|
||||
a: body.GetAngle(),
|
||||
v: body.GetLinearVelocity(),
|
||||
};
|
||||
}
|
||||
} while (body = body.GetNext());
|
||||
|
||||
sendToClients('world-update', update);
|
||||
}
|
||||
|
||||
function sendToClients(message, data) {
|
||||
var packet = {
|
||||
m: message,
|
||||
d: data
|
||||
}
|
||||
//console.log(JSON.stringify(packet));
|
||||
for (var i = 0; i < clients.length; i++) {
|
||||
clients[i].send(JSON.stringify(packet));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
setupWorld();
|
||||
//update();
|
||||
|
||||
// SOCKETS
|
||||
|
||||
var server = http.createServer(
|
||||
function(req, res){
|
||||
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||
res.end('<h1>Hello world</h1>');
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
server.listen(xport, xhost);
|
||||
console.log('port', xport);
|
||||
var socket = io.listen(server);
|
||||
|
||||
socket.configure('development', function(){
|
||||
socket.set('log level', 0);
|
||||
});
|
||||
|
||||
socket.on('connection', function(client) {
|
||||
clients.push(client);
|
||||
console.log("Total clients: " + clients.length);
|
||||
|
||||
client.send(JSON.stringify({"startId" : clients.length}));
|
||||
|
||||
client.on('message', function(data){
|
||||
data = JSON.parse(data);
|
||||
|
||||
if(data && data.m){
|
||||
switch(data.m){
|
||||
case 'jump':
|
||||
jump();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.on('disconnect', function(){
|
||||
console.log("disconnect");
|
||||
});
|
||||
});
|
||||
10864
networking/box2d.js
Normal file
10864
networking/box2d.js
Normal file
File diff suppressed because it is too large
Load diff
107
networking/client.js
Normal file
107
networking/client.js
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
var id = null;
|
||||
|
||||
function setupCanvas() {
|
||||
var debugDraw = new b2DebugDraw();
|
||||
|
||||
debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
|
||||
debugDraw.SetDrawScale(30.0);
|
||||
debugDraw.SetFillAlpha(0.5);
|
||||
debugDraw.SetLineThickness(1.0);
|
||||
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
|
||||
|
||||
world.SetDebugDraw(debugDraw);
|
||||
}
|
||||
|
||||
function _jump() {
|
||||
jump();
|
||||
|
||||
var data = {
|
||||
m: 'jump'
|
||||
};
|
||||
socket.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
function init() {
|
||||
setupWorld();
|
||||
setupCanvas();
|
||||
|
||||
window.setInterval(update, 1000 / 60);
|
||||
|
||||
var body;
|
||||
|
||||
//update
|
||||
function update() {
|
||||
world.Step(1 / 60, 10, 10);
|
||||
world.DrawDebugData();
|
||||
world.ClearForces();
|
||||
}
|
||||
}
|
||||
|
||||
//helpers
|
||||
|
||||
//http://js-tut.aardon.de/js-tut/tutorial/position.html
|
||||
function getElementPosition(element) {
|
||||
var elem = element, tagname = "", x = 0, y = 0;
|
||||
|
||||
while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) {
|
||||
y += elem.offsetTop;
|
||||
x += elem.offsetLeft;
|
||||
|
||||
tagname = elem.tagName.toUpperCase();
|
||||
|
||||
if(tagname == "BODY") elem = 0;
|
||||
|
||||
if(typeof(elem) == "object") {
|
||||
if(typeof(elem.offsetParent) == "object") elem = elem.offsetParent;
|
||||
}
|
||||
|
||||
return {x: x, y: y};
|
||||
}
|
||||
}
|
||||
|
||||
function updateWorld(data) {
|
||||
var body = world.GetBodyList();
|
||||
do {
|
||||
var userData = body.GetUserData();
|
||||
if(userData && userData.bodyId){
|
||||
var update = data[userData.bodyId];
|
||||
body.SetPosition(update.p);
|
||||
body.SetAngle(update.a);
|
||||
body.SetLinearVelocity(update.v);
|
||||
}
|
||||
} while (body = body.GetNext());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var socket = io.connect(xhost + ':' + xport);
|
||||
|
||||
socket.on('connect',function() {
|
||||
console.log('Client has connected to the server!');
|
||||
connected = true;
|
||||
});
|
||||
|
||||
socket.on('message', function(packet) {
|
||||
packet = JSON.parse(packet);
|
||||
//console.log(packet);
|
||||
|
||||
if (packet && packet.m) {
|
||||
switch(packet.m) {
|
||||
case 'world-update':
|
||||
updateWorld(packet.d);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('disconnect',function() {
|
||||
console.log('The client has disconnected!');
|
||||
connected = false;
|
||||
});
|
||||
|
||||
|
||||
window.onload = init;
|
||||
107
networking/client.js~
Normal file
107
networking/client.js~
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
var id = null;
|
||||
|
||||
function setupCanvas() {
|
||||
var debugDraw = new b2DebugDraw();
|
||||
|
||||
debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
|
||||
debugDraw.SetDrawScale(30.0);
|
||||
debugDraw.SetFillAlpha(0.5);
|
||||
debugDraw.SetLineThickness(1.0);
|
||||
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
|
||||
|
||||
world.SetDebugDraw(debugDraw);
|
||||
}
|
||||
|
||||
function _jump() {
|
||||
|
||||
var data = {
|
||||
m: 'jump'
|
||||
};
|
||||
|
||||
socket.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
function init() {
|
||||
setupWorld();
|
||||
setupCanvas();
|
||||
|
||||
window.setInterval(update, 1000 / 60);
|
||||
|
||||
var body;
|
||||
|
||||
//update
|
||||
function update() {
|
||||
world.Step(1 / 60, 10, 10);
|
||||
world.DrawDebugData();
|
||||
world.ClearForces();
|
||||
}
|
||||
}
|
||||
|
||||
//helpers
|
||||
|
||||
//http://js-tut.aardon.de/js-tut/tutorial/position.html
|
||||
function getElementPosition(element) {
|
||||
var elem = element, tagname = "", x = 0, y = 0;
|
||||
|
||||
while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) {
|
||||
y += elem.offsetTop;
|
||||
x += elem.offsetLeft;
|
||||
|
||||
tagname = elem.tagName.toUpperCase();
|
||||
|
||||
if(tagname == "BODY") elem = 0;
|
||||
|
||||
if(typeof(elem) == "object") {
|
||||
if(typeof(elem.offsetParent) == "object") elem = elem.offsetParent;
|
||||
}
|
||||
|
||||
return {x: x, y: y};
|
||||
}
|
||||
}
|
||||
|
||||
function updateWorld(data) {
|
||||
var body = world.GetBodyList();
|
||||
do {
|
||||
var userData = body.GetUserData();
|
||||
if(userData && userData.bodyId){
|
||||
var update = data[userData.bodyId];
|
||||
body.SetPosition(update.p);
|
||||
body.SetAngle(update.a);
|
||||
body.SetLinearVelocity(update.v);
|
||||
}
|
||||
} while (body = body.GetNext());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var socket = io.connect(xhost + ':' + xport);
|
||||
|
||||
socket.on('connect',function() {
|
||||
console.log('Client has connected to the server!');
|
||||
connected = true;
|
||||
});
|
||||
|
||||
socket.on('message', function(packet) {
|
||||
packet = JSON.parse(packet);
|
||||
//console.log(packet);
|
||||
|
||||
if (packet && packet.m) {
|
||||
switch(packet.m) {
|
||||
case 'world-update':
|
||||
updateWorld(packet.d);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('disconnect',function() {
|
||||
console.log('The client has disconnected!');
|
||||
connected = false;
|
||||
});
|
||||
|
||||
|
||||
window.onload = init;
|
||||
82
networking/common.js
Normal file
82
networking/common.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
var bodiesNum = 3;
|
||||
var world;
|
||||
|
||||
var xport = 8003;
|
||||
var xhost = '127.0.0.1';
|
||||
|
||||
var b2Vec2 = Box2D.Common.Math.b2Vec2,
|
||||
b2AABB = Box2D.Collision.b2AABB,
|
||||
b2BodyDef = Box2D.Dynamics.b2BodyDef,
|
||||
b2Body = Box2D.Dynamics.b2Body,
|
||||
b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
|
||||
b2Fixture = Box2D.Dynamics.b2Fixture,
|
||||
b2World = Box2D.Dynamics.b2World,
|
||||
b2MassData = Box2D.Collision.Shapes.b2MassData,
|
||||
b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
|
||||
b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
|
||||
b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
|
||||
b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef;
|
||||
|
||||
function setupWorld() {
|
||||
world = new b2World(new b2Vec2(0, 10), true);
|
||||
|
||||
var fixDef = new b2FixtureDef;
|
||||
fixDef.density = 1.0;
|
||||
fixDef.friction = 0.5;
|
||||
fixDef.restitution = 0.2;
|
||||
|
||||
var bodyDef = new b2BodyDef;
|
||||
|
||||
// create ground
|
||||
bodyDef.type = b2Body.b2_staticBody;
|
||||
fixDef.shape = new b2PolygonShape;
|
||||
fixDef.shape.SetAsBox(20, 2);
|
||||
|
||||
bodyDef.position.Set(10, 400 / 30 + 1.8);
|
||||
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
bodyDef.position.Set(10, -1.8);
|
||||
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
fixDef.shape.SetAsBox(2, 14);
|
||||
|
||||
bodyDef.position.Set(-1.8, 13);
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
|
||||
bodyDef.position.Set(21.8, 13);
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
|
||||
// create some objects
|
||||
bodyDef.type = b2Body.b2_dynamicBody;
|
||||
|
||||
for(var i = 0; i < bodiesNum; i++) {
|
||||
fixDef.shape = new b2PolygonShape;
|
||||
fixDef.shape.SetAsBox(0.5, 0.5);
|
||||
|
||||
bodyDef.position.x = (i + 1) * 4;
|
||||
bodyDef.position.y = 3;
|
||||
|
||||
bodyDef.userData = {"bodyId" : parseInt(i) };
|
||||
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
}
|
||||
}
|
||||
|
||||
function jump() {
|
||||
var body = findBody(1);
|
||||
body.SetAwake(true);
|
||||
body.ApplyImpulse(new b2Vec2(0, -9), body.GetPosition());
|
||||
}
|
||||
|
||||
function findBody(index) {
|
||||
var body = null;
|
||||
|
||||
var nextBody = world.GetBodyList();
|
||||
for (var i = 0; i < bodiesNum; i++) {
|
||||
if (nextBody.GetUserData().bodyId == index) { body = nextBody; break; }
|
||||
nextBody = nextBody.GetNext();
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
82
networking/common.js~
Normal file
82
networking/common.js~
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
var bodiesNum = 3;
|
||||
var world;
|
||||
|
||||
var xport = 8003;
|
||||
var xhost = '127.0.0.1';
|
||||
|
||||
var b2Vec2 = Box2D.Common.Math.b2Vec2,
|
||||
b2AABB = Box2D.Collision.b2AABB,
|
||||
b2BodyDef = Box2D.Dynamics.b2BodyDef,
|
||||
b2Body = Box2D.Dynamics.b2Body,
|
||||
b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
|
||||
b2Fixture = Box2D.Dynamics.b2Fixture,
|
||||
b2World = Box2D.Dynamics.b2World,
|
||||
b2MassData = Box2D.Collision.Shapes.b2MassData,
|
||||
b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
|
||||
b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
|
||||
b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
|
||||
b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef;
|
||||
|
||||
function setupWorld() {
|
||||
world = new b2World(new b2Vec2(0, 10), true);
|
||||
|
||||
var fixDef = new b2FixtureDef;
|
||||
fixDef.density = 1.0;
|
||||
fixDef.friction = 0.5;
|
||||
fixDef.restitution = 0.2;
|
||||
|
||||
var bodyDef = new b2BodyDef;
|
||||
|
||||
// create ground
|
||||
bodyDef.type = b2Body.b2_staticBody;
|
||||
fixDef.shape = new b2PolygonShape;
|
||||
fixDef.shape.SetAsBox(20, 2);
|
||||
|
||||
bodyDef.position.Set(10, 400 / 30 + 1.8);
|
||||
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
bodyDef.position.Set(10, -1.8);
|
||||
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
fixDef.shape.SetAsBox(2, 14);
|
||||
|
||||
bodyDef.position.Set(-1.8, 13);
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
|
||||
bodyDef.position.Set(21.8, 13);
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
|
||||
// create some objects
|
||||
bodyDef.type = b2Body.b2_dynamicBody;
|
||||
|
||||
for(var i = 0; i < bodiesNum; i++) {
|
||||
fixDef.shape = new b2PolygonShape;
|
||||
fixDef.shape.SetAsBox(0.5, 0.5);
|
||||
|
||||
bodyDef.position.x = (i + 1) * 4;
|
||||
bodyDef.position.y = 3;
|
||||
|
||||
bodyDef.userData = {"bodyId" : parseInt(i) };
|
||||
|
||||
world.CreateBody(bodyDef).CreateFixture(fixDef);
|
||||
}
|
||||
}
|
||||
|
||||
function jump() {
|
||||
var body = findBody(1);
|
||||
body.SetAwake(true);
|
||||
body.ApplyImpulse(new b2Vec2(0, -5), body.GetPosition());
|
||||
}
|
||||
|
||||
function findBody(index) {
|
||||
var body = null;
|
||||
|
||||
var nextBody = world.GetBodyList();
|
||||
for (var i = 0; i < bodiesNum; i++) {
|
||||
if (nextBody.GetUserData().bodyId == index) { body = nextBody; break; }
|
||||
nextBody = nextBody.GetNext();
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
15
networking/index.html
Normal file
15
networking/index.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Box2dWeb Demo</title>
|
||||
<script src="http://localhost:8003/socket.io/socket.io.js"></script>
|
||||
<script src="box2d.js"></script>
|
||||
<script src="common.js"></script>
|
||||
<script src="client.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas" width="600" height="400" style="background-color:#333333;"></canvas>
|
||||
<button onclick="_jump()">jump</button>
|
||||
</body>
|
||||
</html>
|
||||
15
networking/index.html~
Normal file
15
networking/index.html~
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Box2dWeb Demo</title>
|
||||
<script src="http://localhost:8003/socket.io/socket.io.js"></script>
|
||||
<script src="box2d.js"></script>
|
||||
<script src="common.js"></script>
|
||||
<script src="client.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas" width="600" height="400" style="background-color:#333333;"></canvas>
|
||||
<button onclick="jump()">jump</button>
|
||||
</body>
|
||||
</html>
|
||||
58
networking/node_modules/box2d/README
generated
vendored
Normal file
58
networking/node_modules/box2d/README
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
@author Josh Adell <josh.adell@gmail.com>
|
||||
|
||||
A port of the box2djs library into a node module.
|
||||
|
||||
Here is the box2d "Hello World" program from http://www.box2d.org/ written for node:
|
||||
|
||||
--- BEGIN CODE EXAMPLE ---
|
||||
|
||||
var sys = require("sys"),
|
||||
b2d = require("./box2dnode");
|
||||
|
||||
// Define world
|
||||
var worldAABB = new b2d.b2AABB();
|
||||
worldAABB.lowerBound.Set(-100.0, -100.0);
|
||||
worldAABB.upperBound.Set(100.0, 100.0);
|
||||
|
||||
var gravity = new b2d.b2Vec2(0.0, -10.0);
|
||||
var doSleep = true;
|
||||
|
||||
var world = new b2d.b2World(worldAABB, gravity, doSleep);
|
||||
|
||||
// Ground Box
|
||||
var groundBodyDef = new b2d.b2BodyDef();
|
||||
groundBodyDef.position.Set(0.0, -10.0);
|
||||
|
||||
var groundBody = world.CreateBody(groundBodyDef);
|
||||
|
||||
var groundShapeDef = new b2d.b2PolygonDef();
|
||||
groundShapeDef.SetAsBox(50.0, 10.0);
|
||||
|
||||
groundBody.CreateShape(groundShapeDef);
|
||||
|
||||
// Dynamic Body
|
||||
var bodyDef = new b2d.b2BodyDef();
|
||||
bodyDef.position.Set(0.0, 4.0);
|
||||
|
||||
var body = world.CreateBody(bodyDef);
|
||||
|
||||
var shapeDef = new b2d.b2PolygonDef();
|
||||
shapeDef.SetAsBox(1.0, 1.0);
|
||||
shapeDef.density = 1.0;
|
||||
shapeDef.friction = 0.3;
|
||||
body.CreateShape(shapeDef);
|
||||
body.SetMassFromShapes();
|
||||
|
||||
// Run Simulation!
|
||||
var timeStep = 1.0 / 60.0;
|
||||
|
||||
var iterations = 10;
|
||||
|
||||
for (var i=0; i < 60; i++) {
|
||||
world.Step(timeStep, iterations);
|
||||
var position = body.GetPosition();
|
||||
var angle = body.GetAngle();
|
||||
sys.puts(i+": <"+position.x+", "+position.y+"> @"+angle);
|
||||
}
|
||||
|
||||
--- END CODE EXAMPLE ---
|
||||
11132
networking/node_modules/box2d/box2dnode.js
generated
vendored
Normal file
11132
networking/node_modules/box2d/box2dnode.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
24
networking/node_modules/box2d/package.json
generated
vendored
Normal file
24
networking/node_modules/box2d/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "box2d",
|
||||
"version": "1.0.0",
|
||||
"description": "2D physics engine",
|
||||
"homepage": "http://github.com/jadell/box2dnode",
|
||||
"author": {
|
||||
"name": "Josh Adell",
|
||||
"email": "josh.adell@gmail.com",
|
||||
"url": "http://everymansoftware.blogspot.com/"
|
||||
},
|
||||
"main": "./box2dnode",
|
||||
"engines": [
|
||||
"node"
|
||||
],
|
||||
"_id": "box2d@1.0.0",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.4",
|
||||
"_nodeVersion": "v0.6.12",
|
||||
"_defaultsLoaded": true,
|
||||
"_from": "box2d"
|
||||
}
|
||||
3
networking/node_modules/socket.io/.npmignore
generated
vendored
Normal file
3
networking/node_modules/socket.io/.npmignore
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
support
|
||||
test
|
||||
examples
|
||||
6
networking/node_modules/socket.io/.travis.yml
generated
vendored
Normal file
6
networking/node_modules/socket.io/.travis.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
|
||||
notifications:
|
||||
irc: "irc.freenode.org#socket.io"
|
||||
260
networking/node_modules/socket.io/History.md
generated
vendored
Normal file
260
networking/node_modules/socket.io/History.md
generated
vendored
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
|
||||
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
|
||||
==================
|
||||
|
||||
* Added JSON decoding on jsonp-polling transport.
|
||||
* Fixed README example.
|
||||
* Major speed optimizations [3rd-Eden] [einaros] [visionmedia]
|
||||
* Added decode/encode benchmarks [visionmedia]
|
||||
* Added support for black-listing client sent events.
|
||||
* Fixed logging options, closes #540 [3rd-Eden]
|
||||
* Added vary header for gzip [3rd-Eden]
|
||||
* Properly cleaned up async websocket / flashsocket tests, after patching node-websocket-client
|
||||
* Patched to properly shut down when a finishClose call is made during connection establishment
|
||||
* Added support for socket.io version on url and far-future Expires [3rd-Eden] [getify]
|
||||
* Began IE10 compatibility [einaros] [tbranyen]
|
||||
* Misc WebSocket fixes [einaros]
|
||||
* Added UTF8 to respone headers for htmlfile [3rd-Eden]
|
||||
|
||||
0.8.5 / 2011-10-07
|
||||
==================
|
||||
|
||||
* Added websocket draft HyBi-16 support. [einaros]
|
||||
* Fixed websocket continuation bugs. [einaros]
|
||||
* Fixed flashsocket transport name.
|
||||
* Fixed websocket tests.
|
||||
* Ensured `parser#decodePayload` doesn't choke.
|
||||
* Added http referrer verification to manager verifyOrigin.
|
||||
* Added access control for cross domain xhr handshakes [3rd-Eden]
|
||||
* Added support for automatic generation of socket.io files [3rd-Eden]
|
||||
* Added websocket binary support [einaros]
|
||||
* Added gzip support for socket.io.js [3rd-Eden]
|
||||
* Expose socket.transport [3rd-Eden]
|
||||
* Updated client.
|
||||
|
||||
0.8.4 / 2011-09-06
|
||||
==================
|
||||
|
||||
* Client build
|
||||
|
||||
0.8.3 / 2011-09-03
|
||||
==================
|
||||
|
||||
* Fixed `\n` parsing for non-JSON packets (fixes #479).
|
||||
* Fixed parsing of certain unicode characters (fixes #451).
|
||||
* Fixed transport message packet logging.
|
||||
* Fixed emission of `error` event resulting in an uncaught exception if unhandled (fixes #476).
|
||||
* Fixed; allow for falsy values as the configuration value of `log level` (fixes #491).
|
||||
* Fixed repository URI in `package.json`. Fixes #504.
|
||||
* Added text/plain content-type to handshake responses [einaros]
|
||||
* Improved single byte writes [einaros]
|
||||
* Updated socket.io-flashsocket default port from 843 to 10843 [3rd-Eden]
|
||||
* Updated client.
|
||||
|
||||
0.8.2 / 2011-08-29
|
||||
==================
|
||||
|
||||
* Updated client.
|
||||
|
||||
0.8.1 / 2011-08-29
|
||||
==================
|
||||
|
||||
* Fixed utf8 bug in send framing in websocket [einaros]
|
||||
* Fixed typo in docs [Znarkus]
|
||||
* Fixed bug in send framing for over 64kB of data in websocket [einaros]
|
||||
* Corrected ping handling in websocket transport [einaros]
|
||||
|
||||
0.8.0 / 2011-08-28
|
||||
==================
|
||||
|
||||
* Updated to work with two-level websocket versioning. [einaros]
|
||||
* Added hybi07 support. [einaros]
|
||||
* Added hybi10 support. [einaros]
|
||||
* Added http referrer verification to manager.js verifyOrigin. [einaors]
|
||||
|
||||
0.7.11 / 2011-08-27
|
||||
===================
|
||||
|
||||
* Updated socket.io-client.
|
||||
|
||||
0.7.10 / 2011-08-27
|
||||
===================
|
||||
|
||||
* Updated socket.io-client.
|
||||
|
||||
0.7.9 / 2011-08-12
|
||||
==================
|
||||
|
||||
* Updated socket.io-client.
|
||||
* Make sure we only do garbage collection when the server we receive is actually run.
|
||||
|
||||
0.7.8 / 2011-08-08
|
||||
==================
|
||||
|
||||
* Changed; make sure sio#listen passes options to both HTTP server and socket.io manager.
|
||||
* Added docs for sio#listen.
|
||||
* Added options parameter support for Manager constructor.
|
||||
* Added memory leaks tests and test-leaks Makefile task.
|
||||
* Removed auto npm-linking from make test.
|
||||
* Make sure that you can disable heartbeats. [3rd-Eden]
|
||||
* Fixed rooms memory leak [3rd-Eden]
|
||||
* Send response once we got all POST data, not immediately [Pita]
|
||||
* Fixed onLeave behavior with missing clientsk [3rd-Eden]
|
||||
* Prevent duplicate references in rooms.
|
||||
* Added alias for `to` to `in` and `in` to `to`.
|
||||
* Fixed roomClients definition.
|
||||
* Removed dependency on redis for installation without npm [3rd-Eden]
|
||||
* Expose path and querystring in handshakeData [3rd-Eden]
|
||||
|
||||
0.7.7 / 2011-07-12
|
||||
==================
|
||||
|
||||
* Fixed double dispatch handling with emit to closed clients.
|
||||
* Added test for emitting to closed clients to prevent regression.
|
||||
* Fixed race condition in redis test.
|
||||
* Changed Transport#end instrumentation.
|
||||
* Leveraged $emit instead of emit internally.
|
||||
* Made tests faster.
|
||||
* Fixed double disconnect events.
|
||||
* Fixed disconnect logic
|
||||
* Simplified remote events handling in Socket.
|
||||
* Increased testcase timeout.
|
||||
* Fixed unknown room emitting (GH-291). [3rd-Eden]
|
||||
* Fixed `address` in handshakeData. [3rd-Eden]
|
||||
* Removed transports definition in chat example.
|
||||
* Fixed room cleanup
|
||||
* Fixed; make sure the client is cleaned up after booting.
|
||||
* Make sure to mark the client as non-open if the connection is closed.
|
||||
* Removed unneeded `buffer` declarations.
|
||||
* Fixed; make sure to clear socket handlers and subscriptions upon transport close.
|
||||
|
||||
0.7.6 / 2011-06-30
|
||||
==================
|
||||
|
||||
* Fixed general dispatching when a client has closed.
|
||||
|
||||
0.7.5 / 2011-06-30
|
||||
==================
|
||||
|
||||
* Fixed dispatching to clients that are disconnected.
|
||||
|
||||
0.7.4 / 2011-06-30
|
||||
==================
|
||||
|
||||
* Fixed; only clear handlers if they were set. [level09]
|
||||
|
||||
0.7.3 / 2011-06-30
|
||||
==================
|
||||
|
||||
* Exposed handshake data to clients.
|
||||
* Refactored dispatcher interface.
|
||||
* Changed; Moved id generation method into the manager.
|
||||
* Added sub-namespace authorization. [3rd-Eden]
|
||||
* Changed; normalized SocketNamespace local eventing [dvv]
|
||||
* Changed; Use packet.reason or default to 'packet' [3rd-Eden]
|
||||
* Changed console.error to console.log.
|
||||
* Fixed; bind both servers at the same time do that the test never times out.
|
||||
* Added 304 support.
|
||||
* Removed `Transport#name` for abstract interface.
|
||||
* Changed; lazily require http and https module only when needed. [3rd-Eden]
|
||||
|
||||
0.7.2 / 2011-06-22
|
||||
==================
|
||||
|
||||
* Make sure to write a packet (of type `noop`) when closing a poll.
|
||||
This solves a problem with cross-domain requests being flagged as aborted and
|
||||
reconnection being triggered.
|
||||
* Added `noop` message type.
|
||||
|
||||
0.7.1 / 2011-06-21
|
||||
==================
|
||||
|
||||
* Fixed cross-domain XHR.
|
||||
* Added CORS test to xhr-polling suite.
|
||||
|
||||
0.7.0 / 2010-06-21
|
||||
==================
|
||||
|
||||
* http://socket.io/announcement.html
|
||||
31
networking/node_modules/socket.io/Makefile
generated
vendored
Normal file
31
networking/node_modules/socket.io/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
ALL_TESTS = $(shell find test/ -name '*.test.js')
|
||||
ALL_BENCH = $(shell find benchmarks -name '*.bench.js')
|
||||
|
||||
run-tests:
|
||||
@./node_modules/.bin/expresso \
|
||||
-t 3000 \
|
||||
-I support \
|
||||
--serial \
|
||||
$(TESTFLAGS) \
|
||||
$(TESTS)
|
||||
|
||||
test:
|
||||
@$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests
|
||||
|
||||
test-cov:
|
||||
@TESTFLAGS=--cov $(MAKE) test
|
||||
|
||||
test-leaks:
|
||||
@ls test/leaks/* | xargs node --expose_debug_as=debug --expose_gc
|
||||
|
||||
run-bench:
|
||||
@node $(PROFILEFLAGS) benchmarks/runner.js
|
||||
|
||||
bench:
|
||||
@$(MAKE) BENCHMARKS="$(ALL_BENCH)" run-bench
|
||||
|
||||
profile:
|
||||
@PROFILEFLAGS='--prof --trace-opt --trace-bailout --trace-deopt' $(MAKE) bench
|
||||
|
||||
.PHONY: test bench profile
|
||||
345
networking/node_modules/socket.io/Readme.md
generated
vendored
Normal file
345
networking/node_modules/socket.io/Readme.md
generated
vendored
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
# Socket.IO
|
||||
|
||||
Socket.IO is a Node.JS project that makes WebSockets and realtime possible in
|
||||
all browsers. It also enhances WebSockets by providing built-in multiplexing,
|
||||
horizontal scalability, automatic JSON encoding/decoding, and more.
|
||||
|
||||
## How to Install
|
||||
|
||||
```bash
|
||||
npm install socket.io
|
||||
```
|
||||
|
||||
## How to use
|
||||
|
||||
First, require `socket.io`:
|
||||
|
||||
```js
|
||||
var io = require('socket.io');
|
||||
```
|
||||
|
||||
Next, attach it to a HTTP/HTTPS server. If you're using the fantastic `express`
|
||||
web framework:
|
||||
|
||||
```js
|
||||
var app = express.createServer()
|
||||
, io = io.listen(app);
|
||||
|
||||
app.listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.emit('news', { hello: 'world' });
|
||||
socket.on('my other event', function (data) {
|
||||
console.log(data);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Finally, load it from the client side code:
|
||||
|
||||
```html
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
var socket = io.connect('http://localhost');
|
||||
socket.on('news', function (data) {
|
||||
console.log(data);
|
||||
socket.emit('my other event', { my: 'data' });
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
For more thorough examples, look at the `examples/` directory.
|
||||
|
||||
## Short recipes
|
||||
|
||||
### Sending and receiving events.
|
||||
|
||||
Socket.IO allows you to emit and receive custom events.
|
||||
Besides `connect`, `message` and `disconnect`, you can emit custom events:
|
||||
|
||||
```js
|
||||
// note, io.listen(<port>) will create a http server for you
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
io.sockets.emit('this', { will: 'be received by everyone' });
|
||||
|
||||
socket.on('private message', function (from, msg) {
|
||||
console.log('I received a private message by ', from, ' saying ', msg);
|
||||
});
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
io.sockets.emit('user disconnected');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Storing data associated to a client
|
||||
|
||||
Sometimes it's necessary to store data associated with a client that's
|
||||
necessary for the duration of the session.
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.on('set nickname', function (name) {
|
||||
socket.set('nickname', name, function () { socket.emit('ready'); });
|
||||
});
|
||||
|
||||
socket.on('msg', function () {
|
||||
socket.get('nickname', function (err, name) {
|
||||
console.log('Chat message by ', name);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Client side
|
||||
|
||||
```html
|
||||
<script>
|
||||
var socket = io.connect('http://localhost');
|
||||
|
||||
socket.on('connect', function () {
|
||||
socket.emit('set nickname', confirm('What is your nickname?'));
|
||||
socket.on('ready', function () {
|
||||
console.log('Connected !');
|
||||
socket.emit('msg', confirm('What is your message?'));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Restricting yourself to a namespace
|
||||
|
||||
If you have control over all the messages and events emitted for a particular
|
||||
application, using the default `/` namespace works.
|
||||
|
||||
If you want to leverage 3rd-party code, or produce code to share with others,
|
||||
socket.io provides a way of namespacing a `socket`.
|
||||
|
||||
This has the benefit of `multiplexing` a single connection. Instead of
|
||||
socket.io using two `WebSocket` connections, it'll use one.
|
||||
|
||||
The following example defines a socket that listens on '/chat' and one for
|
||||
'/news':
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
var chat = io
|
||||
.of('/chat')
|
||||
.on('connection', function (socket) {
|
||||
socket.emit('a message', { that: 'only', '/chat': 'will get' });
|
||||
chat.emit('a message', { everyone: 'in', '/chat': 'will get' });
|
||||
});
|
||||
|
||||
var news = io
|
||||
.of('/news');
|
||||
.on('connection', function (socket) {
|
||||
socket.emit('item', { news: 'item' });
|
||||
});
|
||||
```
|
||||
|
||||
#### Client side:
|
||||
|
||||
```html
|
||||
<script>
|
||||
var chat = io.connect('http://localhost/chat')
|
||||
, news = io.connect('http://localhost/news');
|
||||
|
||||
chat.on('connect', function () {
|
||||
chat.emit('hi!');
|
||||
});
|
||||
|
||||
news.on('news', function () {
|
||||
news.emit('woot');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Sending volatile messages.
|
||||
|
||||
Sometimes certain messages can be dropped. Let's say you have an app that
|
||||
shows realtime tweets for the keyword `bieber`.
|
||||
|
||||
If a certain client is not ready to receive messages (because of network slowness
|
||||
or other issues, or because he's connected through long polling and is in the
|
||||
middle of a request-response cycle), if he doesn't receive ALL the tweets related
|
||||
to bieber your application won't suffer.
|
||||
|
||||
In that case, you might want to send those messages as volatile messages.
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
var tweets = setInterval(function () {
|
||||
getBieberTweet(function (tweet) {
|
||||
socket.volatile.emit('bieber tweet', tweet);
|
||||
});
|
||||
}, 100);
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
clearInterval(tweets);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Client side
|
||||
|
||||
In the client side, messages are received the same way whether they're volatile
|
||||
or not.
|
||||
|
||||
### Getting acknowledgements
|
||||
|
||||
Sometimes, you might want to get a callback when the client confirmed the message
|
||||
reception.
|
||||
|
||||
To do this, simply pass a function as the last parameter of `.send` or `.emit`.
|
||||
What's more, when you use `.emit`, the acknowledgement is done by you, which
|
||||
means you can also pass data along:
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.on('ferret', function (name, fn) {
|
||||
fn('woot');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Client side
|
||||
|
||||
```html
|
||||
<script>
|
||||
var socket = io.connect(); // TIP: .connect with no args does auto-discovery
|
||||
socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
|
||||
socket.emit('ferret', 'tobi', function (data) {
|
||||
console.log(data); // data will be 'woot'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Broadcasting messages
|
||||
|
||||
To broadcast, simply add a `broadcast` flag to `emit` and `send` method calls.
|
||||
Broadcasting means sending a message to everyone else except for the socket
|
||||
that starts it.
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.broadcast.emit('user connected');
|
||||
socket.broadcast.json.send({ a: 'message' });
|
||||
});
|
||||
```
|
||||
|
||||
### Rooms
|
||||
|
||||
Sometimes you want to put certain sockets in the same room, so that it's easy
|
||||
to broadcast to all of them together.
|
||||
|
||||
Think of this as built-in channels for sockets. Sockets `join` and `leave`
|
||||
rooms in each socket.
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.join('justin bieber fans');
|
||||
socket.broadcast.to('justin bieber fans').emit('new fan');
|
||||
io.sockets.in('rammstein fans').emit('new non-fan');
|
||||
});
|
||||
```
|
||||
|
||||
### Using it just as a cross-browser WebSocket
|
||||
|
||||
If you just want the WebSocket semantics, you can do that too.
|
||||
Simply leverage `send` and listen on the `message` event:
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.on('message', function () { });
|
||||
socket.on('disconnect', function () { });
|
||||
});
|
||||
```
|
||||
|
||||
#### Client side
|
||||
|
||||
```html
|
||||
<script>
|
||||
var socket = io.connect('http://localhost/');
|
||||
socket.on('connect', function () {
|
||||
socket.send('hi');
|
||||
|
||||
socket.on('message', function (msg) {
|
||||
// my msg
|
||||
});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Changing configuration
|
||||
|
||||
Configuration in socket.io is TJ-style:
|
||||
|
||||
#### Server side
|
||||
|
||||
```js
|
||||
var io = require('socket.io').listen(80);
|
||||
|
||||
io.configure(function () {
|
||||
io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']);
|
||||
});
|
||||
|
||||
io.configure('development', function () {
|
||||
io.set('transports', ['websocket', 'xhr-polling']);
|
||||
io.enable('log');
|
||||
});
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
(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.
|
||||
64
networking/node_modules/socket.io/benchmarks/decode.bench.js
generated
vendored
Normal file
64
networking/node_modules/socket.io/benchmarks/decode.bench.js
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var benchmark = require('benchmark')
|
||||
, colors = require('colors')
|
||||
, io = require('../')
|
||||
, parser = io.parser
|
||||
, suite = new benchmark.Suite('Decode packet');
|
||||
|
||||
suite.add('string', function () {
|
||||
parser.decodePacket('4:::"2"');
|
||||
});
|
||||
|
||||
suite.add('event', function () {
|
||||
parser.decodePacket('5:::{"name":"woot"}');
|
||||
});
|
||||
|
||||
suite.add('event+ack', function () {
|
||||
parser.decodePacket('5:1+::{"name":"tobi"}');
|
||||
});
|
||||
|
||||
suite.add('event+data', function () {
|
||||
parser.decodePacket('5:::{"name":"edwald","args":[{"a": "b"},2,"3"]}');
|
||||
});
|
||||
|
||||
suite.add('heartbeat', function () {
|
||||
parser.decodePacket('2:::');
|
||||
});
|
||||
|
||||
suite.add('error', function () {
|
||||
parser.decodePacket('7:::2+0');
|
||||
});
|
||||
|
||||
var payload = parser.encodePayload([
|
||||
parser.encodePacket({ type: 'message', data: '5', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: '53d', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
]);
|
||||
|
||||
suite.add('payload', function () {
|
||||
parser.decodePayload(payload);
|
||||
});
|
||||
|
||||
suite.on('cycle', function (bench, details) {
|
||||
console.log('\n' + suite.name.grey, details.name.white.bold);
|
||||
console.log([
|
||||
details.hz.toFixed(2).cyan + ' ops/sec'.grey
|
||||
, details.count.toString().white + ' times executed'.grey
|
||||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey
|
||||
,
|
||||
].join(', '.grey));
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
suite.run();
|
||||
} else {
|
||||
module.exports = suite;
|
||||
}
|
||||
90
networking/node_modules/socket.io/benchmarks/encode.bench.js
generated
vendored
Normal file
90
networking/node_modules/socket.io/benchmarks/encode.bench.js
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var benchmark = require('benchmark')
|
||||
, colors = require('colors')
|
||||
, io = require('../')
|
||||
, parser = io.parser
|
||||
, suite = new benchmark.Suite('Encode packet');
|
||||
|
||||
suite.add('string', function () {
|
||||
parser.encodePacket({
|
||||
type: 'json'
|
||||
, endpoint: ''
|
||||
, data: '2'
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('event', function () {
|
||||
parser.encodePacket({
|
||||
type: 'event'
|
||||
, name: 'woot'
|
||||
, endpoint: ''
|
||||
, args: []
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('event+ack', function () {
|
||||
parser.encodePacket({
|
||||
type: 'json'
|
||||
, id: 1
|
||||
, ack: 'data'
|
||||
, endpoint: ''
|
||||
, data: { a: 'b' }
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('event+data', function () {
|
||||
parser.encodePacket({
|
||||
type: 'event'
|
||||
, name: 'edwald'
|
||||
, endpoint: ''
|
||||
, args: [{a: 'b'}, 2, '3']
|
||||
});
|
||||
});
|
||||
|
||||
suite.add('heartbeat', function () {
|
||||
parser.encodePacket({
|
||||
type: 'heartbeat'
|
||||
, endpoint: ''
|
||||
})
|
||||
});
|
||||
|
||||
suite.add('error', function () {
|
||||
parser.encodePacket({
|
||||
type: 'error'
|
||||
, reason: 'unauthorized'
|
||||
, advice: 'reconnect'
|
||||
, endpoint: ''
|
||||
})
|
||||
})
|
||||
|
||||
suite.add('payload', function () {
|
||||
parser.encodePayload([
|
||||
parser.encodePacket({ type: 'message', data: '5', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: '53d', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
||||
]);
|
||||
});
|
||||
|
||||
suite.on('cycle', function (bench, details) {
|
||||
console.log('\n' + suite.name.grey, details.name.white.bold);
|
||||
console.log([
|
||||
details.hz.toFixed(2).cyan + ' ops/sec'.grey
|
||||
, details.count.toString().white + ' times executed'.grey
|
||||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey
|
||||
,
|
||||
].join(', '.grey));
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
suite.run();
|
||||
} else {
|
||||
module.exports = suite;
|
||||
}
|
||||
55
networking/node_modules/socket.io/benchmarks/runner.js
generated
vendored
Normal file
55
networking/node_modules/socket.io/benchmarks/runner.js
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Benchmark runner dependencies
|
||||
*/
|
||||
|
||||
var colors = require('colors')
|
||||
, path = require('path');
|
||||
|
||||
/**
|
||||
* Find all the benchmarks
|
||||
*/
|
||||
|
||||
var benchmarks_files = process.env.BENCHMARKS.split(' ')
|
||||
, all = [].concat(benchmarks_files)
|
||||
, first = all.shift()
|
||||
, benchmarks = {};
|
||||
|
||||
// find the benchmarks and load them all in our obj
|
||||
benchmarks_files.forEach(function (file) {
|
||||
benchmarks[file] = require(path.join(__dirname, '..', file));
|
||||
});
|
||||
|
||||
// setup the complete listeners
|
||||
benchmarks_files.forEach(function (file) {
|
||||
var benchmark = benchmarks[file]
|
||||
, next_file = all.shift()
|
||||
, next = benchmarks[next_file];
|
||||
|
||||
/**
|
||||
* Generate a oncomplete function for the tests, either we are done or we
|
||||
* have more benchmarks to process.
|
||||
*/
|
||||
|
||||
function complete () {
|
||||
if (!next) {
|
||||
console.log(
|
||||
'\n\nBenchmark completed in'.grey
|
||||
, (Date.now() - start).toString().green + ' ms'.grey
|
||||
);
|
||||
} else {
|
||||
console.log('\nStarting benchmark '.grey + next_file.yellow);
|
||||
next.run();
|
||||
}
|
||||
}
|
||||
|
||||
// attach the listener
|
||||
benchmark.on('complete', complete);
|
||||
});
|
||||
|
||||
/**
|
||||
* Start the benchmark
|
||||
*/
|
||||
|
||||
var start = Date.now();
|
||||
console.log('Starting benchmark '.grey + first.yellow);
|
||||
benchmarks[first].run();
|
||||
80
networking/node_modules/socket.io/examples/chat/app.js
generated
vendored
Normal file
80
networking/node_modules/socket.io/examples/chat/app.js
generated
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('express')
|
||||
, stylus = require('stylus')
|
||||
, nib = require('nib')
|
||||
, sio = require('../../lib/socket.io');
|
||||
|
||||
/**
|
||||
* App.
|
||||
*/
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
/**
|
||||
* App configuration.
|
||||
*/
|
||||
|
||||
app.configure(function () {
|
||||
app.use(stylus.middleware({ src: __dirname + '/public', compile: compile }));
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
app.set('views', __dirname);
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
function compile (str, path) {
|
||||
return stylus(str)
|
||||
.set('filename', path)
|
||||
.use(nib());
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* App routes.
|
||||
*/
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
res.render('index', { layout: false });
|
||||
});
|
||||
|
||||
/**
|
||||
* App listen.
|
||||
*/
|
||||
|
||||
app.listen(3000, function () {
|
||||
var addr = app.address();
|
||||
console.log(' app listening on http://' + addr.address + ':' + addr.port);
|
||||
});
|
||||
|
||||
/**
|
||||
* Socket.IO server (single process only)
|
||||
*/
|
||||
|
||||
var io = sio.listen(app)
|
||||
, nicknames = {};
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.on('user message', function (msg) {
|
||||
socket.broadcast.emit('user message', socket.nickname, msg);
|
||||
});
|
||||
|
||||
socket.on('nickname', function (nick, fn) {
|
||||
if (nicknames[nick]) {
|
||||
fn(true);
|
||||
} else {
|
||||
fn(false);
|
||||
nicknames[nick] = socket.nickname = nick;
|
||||
socket.broadcast.emit('announcement', nick + ' connected');
|
||||
io.sockets.emit('nicknames', nicknames);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
if (!socket.nickname) return;
|
||||
|
||||
delete nicknames[socket.nickname];
|
||||
socket.broadcast.emit('announcement', socket.nickname + ' disconnected');
|
||||
socket.broadcast.emit('nicknames', nicknames);
|
||||
});
|
||||
});
|
||||
83
networking/node_modules/socket.io/examples/chat/index.jade
generated
vendored
Normal file
83
networking/node_modules/socket.io/examples/chat/index.jade
generated
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
doctype 5
|
||||
html
|
||||
head
|
||||
link(href='/stylesheets/style.css', rel='stylesheet')
|
||||
script(src='http://code.jquery.com/jquery-1.6.1.min.js')
|
||||
script(src='/socket.io/socket.io.js')
|
||||
script
|
||||
// socket.io specific code
|
||||
var socket = io.connect();
|
||||
|
||||
socket.on('connect', function () {
|
||||
$('#chat').addClass('connected');
|
||||
});
|
||||
|
||||
socket.on('announcement', function (msg) {
|
||||
$('#lines').append($('<p>').append($('<em>').text(msg)));
|
||||
});
|
||||
|
||||
socket.on('nicknames', function (nicknames) {
|
||||
$('#nicknames').empty().append($('<span>Online: </span>'));
|
||||
for (var i in nicknames) {
|
||||
$('#nicknames').append($('<b>').text(nicknames[i]));
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('user message', message);
|
||||
socket.on('reconnect', function () {
|
||||
$('#lines').remove();
|
||||
message('System', 'Reconnected to the server');
|
||||
});
|
||||
|
||||
socket.on('reconnecting', function () {
|
||||
message('System', 'Attempting to re-connect to the server');
|
||||
});
|
||||
|
||||
socket.on('error', function (e) {
|
||||
message('System', e ? e : 'A unknown error occurred');
|
||||
});
|
||||
|
||||
function message (from, msg) {
|
||||
$('#lines').append($('<p>').append($('<b>').text(from), msg));
|
||||
}
|
||||
|
||||
// dom manipulation
|
||||
$(function () {
|
||||
$('#set-nickname').submit(function (ev) {
|
||||
socket.emit('nickname', $('#nick').val(), function (set) {
|
||||
if (!set) {
|
||||
clear();
|
||||
return $('#chat').addClass('nickname-set');
|
||||
}
|
||||
$('#nickname-err').css('visibility', 'visible');
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#send-message').submit(function () {
|
||||
message('me', $('#message').val());
|
||||
socket.emit('user message', $('#message').val());
|
||||
clear();
|
||||
$('#lines').get(0).scrollTop = 10000000;
|
||||
return false;
|
||||
});
|
||||
|
||||
function clear () {
|
||||
$('#message').val('').focus();
|
||||
};
|
||||
});
|
||||
body
|
||||
#chat
|
||||
#nickname
|
||||
form.wrap#set-nickname
|
||||
p Please type in your nickname and press enter.
|
||||
input#nick
|
||||
p#nickname-err Nickname already in use
|
||||
#connecting
|
||||
.wrap Connecting to socket.io server
|
||||
#messages
|
||||
#nicknames
|
||||
#lines
|
||||
form#send-message
|
||||
input#message
|
||||
button Send
|
||||
11
networking/node_modules/socket.io/examples/chat/package.json
generated
vendored
Normal file
11
networking/node_modules/socket.io/examples/chat/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "chat.io"
|
||||
, "description": "example chat application with socket.io"
|
||||
, "version": "0.0.1"
|
||||
, "dependencies": {
|
||||
"express": "2.5.5"
|
||||
, "jade": "0.16.4"
|
||||
, "stylus": "0.19.0"
|
||||
, "nib": "0.2.0"
|
||||
}
|
||||
}
|
||||
96
networking/node_modules/socket.io/examples/chat/public/stylesheets/mixins.styl
generated
vendored
Normal file
96
networking/node_modules/socket.io/examples/chat/public/stylesheets/mixins.styl
generated
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
border-radius(n)
|
||||
-webkit-border-radius n
|
||||
-moz-border-radius n
|
||||
border-radius n
|
||||
|
||||
// replace str with val
|
||||
|
||||
replace(expr, str, val)
|
||||
expr = clone(expr)
|
||||
for e, i in expr
|
||||
if str == e
|
||||
expr[i] = val
|
||||
expr
|
||||
|
||||
// normalize gradient point (webkit)
|
||||
|
||||
grad-point(pos)
|
||||
if length(pos) == 1
|
||||
return left pos if pos in (top bottom)
|
||||
return pos top if pos in (left right)
|
||||
else if pos[0] in (top bottom)
|
||||
pos[1] pos[0]
|
||||
else
|
||||
pos
|
||||
|
||||
// implicit color stop position
|
||||
|
||||
pos-in-stops(i, stops)
|
||||
len = length(stops)
|
||||
if len - 1 == i
|
||||
100%
|
||||
else if i
|
||||
unit(i / len * 100, '%')
|
||||
else
|
||||
0%
|
||||
|
||||
// normalize color stops
|
||||
// - (color pos) -> (pos color)
|
||||
// - (color) -> (implied-pos color)
|
||||
|
||||
normalize-stops(stops)
|
||||
stops = clone(stops)
|
||||
for stop, i in stops
|
||||
if length(stop) == 1
|
||||
color = stop[0]
|
||||
stop[0] = pos-in-stops(i, stops)
|
||||
stop[1] = color
|
||||
else if typeof(stop[1]) == 'unit'
|
||||
pos = stop[1]
|
||||
stop[1] = stop[0]
|
||||
stop[0] = pos
|
||||
stops
|
||||
|
||||
// join color stops with the given translation function
|
||||
|
||||
join-stops(stops, translate)
|
||||
str = ''
|
||||
len = length(stops)
|
||||
for stop, i in stops
|
||||
str += ', ' if i
|
||||
pos = stop[0]
|
||||
color = stop[1]
|
||||
str += translate(color, pos)
|
||||
unquote(str)
|
||||
|
||||
// webkit translation function
|
||||
|
||||
webkit-stop(color, pos)
|
||||
s('color-stop(%d, %s)', pos / 100, color)
|
||||
|
||||
// mozilla translation function
|
||||
|
||||
moz-stop(color, pos)
|
||||
s('%s %s', color, pos)
|
||||
|
||||
// create a linear gradient with the given start
|
||||
// position, followed by color stops
|
||||
|
||||
linear-gradient(start, stops...)
|
||||
error('color stops required') unless length(stops)
|
||||
prop = current-property[0]
|
||||
val = current-property[1]
|
||||
stops = normalize-stops(stops)
|
||||
|
||||
// webkit
|
||||
end = grad-point(opposite-position(start))
|
||||
webkit = s('-webkit-gradient(linear, %s, %s, %s)', grad-point(start), end, join-stops(stops, webkit-stop))
|
||||
add-property(prop, replace(val, '__CALL__', webkit))
|
||||
|
||||
// moz
|
||||
stops = join-stops(stops, moz-stop)
|
||||
moz = s('-moz-linear-gradient(%s, %s)', start, stops)
|
||||
add-property(prop, replace(val, '__CALL__', moz))
|
||||
|
||||
// literal
|
||||
s('linear-gradient(%s, %s)', start, stops)
|
||||
188
networking/node_modules/socket.io/examples/chat/public/stylesheets/style.css
generated
vendored
Normal file
188
networking/node_modules/socket.io/examples/chat/public/stylesheets/style.css
generated
vendored
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
#chat,
|
||||
#nickname,
|
||||
#messages {
|
||||
width: 600px;
|
||||
}
|
||||
#chat {
|
||||
position: relative;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
#nickname,
|
||||
#connecting {
|
||||
position: absolute;
|
||||
height: 410px;
|
||||
z-index: 100;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
width: 600px;
|
||||
font: 15px Georgia;
|
||||
color: #666;
|
||||
display: block;
|
||||
}
|
||||
#nickname .wrap,
|
||||
#connecting .wrap {
|
||||
padding-top: 150px;
|
||||
}
|
||||
#nickname input {
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
}
|
||||
#nickname input:focus {
|
||||
border-color: #999;
|
||||
outline: 0;
|
||||
}
|
||||
#nickname #nickname-err {
|
||||
color: #8b0000;
|
||||
font-size: 12px;
|
||||
visibility: hidden;
|
||||
}
|
||||
.connected #connecting {
|
||||
display: none;
|
||||
}
|
||||
.nickname-set #nickname {
|
||||
display: none;
|
||||
}
|
||||
#messages {
|
||||
height: 380px;
|
||||
background: #eee;
|
||||
}
|
||||
#messages em {
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
color: #999;
|
||||
}
|
||||
#messages p {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font: 12px Helvetica, Arial;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#messages p b {
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
}
|
||||
#messages p:nth-child(even) {
|
||||
background: #fafafa;
|
||||
}
|
||||
#messages #nicknames {
|
||||
background: #ccc;
|
||||
padding: 2px 4px 4px;
|
||||
font: 11px Helvetica;
|
||||
}
|
||||
#messages #nicknames span {
|
||||
color: #000;
|
||||
}
|
||||
#messages #nicknames b {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
background: #999;
|
||||
padding: 3px 6px;
|
||||
margin-right: 5px;
|
||||
-webkit-border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
text-shadow: 0 1px 0 #666;
|
||||
}
|
||||
#messages #lines {
|
||||
height: 355px;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
#messages #lines::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
#messages #lines::-webkit-scrollbar-button:start:decrement,
|
||||
#messages #lines ::-webkit-scrollbar-button:end:increment {
|
||||
display: block;
|
||||
height: 10px;
|
||||
}
|
||||
#messages #lines::-webkit-scrollbar-button:vertical:increment {
|
||||
background-color: #fff;
|
||||
}
|
||||
#messages #lines::-webkit-scrollbar-track-piece {
|
||||
background-color: #fff;
|
||||
-webkit-border-radius: 3px;
|
||||
}
|
||||
#messages #lines::-webkit-scrollbar-thumb:vertical {
|
||||
height: 50px;
|
||||
background-color: #ccc;
|
||||
-webkit-border-radius: 3px;
|
||||
}
|
||||
#messages #lines::-webkit-scrollbar-thumb:horizontal {
|
||||
width: 50px;
|
||||
background-color: #fff;
|
||||
-webkit-border-radius: 3px;
|
||||
}
|
||||
#send-message {
|
||||
background: #fff;
|
||||
position: relative;
|
||||
}
|
||||
#send-message input {
|
||||
border: none;
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
line-height: 30px;
|
||||
vertical-align: middle;
|
||||
width: 580px;
|
||||
}
|
||||
#send-message input:focus {
|
||||
outline: 0;
|
||||
}
|
||||
#send-message button {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
button {
|
||||
margin: 0;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
background: #43a1f7;
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #43a1f7), color-stop(1, #377ad0));
|
||||
background: -webkit-linear-gradient(top, #43a1f7 0%, #377ad0 100%);
|
||||
background: -moz-linear-gradient(top, #43a1f7 0%, #377ad0 100%);
|
||||
background: linear-gradient(top, #43a1f7 0%, #377ad0 100%);
|
||||
border: 1px solid #2e70c4;
|
||||
-webkit-border-radius: 16px;
|
||||
-moz-border-radius: 16px;
|
||||
border-radius: 16px;
|
||||
color: #fff;
|
||||
font-family: "lucida grande", sans-serif;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
padding: 3px 10px 5px 10px;
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 1px #2d6dc0;
|
||||
}
|
||||
button:hover,
|
||||
button.hover {
|
||||
background: darker;
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #43a1f7), color-stop(1, #2e70c4));
|
||||
background: -webkit-linear-gradient(top, #43a1f7 0%, #2e70c4 100%);
|
||||
background: -moz-linear-gradient(top, #43a1f7 0%, #2e70c4 100%);
|
||||
background: linear-gradient(top, #43a1f7 0%, #2e70c4 100%);
|
||||
border: 1px solid #2e70c4;
|
||||
cursor: pointer;
|
||||
text-shadow: 0 -1px 1px #2c6bbb;
|
||||
}
|
||||
button:active,
|
||||
button.active {
|
||||
background: #2e70c4;
|
||||
border: 1px solid #2e70c4;
|
||||
border-bottom: 1px solid #2861aa;
|
||||
text-shadow: 0 -1px 1px #2b67b5;
|
||||
}
|
||||
button:focus,
|
||||
button.focus {
|
||||
outline: none;
|
||||
-webkit-box-shadow: 0 1px 0 0 rgba(255,255,255,0.4), 0 0 4px 0 #377ad0;
|
||||
-moz-box-shadow: 0 1px 0 0 rgba(255,255,255,0.4), 0 0 4px 0 #377ad0;
|
||||
box-shadow: 0 1px 0 0 rgba(255,255,255,0.4), 0 0 4px 0 #377ad0;
|
||||
}
|
||||
118
networking/node_modules/socket.io/examples/chat/public/stylesheets/style.styl
generated
vendored
Normal file
118
networking/node_modules/socket.io/examples/chat/public/stylesheets/style.styl
generated
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
@import 'nib'
|
||||
|
||||
#chat, #nickname, #messages
|
||||
width 600px
|
||||
|
||||
#chat
|
||||
position relative
|
||||
border 1px solid #ccc
|
||||
|
||||
#nickname, #connecting
|
||||
position absolute
|
||||
height 410px
|
||||
z-index 100
|
||||
left 0
|
||||
top 0
|
||||
background #fff
|
||||
text-align center
|
||||
width 600px
|
||||
font 15px Georgia
|
||||
color #666
|
||||
display block
|
||||
.wrap
|
||||
padding-top 150px
|
||||
|
||||
#nickname
|
||||
input
|
||||
border 1px solid #ccc
|
||||
padding 10px
|
||||
&:focus
|
||||
border-color #999
|
||||
outline 0
|
||||
#nickname-err
|
||||
color darkred
|
||||
font-size 12px
|
||||
visibility hidden
|
||||
|
||||
.connected
|
||||
#connecting
|
||||
display none
|
||||
|
||||
.nickname-set
|
||||
#nickname
|
||||
display none
|
||||
|
||||
#messages
|
||||
height 380px
|
||||
background #eee
|
||||
em
|
||||
text-shadow 0 1px 0 #fff
|
||||
color #999
|
||||
p
|
||||
padding 0
|
||||
margin 0
|
||||
font 12px Helvetica, Arial
|
||||
padding 5px 10px
|
||||
b
|
||||
display inline-block
|
||||
padding-right 10px
|
||||
p:nth-child(even)
|
||||
background #fafafa
|
||||
#nicknames
|
||||
background #ccc
|
||||
padding 2px 4px 4px
|
||||
font 11px Helvetica
|
||||
span
|
||||
color black
|
||||
b
|
||||
display inline-block
|
||||
color #fff
|
||||
background #999
|
||||
padding 3px 6px
|
||||
margin-right 5px
|
||||
border-radius 10px
|
||||
text-shadow 0 1px 0 #666
|
||||
#lines
|
||||
height 355px
|
||||
overflow auto
|
||||
overflow-x hidden
|
||||
overflow-y auto
|
||||
&::-webkit-scrollbar
|
||||
width 6px
|
||||
height 6px
|
||||
&::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:end:increment
|
||||
display block
|
||||
height 10px
|
||||
&::-webkit-scrollbar-button:vertical:increment
|
||||
background-color #fff
|
||||
&::-webkit-scrollbar-track-piece
|
||||
background-color #fff
|
||||
-webkit-border-radius 3px
|
||||
&::-webkit-scrollbar-thumb:vertical
|
||||
height 50px
|
||||
background-color #ccc
|
||||
-webkit-border-radius 3px
|
||||
&::-webkit-scrollbar-thumb:horizontal
|
||||
width 50px
|
||||
background-color #fff
|
||||
-webkit-border-radius 3px
|
||||
|
||||
#send-message
|
||||
background #fff
|
||||
position relative
|
||||
input
|
||||
border none
|
||||
height 30px
|
||||
padding 0 10px
|
||||
line-height 30px
|
||||
vertical-align middle
|
||||
width 580px
|
||||
&:focus
|
||||
outline 0
|
||||
button
|
||||
position absolute
|
||||
top 5px
|
||||
right 5px
|
||||
|
||||
button
|
||||
download-button()
|
||||
74
networking/node_modules/socket.io/examples/irc-output/app.js
generated
vendored
Normal file
74
networking/node_modules/socket.io/examples/irc-output/app.js
generated
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('express')
|
||||
, stylus = require('stylus')
|
||||
, nib = require('nib')
|
||||
, sio = require('../../lib/socket.io')
|
||||
, irc = require('./irc');
|
||||
|
||||
/**
|
||||
* App.
|
||||
*/
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
/**
|
||||
* App configuration.
|
||||
*/
|
||||
|
||||
app.configure(function () {
|
||||
app.use(stylus.middleware({ src: __dirname + '/public', compile: compile }))
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
app.set('views', __dirname);
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
function compile (str, path) {
|
||||
return stylus(str)
|
||||
.set('filename', path)
|
||||
.use(nib());
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* App routes.
|
||||
*/
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
res.render('index', { layout: false });
|
||||
});
|
||||
|
||||
/**
|
||||
* App listen.
|
||||
*/
|
||||
|
||||
app.listen(3000, function () {
|
||||
var addr = app.address();
|
||||
console.log(' app listening on http://' + addr.address + ':' + addr.port);
|
||||
});
|
||||
|
||||
/**
|
||||
* Socket.IO server
|
||||
*/
|
||||
|
||||
var io = sio.listen(app)
|
||||
|
||||
/**
|
||||
* Connect to IRC.
|
||||
*/
|
||||
|
||||
var client = new irc.Client('irc.freenode.net', 6667);
|
||||
client.connect('socketio\\test\\' + String(Math.random()).substr(-3));
|
||||
client.on('001', function () {
|
||||
this.send('JOIN', '#node.js');
|
||||
});
|
||||
client.on('PART', function (prefix) {
|
||||
io.sockets.emit('announcement', irc.user(prefix) + ' left the channel');
|
||||
});
|
||||
client.on('JOIN', function (prefix) {
|
||||
io.sockets.emit('announcement', irc.user(prefix) + ' joined the channel');
|
||||
});
|
||||
client.on('PRIVMSG', function (prefix, channel, text) {
|
||||
io.sockets.emit('irc message', irc.user(prefix), text);
|
||||
});
|
||||
28
networking/node_modules/socket.io/examples/irc-output/index.jade
generated
vendored
Normal file
28
networking/node_modules/socket.io/examples/irc-output/index.jade
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
doctype 5
|
||||
html
|
||||
head
|
||||
link(href='/stylesheets/style.css', rel='stylesheet')
|
||||
script(src='http://code.jquery.com/jquery-1.6.1.min.js')
|
||||
script(src='/socket.io/socket.io.js')
|
||||
script
|
||||
var socket = io.connect();
|
||||
|
||||
socket.on('connect', function () {
|
||||
$('#irc').addClass('connected');
|
||||
});
|
||||
|
||||
socket.on('announcement', function (msg) {
|
||||
$('#messages').append($('<p>').append($('<em>').text(msg)));
|
||||
$('#messages').get(0).scrollTop = 10000000;
|
||||
});
|
||||
|
||||
socket.on('irc message', function (user, msg) {
|
||||
$('#messages').append($('<p>').append($('<b>').text(user), msg));
|
||||
$('#messages').get(0).scrollTop = 10000000;
|
||||
});
|
||||
body
|
||||
h2 Node.JS IRC
|
||||
#irc
|
||||
#connecting
|
||||
.wrap Connecting to socket.io server
|
||||
#messages
|
||||
164
networking/node_modules/socket.io/examples/irc-output/irc.js
generated
vendored
Normal file
164
networking/node_modules/socket.io/examples/irc-output/irc.js
generated
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* From https://github.com/felixge/nodelog/
|
||||
*/
|
||||
|
||||
var sys = require('util');
|
||||
var tcp = require('net');
|
||||
var irc = exports;
|
||||
|
||||
function bind(fn, scope) {
|
||||
var bindArgs = Array.prototype.slice.call(arguments);
|
||||
bindArgs.shift();
|
||||
bindArgs.shift();
|
||||
|
||||
return function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
fn.apply(scope, bindArgs.concat(args));
|
||||
};
|
||||
}
|
||||
|
||||
function each(set, iterator) {
|
||||
for (var i = 0; i < set.length; i++) {
|
||||
var r = iterator(set[i], i);
|
||||
if (r === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var Client = irc.Client = function(host, port) {
|
||||
this.host = host || 'localhost';
|
||||
this.port = port || 6667;
|
||||
|
||||
this.connection = null;
|
||||
this.buffer = '';
|
||||
this.encoding = 'utf8';
|
||||
this.timeout = 10 * 60 * 60 * 1000;
|
||||
|
||||
this.nick = null;
|
||||
this.user = null;
|
||||
this.real = null;
|
||||
}
|
||||
sys.inherits(Client, process.EventEmitter);
|
||||
|
||||
Client.prototype.connect = function(nick, user, real) {
|
||||
var connection = tcp.createConnection(this.port, this.host);
|
||||
connection.setEncoding(this.encoding);
|
||||
connection.setTimeout(this.timeout);
|
||||
connection.addListener('connect', bind(this.onConnect, this));
|
||||
connection.addListener('data', bind(this.onReceive, this));
|
||||
connection.addListener('end', bind(this.onEof, this));
|
||||
connection.addListener('timeout', bind(this.onTimeout, this));
|
||||
connection.addListener('close', bind(this.onClose, this));
|
||||
|
||||
this.nick = nick;
|
||||
this.user = user || 'guest';
|
||||
this.real = real || 'Guest';
|
||||
|
||||
this.connection = connection;
|
||||
};
|
||||
|
||||
Client.prototype.disconnect = function(why) {
|
||||
if (this.connection.readyState !== 'closed') {
|
||||
this.connection.close();
|
||||
sys.puts('disconnected (reason: '+why+')');
|
||||
this.emit('DISCONNECT', why);
|
||||
}
|
||||
};
|
||||
|
||||
Client.prototype.send = function(arg1) {
|
||||
if (this.connection.readyState !== 'open') {
|
||||
return this.disconnect('cannot send with readyState: '+this.connection.readyState);
|
||||
}
|
||||
|
||||
var message = [];
|
||||
for (var i = 0; i< arguments.length; i++) {
|
||||
if (arguments[i]) {
|
||||
message.push(arguments[i]);
|
||||
}
|
||||
}
|
||||
message = message.join(' ');
|
||||
|
||||
sys.puts('> '+message);
|
||||
message = message + "\r\n";
|
||||
this.connection.write(message, this.encoding);
|
||||
};
|
||||
|
||||
Client.prototype.parse = function(message) {
|
||||
var match = message.match(/(?:(:[^\s]+) )?([^\s]+) (.+)/);
|
||||
var parsed = {
|
||||
prefix: match[1],
|
||||
command: match[2]
|
||||
};
|
||||
|
||||
var params = match[3].match(/(.*?) ?:(.*)/);
|
||||
if (params) {
|
||||
// Params before :
|
||||
params[1] = (params[1])
|
||||
? params[1].split(' ')
|
||||
: [];
|
||||
// Rest after :
|
||||
params[2] = params[2]
|
||||
? [params[2]]
|
||||
: [];
|
||||
|
||||
params = params[1].concat(params[2]);
|
||||
} else {
|
||||
params = match[3].split(' ');
|
||||
}
|
||||
|
||||
parsed.params = params;
|
||||
return parsed;
|
||||
};
|
||||
|
||||
Client.prototype.onConnect = function() {
|
||||
this.send('NICK', this.nick);
|
||||
this.send('USER', this.user, '0', '*', ':'+this.real);
|
||||
};
|
||||
|
||||
Client.prototype.onReceive = function(chunk) {
|
||||
this.buffer = this.buffer + chunk;
|
||||
|
||||
while (this.buffer) {
|
||||
var offset = this.buffer.indexOf("\r\n");
|
||||
if (offset < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var message = this.buffer.substr(0, offset);
|
||||
this.buffer = this.buffer.substr(offset + 2);
|
||||
sys.puts('< '+message);
|
||||
|
||||
message = this.parse(message);
|
||||
|
||||
this.emit.apply(this, [message.command, message.prefix].concat(message.params));
|
||||
|
||||
if (message !== false) {
|
||||
this.onMessage(message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Client.prototype.onMessage = function(message) {
|
||||
switch (message.command) {
|
||||
case 'PING':
|
||||
this.send('PONG', ':'+message.params[0]);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
Client.prototype.onEof = function() {
|
||||
this.disconnect('eof');
|
||||
};
|
||||
|
||||
Client.prototype.onTimeout = function() {
|
||||
this.disconnect('timeout');
|
||||
};
|
||||
|
||||
Client.prototype.onClose = function() {
|
||||
this.disconnect('close');
|
||||
};
|
||||
|
||||
exports.user = function(prefix) {
|
||||
return prefix.match(/:([^!]+)!/)[1]
|
||||
};
|
||||
10
networking/node_modules/socket.io/examples/irc-output/package.json
generated
vendored
Normal file
10
networking/node_modules/socket.io/examples/irc-output/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "socket.io-irc"
|
||||
, "version": "0.0.1"
|
||||
, "dependencies": {
|
||||
"express": "2.5.5"
|
||||
, "jade": "0.16.4"
|
||||
, "stylus": "0.19.0"
|
||||
, "nib": "0.2.0"
|
||||
}
|
||||
}
|
||||
69
networking/node_modules/socket.io/examples/irc-output/public/stylesheets/style.styl
generated
vendored
Normal file
69
networking/node_modules/socket.io/examples/irc-output/public/stylesheets/style.styl
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
@import 'nib'
|
||||
|
||||
h2
|
||||
font bold 18px Helvetica Neue, Arial
|
||||
|
||||
#irc, #messages
|
||||
width 600px
|
||||
|
||||
#irc
|
||||
position relative
|
||||
border 1px solid #ccc
|
||||
|
||||
#connecting
|
||||
position absolute
|
||||
height 410px
|
||||
z-index 100
|
||||
left 0
|
||||
top 0
|
||||
background #fff
|
||||
text-align center
|
||||
width 600px
|
||||
font 15px Georgia
|
||||
color #666
|
||||
display block
|
||||
.wrap
|
||||
padding-top 150px
|
||||
|
||||
.connected
|
||||
#connecting
|
||||
display none
|
||||
|
||||
#messages
|
||||
height 380px
|
||||
background #eee
|
||||
overflow auto
|
||||
overflow-x hidden
|
||||
overflow-y auto
|
||||
&::-webkit-scrollbar
|
||||
width 6px
|
||||
height 6px
|
||||
&::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:end:increment
|
||||
display block
|
||||
height 10px
|
||||
&::-webkit-scrollbar-button:vertical:increment
|
||||
background-color #fff
|
||||
&::-webkit-scrollbar-track-piece
|
||||
background-color #fff
|
||||
-webkit-border-radius 3px
|
||||
&::-webkit-scrollbar-thumb:vertical
|
||||
height 50px
|
||||
background-color #ccc
|
||||
-webkit-border-radius 3px
|
||||
&::-webkit-scrollbar-thumb:horizontal
|
||||
width 50px
|
||||
background-color #fff
|
||||
-webkit-border-radius 3px
|
||||
em
|
||||
text-shadow 0 1px 0 #fff
|
||||
color #999
|
||||
p
|
||||
padding 0
|
||||
margin 0
|
||||
font 12px Helvetica, Arial
|
||||
padding 5px 10px
|
||||
b
|
||||
display inline-block
|
||||
padding-right 10px
|
||||
p:nth-child(even)
|
||||
background #fafafa
|
||||
8
networking/node_modules/socket.io/index.js
generated
vendored
Normal file
8
networking/node_modules/socket.io/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
module.exports = require('./lib/socket.io');
|
||||
167
networking/node_modules/socket.io/lib/client.js
generated
vendored
Normal file
167
networking/node_modules/socket.io/lib/client.js
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var parser = require('socket.io-client').parser
|
||||
, EventEmitter = require('events').EventEmitter
|
||||
|
||||
/**
|
||||
* Client constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Client (id, server) {
|
||||
this.id = id;
|
||||
this.acks = {};
|
||||
this.store = server.store;
|
||||
|
||||
var self = this;
|
||||
|
||||
store.subscribe(id, function (packet) {
|
||||
|
||||
});
|
||||
|
||||
store.subscribe(id + '.disconect', function () {
|
||||
self.onDisconnect();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherits from EventEmitter.
|
||||
*/
|
||||
|
||||
Client.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Save reference to original `emit`.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype._emit = Client.prototype.emit;
|
||||
|
||||
/**
|
||||
* Broadcast flag.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.__defineGetter__('broadcast', function () {
|
||||
this.flags.broadcast = true;
|
||||
});
|
||||
|
||||
/**
|
||||
* JSON flag (deprecated)
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.__defineGetter__('json', function () {
|
||||
this.flags.broadcast = true;
|
||||
});
|
||||
|
||||
/**
|
||||
* Joins a group.
|
||||
*
|
||||
* @param {String} group
|
||||
* @return {Client} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.join = function (group, fn) {
|
||||
if (!~this.subscriptions.indexOf(group)) {
|
||||
var self = this;
|
||||
this.subscriptions.push(group);
|
||||
this.store.addToGroup(group, this.sid, function (ev, args) {
|
||||
self.onGroupEvent(ev, args);
|
||||
}, fn);
|
||||
} else {
|
||||
fn && fn();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Leaves a group.
|
||||
*
|
||||
* @return {Client} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.leave = function (group) {
|
||||
var index = this.subscriptions.indexOf(group);
|
||||
if (~index) {
|
||||
this.subscriptions.splice(index, 1);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Client.prototype.disconnect = function () {
|
||||
if (this.socket) {
|
||||
this.socket.disconnect();
|
||||
} else {
|
||||
this.publish('disconnect');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called upon disconnect.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype.onDisconnect = function () {
|
||||
for (var i = 0, l = this.subscriptions; i < l; i++) {
|
||||
this.store.removeFromGroup(id, group, fn);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers ACK.
|
||||
*/
|
||||
|
||||
Client.prototype.ack = function (fn, callback) {
|
||||
this.subscribe('ack');
|
||||
};
|
||||
|
||||
/**
|
||||
* Emits an event.
|
||||
*/
|
||||
|
||||
Client.prototype.emit = function () {
|
||||
var args = toArray(arguments), fn;
|
||||
|
||||
if ('function' == typeof args[args.length - 1]) {
|
||||
fn = args.pop();
|
||||
}
|
||||
|
||||
var data = args.shift();
|
||||
if (args.length) {
|
||||
data += '\n' + JSON.stringify(args);
|
||||
}
|
||||
|
||||
if (fn) {
|
||||
this.ack(fn, function (id) {
|
||||
self.sendPacket('event', data, id);
|
||||
});
|
||||
} else {
|
||||
this.sendPacket('event', data);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a packet.
|
||||
*/
|
||||
|
||||
Client.prototype.sendPacket = function (type, data, id) {
|
||||
var data = parser.encode({ type: type, data: data, id: id });
|
||||
|
||||
if (this.server.sockets[id]) {
|
||||
this.server.sockets[id].write(data);
|
||||
}
|
||||
};
|
||||
97
networking/node_modules/socket.io/lib/logger.js
generated
vendored
Normal file
97
networking/node_modules/socket.io/lib/logger.js
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var util = require('./util')
|
||||
, toArray = util.toArray;
|
||||
|
||||
/**
|
||||
* Log levels.
|
||||
*/
|
||||
|
||||
var levels = [
|
||||
'error'
|
||||
, 'warn'
|
||||
, 'info'
|
||||
, 'debug'
|
||||
];
|
||||
|
||||
/**
|
||||
* Colors for log levels.
|
||||
*/
|
||||
|
||||
var colors = [
|
||||
31
|
||||
, 33
|
||||
, 36
|
||||
, 90
|
||||
];
|
||||
|
||||
/**
|
||||
* Pads the nice output to the longest log level.
|
||||
*/
|
||||
|
||||
function pad (str) {
|
||||
var max = 0;
|
||||
|
||||
for (var i = 0, l = levels.length; i < l; i++)
|
||||
max = Math.max(max, levels[i].length);
|
||||
|
||||
if (str.length < max)
|
||||
return str + new Array(max - str.length + 1).join(' ');
|
||||
|
||||
return str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Logger (console).
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Logger = module.exports = function (opts) {
|
||||
opts = opts || {}
|
||||
this.colors = false !== opts.colors;
|
||||
this.level = 3;
|
||||
this.enabled = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Log method.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Logger.prototype.log = function (type) {
|
||||
var index = levels.indexOf(type);
|
||||
|
||||
if (index > this.level || !this.enabled)
|
||||
return this;
|
||||
|
||||
console.log.apply(
|
||||
console
|
||||
, [this.colors
|
||||
? ' \033[' + colors[index] + 'm' + pad(type) + ' -\033[39m'
|
||||
: type + ':'
|
||||
].concat(toArray(arguments).slice(1))
|
||||
);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate methods.
|
||||
*/
|
||||
|
||||
levels.forEach(function (name) {
|
||||
Logger.prototype[name] = function () {
|
||||
this.log.apply(this, [name].concat(toArray(arguments)));
|
||||
};
|
||||
});
|
||||
984
networking/node_modules/socket.io/lib/manager.js
generated
vendored
Normal file
984
networking/node_modules/socket.io/lib/manager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,984 @@
|
|||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var fs = require('fs')
|
||||
, url = require('url')
|
||||
, tty = require('tty')
|
||||
, util = require('./util')
|
||||
, store = require('./store')
|
||||
, client = require('socket.io-client')
|
||||
, transports = require('./transports')
|
||||
, Logger = require('./logger')
|
||||
, Socket = require('./socket')
|
||||
, MemoryStore = require('./stores/memory')
|
||||
, SocketNamespace = require('./namespace')
|
||||
, Static = require('./static')
|
||||
, EventEmitter = process.EventEmitter;
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = Manager;
|
||||
|
||||
/**
|
||||
* Default transports.
|
||||
*/
|
||||
|
||||
var defaultTransports = exports.defaultTransports = [
|
||||
'websocket'
|
||||
, 'htmlfile'
|
||||
, 'xhr-polling'
|
||||
, 'jsonp-polling'
|
||||
];
|
||||
|
||||
/**
|
||||
* Inherited defaults.
|
||||
*/
|
||||
|
||||
var parent = module.parent.exports
|
||||
, protocol = parent.protocol
|
||||
, jsonpolling_re = /^\d+$/;
|
||||
|
||||
/**
|
||||
* Manager constructor.
|
||||
*
|
||||
* @param {HTTPServer} server
|
||||
* @param {Object} options, optional
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Manager (server, options) {
|
||||
this.server = server;
|
||||
this.namespaces = {};
|
||||
this.sockets = this.of('');
|
||||
this.settings = {
|
||||
origins: '*:*'
|
||||
, log: true
|
||||
, store: new MemoryStore
|
||||
, logger: new Logger
|
||||
, static: new Static(this)
|
||||
, heartbeats: true
|
||||
, resource: '/socket.io'
|
||||
, transports: defaultTransports
|
||||
, authorization: false
|
||||
, blacklist: ['disconnect']
|
||||
, 'log level': 3
|
||||
, '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
|
||||
, 'browser client etag': false
|
||||
, 'browser client expires': 315360000
|
||||
, '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];
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
// default error handler
|
||||
server.on('error', function(err) {
|
||||
self.log.warn('error raised: ' + err);
|
||||
});
|
||||
|
||||
this.initStore();
|
||||
|
||||
this.on('set:store', function() {
|
||||
self.initStore();
|
||||
});
|
||||
|
||||
// reset listeners
|
||||
this.oldListeners = server.listeners('request');
|
||||
server.removeAllListeners('request');
|
||||
|
||||
server.on('request', function (req, res) {
|
||||
self.handleRequest(req, res);
|
||||
});
|
||||
|
||||
server.on('upgrade', function (req, socket, head) {
|
||||
self.handleUpgrade(req, socket, head);
|
||||
});
|
||||
|
||||
server.on('close', function () {
|
||||
clearInterval(self.gc);
|
||||
});
|
||||
|
||||
server.once('listening', function () {
|
||||
self.gc = setInterval(self.garbageCollection.bind(self), 10000);
|
||||
});
|
||||
|
||||
for (var i in transports) {
|
||||
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.log.info('socket.io started');
|
||||
};
|
||||
|
||||
Manager.prototype.__proto__ = EventEmitter.prototype
|
||||
|
||||
/**
|
||||
* Store accessor shortcut.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.__defineGetter__('store', function () {
|
||||
var store = this.get('store');
|
||||
store.manager = this;
|
||||
return store;
|
||||
});
|
||||
|
||||
/**
|
||||
* Logger accessor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.__defineGetter__('log', function () {
|
||||
var logger = this.get('logger');
|
||||
|
||||
logger.level = this.get('log level') || -1;
|
||||
logger.colors = this.get('log colors');
|
||||
logger.enabled = this.enabled('log');
|
||||
|
||||
return logger;
|
||||
});
|
||||
|
||||
/**
|
||||
* Static accessor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.__defineGetter__('static', function () {
|
||||
return this.get('static');
|
||||
});
|
||||
|
||||
/**
|
||||
* Get settings.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.get = function (key) {
|
||||
return this.settings[key];
|
||||
};
|
||||
|
||||
/**
|
||||
* Set settings
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.set = function (key, value) {
|
||||
if (arguments.length == 1) return this.get(key);
|
||||
this.settings[key] = value;
|
||||
this.emit('set:' + key, this.settings[key], key);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable a setting
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.enable = function (key) {
|
||||
this.settings[key] = true;
|
||||
this.emit('set:' + key, this.settings[key], key);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Disable a setting
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.disable = function (key) {
|
||||
this.settings[key] = false;
|
||||
this.emit('set:' + key, this.settings[key], key);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a setting is enabled
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.enabled = function (key) {
|
||||
return !!this.settings[key];
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a setting is disabled
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.disabled = function (key) {
|
||||
return !this.settings[key];
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure callbacks.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.configure = function (env, fn) {
|
||||
if ('function' == typeof env) {
|
||||
env.call(this);
|
||||
} else if (env == (process.env.NODE_ENV || 'development')) {
|
||||
fn.call(this);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes everything related to the message dispatcher.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.initStore = function () {
|
||||
this.handshaken = {};
|
||||
this.connected = {};
|
||||
this.open = {};
|
||||
this.closed = {};
|
||||
this.rooms = {};
|
||||
this.roomClients = {};
|
||||
|
||||
var self = this;
|
||||
|
||||
this.store.subscribe('handshake', function (id, data) {
|
||||
self.onHandshake(id, data);
|
||||
});
|
||||
|
||||
this.store.subscribe('connect', function (id) {
|
||||
self.onConnect(id);
|
||||
});
|
||||
|
||||
this.store.subscribe('open', function (id) {
|
||||
self.onOpen(id);
|
||||
});
|
||||
|
||||
this.store.subscribe('join', function (id, room) {
|
||||
self.onJoin(id, room);
|
||||
});
|
||||
|
||||
this.store.subscribe('leave', function (id, room) {
|
||||
self.onLeave(id, room);
|
||||
});
|
||||
|
||||
this.store.subscribe('close', function (id) {
|
||||
self.onClose(id);
|
||||
});
|
||||
|
||||
this.store.subscribe('dispatch', function (room, packet, volatile, exceptions) {
|
||||
self.onDispatch(room, packet, volatile, exceptions);
|
||||
});
|
||||
|
||||
this.store.subscribe('disconnect', function (id) {
|
||||
self.onDisconnect(id);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a client handshakes.
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
|
||||
Manager.prototype.onHandshake = function (id, data) {
|
||||
this.handshaken[id] = data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a client connects (ie: transport first opens)
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.onConnect = function (id) {
|
||||
this.connected[id] = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a client opens a request in a different node.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
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.store.unsubscribe('dispatch:' + id, function () {
|
||||
delete self.closed[id];
|
||||
});
|
||||
}
|
||||
|
||||
// clear the current transport
|
||||
if (this.transports[id]) {
|
||||
this.transports[id].discard();
|
||||
this.transports[id] = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a message is sent to a namespace and/or room.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.onDispatch = function (room, packet, volatile, exceptions) {
|
||||
if (this.rooms[room]) {
|
||||
for (var i = 0, l = this.rooms[room].length; i < l; i++) {
|
||||
var id = this.rooms[room][i];
|
||||
|
||||
if (!~exceptions.indexOf(id)) {
|
||||
if (this.transports[id] && this.transports[id].open) {
|
||||
this.transports[id].onDispatch(packet, volatile);
|
||||
} else if (!volatile) {
|
||||
this.onClientDispatch(id, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a client joins a nsp / room.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.onJoin = function (id, name) {
|
||||
if (!this.roomClients[id]) {
|
||||
this.roomClients[id] = {};
|
||||
}
|
||||
|
||||
if (!this.rooms[name]) {
|
||||
this.rooms[name] = [];
|
||||
}
|
||||
|
||||
if (!~this.rooms[name].indexOf(id)) {
|
||||
this.rooms[name].push(id);
|
||||
this.roomClients[id][name] = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a client leaves a nsp / room.
|
||||
*
|
||||
* @param private
|
||||
*/
|
||||
|
||||
Manager.prototype.onLeave = function (id, room) {
|
||||
if (this.rooms[room]) {
|
||||
var index = this.rooms[room].indexOf(id);
|
||||
|
||||
if (index >= 0) {
|
||||
this.rooms[room].splice(index, 1);
|
||||
}
|
||||
|
||||
if (!this.rooms[room].length) {
|
||||
delete this.rooms[room];
|
||||
}
|
||||
delete this.roomClients[id][room];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a client closes a request in different node.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.onClose = function (id) {
|
||||
if (this.open[id]) {
|
||||
delete this.open[id];
|
||||
}
|
||||
|
||||
this.closed[id] = [];
|
||||
|
||||
var self = this;
|
||||
|
||||
this.store.subscribe('dispatch:' + id, function (packet, volatile) {
|
||||
if (!volatile) {
|
||||
self.onClientDispatch(id, packet);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches a message for a closed client.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.onClientDispatch = function (id, packet) {
|
||||
if (this.closed[id]) {
|
||||
this.closed[id].push(packet);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Receives a message for a client.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.onClientMessage = function (id, packet) {
|
||||
if (this.namespaces[packet.endpoint]) {
|
||||
this.namespaces[packet.endpoint].handlePacket(id, packet);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Fired when a client disconnects (not triggered).
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.onClientDisconnect = function (id, reason) {
|
||||
for (var name in this.namespaces) {
|
||||
this.namespaces[name].handleDisconnect(id, reason, typeof this.roomClients[id] !== 'undefined' &&
|
||||
typeof this.roomClients[id][name] !== 'undefined');
|
||||
}
|
||||
|
||||
this.onDisconnect(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a client disconnects.
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
|
||||
Manager.prototype.onDisconnect = function (id, local) {
|
||||
delete this.handshaken[id];
|
||||
|
||||
if (this.open[id]) {
|
||||
delete this.open[id];
|
||||
}
|
||||
|
||||
if (this.connected[id]) {
|
||||
delete this.connected[id];
|
||||
}
|
||||
|
||||
if (this.transports[id]) {
|
||||
this.transports[id].discard();
|
||||
delete this.transports[id];
|
||||
}
|
||||
|
||||
if (this.closed[id]) {
|
||||
delete this.closed[id];
|
||||
}
|
||||
|
||||
if (this.roomClients[id]) {
|
||||
for (var room in this.roomClients[id]) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles an HTTP request.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.handleRequest = function (req, res) {
|
||||
var data = this.checkRequest(req);
|
||||
|
||||
if (!data) {
|
||||
for (var i = 0, l = this.oldListeners.length; i < l; i++) {
|
||||
this.oldListeners[i].call(this.server, req, res);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.static || !data.transport && !data.protocol) {
|
||||
if (data.static && this.enabled('browser client')) {
|
||||
this.static.write(data.path, req, res);
|
||||
} else {
|
||||
res.writeHead(200);
|
||||
res.end('Welcome to socket.io.');
|
||||
|
||||
this.log.info('unhandled socket.io url');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.protocol != protocol) {
|
||||
res.writeHead(500);
|
||||
res.end('Protocol version not supported.');
|
||||
|
||||
this.log.info('client protocol version unsupported');
|
||||
} else {
|
||||
if (data.id) {
|
||||
this.handleHTTPRequest(data, req, res);
|
||||
} else {
|
||||
this.handleHandshake(data, req, res);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles an HTTP Upgrade.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.handleUpgrade = function (req, socket, head) {
|
||||
var data = this.checkRequest(req)
|
||||
, self = this;
|
||||
|
||||
if (!data) {
|
||||
if (this.enabled('destroy upgrade')) {
|
||||
socket.end();
|
||||
this.log.debug('destroying non-socket.io upgrade');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
req.head = head;
|
||||
this.handleClient(data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a normal handshaken HTTP request (eg: long-polling)
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.handleHTTPRequest = function (data, req, res) {
|
||||
req.res = res;
|
||||
this.handleClient(data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Intantiantes a new client.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.handleClient = function (data, req) {
|
||||
var socket = req.socket
|
||||
, store = this.store
|
||||
, self = this;
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!~this.get('transports').indexOf(data.transport)) {
|
||||
this.log.warn('unknown transport: "' + data.transport + '"');
|
||||
req.connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
transport.payload(this.closed[data.id]);
|
||||
this.closed[data.id] = [];
|
||||
}
|
||||
|
||||
this.onOpen(data.id);
|
||||
this.store.publish('open', data.id);
|
||||
this.transports[data.id] = transport;
|
||||
}
|
||||
|
||||
if (!this.connected[data.id]) {
|
||||
this.onConnect(data.id);
|
||||
this.store.publish('connect', data.id);
|
||||
|
||||
// flag as used
|
||||
delete handshaken.issued;
|
||||
this.onHandshake(data.id, handshaken);
|
||||
this.store.publish('handshake', data.id, handshaken);
|
||||
|
||||
// initialize the socket for all namespaces
|
||||
for (var i in this.namespaces) {
|
||||
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' });
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
transport.error('client not handshaken', 'reconnect');
|
||||
}
|
||||
|
||||
transport.discard();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a session id.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a handshake request.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.handleHandshake = function (data, req, res) {
|
||||
var self = this
|
||||
, origin = req.headers.origin
|
||||
, headers = {
|
||||
'Content-Type': 'text/plain'
|
||||
};
|
||||
|
||||
function writeErr (status, message) {
|
||||
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 {
|
||||
res.writeHead(status, headers);
|
||||
res.end(message);
|
||||
}
|
||||
};
|
||||
|
||||
function error (err) {
|
||||
writeErr(500, 'handshake error');
|
||||
self.log.warn('handshake error ' + err);
|
||||
};
|
||||
|
||||
if (!this.verifyOrigin(req)) {
|
||||
writeErr(403, 'handshake bad origin');
|
||||
return;
|
||||
}
|
||||
|
||||
var handshakeData = this.handshakeData(data);
|
||||
|
||||
if (origin) {
|
||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
||||
headers['Access-Control-Allow-Origin'] = origin;
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
|
||||
this.authorize(handshakeData, function (err, authorized, newData) {
|
||||
if (err) return error(err);
|
||||
|
||||
if (authorized) {
|
||||
var id = self.generateId()
|
||||
, hs = [
|
||||
id
|
||||
, self.enabled('heartbeats') ? self.get('heartbeat timeout') || '' : ''
|
||||
, self.get('close timeout') || ''
|
||||
, self.transports(data).join(',')
|
||||
].join(':');
|
||||
|
||||
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);
|
||||
|
||||
self.log.info('handshake authorized', id);
|
||||
} else {
|
||||
writeErr(403, 'handshake unauthorized');
|
||||
self.log.info('handshake unauthorized');
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets normalized handshake data
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.handshakeData = function (data) {
|
||||
var connection = data.request.connection
|
||||
, connectionAddress
|
||||
, date = new Date;
|
||||
|
||||
if (connection.remoteAddress) {
|
||||
connectionAddress = {
|
||||
address: connection.remoteAddress
|
||||
, port: connection.remotePort
|
||||
};
|
||||
} else if (connection.socket && connection.socket.remoteAddress) {
|
||||
connectionAddress = {
|
||||
address: connection.socket.remoteAddress
|
||||
, port: connection.socket.remotePort
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
headers: data.headers
|
||||
, address: connectionAddress
|
||||
, time: date.toString()
|
||||
, query: data.query
|
||||
, url: data.request.url
|
||||
, xdomain: !!data.request.headers.origin
|
||||
, secure: data.request.connection.secure
|
||||
, issued: +date
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies the origin of a request.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.verifyOrigin = function (request) {
|
||||
var origin = request.headers.origin || request.headers.referer
|
||||
, origins = this.get('origins');
|
||||
|
||||
if (origin === 'null') origin = '*';
|
||||
|
||||
if (origins.indexOf('*:*') !== -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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 + ':*') ||
|
||||
~origins.indexOf('*:' + parts.port);
|
||||
if (!ok) this.log.warn('illegal origin: ' + origin);
|
||||
return ok;
|
||||
} catch (ex) {
|
||||
this.log.warn('error parsing origin');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.log.warn('origin missing from handshake, yet required by config');
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles an incoming packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.handlePacket = function (sessid, packet) {
|
||||
this.of(packet.endpoint || '').handlePacket(sessid, packet);
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs authentication.
|
||||
*
|
||||
* @param Object client request data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.authorize = function (data, fn) {
|
||||
if (this.get('authorization')) {
|
||||
var self = this;
|
||||
|
||||
this.get('authorization').call(this, data, function (err, authorized) {
|
||||
self.log.debug('client ' + authorized ? 'authorized' : 'unauthorized');
|
||||
fn(err, authorized);
|
||||
});
|
||||
} else {
|
||||
this.log.debug('client authorized');
|
||||
fn(null, true);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the transports adviced to the user.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.transports = function (data) {
|
||||
var transp = this.get('transports')
|
||||
, ret = [];
|
||||
|
||||
for (var i = 0, l = transp.length; i < l; i++) {
|
||||
var transport = transp[i];
|
||||
|
||||
if (transport) {
|
||||
if (!transport.checkClient || transport.checkClient(data)) {
|
||||
ret.push(transport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether a request is a socket.io one.
|
||||
*
|
||||
* @return {Object} a client request data object or `false`
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var regexp = /^\/([^\/]+)\/?([^\/]+)?\/?([^\/]+)?\/?$/
|
||||
|
||||
Manager.prototype.checkRequest = function (req) {
|
||||
var resource = this.get('resource');
|
||||
|
||||
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);
|
||||
|
||||
// client request data
|
||||
var data = {
|
||||
query: uri.query || {}
|
||||
, headers: req.headers
|
||||
, request: req
|
||||
, path: path
|
||||
};
|
||||
|
||||
if (pieces) {
|
||||
data.protocol = Number(pieces[1]);
|
||||
data.transport = pieces[2];
|
||||
data.id = pieces[3];
|
||||
data.static = !!this.static.has(path);
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Declares a socket namespace
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Manager.prototype.of = function (nsp) {
|
||||
if (this.namespaces[nsp]) {
|
||||
return this.namespaces[nsp];
|
||||
}
|
||||
|
||||
return this.namespaces[nsp] = new SocketNamespace(this, nsp);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform garbage collection on long living objects and properties that cannot
|
||||
* be removed automatically.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Manager.prototype.garbageCollection = function () {
|
||||
// clean up unused handshakes
|
||||
var ids = Object.keys(this.handshaken)
|
||||
, i = ids.length
|
||||
, now = Date.now()
|
||||
, handshake;
|
||||
|
||||
while (i--) {
|
||||
handshake = this.handshaken[ids[i]];
|
||||
|
||||
if ('issued' in handshake && (now - handshake.issued) >= 3E4) {
|
||||
this.onDisconnect(ids[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
355
networking/node_modules/socket.io/lib/namespace.js
generated
vendored
Normal file
355
networking/node_modules/socket.io/lib/namespace.js
generated
vendored
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var Socket = require('./socket')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, parser = require('./parser')
|
||||
, util = require('./util');
|
||||
|
||||
/**
|
||||
* Exports the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = SocketNamespace;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @api public.
|
||||
*/
|
||||
|
||||
function SocketNamespace (mgr, name) {
|
||||
this.manager = mgr;
|
||||
this.name = name || '';
|
||||
this.sockets = {};
|
||||
this.auth = false;
|
||||
this.setFlags();
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from EventEmitter.
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Copies emit since we override it.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.$emit = EventEmitter.prototype.emit;
|
||||
|
||||
/**
|
||||
* Retrieves all clients as Socket instances as an array.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.clients = function (room) {
|
||||
var room = this.name + (room !== undefined ?
|
||||
'/' + room : '');
|
||||
|
||||
if (!this.manager.rooms[room]) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.manager.rooms[room].map(function (id) {
|
||||
return this.socket(id);
|
||||
}, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Access logger interface.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.__defineGetter__('log', function () {
|
||||
return this.manager.log;
|
||||
});
|
||||
|
||||
/**
|
||||
* Access store.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.__defineGetter__('store', function () {
|
||||
return this.manager.store;
|
||||
});
|
||||
|
||||
/**
|
||||
* JSON message flag.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.__defineGetter__('json', function () {
|
||||
this.flags.json = true;
|
||||
return this;
|
||||
});
|
||||
|
||||
/**
|
||||
* Volatile message flag.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.__defineGetter__('volatile', function () {
|
||||
this.flags.volatile = true;
|
||||
return this;
|
||||
});
|
||||
|
||||
/**
|
||||
* Overrides the room to relay messages to (flag).
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) {
|
||||
this.flags.endpoint = this.name + (room ? '/' + room : '');
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a session id we should prevent relaying messages to (flag).
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.except = function (id) {
|
||||
this.flags.exceptions.push(id);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the default flags.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.setFlags = function () {
|
||||
this.flags = {
|
||||
endpoint: this.name
|
||||
, exceptions: []
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends out a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.packet = function (packet) {
|
||||
packet.endpoint = this.name;
|
||||
|
||||
var store = this.store
|
||||
, log = this.log
|
||||
, volatile = this.flags.volatile
|
||||
, exceptions = this.flags.exceptions
|
||||
, packet = parser.encodePacket(packet);
|
||||
|
||||
this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions);
|
||||
this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions);
|
||||
|
||||
this.setFlags();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends to everyone.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.send = function (data) {
|
||||
return this.packet({
|
||||
type: this.flags.json ? 'json' : 'message'
|
||||
, data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Emits to everyone (override).
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.emit = function (name) {
|
||||
if (name == 'newListener') {
|
||||
return this.$emit.apply(this, arguments);
|
||||
}
|
||||
|
||||
return this.packet({
|
||||
type: 'event'
|
||||
, name: name
|
||||
, args: util.toArray(arguments).slice(1)
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves or creates a write-only socket for a client, unless specified.
|
||||
*
|
||||
* @param {Boolean} whether the socket will be readable when initialized
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.socket = function (sid, readable) {
|
||||
if (!this.sockets[sid]) {
|
||||
this.sockets[sid] = new Socket(this.manager, sid, this, readable);
|
||||
}
|
||||
|
||||
return this.sockets[sid];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets authorization for this namespace.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.authorization = function (fn) {
|
||||
this.auth = fn;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a socket disconnects entirely.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) {
|
||||
if (this.sockets[sid] && this.sockets[sid].readable) {
|
||||
if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason);
|
||||
delete this.sockets[sid];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs authentication.
|
||||
*
|
||||
* @param Object client request data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.authorize = function (data, fn) {
|
||||
if (this.auth) {
|
||||
var self = this;
|
||||
|
||||
this.auth.call(this, data, function (err, authorized) {
|
||||
self.log.debug('client ' +
|
||||
(authorized ? '' : 'un') + 'authorized for ' + self.name);
|
||||
fn(err, authorized);
|
||||
});
|
||||
} else {
|
||||
this.log.debug('client authorized for ' + this.name);
|
||||
fn(null, true);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SocketNamespace.prototype.handlePacket = function (sessid, packet) {
|
||||
var socket = this.socket(sessid)
|
||||
, dataAck = packet.ack == 'data'
|
||||
, manager = this.manager
|
||||
, self = this;
|
||||
|
||||
function ack () {
|
||||
self.log.debug('sending data ack packet');
|
||||
socket.packet({
|
||||
type: 'ack'
|
||||
, args: util.toArray(arguments)
|
||||
, ackId: packet.id
|
||||
});
|
||||
};
|
||||
|
||||
function error (err) {
|
||||
self.log.warn('handshake error ' + err + ' for ' + self.name);
|
||||
socket.packet({ type: 'error', reason: err });
|
||||
};
|
||||
|
||||
function connect () {
|
||||
self.manager.onJoin(sessid, self.name);
|
||||
self.store.publish('join', sessid, self.name);
|
||||
|
||||
// packet echo
|
||||
socket.packet({ type: 'connect' });
|
||||
|
||||
// emit connection event
|
||||
self.$emit('connection', socket);
|
||||
};
|
||||
|
||||
switch (packet.type) {
|
||||
case 'connect':
|
||||
if (packet.endpoint == '') {
|
||||
connect();
|
||||
} else {
|
||||
var handshakeData = manager.handshaken[sessid];
|
||||
|
||||
this.authorize(handshakeData, function (err, authorized, newData) {
|
||||
if (err) return error(err);
|
||||
|
||||
if (authorized) {
|
||||
manager.onHandshake(sessid, newData || handshakeData);
|
||||
self.store.publish('handshake', sessid, newData || handshakeData);
|
||||
connect();
|
||||
} else {
|
||||
error('unauthorized');
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ack':
|
||||
if (socket.acks[packet.ackId]) {
|
||||
socket.acks[packet.ackId].apply(socket, packet.args);
|
||||
} else {
|
||||
this.log.info('unknown ack packet');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'event':
|
||||
// check if the emitted event is not blacklisted
|
||||
if (-~manager.get('blacklist').indexOf(packet.name)) {
|
||||
this.log.debug('ignoring blacklisted event `' + packet.name + '`');
|
||||
} else {
|
||||
var params = [packet.name].concat(packet.args);
|
||||
|
||||
if (dataAck) {
|
||||
params.push(ack);
|
||||
}
|
||||
|
||||
socket.$emit.apply(socket, params);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'disconnect':
|
||||
this.manager.onLeave(sessid, this.name);
|
||||
this.store.publish('leave', sessid, this.name);
|
||||
|
||||
socket.$emit('disconnect', packet.reason || 'packet');
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
case 'message':
|
||||
var params = ['message', packet.data];
|
||||
|
||||
if (dataAck)
|
||||
params.push(ack);
|
||||
|
||||
socket.$emit.apply(socket, params);
|
||||
};
|
||||
};
|
||||
249
networking/node_modules/socket.io/lib/parser.js
generated
vendored
Normal file
249
networking/node_modules/socket.io/lib/parser.js
generated
vendored
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Packet types.
|
||||
*/
|
||||
|
||||
var packets = exports.packets = {
|
||||
'disconnect': 0
|
||||
, 'connect': 1
|
||||
, 'heartbeat': 2
|
||||
, 'message': 3
|
||||
, 'json': 4
|
||||
, 'event': 5
|
||||
, 'ack': 6
|
||||
, 'error': 7
|
||||
, 'noop': 8
|
||||
}
|
||||
, packetslist = Object.keys(packets);
|
||||
|
||||
/**
|
||||
* Errors reasons.
|
||||
*/
|
||||
|
||||
var reasons = exports.reasons = {
|
||||
'transport not supported': 0
|
||||
, 'client not handshaken': 1
|
||||
, 'unauthorized': 2
|
||||
}
|
||||
, reasonslist = Object.keys(reasons);
|
||||
|
||||
/**
|
||||
* Errors advice.
|
||||
*/
|
||||
|
||||
var advice = exports.advice = {
|
||||
'reconnect': 0
|
||||
}
|
||||
, advicelist = Object.keys(advice);
|
||||
|
||||
/**
|
||||
* Encodes a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.encodePacket = function (packet) {
|
||||
var type = packets[packet.type]
|
||||
, id = packet.id || ''
|
||||
, endpoint = packet.endpoint || ''
|
||||
, ack = packet.ack
|
||||
, data = null;
|
||||
|
||||
switch (packet.type) {
|
||||
case 'message':
|
||||
if (packet.data !== '')
|
||||
data = packet.data;
|
||||
break;
|
||||
|
||||
case 'event':
|
||||
var ev = { name: packet.name };
|
||||
|
||||
if (packet.args && packet.args.length) {
|
||||
ev.args = packet.args;
|
||||
}
|
||||
|
||||
data = JSON.stringify(ev);
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
data = JSON.stringify(packet.data);
|
||||
break;
|
||||
|
||||
case 'ack':
|
||||
data = packet.ackId
|
||||
+ (packet.args && packet.args.length
|
||||
? '+' + JSON.stringify(packet.args) : '');
|
||||
break;
|
||||
|
||||
case 'connect':
|
||||
if (packet.qs)
|
||||
data = packet.qs;
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
var reason = packet.reason ? reasons[packet.reason] : ''
|
||||
, adv = packet.advice ? advice[packet.advice] : ''
|
||||
|
||||
if (reason !== '' || adv !== '')
|
||||
data = reason + (adv !== '' ? ('+' + adv) : '')
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// construct packet with required fragments
|
||||
var encoded = type + ':' + id + (ack == 'data' ? '+' : '') + ':' + endpoint;
|
||||
|
||||
// data fragment is optional
|
||||
if (data !== null && data !== undefined)
|
||||
encoded += ':' + data;
|
||||
|
||||
return encoded;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes multiple messages (payload).
|
||||
*
|
||||
* @param {Array} messages
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.encodePayload = function (packets) {
|
||||
var decoded = '';
|
||||
|
||||
if (packets.length == 1)
|
||||
return packets[0];
|
||||
|
||||
for (var i = 0, l = packets.length; i < l; i++) {
|
||||
var packet = packets[i];
|
||||
decoded += '\ufffd' + packet.length + '\ufffd' + packets[i]
|
||||
}
|
||||
|
||||
return decoded;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes a packet
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
|
||||
|
||||
/**
|
||||
* Wrap the JSON.parse in a seperate function the crankshaft optimizer will
|
||||
* only punish this function for the usage for try catch
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parse (data) {
|
||||
try { return JSON.parse(data) }
|
||||
catch (e) { return false }
|
||||
}
|
||||
|
||||
exports.decodePacket = function (data) {
|
||||
var pieces = data.match(regexp);
|
||||
|
||||
if (!pieces) return {};
|
||||
|
||||
var id = pieces[2] || ''
|
||||
, data = pieces[5] || ''
|
||||
, packet = {
|
||||
type: packetslist[pieces[1]]
|
||||
, endpoint: pieces[4] || ''
|
||||
};
|
||||
|
||||
// whether we need to acknowledge the packet
|
||||
if (id) {
|
||||
packet.id = id;
|
||||
if (pieces[3])
|
||||
packet.ack = 'data';
|
||||
else
|
||||
packet.ack = true;
|
||||
}
|
||||
|
||||
// handle different packet types
|
||||
switch (packet.type) {
|
||||
case 'message':
|
||||
packet.data = data || '';
|
||||
break;
|
||||
|
||||
case 'event':
|
||||
pieces = parse(data);
|
||||
if (pieces) {
|
||||
packet.name = pieces.name;
|
||||
packet.args = pieces.args;
|
||||
}
|
||||
|
||||
packet.args = packet.args || [];
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
packet.data = parse(data);
|
||||
break;
|
||||
|
||||
case 'connect':
|
||||
packet.qs = data || '';
|
||||
break;
|
||||
|
||||
case 'ack':
|
||||
pieces = data.match(/^([0-9]+)(\+)?(.*)/);
|
||||
if (pieces) {
|
||||
packet.ackId = pieces[1];
|
||||
packet.args = [];
|
||||
|
||||
if (pieces[3]) {
|
||||
packet.args = parse(pieces[3]) || [];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
pieces = data.split('+');
|
||||
packet.reason = reasonslist[pieces[0]] || '';
|
||||
packet.advice = advicelist[pieces[1]] || '';
|
||||
}
|
||||
|
||||
return packet;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes data payload. Detects multiple messages
|
||||
*
|
||||
* @return {Array} messages
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.decodePayload = function (data) {
|
||||
if (undefined == data || null == data) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (data[0] == '\ufffd') {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 1, length = ''; i < data.length; i++) {
|
||||
if (data[i] == '\ufffd') {
|
||||
ret.push(exports.decodePacket(data.substr(i + 1, length)));
|
||||
i += Number(length) + 1;
|
||||
length = '';
|
||||
} else {
|
||||
length += data[i];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
return [exports.decodePacket(data)];
|
||||
}
|
||||
};
|
||||
136
networking/node_modules/socket.io/lib/socket.io.js
generated
vendored
Normal file
136
networking/node_modules/socket.io/lib/socket.io.js
generated
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var client = require('socket.io-client');
|
||||
|
||||
/**
|
||||
* Version.
|
||||
*/
|
||||
|
||||
exports.version = '0.9.5';
|
||||
|
||||
/**
|
||||
* Supported protocol version.
|
||||
*/
|
||||
|
||||
exports.protocol = 1;
|
||||
|
||||
/**
|
||||
* Client that we serve.
|
||||
*/
|
||||
|
||||
exports.clientVersion = client.version;
|
||||
|
||||
/**
|
||||
* Attaches a manager
|
||||
*
|
||||
* @param {HTTPServer/Number} a HTTP/S server or a port number to listen on.
|
||||
* @param {Object} opts to be passed to Manager and/or http server
|
||||
* @param {Function} callback if a port is supplied
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.listen = function (server, options, fn) {
|
||||
if ('function' == typeof options) {
|
||||
fn = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
if ('undefined' == typeof server) {
|
||||
// create a server that listens on port 80
|
||||
server = 80;
|
||||
}
|
||||
|
||||
if ('number' == typeof server) {
|
||||
// if a port number is passed
|
||||
var port = server;
|
||||
|
||||
if (options && options.key)
|
||||
server = require('https').createServer(options);
|
||||
else
|
||||
server = require('http').createServer();
|
||||
|
||||
// default response
|
||||
server.on('request', function (req, res) {
|
||||
res.writeHead(200);
|
||||
res.end('Welcome to socket.io.');
|
||||
});
|
||||
|
||||
server.listen(port, fn);
|
||||
}
|
||||
|
||||
// otherwise assume a http/s server
|
||||
return new exports.Manager(server, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Manager constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.Manager = require('./manager');
|
||||
|
||||
/**
|
||||
* Transport constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.Transport = require('./transport');
|
||||
|
||||
/**
|
||||
* Socket constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.Socket = require('./socket');
|
||||
|
||||
/**
|
||||
* Static constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.Static = require('./static');
|
||||
|
||||
/**
|
||||
* Store constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.Store = require('./store');
|
||||
|
||||
/**
|
||||
* Memory Store constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.MemoryStore = require('./stores/memory');
|
||||
|
||||
/**
|
||||
* Redis Store constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.RedisStore = require('./stores/redis');
|
||||
|
||||
/**
|
||||
* Parser.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.parser = require('./parser');
|
||||
369
networking/node_modules/socket.io/lib/socket.js
generated
vendored
Normal file
369
networking/node_modules/socket.io/lib/socket.js
generated
vendored
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var parser = require('./parser')
|
||||
, util = require('./util')
|
||||
, EventEmitter = process.EventEmitter
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = Socket;
|
||||
|
||||
/**
|
||||
* Default error event listener to prevent uncaught exceptions.
|
||||
*/
|
||||
|
||||
var defaultError = function () {};
|
||||
|
||||
/**
|
||||
* Socket constructor.
|
||||
*
|
||||
* @param {Manager} manager instance
|
||||
* @param {String} session id
|
||||
* @param {Namespace} namespace the socket belongs to
|
||||
* @param {Boolean} whether the
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Socket (manager, id, nsp, readable) {
|
||||
this.id = id;
|
||||
this.namespace = nsp;
|
||||
this.manager = manager;
|
||||
this.disconnected = false;
|
||||
this.ackPackets = 0;
|
||||
this.acks = {};
|
||||
this.setFlags();
|
||||
this.readable = readable;
|
||||
this.store = this.manager.store.client(this.id);
|
||||
this.on('error', defaultError);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from EventEmitter.
|
||||
*/
|
||||
|
||||
Socket.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Accessor shortcut for the handshake data
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.__defineGetter__('handshake', function () {
|
||||
return this.manager.handshaken[this.id];
|
||||
});
|
||||
|
||||
/**
|
||||
* Accessor shortcut for the transport type
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.__defineGetter__('transport', function () {
|
||||
return this.manager.transports[this.id].name;
|
||||
});
|
||||
|
||||
/**
|
||||
* Accessor shortcut for the logger.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.__defineGetter__('log', function () {
|
||||
return this.manager.log;
|
||||
});
|
||||
|
||||
/**
|
||||
* JSON message flag.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.__defineGetter__('json', function () {
|
||||
this.flags.json = true;
|
||||
return this;
|
||||
});
|
||||
|
||||
/**
|
||||
* Volatile message flag.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.__defineGetter__('volatile', function () {
|
||||
this.flags.volatile = true;
|
||||
return this;
|
||||
});
|
||||
|
||||
/**
|
||||
* Broadcast message flag.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.__defineGetter__('broadcast', function () {
|
||||
this.flags.broadcast = true;
|
||||
return this;
|
||||
});
|
||||
|
||||
/**
|
||||
* Overrides the room to broadcast messages to (flag)
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.to = Socket.prototype.in = function (room) {
|
||||
this.flags.room = room;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resets flags
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.setFlags = function () {
|
||||
this.flags = {
|
||||
endpoint: this.namespace.name
|
||||
, room: ''
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered on disconnect
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.onDisconnect = function (reason) {
|
||||
if (!this.disconnected) {
|
||||
this.$emit('disconnect', reason);
|
||||
this.disconnected = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins a user to a room.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.join = function (name, fn) {
|
||||
var nsp = this.namespace.name
|
||||
, name = (nsp + '/') + name;
|
||||
|
||||
this.manager.onJoin(this.id, name);
|
||||
this.manager.store.publish('join', this.id, name);
|
||||
|
||||
if (fn) {
|
||||
this.log.warn('Client#join callback is deprecated');
|
||||
fn();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Un-joins a user from a room.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.leave = function (name, fn) {
|
||||
var nsp = this.namespace.name
|
||||
, name = (nsp + '/') + name;
|
||||
|
||||
this.manager.onLeave(this.id, name);
|
||||
this.manager.store.publish('leave', this.id, name);
|
||||
|
||||
if (fn) {
|
||||
this.log.warn('Client#leave callback is deprecated');
|
||||
fn();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transmits a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.packet = function (packet) {
|
||||
if (this.flags.broadcast) {
|
||||
this.log.debug('broadcasting packet');
|
||||
this.namespace.in(this.flags.room).except(this.id).packet(packet);
|
||||
} else {
|
||||
packet.endpoint = this.flags.endpoint;
|
||||
packet = parser.encodePacket(packet);
|
||||
|
||||
this.dispatch(packet, this.flags.volatile);
|
||||
}
|
||||
|
||||
this.setFlags();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches a packet
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.dispatch = function (packet, volatile) {
|
||||
if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
|
||||
this.manager.transports[this.id].onDispatch(packet, volatile);
|
||||
} else {
|
||||
if (!volatile) {
|
||||
this.manager.onClientDispatch(this.id, packet, volatile);
|
||||
}
|
||||
|
||||
this.manager.store.publish('dispatch:' + this.id, packet, volatile);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores data for the client.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.set = function (key, value, fn) {
|
||||
this.store.set(key, value, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves data for the client
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.get = function (key, fn) {
|
||||
this.store.get(key, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks data for the client
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.has = function (key, fn) {
|
||||
this.store.has(key, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes data for the client
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.del = function (key, fn) {
|
||||
this.store.del(key, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Kicks client
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.disconnect = function () {
|
||||
if (!this.disconnected) {
|
||||
this.log.info('booting client');
|
||||
|
||||
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:' + this.id);
|
||||
}
|
||||
} else {
|
||||
this.packet({type: 'disconnect'});
|
||||
this.manager.onLeave(this.id, this.namespace.name);
|
||||
this.$emit('disconnect', 'booted');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a message.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.send = function (data, fn) {
|
||||
var packet = {
|
||||
type: this.flags.json ? 'json' : 'message'
|
||||
, data: data
|
||||
};
|
||||
|
||||
if (fn) {
|
||||
packet.id = ++this.ackPackets;
|
||||
packet.ack = true;
|
||||
this.acks[packet.id] = fn;
|
||||
}
|
||||
|
||||
return this.packet(packet);
|
||||
};
|
||||
|
||||
/**
|
||||
* Original emit function.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.$emit = EventEmitter.prototype.emit;
|
||||
|
||||
/**
|
||||
* Emit override for custom events.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.emit = function (ev) {
|
||||
if (ev == 'newListener') {
|
||||
return this.$emit.apply(this, arguments);
|
||||
}
|
||||
|
||||
var args = util.toArray(arguments).slice(1)
|
||||
, lastArg = args[args.length - 1]
|
||||
, packet = {
|
||||
type: 'event'
|
||||
, name: ev
|
||||
};
|
||||
|
||||
if ('function' == typeof lastArg) {
|
||||
packet.id = ++this.ackPackets;
|
||||
packet.ack = lastArg.length ? 'data' : true;
|
||||
this.acks[packet.id] = lastArg;
|
||||
args = args.slice(0, args.length - 1);
|
||||
}
|
||||
|
||||
packet.args = args;
|
||||
|
||||
return this.packet(packet);
|
||||
};
|
||||
395
networking/node_modules/socket.io/lib/static.js
generated
vendored
Normal file
395
networking/node_modules/socket.io/lib/static.js
generated
vendored
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var client = require('socket.io-client')
|
||||
, cp = require('child_process')
|
||||
, fs = require('fs')
|
||||
, util = require('./util');
|
||||
|
||||
/**
|
||||
* File type details.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var mime = {
|
||||
js: {
|
||||
type: 'application/javascript'
|
||||
, encoding: 'utf8'
|
||||
, gzip: true
|
||||
}
|
||||
, swf: {
|
||||
type: 'application/x-shockwave-flash'
|
||||
, encoding: 'binary'
|
||||
, gzip: false
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Regexp for matching custom transport patterns. Users can configure their own
|
||||
* socket.io bundle based on the url structure. Different transport names are
|
||||
* concatinated using the `+` char. /socket.io/socket.io+websocket.js should
|
||||
* create a bundle that only contains support for the websocket.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/
|
||||
, versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/;
|
||||
|
||||
/**
|
||||
* Export the constructor
|
||||
*/
|
||||
|
||||
exports = module.exports = Static;
|
||||
|
||||
/**
|
||||
* Static constructor
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Static (manager) {
|
||||
this.manager = manager;
|
||||
this.cache = {};
|
||||
this.paths = {};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Static by adding default file paths.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Static.prototype.init = function () {
|
||||
/**
|
||||
* Generates a unique id based the supplied transports array
|
||||
*
|
||||
* @param {Array} transports The array with transport types
|
||||
* @api private
|
||||
*/
|
||||
function id (transports) {
|
||||
var id = transports.join('').split('').map(function (char) {
|
||||
return ('' + char.charCodeAt(0)).split('').pop();
|
||||
}).reduce(function (char, id) {
|
||||
return char +id;
|
||||
});
|
||||
|
||||
return client.version + ':' + id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a socket.io-client file based on the supplied transports.
|
||||
*
|
||||
* @param {Array} transports The array with transport types
|
||||
* @param {Function} callback Callback for the static.write
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function build (transports, callback) {
|
||||
client.builder(transports, {
|
||||
minify: self.manager.enabled('browser client minification')
|
||||
}, function (err, content) {
|
||||
callback(err, content ? new Buffer(content) : null, id(transports));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
// add our default static files
|
||||
this.add('/static/flashsocket/WebSocketMain.swf', {
|
||||
file: client.dist + '/WebSocketMain.swf'
|
||||
});
|
||||
|
||||
this.add('/static/flashsocket/WebSocketMainInsecure.swf', {
|
||||
file: client.dist + '/WebSocketMainInsecure.swf'
|
||||
});
|
||||
|
||||
// generates dedicated build based on the available transports
|
||||
this.add('/socket.io.js', function (path, callback) {
|
||||
build(self.manager.get('transports'), callback);
|
||||
});
|
||||
|
||||
this.add('/socket.io.v', { mime: mime.js }, function (path, callback) {
|
||||
build(self.manager.get('transports'), callback);
|
||||
});
|
||||
|
||||
// allow custom builds based on url paths
|
||||
this.add('/socket.io+', { mime: mime.js }, function (path, callback) {
|
||||
var available = self.manager.get('transports')
|
||||
, matches = path.match(bundle)
|
||||
, transports = [];
|
||||
|
||||
if (!matches) return callback('No valid transports');
|
||||
|
||||
// make sure they valid transports
|
||||
matches[0].split('.')[0].split('+').slice(1).forEach(function (transport) {
|
||||
if (!!~available.indexOf(transport)) {
|
||||
transports.push(transport);
|
||||
}
|
||||
});
|
||||
|
||||
if (!transports.length) return callback('No valid transports');
|
||||
build(transports, callback);
|
||||
});
|
||||
|
||||
// clear cache when transports change
|
||||
this.manager.on('set:transports', function (key, value) {
|
||||
delete self.cache['/socket.io.js'];
|
||||
Object.keys(self.cache).forEach(function (key) {
|
||||
if (bundle.test(key)) {
|
||||
delete self.cache[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gzip compress buffers.
|
||||
*
|
||||
* @param {Buffer} data The buffer that needs gzip compression
|
||||
* @param {Function} callback
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Static.prototype.gzip = function (data, callback) {
|
||||
var gzip = cp.spawn('gzip', ['-9', '-c', '-f', '-n'])
|
||||
, encoding = Buffer.isBuffer(data) ? 'binary' : 'utf8'
|
||||
, buffer = []
|
||||
, err;
|
||||
|
||||
gzip.stdout.on('data', function (data) {
|
||||
buffer.push(data);
|
||||
});
|
||||
|
||||
gzip.stderr.on('data', function (data) {
|
||||
err = data +'';
|
||||
buffer.length = 0;
|
||||
});
|
||||
|
||||
gzip.on('exit', function () {
|
||||
if (err) return callback(err);
|
||||
|
||||
var size = 0
|
||||
, index = 0
|
||||
, i = buffer.length
|
||||
, content;
|
||||
|
||||
while (i--) {
|
||||
size += buffer[i].length;
|
||||
}
|
||||
|
||||
content = new Buffer(size);
|
||||
i = buffer.length;
|
||||
|
||||
buffer.forEach(function (buffer) {
|
||||
var length = buffer.length;
|
||||
|
||||
buffer.copy(content, index, 0, length);
|
||||
index += length;
|
||||
});
|
||||
|
||||
buffer.length = 0;
|
||||
callback(null, content);
|
||||
});
|
||||
|
||||
gzip.stdin.end(data, encoding);
|
||||
};
|
||||
|
||||
/**
|
||||
* Is the path a static file?
|
||||
*
|
||||
* @param {String} path The path that needs to be checked
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Static.prototype.has = function (path) {
|
||||
// fast case
|
||||
if (this.paths[path]) return this.paths[path];
|
||||
|
||||
var keys = Object.keys(this.paths)
|
||||
, i = keys.length;
|
||||
|
||||
while (i--) {
|
||||
if (-~path.indexOf(keys[i])) return this.paths[keys[i]];
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add new paths new paths that can be served using the static provider.
|
||||
*
|
||||
* @param {String} path The path to respond to
|
||||
* @param {Options} options Options for writing out the response
|
||||
* @param {Function} [callback] Optional callback if no options.file is
|
||||
* supplied this would be called instead.
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Static.prototype.add = function (path, options, callback) {
|
||||
var extension = /(?:\.(\w{1,4}))$/.exec(path);
|
||||
|
||||
if (!callback && typeof options == 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
options.mime = options.mime || (extension ? mime[extension[1]] : false);
|
||||
|
||||
if (callback) options.callback = callback;
|
||||
if (!(options.file || options.callback) || !options.mime) return false;
|
||||
|
||||
this.paths[path] = options;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a static response.
|
||||
*
|
||||
* @param {String} path The path for the static content
|
||||
* @param {HTTPRequest} req The request object
|
||||
* @param {HTTPResponse} res The response object
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Static.prototype.write = function (path, req, res) {
|
||||
/**
|
||||
* Write a response without throwing errors because can throw error if the
|
||||
* response is no longer writable etc.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function write (status, headers, content, encoding) {
|
||||
try {
|
||||
res.writeHead(status, headers || undefined);
|
||||
|
||||
// only write content if it's not a HEAD request and we actually have
|
||||
// some content to write (304's doesn't have content).
|
||||
res.end(
|
||||
req.method !== 'HEAD' && content ? content : ''
|
||||
, encoding || undefined
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers requests depending on the request properties and the reply object.
|
||||
*
|
||||
* @param {Object} reply The details and content to reply the response with
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function answer (reply) {
|
||||
var cached = req.headers['if-none-match'] === reply.etag;
|
||||
if (cached && self.manager.enabled('browser client etag')) {
|
||||
return write(304);
|
||||
}
|
||||
|
||||
var accept = req.headers['accept-encoding'] || ''
|
||||
, gzip = !!~accept.toLowerCase().indexOf('gzip')
|
||||
, mime = reply.mime
|
||||
, versioned = reply.versioned
|
||||
, headers = {
|
||||
'Content-Type': mime.type
|
||||
};
|
||||
|
||||
// check if we can add a etag
|
||||
if (self.manager.enabled('browser client etag') && reply.etag && !versioned) {
|
||||
headers['Etag'] = reply.etag;
|
||||
}
|
||||
|
||||
// see if we need to set Expire headers because the path is versioned
|
||||
if (versioned) {
|
||||
var expires = self.manager.get('browser client expires');
|
||||
headers['Cache-Control'] = 'private, x-gzip-ok="", max-age=' + expires;
|
||||
headers['Date'] = new Date().toUTCString();
|
||||
headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString();
|
||||
}
|
||||
|
||||
if (gzip && reply.gzip) {
|
||||
headers['Content-Length'] = reply.gzip.length;
|
||||
headers['Content-Encoding'] = 'gzip';
|
||||
headers['Vary'] = 'Accept-Encoding';
|
||||
write(200, headers, reply.gzip.content, mime.encoding);
|
||||
} else {
|
||||
headers['Content-Length'] = reply.length;
|
||||
write(200, headers, reply.content, mime.encoding);
|
||||
}
|
||||
|
||||
self.manager.log.debug('served static content ' + path);
|
||||
}
|
||||
|
||||
var self = this
|
||||
, details;
|
||||
|
||||
// most common case first
|
||||
if (this.manager.enabled('browser client cache') && this.cache[path]) {
|
||||
return answer(this.cache[path]);
|
||||
} else if (this.manager.get('browser client handler')) {
|
||||
return this.manager.get('browser client handler').call(this, req, res);
|
||||
} else if ((details = this.has(path))) {
|
||||
/**
|
||||
* A small helper function that will let us deal with fs and dynamic files
|
||||
*
|
||||
* @param {Object} err Optional error
|
||||
* @param {Buffer} content The data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function ready (err, content, etag) {
|
||||
if (err) {
|
||||
self.manager.log.warn('Unable to serve file. ' + (err.message || err));
|
||||
return write(500, null, 'Error serving static ' + path);
|
||||
}
|
||||
|
||||
// store the result in the cache
|
||||
var reply = self.cache[path] = {
|
||||
content: content
|
||||
, length: content.length
|
||||
, mime: details.mime
|
||||
, etag: etag || client.version
|
||||
, versioned: versioning.test(path)
|
||||
};
|
||||
|
||||
// check if gzip is enabled
|
||||
if (details.mime.gzip && self.manager.enabled('browser client gzip')) {
|
||||
self.gzip(content, function (err, content) {
|
||||
if (!err) {
|
||||
reply.gzip = {
|
||||
content: content
|
||||
, length: content.length
|
||||
}
|
||||
}
|
||||
|
||||
answer(reply);
|
||||
});
|
||||
} else {
|
||||
answer(reply);
|
||||
}
|
||||
}
|
||||
|
||||
if (details.file) {
|
||||
fs.readFile(details.file, ready);
|
||||
} else if(details.callback) {
|
||||
details.callback.call(this, path, ready);
|
||||
} else {
|
||||
write(404, null, 'File handle not found');
|
||||
}
|
||||
} else {
|
||||
write(404, null, 'File not found');
|
||||
}
|
||||
};
|
||||
98
networking/node_modules/socket.io/lib/store.js
generated
vendored
Normal file
98
networking/node_modules/socket.io/lib/store.js
generated
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Expose the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = Store;
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var EventEmitter = process.EventEmitter;
|
||||
|
||||
/**
|
||||
* Store interface
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Store (options) {
|
||||
this.options = options;
|
||||
this.clients = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherit from EventEmitter.
|
||||
*/
|
||||
|
||||
Store.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Initializes a client store
|
||||
*
|
||||
* @param {String} id
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Store.prototype.client = function (id) {
|
||||
if (!this.clients[id]) {
|
||||
this.clients[id] = new (this.constructor.Client)(this, id);
|
||||
}
|
||||
|
||||
return this.clients[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys a client
|
||||
*
|
||||
* @api {String} sid
|
||||
* @param {Number} number of seconds to expire client data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Store.prototype.destroyClient = function (id, expiration) {
|
||||
if (this.clients[id]) {
|
||||
this.clients[id].destroy(expiration);
|
||||
delete this.clients[id];
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys the store
|
||||
*
|
||||
* @param {Number} number of seconds to expire client data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Store.prototype.destroy = function (clientExpiration) {
|
||||
var keys = Object.keys(this.clients)
|
||||
, count = keys.length;
|
||||
|
||||
for (var i = 0, l = count; i < l; i++) {
|
||||
this.destroyClient(keys[i], clientExpiration);
|
||||
}
|
||||
|
||||
this.clients = {};
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Store.Client = function (store, id) {
|
||||
this.store = store;
|
||||
this.id = id;
|
||||
};
|
||||
143
networking/node_modules/socket.io/lib/stores/memory.js
generated
vendored
Normal file
143
networking/node_modules/socket.io/lib/stores/memory.js
generated
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var crypto = require('crypto')
|
||||
, Store = require('../store');
|
||||
|
||||
/**
|
||||
* Exports the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = Memory;
|
||||
Memory.Client = Client;
|
||||
|
||||
/**
|
||||
* Memory store
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Memory (opts) {
|
||||
Store.call(this, opts);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Store.
|
||||
*/
|
||||
|
||||
Memory.prototype.__proto__ = Store.prototype;
|
||||
|
||||
/**
|
||||
* Publishes a message.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Memory.prototype.publish = function () { };
|
||||
|
||||
/**
|
||||
* Subscribes to a channel
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Memory.prototype.subscribe = function () { };
|
||||
|
||||
/**
|
||||
* Unsubscribes
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Memory.prototype.unsubscribe = function () { };
|
||||
|
||||
/**
|
||||
* Client constructor
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function Client () {
|
||||
Store.Client.apply(this, arguments);
|
||||
this.data = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Store.Client
|
||||
*/
|
||||
|
||||
Client.prototype.__proto__ = Store.Client;
|
||||
|
||||
/**
|
||||
* Gets a key
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.get = function (key, fn) {
|
||||
fn(null, this.data[key] === undefined ? null : this.data[key]);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a key
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.set = function (key, value, fn) {
|
||||
this.data[key] = value;
|
||||
fn && fn(null);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Has a key
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.has = function (key, fn) {
|
||||
fn(null, key in this.data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a key
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Client.prototype.del = function (key, fn) {
|
||||
delete this.data[key];
|
||||
fn && fn(null);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys the client.
|
||||
*
|
||||
* @param {Number} number of seconds to expire data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype.destroy = function (expiration) {
|
||||
if ('number' != typeof expiration) {
|
||||
this.data = {};
|
||||
} else {
|
||||
var self = this;
|
||||
|
||||
setTimeout(function () {
|
||||
self.data = {};
|
||||
}, expiration * 1000);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
269
networking/node_modules/socket.io/lib/stores/redis.js
generated
vendored
Normal file
269
networking/node_modules/socket.io/lib/stores/redis.js
generated
vendored
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var crypto = require('crypto')
|
||||
, Store = require('../store')
|
||||
, assert = require('assert');
|
||||
|
||||
/**
|
||||
* Exports the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = Redis;
|
||||
Redis.Client = Client;
|
||||
|
||||
/**
|
||||
* Redis store.
|
||||
* Options:
|
||||
* - nodeId (fn) gets an id that uniquely identifies this node
|
||||
* - redis (fn) redis constructor, defaults to redis
|
||||
* - redisPub (object) options to pass to the pub redis client
|
||||
* - redisSub (object) options to pass to the sub redis client
|
||||
* - redisClient (object) options to pass to the general redis client
|
||||
* - pack (fn) custom packing, defaults to JSON or msgpack if installed
|
||||
* - unpack (fn) custom packing, defaults to JSON or msgpack if installed
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Redis (opts) {
|
||||
opts = opts || {};
|
||||
|
||||
// node id to uniquely identify this node
|
||||
var nodeId = opts.nodeId || function () {
|
||||
// by default, we generate a random id
|
||||
return Math.abs(Math.random() * Math.random() * Date.now() | 0);
|
||||
};
|
||||
|
||||
this.nodeId = nodeId();
|
||||
|
||||
// packing / unpacking mechanism
|
||||
if (opts.pack) {
|
||||
this.pack = opts.pack;
|
||||
this.unpack = opts.unpack;
|
||||
} else {
|
||||
try {
|
||||
var msgpack = require('msgpack');
|
||||
this.pack = msgpack.pack;
|
||||
this.unpack = msgpack.unpack;
|
||||
} catch (e) {
|
||||
this.pack = JSON.stringify;
|
||||
this.unpack = JSON.parse;
|
||||
}
|
||||
}
|
||||
|
||||
var redis = opts.redis || require('redis')
|
||||
, RedisClient = redis.RedisClient;
|
||||
|
||||
// initialize a pubsub client and a regular client
|
||||
if (opts.redisPub instanceof RedisClient) {
|
||||
this.pub = opts.redisPub;
|
||||
} else {
|
||||
opts.redisPub || (opts.redisPub = {});
|
||||
this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
|
||||
}
|
||||
if (opts.redisSub instanceof RedisClient) {
|
||||
this.sub = opts.redisSub;
|
||||
} else {
|
||||
opts.redisSub || (opts.redisSub = {});
|
||||
this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
|
||||
}
|
||||
if (opts.redisClient instanceof RedisClient) {
|
||||
this.cmd = opts.redisClient;
|
||||
} else {
|
||||
opts.redisClient || (opts.redisClient = {});
|
||||
this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
|
||||
}
|
||||
|
||||
Store.call(this, opts);
|
||||
|
||||
this.sub.setMaxListeners(0);
|
||||
this.setMaxListeners(0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Store.
|
||||
*/
|
||||
|
||||
Redis.prototype.__proto__ = Store.prototype;
|
||||
|
||||
/**
|
||||
* Publishes a message.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Redis.prototype.publish = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args }));
|
||||
this.emit.apply(this, ['publish', name].concat(args));
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribes to a channel
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Redis.prototype.subscribe = function (name, consumer, fn) {
|
||||
this.sub.subscribe(name);
|
||||
|
||||
if (consumer || fn) {
|
||||
var self = this;
|
||||
|
||||
self.sub.on('subscribe', function subscribe (ch) {
|
||||
if (name == ch) {
|
||||
function message (ch, msg) {
|
||||
if (name == ch) {
|
||||
msg = self.unpack(msg);
|
||||
|
||||
// we check that the message consumed wasnt emitted by this node
|
||||
if (self.nodeId != msg.nodeId) {
|
||||
consumer.apply(null, msg.args);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.sub.on('message', message);
|
||||
|
||||
self.on('unsubscribe', function unsubscribe (ch) {
|
||||
if (name == ch) {
|
||||
self.sub.removeListener('message', message);
|
||||
self.removeListener('unsubscribe', unsubscribe);
|
||||
}
|
||||
});
|
||||
|
||||
self.sub.removeListener('subscribe', subscribe);
|
||||
|
||||
fn && fn();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('subscribe', name, consumer, fn);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unsubscribes
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Redis.prototype.unsubscribe = function (name, fn) {
|
||||
this.sub.unsubscribe(name);
|
||||
|
||||
if (fn) {
|
||||
var client = this.sub;
|
||||
|
||||
client.on('unsubscribe', function unsubscribe (ch) {
|
||||
if (name == ch) {
|
||||
fn();
|
||||
client.removeListener('unsubscribe', unsubscribe);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('unsubscribe', name, fn);
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys the store
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Redis.prototype.destroy = function () {
|
||||
Store.prototype.destroy.call(this);
|
||||
|
||||
this.pub.end();
|
||||
this.sub.end();
|
||||
this.cmd.end();
|
||||
};
|
||||
|
||||
/**
|
||||
* Client constructor
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function Client (store, id) {
|
||||
Store.Client.call(this, store, id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Store.Client
|
||||
*/
|
||||
|
||||
Client.prototype.__proto__ = Store.Client;
|
||||
|
||||
/**
|
||||
* Redis hash get
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype.get = function (key, fn) {
|
||||
this.store.cmd.hget(this.id, key, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Redis hash set
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype.set = function (key, value, fn) {
|
||||
this.store.cmd.hset(this.id, key, value, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Redis hash del
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype.del = function (key, fn) {
|
||||
this.store.cmd.hdel(this.id, key, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Redis hash has
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype.has = function (key, fn) {
|
||||
this.store.cmd.hexists(this.id, key, function (err, has) {
|
||||
if (err) return fn(err);
|
||||
fn(null, !!has);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys client
|
||||
*
|
||||
* @param {Number} number of seconds to expire data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Client.prototype.destroy = function (expiration) {
|
||||
if ('number' != typeof expiration) {
|
||||
this.store.cmd.del(this.id);
|
||||
} else {
|
||||
this.store.cmd.expire(this.id, expiration);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
534
networking/node_modules/socket.io/lib/transport.js
generated
vendored
Normal file
534
networking/node_modules/socket.io/lib/transport.js
generated
vendored
Normal file
|
|
@ -0,0 +1,534 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var parser = require('./parser');
|
||||
|
||||
/**
|
||||
* Expose the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = Transport;
|
||||
|
||||
/**
|
||||
* Transport constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Transport (mng, data, req) {
|
||||
this.manager = mng;
|
||||
this.id = data.id;
|
||||
this.disconnected = false;
|
||||
this.drained = true;
|
||||
this.handleRequest(req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Access the logger.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Transport.prototype.__defineGetter__('log', function () {
|
||||
return this.manager.log;
|
||||
});
|
||||
|
||||
/**
|
||||
* Access the store.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Transport.prototype.__defineGetter__('store', function () {
|
||||
return this.manager.store;
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles a request when it's set.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.handleRequest = function (req) {
|
||||
this.log.debug('setting request', req.method, req.url);
|
||||
this.req = req;
|
||||
|
||||
if (req.method == 'GET') {
|
||||
this.socket = req.socket;
|
||||
this.open = true;
|
||||
this.drained = true;
|
||||
this.setHeartbeatInterval();
|
||||
|
||||
this.setHandlers();
|
||||
this.onSocketConnect();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a connection is first set.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onSocketConnect = function () { };
|
||||
|
||||
/**
|
||||
* Sets transport handlers
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
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)
|
||||
, error: this.onSocketError.bind(this)
|
||||
, drain: this.onSocketDrain.bind(this)
|
||||
};
|
||||
|
||||
this.socket.on('end', this.bound.end);
|
||||
this.socket.on('close', this.bound.close);
|
||||
this.socket.on('error', this.bound.error);
|
||||
this.socket.on('drain', this.bound.drain);
|
||||
|
||||
this.handlersSet = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes transport handlers
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
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);
|
||||
this.socket.removeListener('drain', this.bound.drain);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the connection dies
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onSocketEnd = function () {
|
||||
this.end('socket end');
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the connection dies
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onSocketClose = function (error) {
|
||||
this.end(error ? 'socket error' : 'socket close');
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the connection has an error.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onSocketError = function (err) {
|
||||
if (this.open) {
|
||||
this.socket.destroy();
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
this.log.info('socket error ' + err.stack);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the connection is drained.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onSocketDrain = function () {
|
||||
this.drained = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called upon receiving a heartbeat packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onHeartbeatClear = function () {
|
||||
this.clearHeartbeatTimeout();
|
||||
this.setHeartbeatInterval();
|
||||
};
|
||||
|
||||
/**
|
||||
* Called upon a forced disconnection.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onForcedDisconnect = function () {
|
||||
if (!this.disconnected) {
|
||||
this.log.info('transport end by forced client disconnection');
|
||||
if (this.open) {
|
||||
this.packet({ type: 'disconnect' });
|
||||
}
|
||||
this.end('booted');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onDispatch = function (packet, volatile) {
|
||||
if (volatile) {
|
||||
this.writeVolatile(packet);
|
||||
} else {
|
||||
this.write(packet);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the close timeout.
|
||||
*/
|
||||
|
||||
Transport.prototype.setCloseTimeout = function () {
|
||||
if (!this.closeTimeout) {
|
||||
var self = this;
|
||||
|
||||
this.closeTimeout = setTimeout(function () {
|
||||
self.log.debug('fired close timeout for client', self.id);
|
||||
self.closeTimeout = null;
|
||||
self.end('close timeout');
|
||||
}, this.manager.get('close timeout') * 1000);
|
||||
|
||||
this.log.debug('set close timeout for client', this.id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the close timeout.
|
||||
*/
|
||||
|
||||
Transport.prototype.clearCloseTimeout = function () {
|
||||
if (this.closeTimeout) {
|
||||
clearTimeout(this.closeTimeout);
|
||||
this.closeTimeout = null;
|
||||
|
||||
this.log.debug('cleared close timeout for client', this.id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the heartbeat timeout
|
||||
*/
|
||||
|
||||
Transport.prototype.setHeartbeatTimeout = function () {
|
||||
if (!this.heartbeatTimeout && this.manager.enabled('heartbeats')) {
|
||||
var self = this;
|
||||
|
||||
this.heartbeatTimeout = setTimeout(function () {
|
||||
self.log.debug('fired heartbeat timeout for client', self.id);
|
||||
self.heartbeatTimeout = null;
|
||||
self.end('heartbeat timeout');
|
||||
}, this.manager.get('heartbeat timeout') * 1000);
|
||||
|
||||
this.log.debug('set heartbeat timeout for client', this.id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the heartbeat timeout
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
|
||||
Transport.prototype.clearHeartbeatTimeout = function () {
|
||||
if (this.heartbeatTimeout && this.manager.enabled('heartbeats')) {
|
||||
clearTimeout(this.heartbeatTimeout);
|
||||
this.heartbeatTimeout = null;
|
||||
this.log.debug('cleared heartbeat timeout for client', this.id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the heartbeat interval. To be called when a connection opens and when
|
||||
* a heartbeat is received.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.setHeartbeatInterval = function () {
|
||||
if (!this.heartbeatInterval && this.manager.enabled('heartbeats')) {
|
||||
var self = this;
|
||||
|
||||
this.heartbeatInterval = setTimeout(function () {
|
||||
self.heartbeat();
|
||||
self.heartbeatInterval = null;
|
||||
}, this.manager.get('heartbeat interval') * 1000);
|
||||
|
||||
this.log.debug('set heartbeat interval for client', this.id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears all timeouts.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.clearTimeouts = function () {
|
||||
this.clearCloseTimeout();
|
||||
this.clearHeartbeatTimeout();
|
||||
this.clearHeartbeatInterval();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a heartbeat
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.heartbeat = function () {
|
||||
if (this.open) {
|
||||
this.log.debug('emitting heartbeat for client', this.id);
|
||||
this.packet({ type: 'heartbeat' });
|
||||
this.setHeartbeatTimeout();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a message.
|
||||
*
|
||||
* @param {Object} packet object
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onMessage = function (packet) {
|
||||
var current = this.manager.transports[this.id];
|
||||
|
||||
if ('heartbeat' == packet.type) {
|
||||
this.log.debug('got heartbeat packet');
|
||||
|
||||
if (current && current.open) {
|
||||
current.onHeartbeatClear();
|
||||
} else {
|
||||
this.store.publish('heartbeat-clear:' + this.id);
|
||||
}
|
||||
} else {
|
||||
if ('disconnect' == packet.type && packet.endpoint == '') {
|
||||
this.log.debug('got disconnection packet');
|
||||
|
||||
if (current) {
|
||||
current.onForcedDisconnect();
|
||||
} else {
|
||||
this.store.publish('disconnect-force:' + this.id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet.id && packet.ack != 'data') {
|
||||
this.log.debug('acknowledging packet automatically');
|
||||
|
||||
var ack = parser.encodePacket({
|
||||
type: 'ack'
|
||||
, ackId: packet.id
|
||||
, endpoint: packet.endpoint || ''
|
||||
});
|
||||
|
||||
if (current && current.open) {
|
||||
current.onDispatch(ack);
|
||||
} else {
|
||||
this.manager.onClientDispatch(this.id, ack);
|
||||
this.store.publish('dispatch:' + this.id, ack);
|
||||
}
|
||||
}
|
||||
|
||||
// handle packet locally or publish it
|
||||
if (current) {
|
||||
this.manager.onClientMessage(this.id, packet);
|
||||
} else {
|
||||
this.store.publish('message:' + this.id, packet);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the heartbeat interval
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.clearHeartbeatInterval = function () {
|
||||
if (this.heartbeatInterval && this.manager.enabled('heartbeats')) {
|
||||
clearTimeout(this.heartbeatInterval);
|
||||
this.heartbeatInterval = null;
|
||||
this.log.debug('cleared heartbeat interval for client', this.id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes the connection and makes sure client doesn't reopen
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.disconnect = function (reason) {
|
||||
this.packet({ type: 'disconnect' });
|
||||
this.end(reason);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.close = function () {
|
||||
if (this.open) {
|
||||
this.doClose();
|
||||
this.onClose();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called upon a connection close.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.onClose = function () {
|
||||
if (this.open) {
|
||||
this.setCloseTimeout();
|
||||
this.clearHandlers();
|
||||
this.open = false;
|
||||
this.manager.onClose(this.id);
|
||||
this.store.publish('close', this.id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cleans up the connection, considers the client disconnected.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.end = function (reason) {
|
||||
if (!this.disconnected) {
|
||||
this.log.info('transport end (' + reason + ')');
|
||||
|
||||
var local = this.manager.transports[this.id];
|
||||
|
||||
this.close();
|
||||
this.clearTimeouts();
|
||||
this.disconnected = true;
|
||||
|
||||
if (local) {
|
||||
this.manager.onClientDisconnect(this.id, reason, true);
|
||||
} else {
|
||||
this.store.publish('disconnect:' + this.id, reason);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Signals that the transport should pause and buffer data.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Transport.prototype.discard = function () {
|
||||
this.log.debug('discarding transport');
|
||||
this.discarded = true;
|
||||
this.clearTimeouts();
|
||||
this.clearHandlers();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes an error packet with the specified reason and advice.
|
||||
*
|
||||
* @param {Number} advice
|
||||
* @param {Number} reason
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Transport.prototype.error = function (reason, advice) {
|
||||
this.packet({
|
||||
type: 'error'
|
||||
, reason: reason
|
||||
, advice: advice
|
||||
});
|
||||
|
||||
this.log.warn(reason, advice ? ('client should ' + advice) : '');
|
||||
this.end('error');
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a packet.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Transport.prototype.packet = function (obj) {
|
||||
return this.write(parser.encodePacket(obj));
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a volatile message.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Transport.prototype.writeVolatile = function (msg) {
|
||||
if (this.open) {
|
||||
if (this.drained) {
|
||||
this.write(msg);
|
||||
} else {
|
||||
this.log.debug('ignoring volatile packet, buffer not drained');
|
||||
}
|
||||
} else {
|
||||
this.log.debug('ignoring volatile packet, transport not open');
|
||||
}
|
||||
};
|
||||
106
networking/node_modules/socket.io/lib/transports/flashsocket.js
generated
vendored
Normal file
106
networking/node_modules/socket.io/lib/transports/flashsocket.js
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
var WebSocket = require('./websocket');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = FlashSocket;
|
||||
|
||||
/**
|
||||
* The FlashSocket transport is just a proxy
|
||||
* for WebSocket connections.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function FlashSocket (mng, data, req) {
|
||||
return WebSocket.call(this, mng, data, req);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherits from WebSocket.
|
||||
*/
|
||||
|
||||
FlashSocket.prototype.__proto__ = WebSocket.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
FlashSocket.prototype.name = 'flashsocket';
|
||||
|
||||
/**
|
||||
* Listens for new configuration changes of the Manager
|
||||
* this way we can enable and disable the flash server.
|
||||
*
|
||||
* @param {Manager} Manager instance.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
|
||||
FlashSocket.init = function (manager) {
|
||||
var server;
|
||||
function create () {
|
||||
server = require('policyfile').createServer({
|
||||
log: function(msg){
|
||||
manager.log.info(msg.toLowerCase());
|
||||
}
|
||||
}, manager.get('origins'));
|
||||
|
||||
server.on('close', function (e) {
|
||||
server = null;
|
||||
});
|
||||
|
||||
server.listen(manager.get('flash policy port'), manager.server);
|
||||
|
||||
manager.flashPolicyServer = server;
|
||||
}
|
||||
|
||||
// listen for origin changes, so we can update the server
|
||||
manager.on('set:origins', function (value, key) {
|
||||
if (!server) return;
|
||||
|
||||
// update the origins and compile a new response buffer
|
||||
server.origins = Array.isArray(value) ? value : [value];
|
||||
server.compile();
|
||||
});
|
||||
|
||||
// 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();
|
||||
}
|
||||
});
|
||||
|
||||
// only start the server
|
||||
manager.on('set:transports', function (value, key){
|
||||
if (!server && ~manager.get('transports').indexOf('flashsocket')) {
|
||||
create();
|
||||
}
|
||||
});
|
||||
// check if we need to initialize at start
|
||||
if (~manager.get('transports').indexOf('flashsocket')){
|
||||
create();
|
||||
}
|
||||
};
|
||||
82
networking/node_modules/socket.io/lib/transports/htmlfile.js
generated
vendored
Normal file
82
networking/node_modules/socket.io/lib/transports/htmlfile.js
generated
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var HTTPTransport = require('./http');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = HTMLFile;
|
||||
|
||||
/**
|
||||
* HTMLFile transport constructor.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function HTMLFile (mng, data, req) {
|
||||
HTTPTransport.call(this, mng, data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Transport.
|
||||
*/
|
||||
|
||||
HTMLFile.prototype.__proto__ = HTTPTransport.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
HTMLFile.prototype.name = 'htmlfile';
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTMLFile.prototype.handleRequest = function (req) {
|
||||
HTTPTransport.prototype.handleRequest.call(this, req);
|
||||
|
||||
if (req.method == 'GET') {
|
||||
req.res.writeHead(200, {
|
||||
'Content-Type': 'text/html; charset=UTF-8'
|
||||
, 'Connection': 'keep-alive'
|
||||
, 'Transfer-Encoding': 'chunked'
|
||||
});
|
||||
|
||||
req.res.write(
|
||||
'<html><body>'
|
||||
+ '<script>var _ = function (msg) { parent.s._(msg, document); };</script>'
|
||||
+ new Array(174).join(' ')
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the write.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTMLFile.prototype.write = function (data) {
|
||||
data = '<script>_(' + JSON.stringify(data) + ');</script>';
|
||||
|
||||
if (this.response.write(data)) {
|
||||
this.drained = true;
|
||||
}
|
||||
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
};
|
||||
147
networking/node_modules/socket.io/lib/transports/http-polling.js
generated
vendored
Normal file
147
networking/node_modules/socket.io/lib/transports/http-polling.js
generated
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var HTTPTransport = require('./http');
|
||||
|
||||
/**
|
||||
* Exports the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = HTTPPolling;
|
||||
|
||||
/**
|
||||
* HTTP polling constructor.
|
||||
*
|
||||
* @api public.
|
||||
*/
|
||||
|
||||
function HTTPPolling (mng, data, req) {
|
||||
HTTPTransport.call(this, mng, data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from HTTPTransport.
|
||||
*
|
||||
* @api public.
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.__proto__ = HTTPTransport.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.setHeartbeatInterval = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a request
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.handleRequest = function (req) {
|
||||
HTTPTransport.prototype.handleRequest.call(this, req);
|
||||
|
||||
if (req.method == 'GET') {
|
||||
var self = this;
|
||||
|
||||
this.pollTimeout = setTimeout(function () {
|
||||
self.packet({ type: 'noop' });
|
||||
self.log.debug(self.name + ' closed due to exceeded duration');
|
||||
}, this.manager.get('polling duration') * 1000);
|
||||
|
||||
this.log.debug('setting poll timeout');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears polling timeout
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.clearPollTimeout = function () {
|
||||
if (this.pollTimeout) {
|
||||
clearTimeout(this.pollTimeout);
|
||||
this.pollTimeout = null;
|
||||
this.log.debug('clearing poll timeout');
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Override clear timeouts to clear the poll timeout
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.clearTimeouts = function () {
|
||||
HTTPTransport.prototype.clearTimeouts.call(this);
|
||||
|
||||
this.clearPollTimeout();
|
||||
};
|
||||
|
||||
/**
|
||||
* doWrite to clear poll timeout
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.doWrite = function () {
|
||||
this.clearPollTimeout();
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a write.
|
||||
*
|
||||
* @api private.
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.write = function (data, close) {
|
||||
this.doWrite(data);
|
||||
this.response.end();
|
||||
this.onClose();
|
||||
};
|
||||
|
||||
/**
|
||||
* Override end.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPPolling.prototype.end = function (reason) {
|
||||
this.clearPollTimeout();
|
||||
return HTTPTransport.prototype.end.call(this, reason);
|
||||
};
|
||||
|
||||
119
networking/node_modules/socket.io/lib/transports/http.js
generated
vendored
Normal file
119
networking/node_modules/socket.io/lib/transports/http.js
generated
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var Transport = require('../transport')
|
||||
, parser = require('../parser')
|
||||
, qs = require('querystring');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = HTTPTransport;
|
||||
|
||||
/**
|
||||
* HTTP interface constructor. For all non-websocket transports.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function HTTPTransport (mng, data, req) {
|
||||
Transport.call(this, mng, data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Transport.
|
||||
*/
|
||||
|
||||
HTTPTransport.prototype.__proto__ = Transport.prototype;
|
||||
|
||||
/**
|
||||
* Handles a request.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPTransport.prototype.handleRequest = function (req) {
|
||||
if (req.method == 'POST') {
|
||||
var buffer = ''
|
||||
, res = req.res
|
||||
, origin = req.headers.origin
|
||||
, 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 () {
|
||||
res.writeHead(200, headers);
|
||||
res.end('1');
|
||||
|
||||
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'] = origin;
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
} else {
|
||||
this.response = req.res;
|
||||
|
||||
Transport.prototype.handleRequest.call(this, req);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles data payload.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPTransport.prototype.onData = function (data) {
|
||||
var messages = parser.decodePayload(data);
|
||||
this.log.debug(this.name + ' received data packet', data);
|
||||
|
||||
for (var i = 0, l = messages.length; i < l; i++) {
|
||||
this.onMessage(messages[i]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the request-response cycle
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPTransport.prototype.doClose = function () {
|
||||
this.response.end();
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a payload of messages
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
HTTPTransport.prototype.payload = function (msgs) {
|
||||
this.write(parser.encodePayload(msgs));
|
||||
};
|
||||
12
networking/node_modules/socket.io/lib/transports/index.js
generated
vendored
Normal file
12
networking/node_modules/socket.io/lib/transports/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
/**
|
||||
* Export transports.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
websocket: require('./websocket')
|
||||
, flashsocket: require('./flashsocket')
|
||||
, htmlfile: require('./htmlfile')
|
||||
, 'xhr-polling': require('./xhr-polling')
|
||||
, 'jsonp-polling': require('./jsonp-polling')
|
||||
};
|
||||
97
networking/node_modules/socket.io/lib/transports/jsonp-polling.js
generated
vendored
Normal file
97
networking/node_modules/socket.io/lib/transports/jsonp-polling.js
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var HTTPPolling = require('./http-polling');
|
||||
var jsonpolling_re = /^\d+$/
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = JSONPPolling;
|
||||
|
||||
/**
|
||||
* JSON-P polling transport.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function JSONPPolling (mng, data, req) {
|
||||
HTTPPolling.call(this, mng, data, req);
|
||||
|
||||
this.head = 'io.j[0](';
|
||||
this.foot = ');';
|
||||
|
||||
if (data.query.i && jsonpolling_re.test(data.query.i)) {
|
||||
this.head = 'io.j[' + data.query.i + '](';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Transport.
|
||||
*/
|
||||
|
||||
JSONPPolling.prototype.__proto__ = HTTPPolling.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
JSONPPolling.prototype.name = 'jsonppolling';
|
||||
|
||||
/**
|
||||
* Make sure POST are decoded.
|
||||
*/
|
||||
|
||||
JSONPPolling.prototype.postEncoded = true;
|
||||
|
||||
/**
|
||||
* Handles incoming data.
|
||||
* Due to a bug in \n handling by browsers, we expect a JSONified string.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
JSONPPolling.prototype.onData = function (data) {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {
|
||||
this.error('parse', 'reconnect');
|
||||
return;
|
||||
}
|
||||
|
||||
HTTPPolling.prototype.onData.call(this, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the write.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
JSONPPolling.prototype.doWrite = function (data) {
|
||||
HTTPPolling.prototype.doWrite.call(this);
|
||||
|
||||
var data = data === undefined
|
||||
? '' : this.head + JSON.stringify(data) + this.foot;
|
||||
|
||||
this.response.writeHead(200, {
|
||||
'Content-Type': 'text/javascript; charset=UTF-8'
|
||||
, 'Content-Length': Buffer.byteLength(data)
|
||||
, 'Connection': 'Keep-Alive'
|
||||
, 'X-XSS-Protection': '0'
|
||||
});
|
||||
|
||||
this.response.write(data);
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
};
|
||||
36
networking/node_modules/socket.io/lib/transports/websocket.js
generated
vendored
Normal file
36
networking/node_modules/socket.io/lib/transports/websocket.js
generated
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var protocolVersions = require('./websocket/');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = WebSocket;
|
||||
|
||||
/**
|
||||
* HTTP interface constructor. Interface compatible with all transports that
|
||||
* depend on request-response cycles.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function WebSocket (mng, data, req) {
|
||||
var transport
|
||||
, version = req.headers['sec-websocket-version'];
|
||||
if (typeof version !== 'undefined' && typeof protocolVersions[version] !== 'undefined') {
|
||||
transport = new protocolVersions[version](mng, data, req);
|
||||
}
|
||||
else transport = new protocolVersions['default'](mng, data, req);
|
||||
if (typeof this.name !== 'undefined') transport.name = this.name;
|
||||
return transport;
|
||||
};
|
||||
360
networking/node_modules/socket.io/lib/transports/websocket/default.js
generated
vendored
Normal file
360
networking/node_modules/socket.io/lib/transports/websocket/default.js
generated
vendored
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var Transport = require('../../transport')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, crypto = require('crypto')
|
||||
, parser = require('../../parser');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = WebSocket;
|
||||
|
||||
/**
|
||||
* HTTP interface constructor. Interface compatible with all transports that
|
||||
* depend on request-response cycles.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function WebSocket (mng, data, req) {
|
||||
// parser
|
||||
var self = this;
|
||||
|
||||
this.parser = new Parser();
|
||||
this.parser.on('data', function (packet) {
|
||||
self.log.debug(self.name + ' received data packet', packet);
|
||||
self.onMessage(parser.decodePacket(packet));
|
||||
});
|
||||
this.parser.on('close', function () {
|
||||
self.end();
|
||||
});
|
||||
this.parser.on('error', function () {
|
||||
self.end();
|
||||
});
|
||||
|
||||
Transport.call(this, mng, data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Transport.
|
||||
*/
|
||||
|
||||
WebSocket.prototype.__proto__ = Transport.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
WebSocket.prototype.name = 'websocket';
|
||||
|
||||
/**
|
||||
* Websocket draft version
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
WebSocket.prototype.protocolVersion = 'hixie-76';
|
||||
|
||||
/**
|
||||
* Called when the socket connects.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.onSocketConnect = function () {
|
||||
var self = this;
|
||||
|
||||
this.socket.setNoDelay(true);
|
||||
|
||||
this.buffer = true;
|
||||
this.buffered = [];
|
||||
|
||||
if (this.req.headers.upgrade !== 'WebSocket') {
|
||||
this.log.warn(this.name + ' connection invalid');
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
, waitingForNonce = false;
|
||||
|
||||
if (this.req.headers['sec-websocket-key1']) {
|
||||
// If we don't have the nonce yet, wait for it (HAProxy compatibility).
|
||||
if (! (this.req.head && this.req.head.length >= 8)) {
|
||||
waitingForNonce = true;
|
||||
}
|
||||
|
||||
var headers = [
|
||||
'HTTP/1.1 101 WebSocket Protocol Handshake'
|
||||
, 'Upgrade: WebSocket'
|
||||
, 'Connection: Upgrade'
|
||||
, 'Sec-WebSocket-Origin: ' + origin
|
||||
, 'Sec-WebSocket-Location: ' + location
|
||||
];
|
||||
|
||||
if (this.req.headers['sec-websocket-protocol']){
|
||||
headers.push('Sec-WebSocket-Protocol: '
|
||||
+ this.req.headers['sec-websocket-protocol']);
|
||||
}
|
||||
} else {
|
||||
var headers = [
|
||||
'HTTP/1.1 101 Web Socket Protocol Handshake'
|
||||
, 'Upgrade: WebSocket'
|
||||
, 'Connection: Upgrade'
|
||||
, 'WebSocket-Origin: ' + origin
|
||||
, 'WebSocket-Location: ' + location
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
this.socket.write(headers.concat('', '').join('\r\n'));
|
||||
this.socket.setTimeout(0);
|
||||
this.socket.setNoDelay(true);
|
||||
this.socket.setEncoding('utf8');
|
||||
} catch (e) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (waitingForNonce) {
|
||||
this.socket.setEncoding('binary');
|
||||
} else if (this.proveReception(headers)) {
|
||||
self.flush();
|
||||
}
|
||||
|
||||
var headBuffer = '';
|
||||
|
||||
this.socket.on('data', function (data) {
|
||||
if (waitingForNonce) {
|
||||
headBuffer += data;
|
||||
|
||||
if (headBuffer.length < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Restore the connection to utf8 encoding after receiving the nonce
|
||||
self.socket.setEncoding('utf8');
|
||||
waitingForNonce = false;
|
||||
|
||||
// Stuff the nonce into the location where it's expected to be
|
||||
self.req.head = headBuffer.substr(0, 8);
|
||||
headBuffer = '';
|
||||
|
||||
if (self.proveReception(headers)) {
|
||||
self.flush();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
self.parser.add(data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes to the socket.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.write = function (data) {
|
||||
if (this.open) {
|
||||
this.drained = false;
|
||||
|
||||
if (this.buffer) {
|
||||
this.buffered.push(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
var length = Buffer.byteLength(data)
|
||||
, buffer = new Buffer(2 + length);
|
||||
|
||||
buffer.write('\x00', 'binary');
|
||||
buffer.write(data, 1, 'utf8');
|
||||
buffer.write('\xff', 1 + length, 'binary');
|
||||
|
||||
try {
|
||||
if (this.socket.write(buffer)) {
|
||||
this.drained = true;
|
||||
}
|
||||
} catch (e) {
|
||||
this.end();
|
||||
}
|
||||
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Flushes the internal buffer
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.flush = function () {
|
||||
this.buffer = false;
|
||||
|
||||
for (var i = 0, l = this.buffered.length; i < l; i++) {
|
||||
this.write(this.buffered.splice(0, 1)[0]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes the handshake.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.proveReception = function (headers) {
|
||||
var self = this
|
||||
, k1 = this.req.headers['sec-websocket-key1']
|
||||
, k2 = this.req.headers['sec-websocket-key2'];
|
||||
|
||||
if (k1 && k2){
|
||||
var md5 = crypto.createHash('md5');
|
||||
|
||||
[k1, k2].forEach(function (k) {
|
||||
var n = parseInt(k.replace(/[^\d]/g, ''))
|
||||
, spaces = k.replace(/[^ ]/g, '').length;
|
||||
|
||||
if (spaces === 0 || n % spaces !== 0){
|
||||
self.log.warn('Invalid ' + self.name + ' key: "' + k + '".');
|
||||
self.end();
|
||||
return false;
|
||||
}
|
||||
|
||||
n /= spaces;
|
||||
|
||||
md5.update(String.fromCharCode(
|
||||
n >> 24 & 0xFF,
|
||||
n >> 16 & 0xFF,
|
||||
n >> 8 & 0xFF,
|
||||
n & 0xFF));
|
||||
});
|
||||
|
||||
md5.update(this.req.head.toString('binary'));
|
||||
|
||||
try {
|
||||
this.socket.write(md5.digest('binary'), 'binary');
|
||||
} catch (e) {
|
||||
this.end();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a payload.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.payload = function (msgs) {
|
||||
for (var i = 0, l = msgs.length; i < l; i++) {
|
||||
this.write(msgs[i]);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.doClose = function () {
|
||||
this.socket.end();
|
||||
};
|
||||
|
||||
/**
|
||||
* WebSocket parser
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Parser () {
|
||||
this.buffer = '';
|
||||
this.i = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from EventEmitter.
|
||||
*/
|
||||
|
||||
Parser.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Adds data to the buffer.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Parser.prototype.add = function (data) {
|
||||
this.buffer += data;
|
||||
this.parse();
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses the buffer.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.parse = function () {
|
||||
for (var i = this.i, chr, l = this.buffer.length; i < l; i++){
|
||||
chr = this.buffer[i];
|
||||
|
||||
if (this.buffer.length == 2 && this.buffer[1] == '\u0000') {
|
||||
this.emit('close');
|
||||
this.buffer = '';
|
||||
this.i = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (i === 0){
|
||||
if (chr != '\u0000')
|
||||
this.error('Bad framing. Expected null byte as first frame');
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chr == '\ufffd'){
|
||||
this.emit('data', this.buffer.substr(1, i - 1));
|
||||
this.buffer = this.buffer.substr(i + 1);
|
||||
this.i = 0;
|
||||
return this.parse();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles an error
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.error = function (reason) {
|
||||
this.buffer = '';
|
||||
this.i = 0;
|
||||
this.emit('error', reason);
|
||||
return this;
|
||||
};
|
||||
622
networking/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js
generated
vendored
Normal file
622
networking/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js
generated
vendored
Normal file
|
|
@ -0,0 +1,622 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var Transport = require('../../transport')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, crypto = require('crypto')
|
||||
, url = require('url')
|
||||
, parser = require('../../parser')
|
||||
, util = require('../../util');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = WebSocket;
|
||||
exports.Parser = Parser;
|
||||
|
||||
/**
|
||||
* HTTP interface constructor. Interface compatible with all transports that
|
||||
* depend on request-response cycles.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function WebSocket (mng, data, req) {
|
||||
// parser
|
||||
var self = this;
|
||||
|
||||
this.manager = mng;
|
||||
this.parser = new Parser();
|
||||
this.parser.on('data', function (packet) {
|
||||
self.onMessage(parser.decodePacket(packet));
|
||||
});
|
||||
this.parser.on('ping', function () {
|
||||
// version 8 ping => pong
|
||||
try {
|
||||
self.socket.write('\u008a\u0000');
|
||||
}
|
||||
catch (e) {
|
||||
self.end();
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.parser.on('close', function () {
|
||||
self.end();
|
||||
});
|
||||
this.parser.on('error', function (reason) {
|
||||
self.log.warn(self.name + ' parser error: ' + reason);
|
||||
self.end();
|
||||
});
|
||||
|
||||
Transport.call(this, mng, data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Transport.
|
||||
*/
|
||||
|
||||
WebSocket.prototype.__proto__ = Transport.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
WebSocket.prototype.name = 'websocket';
|
||||
|
||||
/**
|
||||
* Websocket draft version
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
WebSocket.prototype.protocolVersion = '07-12';
|
||||
|
||||
/**
|
||||
* Called when the socket connects.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.onSocketConnect = function () {
|
||||
var self = this;
|
||||
|
||||
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.manager.settings['match origin protocol'] ?
|
||||
origin.match(/^https/) : this.socket.encrypted) ?
|
||||
'wss' : 'ws')
|
||||
+ '://' + this.req.headers.host + this.req.url;
|
||||
|
||||
if (!this.verifyOrigin(origin)) {
|
||||
this.log.warn(this.name + ' connection invalid: origin mismatch');
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.req.headers['sec-websocket-key']) {
|
||||
this.log.warn(this.name + ' connection invalid: received no key');
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// calc key
|
||||
var key = this.req.headers['sec-websocket-key'];
|
||||
var shasum = crypto.createHash('sha1');
|
||||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
key = shasum.digest('base64');
|
||||
|
||||
var headers = [
|
||||
'HTTP/1.1 101 Switching Protocols'
|
||||
, 'Upgrade: websocket'
|
||||
, 'Connection: Upgrade'
|
||||
, 'Sec-WebSocket-Accept: ' + key
|
||||
];
|
||||
|
||||
try {
|
||||
this.socket.write(headers.concat('', '').join('\r\n'));
|
||||
this.socket.setTimeout(0);
|
||||
this.socket.setNoDelay(true);
|
||||
} catch (e) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
this.socket.on('data', function (data) {
|
||||
self.parser.add(data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies the origin of a request.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.verifyOrigin = function (origin) {
|
||||
var origins = this.manager.get('origins');
|
||||
|
||||
if (origin === 'null') origin = '*';
|
||||
|
||||
if (origins.indexOf('*:*') !== -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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 + ':*') ||
|
||||
~origins.indexOf('*:' + parts.port);
|
||||
if (!ok) this.log.warn('illegal origin: ' + origin);
|
||||
return ok;
|
||||
} catch (ex) {
|
||||
this.log.warn('error parsing origin');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.log.warn('origin missing from websocket call, yet required by config');
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes to the socket.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.write = function (data) {
|
||||
if (this.open) {
|
||||
var buf = this.frame(0x81, data);
|
||||
try {
|
||||
this.socket.write(buf, 'binary');
|
||||
}
|
||||
catch (e) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a payload.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.payload = function (msgs) {
|
||||
for (var i = 0, l = msgs.length; i < l; i++) {
|
||||
this.write(msgs[i]);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Frame server-to-client output as a text packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.frame = function (opcode, str) {
|
||||
var dataBuffer = new Buffer(str)
|
||||
, dataLength = dataBuffer.length
|
||||
, startOffset = 2
|
||||
, secondByte = dataLength;
|
||||
if (dataLength > 65536) {
|
||||
startOffset = 10;
|
||||
secondByte = 127;
|
||||
}
|
||||
else if (dataLength > 125) {
|
||||
startOffset = 4;
|
||||
secondByte = 126;
|
||||
}
|
||||
var outputBuffer = new Buffer(dataLength + startOffset);
|
||||
outputBuffer[0] = opcode;
|
||||
outputBuffer[1] = secondByte;
|
||||
dataBuffer.copy(outputBuffer, startOffset);
|
||||
switch (secondByte) {
|
||||
case 126:
|
||||
outputBuffer[2] = dataLength >>> 8;
|
||||
outputBuffer[3] = dataLength % 256;
|
||||
break;
|
||||
case 127:
|
||||
var l = dataLength;
|
||||
for (var i = 1; i <= 8; ++i) {
|
||||
outputBuffer[startOffset - i] = l & 0xff;
|
||||
l >>>= 8;
|
||||
}
|
||||
}
|
||||
return outputBuffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.doClose = function () {
|
||||
this.socket.end();
|
||||
};
|
||||
|
||||
/**
|
||||
* WebSocket parser
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Parser () {
|
||||
this.state = {
|
||||
activeFragmentedOperation: null,
|
||||
lastFragment: false,
|
||||
masked: false,
|
||||
opcode: 0
|
||||
};
|
||||
this.overflow = null;
|
||||
this.expectOffset = 0;
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
this.currentMessage = '';
|
||||
|
||||
var self = this;
|
||||
this.opcodeHandlers = {
|
||||
// text
|
||||
'1': function(data) {
|
||||
var finish = function(mask, data) {
|
||||
self.currentMessage += self.unmask(mask, data);
|
||||
if (self.state.lastFragment) {
|
||||
self.emit('data', self.currentMessage);
|
||||
self.currentMessage = '';
|
||||
}
|
||||
self.endPacket();
|
||||
}
|
||||
|
||||
var expectData = function(length) {
|
||||
if (self.state.masked) {
|
||||
self.expect('Mask', 4, function(data) {
|
||||
var mask = data;
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(mask, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(null, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// decode length
|
||||
var firstLength = data[1] & 0x7f;
|
||||
if (firstLength < 126) {
|
||||
expectData(firstLength);
|
||||
}
|
||||
else if (firstLength == 126) {
|
||||
self.expect('Length', 2, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
else if (firstLength == 127) {
|
||||
self.expect('Length', 8, function(data) {
|
||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
||||
return;
|
||||
}
|
||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
},
|
||||
// binary
|
||||
'2': function(data) {
|
||||
var finish = function(mask, data) {
|
||||
if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list
|
||||
self.currentMessage.push(self.unmask(mask, data, true));
|
||||
if (self.state.lastFragment) {
|
||||
self.emit('binary', self.concatBuffers(self.currentMessage));
|
||||
self.currentMessage = '';
|
||||
}
|
||||
self.endPacket();
|
||||
}
|
||||
|
||||
var expectData = function(length) {
|
||||
if (self.state.masked) {
|
||||
self.expect('Mask', 4, function(data) {
|
||||
var mask = data;
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(mask, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(null, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// decode length
|
||||
var firstLength = data[1] & 0x7f;
|
||||
if (firstLength < 126) {
|
||||
expectData(firstLength);
|
||||
}
|
||||
else if (firstLength == 126) {
|
||||
self.expect('Length', 2, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
else if (firstLength == 127) {
|
||||
self.expect('Length', 8, function(data) {
|
||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
||||
return;
|
||||
}
|
||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
},
|
||||
// close
|
||||
'8': function(data) {
|
||||
self.emit('close');
|
||||
self.reset();
|
||||
},
|
||||
// ping
|
||||
'9': function(data) {
|
||||
if (self.state.lastFragment == false) {
|
||||
self.error('fragmented ping is not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
var finish = function(mask, data) {
|
||||
self.emit('ping', self.unmask(mask, data));
|
||||
self.endPacket();
|
||||
}
|
||||
|
||||
var expectData = function(length) {
|
||||
if (self.state.masked) {
|
||||
self.expect('Mask', 4, function(data) {
|
||||
var mask = data;
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(mask, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(null, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// decode length
|
||||
var firstLength = data[1] & 0x7f;
|
||||
if (firstLength == 0) {
|
||||
finish(null, null);
|
||||
}
|
||||
else if (firstLength < 126) {
|
||||
expectData(firstLength);
|
||||
}
|
||||
else if (firstLength == 126) {
|
||||
self.expect('Length', 2, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
else if (firstLength == 127) {
|
||||
self.expect('Length', 8, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.expect('Opcode', 2, this.processPacket);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from EventEmitter.
|
||||
*/
|
||||
|
||||
Parser.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Add new data to the parser.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Parser.prototype.add = function(data) {
|
||||
if (this.expectBuffer == null) {
|
||||
this.addToOverflow(data);
|
||||
return;
|
||||
}
|
||||
var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset);
|
||||
data.copy(this.expectBuffer, this.expectOffset, 0, toRead);
|
||||
this.expectOffset += toRead;
|
||||
if (toRead < data.length) {
|
||||
// at this point the overflow buffer shouldn't at all exist
|
||||
this.overflow = new Buffer(data.length - toRead);
|
||||
data.copy(this.overflow, 0, toRead, toRead + this.overflow.length);
|
||||
}
|
||||
if (this.expectOffset == this.expectBuffer.length) {
|
||||
var bufferForHandler = this.expectBuffer;
|
||||
this.expectBuffer = null;
|
||||
this.expectOffset = 0;
|
||||
this.expectHandler.call(this, bufferForHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a piece of data to the overflow.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.addToOverflow = function(data) {
|
||||
if (this.overflow == null) this.overflow = data;
|
||||
else {
|
||||
var prevOverflow = this.overflow;
|
||||
this.overflow = new Buffer(this.overflow.length + data.length);
|
||||
prevOverflow.copy(this.overflow, 0);
|
||||
data.copy(this.overflow, prevOverflow.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a certain amount of bytes to be available, then fires a callback.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.expect = function(what, length, handler) {
|
||||
this.expectBuffer = new Buffer(length);
|
||||
this.expectOffset = 0;
|
||||
this.expectHandler = handler;
|
||||
if (this.overflow != null) {
|
||||
var toOverflow = this.overflow;
|
||||
this.overflow = null;
|
||||
this.add(toOverflow);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start processing a new packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.processPacket = function (data) {
|
||||
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;
|
||||
if (opcode == 0) {
|
||||
// continuation frame
|
||||
this.state.opcode = this.state.activeFragmentedOperation;
|
||||
if (!(this.state.opcode == 1 || this.state.opcode == 2)) {
|
||||
this.error('continuation frame cannot follow current opcode')
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.state.opcode = opcode;
|
||||
if (this.state.lastFragment === false) {
|
||||
this.state.activeFragmentedOperation = opcode;
|
||||
}
|
||||
}
|
||||
var handler = this.opcodeHandlers[this.state.opcode];
|
||||
if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode);
|
||||
else handler(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Endprocessing a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.endPacket = function() {
|
||||
this.expectOffset = 0;
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) {
|
||||
// end current fragmented operation
|
||||
this.state.activeFragmentedOperation = null;
|
||||
}
|
||||
this.state.lastFragment = false;
|
||||
this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0;
|
||||
this.state.masked = false;
|
||||
this.expect('Opcode', 2, this.processPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the parser state.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.reset = function() {
|
||||
this.state = {
|
||||
activeFragmentedOperation: null,
|
||||
lastFragment: false,
|
||||
masked: false,
|
||||
opcode: 0
|
||||
};
|
||||
this.expectOffset = 0;
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
this.overflow = null;
|
||||
this.currentMessage = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmask received data.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.unmask = function (mask, buf, binary) {
|
||||
if (mask != null) {
|
||||
for (var i = 0, ll = buf.length; i < ll; i++) {
|
||||
buf[i] ^= mask[i % 4];
|
||||
}
|
||||
}
|
||||
if (binary) return buf;
|
||||
return buf != null ? buf.toString('utf8') : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates a list of buffers.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.concatBuffers = function(buffers) {
|
||||
var length = 0;
|
||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
||||
length += buffers[i].length;
|
||||
}
|
||||
var mergedBuffer = new Buffer(length);
|
||||
var offset = 0;
|
||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
||||
buffers[i].copy(mergedBuffer, offset);
|
||||
offset += buffers[i].length;
|
||||
}
|
||||
return mergedBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an error
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.error = function (reason) {
|
||||
this.reset();
|
||||
this.emit('error', reason);
|
||||
return this;
|
||||
};
|
||||
622
networking/node_modules/socket.io/lib/transports/websocket/hybi-16.js
generated
vendored
Normal file
622
networking/node_modules/socket.io/lib/transports/websocket/hybi-16.js
generated
vendored
Normal file
|
|
@ -0,0 +1,622 @@
|
|||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var Transport = require('../../transport')
|
||||
, EventEmitter = process.EventEmitter
|
||||
, crypto = require('crypto')
|
||||
, url = require('url')
|
||||
, parser = require('../../parser')
|
||||
, util = require('../../util');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = WebSocket;
|
||||
exports.Parser = Parser;
|
||||
|
||||
/**
|
||||
* HTTP interface constructor. Interface compatible with all transports that
|
||||
* depend on request-response cycles.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function WebSocket (mng, data, req) {
|
||||
// parser
|
||||
var self = this;
|
||||
|
||||
this.manager = mng;
|
||||
this.parser = new Parser();
|
||||
this.parser.on('data', function (packet) {
|
||||
self.onMessage(parser.decodePacket(packet));
|
||||
});
|
||||
this.parser.on('ping', function () {
|
||||
// version 8 ping => pong
|
||||
try {
|
||||
self.socket.write('\u008a\u0000');
|
||||
}
|
||||
catch (e) {
|
||||
self.end();
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.parser.on('close', function () {
|
||||
self.end();
|
||||
});
|
||||
this.parser.on('error', function (reason) {
|
||||
self.log.warn(self.name + ' parser error: ' + reason);
|
||||
self.end();
|
||||
});
|
||||
|
||||
Transport.call(this, mng, data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Transport.
|
||||
*/
|
||||
|
||||
WebSocket.prototype.__proto__ = Transport.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
WebSocket.prototype.name = 'websocket';
|
||||
|
||||
/**
|
||||
* Websocket draft version
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
WebSocket.prototype.protocolVersion = '16';
|
||||
|
||||
/**
|
||||
* Called when the socket connects.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.onSocketConnect = function () {
|
||||
var self = this;
|
||||
|
||||
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.manager.settings['match origin protocol'] ?
|
||||
origin.match(/^https/) : this.socket.encrypted) ?
|
||||
'wss' : 'ws')
|
||||
+ '://' + this.req.headers.host + this.req.url;
|
||||
|
||||
if (!this.verifyOrigin(origin)) {
|
||||
this.log.warn(this.name + ' connection invalid: origin mismatch');
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.req.headers['sec-websocket-key']) {
|
||||
this.log.warn(this.name + ' connection invalid: received no key');
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// calc key
|
||||
var key = this.req.headers['sec-websocket-key'];
|
||||
var shasum = crypto.createHash('sha1');
|
||||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
key = shasum.digest('base64');
|
||||
|
||||
var headers = [
|
||||
'HTTP/1.1 101 Switching Protocols'
|
||||
, 'Upgrade: websocket'
|
||||
, 'Connection: Upgrade'
|
||||
, 'Sec-WebSocket-Accept: ' + key
|
||||
];
|
||||
|
||||
try {
|
||||
this.socket.write(headers.concat('', '').join('\r\n'));
|
||||
this.socket.setTimeout(0);
|
||||
this.socket.setNoDelay(true);
|
||||
} catch (e) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
this.socket.on('data', function (data) {
|
||||
self.parser.add(data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies the origin of a request.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.verifyOrigin = function (origin) {
|
||||
var origins = this.manager.get('origins');
|
||||
|
||||
if (origin === 'null') origin = '*';
|
||||
|
||||
if (origins.indexOf('*:*') !== -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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 + ':*') ||
|
||||
~origins.indexOf('*:' + parts.port);
|
||||
if (!ok) this.log.warn('illegal origin: ' + origin);
|
||||
return ok;
|
||||
} catch (ex) {
|
||||
this.log.warn('error parsing origin');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.log.warn('origin missing from websocket call, yet required by config');
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes to the socket.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.write = function (data) {
|
||||
if (this.open) {
|
||||
var buf = this.frame(0x81, data);
|
||||
try {
|
||||
this.socket.write(buf, 'binary');
|
||||
}
|
||||
catch (e) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a payload.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.payload = function (msgs) {
|
||||
for (var i = 0, l = msgs.length; i < l; i++) {
|
||||
this.write(msgs[i]);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Frame server-to-client output as a text packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.frame = function (opcode, str) {
|
||||
var dataBuffer = new Buffer(str)
|
||||
, dataLength = dataBuffer.length
|
||||
, startOffset = 2
|
||||
, secondByte = dataLength;
|
||||
if (dataLength > 65536) {
|
||||
startOffset = 10;
|
||||
secondByte = 127;
|
||||
}
|
||||
else if (dataLength > 125) {
|
||||
startOffset = 4;
|
||||
secondByte = 126;
|
||||
}
|
||||
var outputBuffer = new Buffer(dataLength + startOffset);
|
||||
outputBuffer[0] = opcode;
|
||||
outputBuffer[1] = secondByte;
|
||||
dataBuffer.copy(outputBuffer, startOffset);
|
||||
switch (secondByte) {
|
||||
case 126:
|
||||
outputBuffer[2] = dataLength >>> 8;
|
||||
outputBuffer[3] = dataLength % 256;
|
||||
break;
|
||||
case 127:
|
||||
var l = dataLength;
|
||||
for (var i = 1; i <= 8; ++i) {
|
||||
outputBuffer[startOffset - i] = l & 0xff;
|
||||
l >>>= 8;
|
||||
}
|
||||
}
|
||||
return outputBuffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
WebSocket.prototype.doClose = function () {
|
||||
this.socket.end();
|
||||
};
|
||||
|
||||
/**
|
||||
* WebSocket parser
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Parser () {
|
||||
this.state = {
|
||||
activeFragmentedOperation: null,
|
||||
lastFragment: false,
|
||||
masked: false,
|
||||
opcode: 0
|
||||
};
|
||||
this.overflow = null;
|
||||
this.expectOffset = 0;
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
this.currentMessage = '';
|
||||
|
||||
var self = this;
|
||||
this.opcodeHandlers = {
|
||||
// text
|
||||
'1': function(data) {
|
||||
var finish = function(mask, data) {
|
||||
self.currentMessage += self.unmask(mask, data);
|
||||
if (self.state.lastFragment) {
|
||||
self.emit('data', self.currentMessage);
|
||||
self.currentMessage = '';
|
||||
}
|
||||
self.endPacket();
|
||||
}
|
||||
|
||||
var expectData = function(length) {
|
||||
if (self.state.masked) {
|
||||
self.expect('Mask', 4, function(data) {
|
||||
var mask = data;
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(mask, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(null, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// decode length
|
||||
var firstLength = data[1] & 0x7f;
|
||||
if (firstLength < 126) {
|
||||
expectData(firstLength);
|
||||
}
|
||||
else if (firstLength == 126) {
|
||||
self.expect('Length', 2, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
else if (firstLength == 127) {
|
||||
self.expect('Length', 8, function(data) {
|
||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
||||
return;
|
||||
}
|
||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
},
|
||||
// binary
|
||||
'2': function(data) {
|
||||
var finish = function(mask, data) {
|
||||
if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list
|
||||
self.currentMessage.push(self.unmask(mask, data, true));
|
||||
if (self.state.lastFragment) {
|
||||
self.emit('binary', self.concatBuffers(self.currentMessage));
|
||||
self.currentMessage = '';
|
||||
}
|
||||
self.endPacket();
|
||||
}
|
||||
|
||||
var expectData = function(length) {
|
||||
if (self.state.masked) {
|
||||
self.expect('Mask', 4, function(data) {
|
||||
var mask = data;
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(mask, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(null, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// decode length
|
||||
var firstLength = data[1] & 0x7f;
|
||||
if (firstLength < 126) {
|
||||
expectData(firstLength);
|
||||
}
|
||||
else if (firstLength == 126) {
|
||||
self.expect('Length', 2, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
else if (firstLength == 127) {
|
||||
self.expect('Length', 8, function(data) {
|
||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
||||
return;
|
||||
}
|
||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
},
|
||||
// close
|
||||
'8': function(data) {
|
||||
self.emit('close');
|
||||
self.reset();
|
||||
},
|
||||
// ping
|
||||
'9': function(data) {
|
||||
if (self.state.lastFragment == false) {
|
||||
self.error('fragmented ping is not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
var finish = function(mask, data) {
|
||||
self.emit('ping', self.unmask(mask, data));
|
||||
self.endPacket();
|
||||
}
|
||||
|
||||
var expectData = function(length) {
|
||||
if (self.state.masked) {
|
||||
self.expect('Mask', 4, function(data) {
|
||||
var mask = data;
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(mask, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.expect('Data', length, function(data) {
|
||||
finish(null, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// decode length
|
||||
var firstLength = data[1] & 0x7f;
|
||||
if (firstLength == 0) {
|
||||
finish(null, null);
|
||||
}
|
||||
else if (firstLength < 126) {
|
||||
expectData(firstLength);
|
||||
}
|
||||
else if (firstLength == 126) {
|
||||
self.expect('Length', 2, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
else if (firstLength == 127) {
|
||||
self.expect('Length', 8, function(data) {
|
||||
expectData(util.unpack(data));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.expect('Opcode', 2, this.processPacket);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from EventEmitter.
|
||||
*/
|
||||
|
||||
Parser.prototype.__proto__ = EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Add new data to the parser.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Parser.prototype.add = function(data) {
|
||||
if (this.expectBuffer == null) {
|
||||
this.addToOverflow(data);
|
||||
return;
|
||||
}
|
||||
var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset);
|
||||
data.copy(this.expectBuffer, this.expectOffset, 0, toRead);
|
||||
this.expectOffset += toRead;
|
||||
if (toRead < data.length) {
|
||||
// at this point the overflow buffer shouldn't at all exist
|
||||
this.overflow = new Buffer(data.length - toRead);
|
||||
data.copy(this.overflow, 0, toRead, toRead + this.overflow.length);
|
||||
}
|
||||
if (this.expectOffset == this.expectBuffer.length) {
|
||||
var bufferForHandler = this.expectBuffer;
|
||||
this.expectBuffer = null;
|
||||
this.expectOffset = 0;
|
||||
this.expectHandler.call(this, bufferForHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a piece of data to the overflow.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.addToOverflow = function(data) {
|
||||
if (this.overflow == null) this.overflow = data;
|
||||
else {
|
||||
var prevOverflow = this.overflow;
|
||||
this.overflow = new Buffer(this.overflow.length + data.length);
|
||||
prevOverflow.copy(this.overflow, 0);
|
||||
data.copy(this.overflow, prevOverflow.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a certain amount of bytes to be available, then fires a callback.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.expect = function(what, length, handler) {
|
||||
this.expectBuffer = new Buffer(length);
|
||||
this.expectOffset = 0;
|
||||
this.expectHandler = handler;
|
||||
if (this.overflow != null) {
|
||||
var toOverflow = this.overflow;
|
||||
this.overflow = null;
|
||||
this.add(toOverflow);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start processing a new packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.processPacket = function (data) {
|
||||
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;
|
||||
if (opcode == 0) {
|
||||
// continuation frame
|
||||
this.state.opcode = this.state.activeFragmentedOperation;
|
||||
if (!(this.state.opcode == 1 || this.state.opcode == 2)) {
|
||||
this.error('continuation frame cannot follow current opcode')
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.state.opcode = opcode;
|
||||
if (this.state.lastFragment === false) {
|
||||
this.state.activeFragmentedOperation = opcode;
|
||||
}
|
||||
}
|
||||
var handler = this.opcodeHandlers[this.state.opcode];
|
||||
if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode);
|
||||
else handler(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Endprocessing a packet.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.endPacket = function() {
|
||||
this.expectOffset = 0;
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) {
|
||||
// end current fragmented operation
|
||||
this.state.activeFragmentedOperation = null;
|
||||
}
|
||||
this.state.lastFragment = false;
|
||||
this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0;
|
||||
this.state.masked = false;
|
||||
this.expect('Opcode', 2, this.processPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the parser state.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.reset = function() {
|
||||
this.state = {
|
||||
activeFragmentedOperation: null,
|
||||
lastFragment: false,
|
||||
masked: false,
|
||||
opcode: 0
|
||||
};
|
||||
this.expectOffset = 0;
|
||||
this.expectBuffer = null;
|
||||
this.expectHandler = null;
|
||||
this.overflow = null;
|
||||
this.currentMessage = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmask received data.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.unmask = function (mask, buf, binary) {
|
||||
if (mask != null) {
|
||||
for (var i = 0, ll = buf.length; i < ll; i++) {
|
||||
buf[i] ^= mask[i % 4];
|
||||
}
|
||||
}
|
||||
if (binary) return buf;
|
||||
return buf != null ? buf.toString('utf8') : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates a list of buffers.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.concatBuffers = function(buffers) {
|
||||
var length = 0;
|
||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
||||
length += buffers[i].length;
|
||||
}
|
||||
var mergedBuffer = new Buffer(length);
|
||||
var offset = 0;
|
||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
||||
buffers[i].copy(mergedBuffer, offset);
|
||||
offset += buffers[i].length;
|
||||
}
|
||||
return mergedBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an error
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Parser.prototype.error = function (reason) {
|
||||
this.reset();
|
||||
this.emit('error', reason);
|
||||
return this;
|
||||
};
|
||||
11
networking/node_modules/socket.io/lib/transports/websocket/index.js
generated
vendored
Normal file
11
networking/node_modules/socket.io/lib/transports/websocket/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
/**
|
||||
* Export websocket versions.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
7: require('./hybi-07-12'),
|
||||
8: require('./hybi-07-12'),
|
||||
13: require('./hybi-16'),
|
||||
default: require('./default')
|
||||
};
|
||||
69
networking/node_modules/socket.io/lib/transports/xhr-polling.js
generated
vendored
Normal file
69
networking/node_modules/socket.io/lib/transports/xhr-polling.js
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var HTTPPolling = require('./http-polling');
|
||||
|
||||
/**
|
||||
* Export the constructor.
|
||||
*/
|
||||
|
||||
exports = module.exports = XHRPolling;
|
||||
|
||||
/**
|
||||
* Ajax polling transport.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function XHRPolling (mng, data, req) {
|
||||
HTTPPolling.call(this, mng, data, req);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherits from Transport.
|
||||
*/
|
||||
|
||||
XHRPolling.prototype.__proto__ = HTTPPolling.prototype;
|
||||
|
||||
/**
|
||||
* Transport name
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
XHRPolling.prototype.name = 'xhr-polling';
|
||||
|
||||
/**
|
||||
* Frames data prior to write.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
XHRPolling.prototype.doWrite = function (data) {
|
||||
HTTPPolling.prototype.doWrite.call(this);
|
||||
|
||||
var origin = this.req.headers.origin
|
||||
, headers = {
|
||||
'Content-Type': 'text/plain; charset=UTF-8'
|
||||
, 'Content-Length': data === undefined ? 0 : Buffer.byteLength(data)
|
||||
, 'Connection': 'Keep-Alive'
|
||||
};
|
||||
|
||||
if (origin) {
|
||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
||||
headers['Access-Control-Allow-Origin'] = origin;
|
||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
||||
}
|
||||
|
||||
this.response.writeHead(200, headers);
|
||||
this.response.write(data);
|
||||
this.log.debug(this.name + ' writing', data);
|
||||
};
|
||||
50
networking/node_modules/socket.io/lib/util.js
generated
vendored
Normal file
50
networking/node_modules/socket.io/lib/util.js
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
/*!
|
||||
* socket.io-node
|
||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Converts an enumerable to an array.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.toArray = function (enu) {
|
||||
var arr = [];
|
||||
|
||||
for (var i = 0, l = enu.length; i < l; i++)
|
||||
arr.push(enu[i]);
|
||||
|
||||
return arr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unpacks a buffer to a number.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.unpack = function (buffer) {
|
||||
var n = 0;
|
||||
for (var i = 0; i < buffer.length; ++i) {
|
||||
n = (i == 0) ? buffer[i] : (n * 256) + buffer[i];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Left pads a string.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.padl = function (s,n,c) {
|
||||
return new Array(1 + n - s.length).join(c) + s;
|
||||
}
|
||||
|
||||
1
networking/node_modules/socket.io/node_modules/policyfile/.npmignore
generated
vendored
Normal file
1
networking/node_modules/socket.io/node_modules/policyfile/.npmignore
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
||||
19
networking/node_modules/socket.io/node_modules/policyfile/LICENSE
generated
vendored
Normal file
19
networking/node_modules/socket.io/node_modules/policyfile/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2011 Arnout Kazemier,3rd-Eden
|
||||
|
||||
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.
|
||||
7
networking/node_modules/socket.io/node_modules/policyfile/Makefile
generated
vendored
Normal file
7
networking/node_modules/socket.io/node_modules/policyfile/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
doc:
|
||||
dox --title "FlashPolicyFileServer" lib/* > doc/index.html
|
||||
|
||||
test:
|
||||
expresso -I lib $(TESTFLAGS) tests/*.test.js
|
||||
|
||||
.PHONY: test doc
|
||||
98
networking/node_modules/socket.io/node_modules/policyfile/README.md
generated
vendored
Normal file
98
networking/node_modules/socket.io/node_modules/policyfile/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
## LOL, WUT?
|
||||
It basically allows you to allow or disallow Flash Player sockets from accessing your site.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install policyfile
|
||||
```
|
||||
## Usage
|
||||
|
||||
The server is based on the regular and know `net` and `http` server patterns. So it you can just listen
|
||||
for all the events that a `net` based server emits etc. But there is one extra event, the `connect_failed`
|
||||
event. This event is triggered when we are unable to listen on the supplied port number.
|
||||
|
||||
### createServer
|
||||
Creates a new server instance and accepts 2 optional arguments:
|
||||
|
||||
- `options` **Object** Options to configure the server instance
|
||||
- `log` **Boolean** Enable logging to STDOUT and STDERR (defaults to true)
|
||||
- `origins` **Array** An Array of origins that are allowed by the server (defaults to *:*)
|
||||
|
||||
```js
|
||||
var pf = require('policyfile');
|
||||
pf.createServer();
|
||||
pf.listen();
|
||||
```
|
||||
|
||||
#### server.listen
|
||||
Start listening on the server and it takes 3 optional arguments
|
||||
|
||||
- `port` **Number** On which port number should we listen? (defaults to 843, which is the first port number the FlashPlayer checks)
|
||||
- `server` **Server** A http server, if we are unable to accept requests or run the server we can also answer the policy requests inline over the supplied HTTP server.
|
||||
- `callback` **Function** A callback function that is called when listening to the server was successful.
|
||||
|
||||
```js
|
||||
var pf = require('policyfile');
|
||||
pf.createServer();
|
||||
pf.listen(1337, function(){
|
||||
console.log(':3 yay')
|
||||
});
|
||||
```
|
||||
|
||||
Changing port numbers can be handy if you do not want to run your server as root and have port 843 forward to a non root port number (aka a number above 1024).
|
||||
|
||||
```js
|
||||
var pf = require('policyfile')
|
||||
, http = require('http');
|
||||
|
||||
server = http.createServer(function(q,r){r.writeHead(200);r.end('hello world')});
|
||||
server.listen(80);
|
||||
|
||||
pf.createServer();
|
||||
pf.listen(1337, server, function(){
|
||||
console.log(':3 yay')
|
||||
});
|
||||
```
|
||||
|
||||
Support for serving inline requests over a existing HTTP connection as the FlashPlayer will first check port 843, but if it's unable to get a response there it will send a policy file request over port 80, which is usually your http server.
|
||||
|
||||
#### server.add
|
||||
Adds more origins to the policy file you can add as many arguments as you like.
|
||||
|
||||
```js
|
||||
var pf = require('policyfile');
|
||||
pf.createServer(['google.com:80']);
|
||||
pf.listen();
|
||||
pf.add('blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080'); // now has 3 origins
|
||||
```
|
||||
|
||||
#### server.add
|
||||
Adds more origins to the policy file you can add as many arguments as you like.
|
||||
|
||||
```js
|
||||
var pf = require('policyfile');
|
||||
pf.createServer(['blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080']);
|
||||
pf.listen();
|
||||
pf.remove('blog.3rd-Eden.com:8080'); // only contains the :80 version now
|
||||
```
|
||||
|
||||
#### server.close
|
||||
Shuts down the server
|
||||
|
||||
```js
|
||||
var pf = require('policyfile');
|
||||
pf.createServer();
|
||||
pf.listen();
|
||||
pf.close(); // OH NVM.
|
||||
```
|
||||
|
||||
## API
|
||||
http://3rd-eden.com/FlashPolicyFileServer/
|
||||
|
||||
## Examples
|
||||
See https://github.com/3rd-Eden/FlashPolicyFileServer/tree/master/examples for examples
|
||||
|
||||
## Licence
|
||||
|
||||
MIT see LICENSE file in the repository
|
||||
375
networking/node_modules/socket.io/node_modules/policyfile/doc/index.html
generated
vendored
Normal file
375
networking/node_modules/socket.io/node_modules/policyfile/doc/index.html
generated
vendored
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>FlashPolicyFileServer</title>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
|
||||
<style>body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font: 14px/1.5 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
color: #252519;
|
||||
}
|
||||
a {
|
||||
color: #252519;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
color: #19469D;
|
||||
}
|
||||
p {
|
||||
margin: 12px 0;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table#source {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table#source td:first-child {
|
||||
padding: 30px 40px 30px 40px;
|
||||
vertical-align: top;
|
||||
}
|
||||
table#source td:first-child,
|
||||
table#source td:first-child pre {
|
||||
width: 450px;
|
||||
}
|
||||
table#source td:last-child {
|
||||
padding: 30px 0 30px 40px;
|
||||
border-left: 1px solid #E5E5EE;
|
||||
background: #F5F5FF;
|
||||
}
|
||||
table#source tr {
|
||||
border-bottom: 1px solid #E5E5EE;
|
||||
}
|
||||
table#source tr.filename {
|
||||
padding-top: 40px;
|
||||
border-top: 1px solid #E5E5EE;
|
||||
}
|
||||
table#source tr.filename td:first-child {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
table#source tr.filename td:last-child {
|
||||
font-size: 12px;
|
||||
}
|
||||
table#source tr.filename h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
table#source tr.code h1,
|
||||
table#source tr.code h2,
|
||||
table#source tr.code h3 {
|
||||
margin-top: 30px;
|
||||
font-family: "Lucida Grande", "Helvetica Nueue", Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
table#source tr.code h2 {
|
||||
font-size: 16px;
|
||||
}
|
||||
table#source tr.code h3 {
|
||||
font-size: 14px;
|
||||
}
|
||||
table#source tr.code ul {
|
||||
margin: 15px 0 15px 35px;
|
||||
padding: 0;
|
||||
}
|
||||
table#source tr.code ul li {
|
||||
margin: 0;
|
||||
padding: 1px 0;
|
||||
}
|
||||
table#source tr.code ul li p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table#source tr.code td:first-child pre {
|
||||
padding: 20px;
|
||||
}
|
||||
#ribbon {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
code .string { color: #219161; }
|
||||
code .regexp { color: #219161; }
|
||||
code .keyword { color: #954121; }
|
||||
code .number { color: #19469D; }
|
||||
code .comment { color: #bbb; }
|
||||
code .this { color: #19469D; }</style>
|
||||
<script>
|
||||
$(function(){
|
||||
$('tr.code').hide();
|
||||
$('tr.filename').toggle(function(){
|
||||
$(this).nextUntil('.filename').fadeIn();
|
||||
}, function(){
|
||||
$(this).nextUntil('.filename').fadeOut();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<table id="source"><tbody><tr><td><h1>FlashPolicyFileServer</h1></td><td></td></tr><tr class="filename"><td><h2 id="lib/server.js"><a href="#">server</a></h2></td><td>lib/server.js</td></tr><tr class="code">
|
||||
<td class="docs">
|
||||
<p>Module dependencies and cached references.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="keyword">var</span> <span class="variable">slice</span> = <span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">slice</span>
|
||||
, <span class="variable">net</span> = <span class="variable">require</span>(<span class="string">'net'</span>);</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>The server that does the Policy File severing</p>
|
||||
|
||||
<h2>Options</h2>
|
||||
|
||||
<ul><li><code>log</code> false or a function that can output log information, defaults to console.log?</li></ul>
|
||||
|
||||
<h2></h2>
|
||||
|
||||
<ul><li><p><strong>param</strong>: <em>Object</em> options Options to customize the servers functionality.</p></li><li><p><strong>param</strong>: <em>Array</em> origins The origins that are allowed on this server, defaults to <code>*:*</code>.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="keyword">function</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
|
||||
<span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>;
|
||||
|
||||
<span class="this">this</span>.<span class="variable">origins</span> = <span class="variable">origins</span> || [<span class="string">'*:*'</span>];
|
||||
<span class="this">this</span>.<span class="variable">port</span> = <span class="number integer">843</span>;
|
||||
<span class="this">this</span>.<span class="variable">log</span> = <span class="variable">console</span>.<span class="variable">log</span>;
|
||||
|
||||
<span class="comment">// merge `this` with the options</span>
|
||||
<span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">options</span>).<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">key</span>){
|
||||
<span class="variable">me</span>[<span class="variable">key</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">me</span>[<span class="variable">key</span>] = <span class="variable">options</span>[<span class="variable">key</span>])
|
||||
});
|
||||
|
||||
<span class="comment">// create the net server</span>
|
||||
<span class="this">this</span>.<span class="variable">socket</span> = <span class="variable">net</span>.<span class="variable">createServer</span>(<span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">socket</span>){
|
||||
<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">socketError</span>(){ <span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>) });
|
||||
<span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>);
|
||||
});
|
||||
|
||||
<span class="comment">// Listen for errors as the port might be blocked because we do not have root priv.</span>
|
||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">serverError</span>(<span class="variable">err</span>){
|
||||
<span class="comment">// Special and common case error handling</span>
|
||||
<span class="keyword">if</span> (<span class="variable">err</span>.<span class="variable">errno</span> == <span class="number integer">13</span>){
|
||||
<span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(
|
||||
<span class="string">'Unable to listen to port `'</span> + <span class="variable">me</span>.<span class="variable">port</span> + <span class="string">'` as your Node.js instance does not have root privileges. '</span> +
|
||||
(
|
||||
<span class="variable">me</span>.<span class="variable">server</span>
|
||||
? <span class="string">'The Flash Policy file will now be served inline over the supplied HTTP server, Flash Policy files request will suffer.'</span>
|
||||
: <span class="string">'No fallback server supplied.'</span>
|
||||
)
|
||||
);
|
||||
|
||||
<span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
|
||||
<span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">socket</span>;
|
||||
|
||||
<span class="variable">me</span>.<span class="variable">emit</span>(<span class="string">'connect_failed'</span>, <span class="variable">err</span>);
|
||||
} <span class="keyword">else</span> {
|
||||
<span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'FlashPolicyFileServer received a error event:\n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
|
||||
}
|
||||
});
|
||||
|
||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'timeout'</span>, <span class="keyword">function</span> <span class="variable">serverTimeout</span>(){});
|
||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'close'</span>, <span class="keyword">function</span> <span class="variable">serverClosed</span>(<span class="variable">err</span>){
|
||||
<span class="variable">err</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Server closing due to an error: \n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
|
||||
|
||||
<span class="keyword">if</span> (<span class="variable">me</span>.<span class="variable">server</span>){
|
||||
<span class="comment">// not online anymore</span>
|
||||
<span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>;
|
||||
|
||||
<span class="comment">// Remove the inline policy listener if we close down</span>
|
||||
<span class="comment">// but only when the server was `online` (see listen prototype)</span>
|
||||
<span class="keyword">if</span>( <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>){
|
||||
<span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">removeListener</span>(<span class="string">'connection'</span>, <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
|
||||
}
|
||||
}
|
||||
<span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Shutting down FlashPolicyFileServer'</span>);
|
||||
});
|
||||
|
||||
<span class="comment">// Compile the initial `buffer`</span>
|
||||
<span class="this">this</span>.<span class="variable">compile</span>();
|
||||
}</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Start listening for requests</p>
|
||||
|
||||
<h2></h2>
|
||||
|
||||
<ul><li><p><strong>param</strong>: <em>Number</em> port The port number it should be listening to.</p></li><li><p><strong>param</strong>: <em>Server</em> server A HTTP server instance, this will be used to listen for inline requests</p></li><li><p><strong>param</strong>: <em>Function</em> cb The callback needs to be called once server is ready</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">listen</span> = <span class="keyword">function</span> <span class="variable">listen</span>(<span class="variable">port</span>, <span class="variable">server</span>, <span class="variable">cb</span>){
|
||||
<span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>
|
||||
, <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
|
||||
, <span class="variable">callback</span>;
|
||||
|
||||
<span class="comment">// assign the correct vars, for flexible arguments</span>
|
||||
<span class="variable">args</span>.<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">args</span>(<span class="variable">arg</span>){
|
||||
<span class="keyword">var</span> <span class="variable">type</span> = <span class="keyword">typeof</span> <span class="variable">arg</span>;
|
||||
|
||||
<span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'number'</span>) <span class="variable">me</span>.<span class="variable">port</span> = <span class="variable">arg</span>;
|
||||
<span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'function'</span>) <span class="variable">callback</span> = <span class="variable">arg</span>;
|
||||
<span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'object'</span>) <span class="variable">me</span>.<span class="variable">server</span> = <span class="variable">arg</span>;
|
||||
});
|
||||
|
||||
<span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">server</span>){
|
||||
|
||||
<span class="comment">// no one in their right mind would ever create a `@` prototype, so Im just gonna store</span>
|
||||
<span class="comment">// my function on the server, so I can remove it later again once the server(s) closes</span>
|
||||
<span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>] = <span class="keyword">function</span> <span class="variable">connection</span>(<span class="variable">socket</span>){
|
||||
<span class="variable">socket</span>.<span class="variable">once</span>(<span class="string">'data'</span>, <span class="keyword">function</span> <span class="variable">requestData</span>(<span class="variable">data</span>){
|
||||
<span class="comment">// if it's a Flash policy request, and we can write to the </span>
|
||||
<span class="keyword">if</span> (
|
||||
<span class="variable">data</span>
|
||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>[<span class="number integer">0</span>] === <span class="number integer">60</span>
|
||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>.<span class="variable">toString</span>() === <span class="string">'<policy-file-request/>\0'</span>
|
||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">socket</span>
|
||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'open'</span> || <span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'writeOnly'</span>)
|
||||
){
|
||||
<span class="comment">// send the buffer</span>
|
||||
<span class="variable">socket</span>.<span class="variable">end</span>(<span class="variable">me</span>.<span class="variable">buffer</span>);
|
||||
}
|
||||
});
|
||||
};
|
||||
<span class="comment">// attach it</span>
|
||||
<span class="this">this</span>.<span class="variable">server</span>.<span class="variable">on</span>(<span class="string">'connection'</span>, <span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
|
||||
}
|
||||
|
||||
<span class="comment">// We add a callback method, so we can set a flag for when the server is `enabled` or `online`.</span>
|
||||
<span class="comment">// this flag is needed because if a error occurs and the we cannot boot up the server the</span>
|
||||
<span class="comment">// fallback functionality should not be removed during the `close` event</span>
|
||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">listen</span>(<span class="this">this</span>.<span class="variable">port</span>, <span class="keyword">function</span> <span class="variable">serverListening</span>(){
|
||||
<span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">online</span> = <span class="variable">true</span>;
|
||||
|
||||
<span class="keyword">if</span> (<span class="variable">callback</span>) <span class="variable">callback</span>(), <span class="variable">callback</span> = <span class="variable">undefined</span>;
|
||||
|
||||
});
|
||||
|
||||
<span class="keyword">return</span> <span class="this">this</span>;
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Adds a new origin to the Flash Policy File.</p>
|
||||
|
||||
<h2></h2>
|
||||
|
||||
<ul><li><p><strong>param</strong>: <em>Arguments</em> The origins that need to be added.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">add</span> = <span class="keyword">function</span> <span class="variable">add</span>(){
|
||||
<span class="keyword">var</span> <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
|
||||
, <span class="variable">i</span> = <span class="variable">args</span>.<span class="variable">length</span>;
|
||||
|
||||
<span class="comment">// flag duplicates</span>
|
||||
<span class="keyword">while</span> (<span class="variable">i</span>--){
|
||||
<span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">args</span>[<span class="variable">i</span>]) &<span class="variable">gt</span>;= <span class="number integer">0</span>){
|
||||
<span class="variable">args</span>[<span class="variable">i</span>] = <span class="keyword">null</span>;
|
||||
}
|
||||
}
|
||||
|
||||
<span class="comment">// Add all the arguments to the array</span>
|
||||
<span class="comment">// but first we want to remove all `falsy` values from the args</span>
|
||||
<span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">push</span>.<span class="variable">apply</span>(
|
||||
<span class="this">this</span>.<span class="variable">origins</span>
|
||||
, <span class="variable">args</span>.<span class="variable">filter</span>(<span class="keyword">function</span>(<span class="variable">value</span>){ <span class="keyword">return</span> !!<span class="variable">value</span> })
|
||||
);
|
||||
|
||||
<span class="this">this</span>.<span class="variable">compile</span>();
|
||||
<span class="keyword">return</span> <span class="this">this</span>;
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Removes a origin from the Flash Policy File.</p>
|
||||
|
||||
<h2></h2>
|
||||
|
||||
<ul><li><p><strong>param</strong>: <em>String</em> origin The origin that needs to be removed from the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">remove</span> = <span class="keyword">function</span> <span class="variable">remove</span>(<span class="variable">origin</span>){
|
||||
<span class="keyword">var</span> <span class="variable">position</span> = <span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">origin</span>);
|
||||
|
||||
<span class="comment">// only remove and recompile if we have a match</span>
|
||||
<span class="keyword">if</span> (<span class="variable">position</span> &<span class="variable">gt</span>; <span class="number integer">0</span>){
|
||||
<span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">splice</span>(<span class="variable">position</span>,<span class="number integer">1</span>);
|
||||
<span class="this">this</span>.<span class="variable">compile</span>();
|
||||
}
|
||||
|
||||
<span class="keyword">return</span> <span class="this">this</span>;
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Closes and cleans up the server</p>
|
||||
|
||||
<ul><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">close</span> = <span class="keyword">function</span> <span class="variable">close</span>(){
|
||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
|
||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">close</span>();
|
||||
|
||||
<span class="keyword">return</span> <span class="this">this</span>;
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Proxy the event listener requests to the created Net server
|
||||
</p>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">process</span>.<span class="class">EventEmitter</span>.<span class="variable">prototype</span>).<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">proxy</span>(<span class="variable">key</span>){
|
||||
<span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] = <span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] || <span class="keyword">function</span> (){
|
||||
<span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">socket</span>) <span class="this">this</span>.<span class="variable">socket</span>[<span class="variable">key</span>].<span class="variable">apply</span>(<span class="this">this</span>.<span class="variable">socket</span>, <span class="variable">arguments</span>);
|
||||
<span class="keyword">return</span> <span class="this">this</span>;
|
||||
};
|
||||
});</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Creates a new server instance.</p>
|
||||
|
||||
<h2></h2>
|
||||
|
||||
<ul><li><p><strong>param</strong>: <em>Object</em> options A options object to override the default config</p></li><li><p><strong>param</strong>: <em>Array</em> origins The origins that should be allowed by the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="variable">exports</span>.<span class="variable">createServer</span> = <span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
|
||||
<span class="variable">origins</span> = <span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">origins</span>) ? <span class="variable">origins</span> : (<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) ? <span class="variable">options</span> : <span class="variable">false</span>);
|
||||
<span class="variable">options</span> = !<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">options</span> ? <span class="variable">options</span> : {};
|
||||
|
||||
<span class="keyword">return</span> <span class="keyword">new</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>);
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Provide a hook to the original server, so it can be extended if needed.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="variable">exports</span>.<span class="class">Server</span> = <span class="class">Server</span>;</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="code">
|
||||
<td class="docs">
|
||||
<p>Module version
|
||||
</p>
|
||||
</td>
|
||||
<td class="code">
|
||||
<pre><code><span class="variable">exports</span>.<span class="variable">version</span> = <span class="string">'0.0.2'</span>;
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr> </body>
|
||||
</html></tbody></table>
|
||||
8
networking/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js
generated
vendored
Normal file
8
networking/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var http = require('http')
|
||||
, fspfs = require('../');
|
||||
|
||||
var server = http.createServer(function(q,r){ r.writeHead(200); r.end(':3') })
|
||||
, flash = fspfs.createServer();
|
||||
|
||||
server.listen(8080);
|
||||
flash.listen(8081,server);
|
||||
5
networking/node_modules/socket.io/node_modules/policyfile/examples/basic.js
generated
vendored
Normal file
5
networking/node_modules/socket.io/node_modules/policyfile/examples/basic.js
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
var http = require('http')
|
||||
, fspfs = require('../');
|
||||
|
||||
var flash = fspfs.createServer();
|
||||
flash.listen();
|
||||
1
networking/node_modules/socket.io/node_modules/policyfile/index.js
generated
vendored
Normal file
1
networking/node_modules/socket.io/node_modules/policyfile/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
module.exports = require('./lib/server.js');
|
||||
289
networking/node_modules/socket.io/node_modules/policyfile/lib/server.js
generated
vendored
Normal file
289
networking/node_modules/socket.io/node_modules/policyfile/lib/server.js
generated
vendored
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/**
|
||||
* Module dependencies and cached references.
|
||||
*/
|
||||
|
||||
var slice = Array.prototype.slice
|
||||
, net = require('net');
|
||||
|
||||
/**
|
||||
* The server that does the Policy File severing
|
||||
*
|
||||
* Options:
|
||||
* - `log` false or a function that can output log information, defaults to console.log?
|
||||
*
|
||||
* @param {Object} options Options to customize the servers functionality.
|
||||
* @param {Array} origins The origins that are allowed on this server, defaults to `*:*`.
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Server (options, origins) {
|
||||
var me = this;
|
||||
|
||||
this.origins = origins || ['*:*'];
|
||||
this.port = 843;
|
||||
this.log = console.log;
|
||||
|
||||
// merge `this` with the options
|
||||
Object.keys(options).forEach(function (key) {
|
||||
me[key] && (me[key] = options[key])
|
||||
});
|
||||
|
||||
// create the net server
|
||||
this.socket = net.createServer(function createServer (socket) {
|
||||
socket.on('error', function socketError () {
|
||||
me.responder.call(me, socket);
|
||||
});
|
||||
|
||||
me.responder.call(me, socket);
|
||||
});
|
||||
|
||||
// Listen for errors as the port might be blocked because we do not have root priv.
|
||||
this.socket.on('error', function serverError (err) {
|
||||
// Special and common case error handling
|
||||
if (err.errno == 13) {
|
||||
me.log && me.log(
|
||||
'Unable to listen to port `' + me.port + '` as your Node.js instance does not have root privileges. ' +
|
||||
(
|
||||
me.server
|
||||
? 'The Flash Policy File requests will only be served inline over the supplied HTTP server. Inline serving is slower than a dedicated server instance.'
|
||||
: 'No fallback server supplied, we will be unable to answer Flash Policy File requests.'
|
||||
)
|
||||
);
|
||||
|
||||
me.emit('connect_failed', err);
|
||||
me.socket.removeAllListeners();
|
||||
delete me.socket;
|
||||
} else {
|
||||
me.log && me.log('FlashPolicyFileServer received an error event:\n' + (err.message ? err.message : err));
|
||||
}
|
||||
});
|
||||
|
||||
this.socket.on('timeout', function serverTimeout () {});
|
||||
this.socket.on('close', function serverClosed (err) {
|
||||
err && me.log && me.log('Server closing due to an error: \n' + (err.message ? err.message : err));
|
||||
|
||||
if (me.server) {
|
||||
// Remove the inline policy listener if we close down
|
||||
// but only when the server was `online` (see listen prototype)
|
||||
if (me.server['@'] && me.server.online) {
|
||||
me.server.removeListener('connection', me.server['@']);
|
||||
}
|
||||
|
||||
// not online anymore
|
||||
delete me.server.online;
|
||||
}
|
||||
});
|
||||
|
||||
// Compile the initial `buffer`
|
||||
this.compile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start listening for requests
|
||||
*
|
||||
* @param {Number} port The port number it should be listening to.
|
||||
* @param {Server} server A HTTP server instance, this will be used to listen for inline requests
|
||||
* @param {Function} cb The callback needs to be called once server is ready
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Server.prototype.listen = function listen (port, server, cb){
|
||||
var me = this
|
||||
, args = slice.call(arguments, 0)
|
||||
, callback;
|
||||
|
||||
// assign the correct vars, for flexible arguments
|
||||
args.forEach(function args (arg){
|
||||
var type = typeof arg;
|
||||
|
||||
if (type === 'number') me.port = arg;
|
||||
if (type === 'function') callback = arg;
|
||||
if (type === 'object') me.server = arg;
|
||||
});
|
||||
|
||||
if (this.server) {
|
||||
|
||||
// no one in their right mind would ever create a `@` prototype, so Im just gonna store
|
||||
// my function on the server, so I can remove it later again once the server(s) closes
|
||||
this.server['@'] = function connection (socket) {
|
||||
socket.once('data', function requestData (data) {
|
||||
// if it's a Flash policy request, and we can write to the
|
||||
if (
|
||||
data
|
||||
&& data[0] === 60
|
||||
&& data.toString() === '<policy-file-request/>\0'
|
||||
&& socket
|
||||
&& (socket.readyState === 'open' || socket.readyState === 'writeOnly')
|
||||
){
|
||||
// send the buffer
|
||||
try {
|
||||
socket.end(me.buffer);
|
||||
} catch (e) {}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// attach it
|
||||
this.server.on('connection', this.server['@']);
|
||||
}
|
||||
|
||||
// We add a callback method, so we can set a flag for when the server is `enabled` or `online`.
|
||||
// this flag is needed because if a error occurs and the we cannot boot up the server the
|
||||
// fallback functionality should not be removed during the `close` event
|
||||
this.port >= 0 && this.socket.listen(this.port, function serverListening () {
|
||||
me.socket.online = true;
|
||||
if (callback) {
|
||||
callback.call(me);
|
||||
callback = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Responds to socket connects and writes the compile policy file.
|
||||
*
|
||||
* @param {net.Socket} socket The socket that needs to receive the message
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Server.prototype.responder = function responder (socket){
|
||||
if (socket && socket.readyState == 'open' && socket.end) {
|
||||
try {
|
||||
socket.end(this.buffer);
|
||||
} catch (e) {}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Compiles the supplied origins to a Flash Policy File format and stores it in a Node.js Buffer
|
||||
* this way it can be send over the wire without any performance loss.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Server.prototype.compile = function compile (){
|
||||
var xml = [
|
||||
'<?xml version="1.0"?>'
|
||||
, '<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">'
|
||||
, '<cross-domain-policy>'
|
||||
];
|
||||
|
||||
// add the allow access element
|
||||
this.origins.forEach(function origin (origin){
|
||||
var parts = origin.split(':');
|
||||
xml.push('<allow-access-from domain="' + parts[0] + '" to-ports="'+ parts[1] +'"/>');
|
||||
});
|
||||
|
||||
xml.push('</cross-domain-policy>');
|
||||
|
||||
// store the result in a buffer so we don't have to re-generate it all the time
|
||||
this.buffer = new Buffer(xml.join(''), 'utf8');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a new origin to the Flash Policy File.
|
||||
*
|
||||
* @param {Arguments} The origins that need to be added.
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Server.prototype.add = function add(){
|
||||
var args = slice.call(arguments, 0)
|
||||
, i = args.length;
|
||||
|
||||
// flag duplicates
|
||||
while (i--) {
|
||||
if (this.origins.indexOf(args[i]) >= 0){
|
||||
args[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Add all the arguments to the array
|
||||
// but first we want to remove all `falsy` values from the args
|
||||
Array.prototype.push.apply(
|
||||
this.origins
|
||||
, args.filter(function filter (value) {
|
||||
return !!value;
|
||||
})
|
||||
);
|
||||
|
||||
this.compile();
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a origin from the Flash Policy File.
|
||||
*
|
||||
* @param {String} origin The origin that needs to be removed from the server
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Server.prototype.remove = function remove (origin){
|
||||
var position = this.origins.indexOf(origin);
|
||||
|
||||
// only remove and recompile if we have a match
|
||||
if (position > 0) {
|
||||
this.origins.splice(position,1);
|
||||
this.compile();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes and cleans up the server
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Server.prototype.close = function close () {
|
||||
this.socket.removeAllListeners();
|
||||
this.socket.close();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Proxy the event listener requests to the created Net server
|
||||
*/
|
||||
|
||||
Object.keys(process.EventEmitter.prototype).forEach(function proxy (key){
|
||||
Server.prototype[key] = Server.prototype[key] || function () {
|
||||
if (this.socket) {
|
||||
this.socket[key].apply(this.socket, arguments);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new server instance.
|
||||
*
|
||||
* @param {Object} options A options object to override the default config
|
||||
* @param {Array} origins The origins that should be allowed by the server
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.createServer = function createServer(options, origins){
|
||||
origins = Array.isArray(origins) ? origins : (Array.isArray(options) ? options : false);
|
||||
options = !Array.isArray(options) && options ? options : {};
|
||||
|
||||
return new Server(options, origins);
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide a hook to the original server, so it can be extended if needed.
|
||||
*/
|
||||
|
||||
exports.Server = Server;
|
||||
|
||||
/**
|
||||
* Module version
|
||||
*/
|
||||
|
||||
exports.version = '0.0.4';
|
||||
55
networking/node_modules/socket.io/node_modules/policyfile/package.json
generated
vendored
Normal file
55
networking/node_modules/socket.io/node_modules/policyfile/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"name": "policyfile",
|
||||
"version": "0.0.4",
|
||||
"author": {
|
||||
"name": "Arnout Kazemier"
|
||||
},
|
||||
"description": "Flash Socket Policy File Server. A server to respond to Flash Socket Policy requests, both inline and through a dedicated server instance.",
|
||||
"main": "index",
|
||||
"keywords": [
|
||||
"flash",
|
||||
"socket",
|
||||
"policy",
|
||||
"file",
|
||||
"server",
|
||||
"Flash Socket Policy File Server",
|
||||
"cross domain"
|
||||
],
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Arnout Kazemier",
|
||||
"email": "info@3rd-Eden.com",
|
||||
"url": "http://blog.3rd-Eden.com"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/3rd-Eden/FlashPolicyFileServer/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/3rd-Eden/FlashPolicyFileServer.git"
|
||||
}
|
||||
],
|
||||
"_id": "policyfile@0.0.4",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.4",
|
||||
"_nodeVersion": "v0.6.12",
|
||||
"_defaultsLoaded": true,
|
||||
"dist": {
|
||||
"shasum": "6abed755dc4c523bb66e1ad141721109483381d0"
|
||||
},
|
||||
"_from": "policyfile@0.0.4"
|
||||
}
|
||||
21
networking/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt
generated
vendored
Normal file
21
networking/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDXTCCAkWgAwIBAgIJAMUSOvlaeyQHMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTAxMTE2MDkzMjQ5WhcNMTMxMTE1MDkzMjQ5WjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEVwfPQQp4X
|
||||
wtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+1FAE0c5o
|
||||
exPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404WthquTqg
|
||||
S7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy25IyBK3QJ
|
||||
c+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWAQsqW+COL
|
||||
0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABo1AwTjAdBgNVHQ4EFgQUDnV4d6mD
|
||||
tOnluLoCjkUHTX/n4agwHwYDVR0jBBgwFoAUDnV4d6mDtOnluLoCjkUHTX/n4agw
|
||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAFwV4MQfTo+qMv9JMiyno
|
||||
IEiqfOz4RgtmBqRnXUffcjS2dhc7/z+FPZnM79Kej8eLHoVfxCyWRHFlzm93vEdv
|
||||
wxOCrD13EDOi08OOZfxWyIlCa6Bg8cMAKqQzd2OvQOWqlRWBTThBJIhWflU33izX
|
||||
Qn5GdmYqhfpc+9ZHHGhvXNydtRQkdxVK2dZNzLBvBlLlRmtoClU7xm3A+/5dddeP
|
||||
AQHEPtyFlUw49VYtZ3ru6KqPms7MKvcRhYLsy9rwSfuuniMlx4d0bDR7TOkw0QQS
|
||||
A0N8MGQRQpzl4mw4jLzyM5d5QtuGBh2P6hPGa0YQxtI3RPT/p6ENzzBiAKXiSfzo
|
||||
xw==
|
||||
-----END CERTIFICATE-----
|
||||
27
networking/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key
generated
vendored
Normal file
27
networking/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEV
|
||||
wfPQQp4XwtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+
|
||||
1FAE0c5oexPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404
|
||||
WthquTqgS7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy2
|
||||
5IyBK3QJc+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWA
|
||||
QsqW+COL0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABAoIBAGe4+9VqZfJN+dsq
|
||||
8Osyuz01uQ8OmC0sAWTIqUlQgENIyf9rCJsUBlYmwR5BT6Z69XP6QhHdpSK+TiAR
|
||||
XUz0EqG9HYzcxHIBaACP7j6iRoQ8R4kbbiWKo0z3WqQGIOqFjvD/mKEuQdE5mEYw
|
||||
eOUCG6BnX1WY2Yr8WKd2AA/tp0/Y4d8z04u9eodMpSTbHTzYMJb5SbBN1vo6FY7q
|
||||
8zSuO0BMzXlAxUsCwHsk1GQHFr8Oh3zIR7bQGtMBouI+6Lhh7sjFYsfxJboqMTBV
|
||||
IKaA216M6ggHG7MU1/jeKcMGDmEfqQLQoyWp29rMK6TklUgipME2L3UD7vTyAVzz
|
||||
xbVOpZkCgYEA8CXW4sZBBrSSrLR5SB+Ubu9qNTggLowOsC/kVKB2WJ4+xooc5HQo
|
||||
mFhq1v/WxPQoWIxdYsfg2odlL+JclK5Qcy6vXmRSdAQ5lK9gBDKxZSYc3NwAw2HA
|
||||
zyHCTK+I0n8PBYQ+yGcrxu0WqTGnlLW+Otk4CejO34WlgHwbH9bbY5UCgYEA3ZvT
|
||||
C4+OoMHXlmICSt29zUrYiL33IWsR3/MaONxTEDuvgkOSXXQOl/8Ebd6Nu+3WbsSN
|
||||
bjiPC/JyL1YCVmijdvFpl4gjtgvfJifs4G+QHvO6YfsYoVANk4u6g6rUuBIOwNK4
|
||||
RwYxwDc0oysp+g7tPxoSgDHReEVKJNzGBe9NGGsCgYEA4O4QP4gCEA3B9BF2J5+s
|
||||
n9uPVxmiyvZUK6Iv8zP4pThTBBMIzNIf09G9AHPQ7djikU2nioY8jXKTzC3xGTHM
|
||||
GJZ5m6fLsu7iH+nDvSreDSeNkTBfZqGAvoGYQ8uGE+L+ZuRfCcXYsxIOT5s6o4c3
|
||||
Dle2rVFpsuKzCY00urW796ECgYBn3go75+xEwrYGQSer6WR1nTgCV29GVYXKPooy
|
||||
zmmMOT1Yw80NSkEw0pFD4cTyqVYREsTrPU0mn1sPfrOXxnGfZSVFpcR/Je9QVfQ7
|
||||
eW7GYxwfom335aqHVj10SxRqteP+UoWWnHujCPz94VRKZMakBddYCIGSan+G6YdS
|
||||
7sdmwwKBgBc2qj0wvGXDF2kCLwSGfWoMf8CS1+5fIiUIdT1e/+7MfDdbmLMIFVjF
|
||||
QKS3zVViXCbrG5SY6wS9hxoc57f6E2A8vcaX6zy2xkZlGHQCpWRtEM5R01OWJQaH
|
||||
HsHMmQZGUQVoDm1oRkDhrTFK4K3ukc3rAxzeTZ96utOQN8/KJsTv
|
||||
-----END RSA PRIVATE KEY-----
|
||||
231
networking/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js
generated
vendored
Normal file
231
networking/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js
generated
vendored
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
var fspfs = require('../')
|
||||
, fs = require('fs')
|
||||
, http = require('http')
|
||||
, https = require('https')
|
||||
, net = require('net')
|
||||
, should = require('should')
|
||||
, assert = require('assert');
|
||||
|
||||
module.exports = {
|
||||
// Library version should be Semver compatible
|
||||
'Library version': function(){
|
||||
fspfs.version.should.match(/^\d+\.\d+\.\d+$/);
|
||||
}
|
||||
|
||||
// Creating a server instace should not cause any problems
|
||||
// either using the new Server or createServer method.
|
||||
, 'Create Server instance': function(){
|
||||
var server = fspfs.createServer()
|
||||
, server2 = new fspfs.Server({log:false}, ['blog.3rd-Eden.com:1337']);
|
||||
|
||||
// server 2 options test
|
||||
server2.log.should.be.false;
|
||||
server2.origins.length.should.equal(1);
|
||||
server2.origins[0].should.equal('blog.3rd-Eden.com:1337');
|
||||
|
||||
// server defaults
|
||||
(typeof server.log).should.be.equal('function');
|
||||
server.origins.length.should.equal(1);
|
||||
server.origins[0].should.equal('*:*');
|
||||
|
||||
// instance checking, sanity check
|
||||
assert.ok(server instanceof fspfs.Server);
|
||||
assert.ok(!!server.buffer);
|
||||
|
||||
// more options testing
|
||||
server = fspfs.createServer(['blog.3rd-Eden.com:80']);
|
||||
server.origins.length.should.equal(1);
|
||||
server.origins[0].should.equal('blog.3rd-Eden.com:80');
|
||||
|
||||
server = fspfs.createServer({log:false},['blog.3rd-Eden.com:80']);
|
||||
server.log.should.be.false;
|
||||
server.origins.length.should.equal(1);
|
||||
server.origins[0].should.equal('blog.3rd-Eden.com:80');
|
||||
|
||||
}
|
||||
|
||||
, 'Add origin': function(){
|
||||
var server = fspfs.createServer();
|
||||
server.add('google.com:80', 'blog.3rd-Eden.com:1337');
|
||||
|
||||
server.origins.length.should.equal(3);
|
||||
server.origins.indexOf('google.com:80').should.be.above(0);
|
||||
|
||||
// don't allow duplicates
|
||||
server.add('google.com:80', 'google.com:80');
|
||||
|
||||
var i = server.origins.length
|
||||
, count = 0;
|
||||
|
||||
while(i--){
|
||||
if (server.origins[i] === 'google.com:80'){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
count.should.equal(1);
|
||||
}
|
||||
|
||||
, 'Remove origin': function(){
|
||||
var server = fspfs.createServer();
|
||||
server.add('google.com:80', 'blog.3rd-Eden.com:1337');
|
||||
server.origins.length.should.equal(3);
|
||||
|
||||
server.remove('google.com:80');
|
||||
server.origins.length.should.equal(2);
|
||||
server.origins.indexOf('google.com:80').should.equal(-1);
|
||||
}
|
||||
|
||||
, 'Buffer': function(){
|
||||
var server = fspfs.createServer();
|
||||
|
||||
Buffer.isBuffer(server.buffer).should.be.true;
|
||||
server.buffer.toString().indexOf('to-ports="*"').should.be.above(0);
|
||||
server.buffer.toString().indexOf('domain="*"').should.be.above(0);
|
||||
server.buffer.toString().indexOf('domain="google.com"').should.equal(-1);
|
||||
|
||||
// The buffers should be rebuild when new origins are added
|
||||
server.add('google.com:80');
|
||||
server.buffer.toString().indexOf('to-ports="80"').should.be.above(0);
|
||||
server.buffer.toString().indexOf('domain="google.com"').should.be.above(0);
|
||||
|
||||
server.remove('google.com:80');
|
||||
server.buffer.toString().indexOf('to-ports="80"').should.equal(-1);
|
||||
server.buffer.toString().indexOf('domain="google.com"').should.equal(-1);
|
||||
}
|
||||
|
||||
, 'Responder': function(){
|
||||
var server = fspfs.createServer()
|
||||
, calls = 0
|
||||
// dummy socket to emulate a `real` socket
|
||||
, dummySocket = {
|
||||
readyState: 'open'
|
||||
, end: function(buffer){
|
||||
calls++;
|
||||
Buffer.isBuffer(buffer).should.be.true;
|
||||
buffer.toString().should.equal(server.buffer.toString());
|
||||
}
|
||||
};
|
||||
|
||||
server.responder(dummySocket);
|
||||
calls.should.equal(1);
|
||||
}
|
||||
|
||||
, 'Event proxy': function(){
|
||||
var server = fspfs.createServer()
|
||||
, calls = 0;
|
||||
|
||||
Object.keys(process.EventEmitter.prototype).forEach(function proxy(key){
|
||||
assert.ok(!!server[key] && typeof server[key] === 'function');
|
||||
});
|
||||
|
||||
// test if it works by calling a none default event
|
||||
server.on('pew', function(){
|
||||
calls++;
|
||||
});
|
||||
|
||||
server.emit('pew');
|
||||
calls.should.equal(1);
|
||||
}
|
||||
|
||||
, 'inline response http': function(){
|
||||
var port = 1335
|
||||
, httpserver = http.createServer(function(q,r){r.writeHead(200);r.end(':3')})
|
||||
, server = fspfs.createServer();
|
||||
|
||||
httpserver.listen(port, function(){
|
||||
server.listen(port + 1, httpserver, function(){
|
||||
var client = net.createConnection(port);
|
||||
client.write('<policy-file-request/>\0');
|
||||
client.on('error', function(err){
|
||||
assert.ok(!err, err)
|
||||
});
|
||||
client.on('data', function(data){
|
||||
|
||||
var response = data.toString();
|
||||
console.log(response);
|
||||
|
||||
response.indexOf('to-ports="*"').should.be.above(0);
|
||||
response.indexOf('domain="*"').should.be.above(0);
|
||||
response.indexOf('domain="google.com"').should.equal(-1);
|
||||
|
||||
// clean up
|
||||
client.destroy();
|
||||
server.close();
|
||||
httpserver.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
, 'server response': function(){
|
||||
var port = 1340
|
||||
, server = fspfs.createServer();
|
||||
|
||||
server.listen(port, function(){
|
||||
var client = net.createConnection(port);
|
||||
client.write('<policy-file-request/>\0');
|
||||
client.on('error', function(err){
|
||||
assert.ok(!err, err)
|
||||
});
|
||||
client.on('data', function(data){
|
||||
|
||||
var response = data.toString();
|
||||
|
||||
response.indexOf('to-ports="*"').should.be.above(0);
|
||||
response.indexOf('domain="*"').should.be.above(0);
|
||||
response.indexOf('domain="google.com"').should.equal(-1);
|
||||
|
||||
// clean up
|
||||
client.destroy();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
, 'inline response https': function(){
|
||||
var port = 1345
|
||||
, ssl = {
|
||||
key: fs.readFileSync(__dirname + '/ssl/ssl.private.key').toString()
|
||||
, cert: fs.readFileSync(__dirname + '/ssl/ssl.crt').toString()
|
||||
}
|
||||
, httpserver = https.createServer(ssl, function(q,r){r.writeHead(200);r.end(':3')})
|
||||
, server = fspfs.createServer();
|
||||
|
||||
httpserver.listen(port, function(){
|
||||
server.listen(port + 1, httpserver, function(){
|
||||
var client = net.createConnection(port);
|
||||
client.write('<policy-file-request/>\0');
|
||||
client.on('error', function(err){
|
||||
assert.ok(!err, err)
|
||||
});
|
||||
client.on('data', function(data){
|
||||
|
||||
var response = data.toString();
|
||||
|
||||
response.indexOf('to-ports="*"').should.be.above(0);
|
||||
response.indexOf('domain="*"').should.be.above(0);
|
||||
response.indexOf('domain="google.com"').should.equal(-1);
|
||||
|
||||
// clean up
|
||||
client.destroy();
|
||||
server.close();
|
||||
httpserver.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
, 'connect_failed': function(){
|
||||
var server = fspfs.createServer();
|
||||
|
||||
server.on('connect_failed', function(){
|
||||
assert.ok(true);
|
||||
});
|
||||
|
||||
server.listen(function(){
|
||||
assert.ok(false, 'Run this test without root access');
|
||||
server.close();
|
||||
});
|
||||
}
|
||||
};
|
||||
567
networking/node_modules/socket.io/node_modules/redis/README.md
generated
vendored
Normal file
567
networking/node_modules/socket.io/node_modules/redis/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,567 @@
|
|||
redis - a node.js redis client
|
||||
===========================
|
||||
|
||||
This is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from
|
||||
experimental Redis server branches.
|
||||
|
||||
|
||||
Install with:
|
||||
|
||||
npm install redis
|
||||
|
||||
Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do:
|
||||
|
||||
npm install hiredis redis
|
||||
|
||||
If `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used.
|
||||
|
||||
If you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can
|
||||
happen between node and native code modules after a node upgrade.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Simple example, included as `examples/simple.js`:
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
client.on("error", function (err) {
|
||||
console.log("Error " + err);
|
||||
});
|
||||
|
||||
client.set("string key", "string val", redis.print);
|
||||
client.hset("hash key", "hashtest 1", "some value", redis.print);
|
||||
client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
|
||||
client.hkeys("hash key", function (err, replies) {
|
||||
console.log(replies.length + " replies:");
|
||||
replies.forEach(function (reply, i) {
|
||||
console.log(" " + i + ": " + reply);
|
||||
});
|
||||
client.quit();
|
||||
});
|
||||
|
||||
This will display:
|
||||
|
||||
mjr:~/work/node_redis (master)$ node example.js
|
||||
Reply: OK
|
||||
Reply: 0
|
||||
Reply: 0
|
||||
2 replies:
|
||||
0: hashtest 1
|
||||
1: hashtest 2
|
||||
mjr:~/work/node_redis (master)$
|
||||
|
||||
|
||||
## Performance
|
||||
|
||||
Here are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution.
|
||||
It uses 50 concurrent connections with no pipelining.
|
||||
|
||||
JavaScript parser:
|
||||
|
||||
PING: 20000 ops 42283.30 ops/sec 0/5/1.182
|
||||
SET: 20000 ops 32948.93 ops/sec 1/7/1.515
|
||||
GET: 20000 ops 28694.40 ops/sec 0/9/1.740
|
||||
INCR: 20000 ops 39370.08 ops/sec 0/8/1.269
|
||||
LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370
|
||||
LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048
|
||||
LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072
|
||||
|
||||
hiredis parser:
|
||||
|
||||
PING: 20000 ops 46189.38 ops/sec 1/4/1.082
|
||||
SET: 20000 ops 41237.11 ops/sec 0/6/1.210
|
||||
GET: 20000 ops 39682.54 ops/sec 1/7/1.257
|
||||
INCR: 20000 ops 40080.16 ops/sec 0/8/1.242
|
||||
LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212
|
||||
LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363
|
||||
LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287
|
||||
|
||||
The performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs.
|
||||
|
||||
|
||||
### Sending Commands
|
||||
|
||||
Each Redis command is exposed as a function on the `client` object.
|
||||
All functions take either take either an `args` Array plus optional `callback` Function or
|
||||
a variable number of individual arguments followed by an optional callback.
|
||||
Here is an example of passing an array of arguments and a callback:
|
||||
|
||||
client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});
|
||||
|
||||
Here is that same call in the second style:
|
||||
|
||||
client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});
|
||||
|
||||
Note that in either form the `callback` is optional:
|
||||
|
||||
client.set("some key", "some val");
|
||||
client.set(["some other key", "some val"]);
|
||||
|
||||
For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)
|
||||
|
||||
The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`.
|
||||
|
||||
Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,
|
||||
integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a
|
||||
JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys.
|
||||
|
||||
# API
|
||||
|
||||
## Connection Events
|
||||
|
||||
`client` will emit some events about the state of the connection to the Redis server.
|
||||
|
||||
### "ready"
|
||||
|
||||
`client` will emit `ready` a connection is established to the Redis server and the server reports
|
||||
that it is ready to receive commands. Commands issued before the `ready` event are queued,
|
||||
then replayed just before this event is emitted.
|
||||
|
||||
### "connect"
|
||||
|
||||
`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check`
|
||||
is set. If this options is set, `connect` will be emitted when the stream is connected, and then
|
||||
you are free to try to send commands.
|
||||
|
||||
### "error"
|
||||
|
||||
`client` will emit `error` when encountering an error connecting to the Redis server.
|
||||
|
||||
Note that "error" is a special event type in node. If there are no listeners for an
|
||||
"error" event, node will exit. This is usually what you want, but it can lead to some
|
||||
cryptic error messages like this:
|
||||
|
||||
mjr:~/work/node_redis (master)$ node example.js
|
||||
|
||||
node.js:50
|
||||
throw e;
|
||||
^
|
||||
Error: ECONNREFUSED, Connection refused
|
||||
at IOWatcher.callback (net:870:22)
|
||||
at node.js:607:9
|
||||
|
||||
Not very useful in diagnosing the problem, but if your program isn't ready to handle this,
|
||||
it is probably the right thing to just exit.
|
||||
|
||||
`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason.
|
||||
It would be nice to distinguish these two cases.
|
||||
|
||||
### "end"
|
||||
|
||||
`client` will emit `end` when an established Redis server connection has closed.
|
||||
|
||||
### "drain"
|
||||
|
||||
`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now
|
||||
writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,
|
||||
you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can
|
||||
resume sending when you get `drain`.
|
||||
|
||||
### "idle"
|
||||
|
||||
`client` will emit `idle` when there are no outstanding commands that are awaiting a response.
|
||||
|
||||
## redis.createClient(port, host, options)
|
||||
|
||||
Create a new client connection. `port` defaults to `6379` and `host` defaults
|
||||
to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for
|
||||
port and host are probably fine. `options` in an object with the following possible properties:
|
||||
|
||||
* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed.
|
||||
This may also be set to `javascript`.
|
||||
* `return_buffers`: defaults to false. If set to `true`, then bulk data replies will be returned as node Buffer
|
||||
objects instead of JavaScript Strings.
|
||||
|
||||
`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.
|
||||
|
||||
## client.auth(password, callback)
|
||||
|
||||
When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the
|
||||
first command after connecting. This can be tricky to coordinate with reconnections, the ready check,
|
||||
etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,
|
||||
including reconnections. `callback` is invoked only once, after the response to the very first
|
||||
`AUTH` command sent.
|
||||
|
||||
## client.end()
|
||||
|
||||
Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.
|
||||
If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies.
|
||||
|
||||
This example closes the connection to the Redis server before the replies have been read. You probably don't
|
||||
want to do this:
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
client.set("foo_rand000000000000", "some fantastic value");
|
||||
client.get("foo_rand000000000000", function (err, reply) {
|
||||
console.log(reply.toString());
|
||||
});
|
||||
client.end();
|
||||
|
||||
`client.end()` is useful for timeout cases where something is stuck or taking too long and you want
|
||||
to start over.
|
||||
|
||||
## Friendlier hash commands
|
||||
|
||||
Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. When dealing with hash values, there are a couple of useful exceptions to this.
|
||||
|
||||
### client.hgetall(hash)
|
||||
|
||||
The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact
|
||||
with the responses using JavaScript syntax.
|
||||
|
||||
Example:
|
||||
|
||||
client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234");
|
||||
client.hgetall("hosts", function (err, obj) {
|
||||
console.dir(obj);
|
||||
});
|
||||
|
||||
Output:
|
||||
|
||||
{ mjr: '1', another: '23', home: '1234' }
|
||||
|
||||
### client.hmset(hash, obj, [callback])
|
||||
|
||||
Multiple values in a hash can be set by supplying an object:
|
||||
|
||||
client.HMSET(key2, {
|
||||
"0123456789": "abcdefghij",
|
||||
"some manner of key": "a type of value"
|
||||
});
|
||||
|
||||
The properties and values of this Object will be set as keys and values in the Redis hash.
|
||||
|
||||
### client.hmset(hash, key1, val1, ... keyn, valn, [callback])
|
||||
|
||||
Multiple values may also be set by supplying a list:
|
||||
|
||||
client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value");
|
||||
|
||||
|
||||
## Publish / Subscribe
|
||||
|
||||
Here is a simple example of the API for publish / subscribe. This program opens two
|
||||
client connections, subscribes to a channel on one of them, and publishes to that
|
||||
channel on the other:
|
||||
|
||||
var redis = require("redis"),
|
||||
client1 = redis.createClient(), client2 = redis.createClient(),
|
||||
msg_count = 0;
|
||||
|
||||
client1.on("subscribe", function (channel, count) {
|
||||
client2.publish("a nice channel", "I am sending a message.");
|
||||
client2.publish("a nice channel", "I am sending a second message.");
|
||||
client2.publish("a nice channel", "I am sending my last message.");
|
||||
});
|
||||
|
||||
client1.on("message", function (channel, message) {
|
||||
console.log("client1 channel " + channel + ": " + message);
|
||||
msg_count += 1;
|
||||
if (msg_count === 3) {
|
||||
client1.unsubscribe();
|
||||
client1.end();
|
||||
client2.end();
|
||||
}
|
||||
});
|
||||
|
||||
client1.incr("did a thing");
|
||||
client1.subscribe("a nice channel");
|
||||
|
||||
When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into "pub/sub" mode.
|
||||
At that point, only commands that modify the subscription set are valid. When the subscription
|
||||
set is empty, the connection is put back into regular mode.
|
||||
|
||||
If you need to send regular commands to Redis while in pub/sub mode, just open another connection.
|
||||
|
||||
## Pub / Sub Events
|
||||
|
||||
If a client has subscriptions active, it may emit these events:
|
||||
|
||||
### "message" (channel, message)
|
||||
|
||||
Client will emit `message` for every message received that matches an active subscription.
|
||||
Listeners are passed the channel name as `channel` and the message Buffer as `message`.
|
||||
|
||||
### "pmessage" (pattern, channel, message)
|
||||
|
||||
Client will emit `pmessage` for every message received that matches an active subscription pattern.
|
||||
Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel
|
||||
name as `channel`, and the message Buffer as `message`.
|
||||
|
||||
### "subscribe" (channel, count)
|
||||
|
||||
Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the
|
||||
channel name as `channel` and the new count of subscriptions for this client as `count`.
|
||||
|
||||
### "psubscribe" (pattern, count)
|
||||
|
||||
Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the
|
||||
original pattern as `pattern`, and the new count of subscriptions for this client as `count`.
|
||||
|
||||
### "unsubscribe" (channel, count)
|
||||
|
||||
Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the
|
||||
channel name as `channel` and the new count of subscriptions for this client as `count`. When
|
||||
`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
|
||||
|
||||
### "punsubscribe" (pattern, count)
|
||||
|
||||
Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the
|
||||
channel name as `channel` and the new count of subscriptions for this client as `count`. When
|
||||
`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
|
||||
|
||||
## client.multi([commands])
|
||||
|
||||
`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by
|
||||
Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`.
|
||||
|
||||
var redis = require("./index"),
|
||||
client = redis.createClient(), set_size = 20;
|
||||
|
||||
client.sadd("bigset", "a member");
|
||||
client.sadd("bigset", "another member");
|
||||
|
||||
while (set_size > 0) {
|
||||
client.sadd("bigset", "member " + set_size);
|
||||
set_size -= 1;
|
||||
}
|
||||
|
||||
// multi chain with an individual callback
|
||||
client.multi()
|
||||
.scard("bigset")
|
||||
.smembers("bigset")
|
||||
.keys("*", function (err, replies) {
|
||||
client.mget(replies, redis.print);
|
||||
})
|
||||
.dbsize()
|
||||
.exec(function (err, replies) {
|
||||
console.log("MULTI got " + replies.length + " replies");
|
||||
replies.forEach(function (reply, index) {
|
||||
console.log("Reply " + index + ": " + reply.toString());
|
||||
});
|
||||
});
|
||||
|
||||
`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the
|
||||
same command methods as `client` objects do. Commands are queued up inside the `Multi` object
|
||||
until `Multi.exec()` is invoked.
|
||||
|
||||
You can either chain together `MULTI` commands as in the above example, or you can queue individual
|
||||
commands while still sending regular client command as in this example:
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient(), multi;
|
||||
|
||||
// start a separate multi command queue
|
||||
multi = client.multi();
|
||||
multi.incr("incr thing", redis.print);
|
||||
multi.incr("incr other thing", redis.print);
|
||||
|
||||
// runs immediately
|
||||
client.mset("incr thing", 100, "incr other thing", 1, redis.print);
|
||||
|
||||
// drains multi queue and runs atomically
|
||||
multi.exec(function (err, replies) {
|
||||
console.log(replies); // 101, 2
|
||||
});
|
||||
|
||||
// you can re-run the same transaction if you like
|
||||
multi.exec(function (err, replies) {
|
||||
console.log(replies); // 102, 3
|
||||
client.quit();
|
||||
});
|
||||
|
||||
In addition to adding commands to the `MULTI` queue individually, you can also pass an array
|
||||
of commands and arguments to the constructor:
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient(), multi;
|
||||
|
||||
client.multi([
|
||||
["mget", "multifoo", "multibar", redis.print],
|
||||
["incr", "multifoo"],
|
||||
["incr", "multibar"]
|
||||
]).exec(function (err, replies) {
|
||||
console.log(replies);
|
||||
});
|
||||
|
||||
|
||||
## Monitor mode
|
||||
|
||||
Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server
|
||||
across all client connections, including from other client libraries and other computers.
|
||||
|
||||
After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis`
|
||||
will emit a `monitor` event for every new monitor message that comes across. The callback for the
|
||||
`monitor` event takes a timestamp from the Redis server and an array of command arguments.
|
||||
|
||||
Here is a simple example:
|
||||
|
||||
var client = require("redis").createClient(),
|
||||
util = require("util");
|
||||
|
||||
client.monitor(function (err, res) {
|
||||
console.log("Entering monitoring mode.");
|
||||
});
|
||||
|
||||
client.on("monitor", function (time, args) {
|
||||
console.log(time + ": " + util.inspect(args));
|
||||
});
|
||||
|
||||
|
||||
# Extras
|
||||
|
||||
Some other things you might like to know about.
|
||||
|
||||
## client.server_info
|
||||
|
||||
After the ready probe completes, the results from the INFO command are saved in the `client.server_info`
|
||||
object.
|
||||
|
||||
The `versions` key contains an array of the elements of the version string for easy comparison.
|
||||
|
||||
> client.server_info.redis_version
|
||||
'2.3.0'
|
||||
> client.server_info.versions
|
||||
[ 2, 3, 0 ]
|
||||
|
||||
## redis.print()
|
||||
|
||||
A handy callback function for displaying return values when testing. Example:
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
client.on("connect", function () {
|
||||
client.set("foo_rand000000000000", "some fantastic value", redis.print);
|
||||
client.get("foo_rand000000000000", redis.print);
|
||||
});
|
||||
|
||||
This will print:
|
||||
|
||||
Reply: OK
|
||||
Reply: some fantastic value
|
||||
|
||||
Note that this program will not exit cleanly because the client is still connected.
|
||||
|
||||
## redis.debug_mode
|
||||
|
||||
Boolean to enable debug mode and protocol tracing.
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
redis.debug_mode = true;
|
||||
|
||||
client.on("connect", function () {
|
||||
client.set("foo_rand000000000000", "some fantastic value");
|
||||
});
|
||||
|
||||
This will display:
|
||||
|
||||
mjr:~/work/node_redis (master)$ node ~/example.js
|
||||
send command: *3
|
||||
$3
|
||||
SET
|
||||
$20
|
||||
foo_rand000000000000
|
||||
$20
|
||||
some fantastic value
|
||||
|
||||
on_data: +OK
|
||||
|
||||
`send command` is data sent into Redis and `on_data` is data received from Redis.
|
||||
|
||||
## client.send_command(command_name, args, callback)
|
||||
|
||||
Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis
|
||||
Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before
|
||||
this library is updated, you can use `send_command()` to send arbitrary commands to Redis.
|
||||
|
||||
All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or individual arguments,
|
||||
or omitted completely.
|
||||
|
||||
## client.connected
|
||||
|
||||
Boolean tracking the state of the connection to the Redis server.
|
||||
|
||||
## client.command_queue.length
|
||||
|
||||
The number of commands that have been sent to the Redis server but not yet replied to. You can use this to
|
||||
enforce some kind of maximum queue depth for commands while connected.
|
||||
|
||||
Don't mess with `client.command_queue` though unless you really know what you are doing.
|
||||
|
||||
## client.offline_queue.length
|
||||
|
||||
The number of commands that have been queued up for a future connection. You can use this to enforce
|
||||
some kind of maximum queue depth for pre-connection commands.
|
||||
|
||||
## client.retry_delay
|
||||
|
||||
Current delay in milliseconds before a connection retry will be attempted. This starts at `250`.
|
||||
|
||||
## client.retry_backoff
|
||||
|
||||
Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries.
|
||||
Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc.
|
||||
|
||||
|
||||
## TODO
|
||||
|
||||
Better tests for monitor mode, auth, disconnect/reconnect, and all combinations thereof.
|
||||
|
||||
Stream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory.
|
||||
|
||||
Performance can be better for very large values.
|
||||
|
||||
I think there are more performance improvements left in there for smaller values, especially for large lists of small values.
|
||||
|
||||
## Contributors
|
||||
|
||||
Some people have have added features and fixed bugs in `node_redis` other than me.
|
||||
|
||||
In order of first contribution, they are:
|
||||
|
||||
* [Tim Smart](https://github.com/Tim-Smart)
|
||||
* [TJ Holowaychuk](https://github.com/visionmedia)
|
||||
* [Rick Olson](https://github.com/technoweenie)
|
||||
* [Orion Henry](https://github.com/orionz)
|
||||
* [Hank Sims](https://github.com/hanksims)
|
||||
* [Aivo Paas](https://github.com/aivopaas)
|
||||
* [Paul Carey](https://github.com/paulcarey)
|
||||
* [Pieter Noordhuis](https://github.com/pietern)
|
||||
* [Vladimir Dronnikov](https://github.com/dvv)
|
||||
* [Dave Hoover](https://github.com/redsquirrel)
|
||||
|
||||
Thanks.
|
||||
|
||||
## LICENSE - "MIT License"
|
||||
|
||||
Copyright (c) 2010 Matthew Ranney, http://ranney.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.
|
||||
|
||||

|
||||
184
networking/node_modules/socket.io/node_modules/redis/changelog.md
generated
vendored
Normal file
184
networking/node_modules/socket.io/node_modules/redis/changelog.md
generated
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
## v0.6.7 - July 30, 2011
|
||||
|
||||
(accidentally skipped v0.6.6)
|
||||
|
||||
Fix and test for [GH-123]
|
||||
|
||||
Passing an Array as as the last argument should expand as users
|
||||
expect. The old behavior was to coerce the arguments into Strings,
|
||||
which did surprising things with Arrays.
|
||||
|
||||
## v0.6.5 - July 6, 2011
|
||||
|
||||
Contributed changes:
|
||||
|
||||
* Support SlowBuffers (Umair Siddique)
|
||||
* Add Multi to exports (Louis-Philippe Perron)
|
||||
* Fix for drain event calculation (Vladimir Dronnikov)
|
||||
|
||||
Thanks!
|
||||
|
||||
## v0.6.4 - June 30, 2011
|
||||
|
||||
Fix bug with optional callbacks for hmset.
|
||||
|
||||
## v0.6.2 - June 30, 2011
|
||||
|
||||
Bugs fixed:
|
||||
|
||||
* authentication retry while server is loading db (danmaz74) [GH-101]
|
||||
* command arguments processing issue with arrays
|
||||
|
||||
New features:
|
||||
|
||||
* Auto update of new commands from redis.io (Dave Hoover)
|
||||
* Performance improvements and backpressure controls.
|
||||
* Commands now return the true/false value from the underlying socket write(s).
|
||||
* Implement command_queue high water and low water for more better control of queueing.
|
||||
|
||||
See `examples/backpressure_drain.js` for more information.
|
||||
|
||||
## v0.6.1 - June 29, 2011
|
||||
|
||||
Add support and tests for Redis scripting through EXEC command.
|
||||
|
||||
Bug fix for monitor mode. (forddg)
|
||||
|
||||
Auto update of new commands from redis.io (Dave Hoover)
|
||||
|
||||
## v0.6.0 - April 21, 2011
|
||||
|
||||
Lots of bugs fixed.
|
||||
|
||||
* connection error did not properly trigger reconnection logic [GH-85]
|
||||
* client.hmget(key, [val1, val2]) was not expanding properly [GH-66]
|
||||
* client.quit() while in pub/sub mode would throw an error [GH-87]
|
||||
* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92]
|
||||
* unsubscribe before subscribe would make things very confused [GH-88]
|
||||
* Add BRPOPLPUSH [GH-79]
|
||||
|
||||
## v0.5.11 - April 7, 2011
|
||||
|
||||
Added DISCARD
|
||||
|
||||
I originally didn't think DISCARD would do anything here because of the clever MULTI interface, but somebody
|
||||
pointed out to me that DISCARD can be used to flush the WATCH set.
|
||||
|
||||
## v0.5.10 - April 6, 2011
|
||||
|
||||
Added HVALS
|
||||
|
||||
## v0.5.9 - March 14, 2011
|
||||
|
||||
Fix bug with empty Array arguments - Andy Ray
|
||||
|
||||
## v0.5.8 - March 14, 2011
|
||||
|
||||
Add `MONITOR` command and special monitor command reply parsing.
|
||||
|
||||
## v0.5.7 - February 27, 2011
|
||||
|
||||
Add magical auth command.
|
||||
|
||||
Authentication is now remembered by the client and will be automatically sent to the server
|
||||
on every connection, including any reconnections.
|
||||
|
||||
## v0.5.6 - February 22, 2011
|
||||
|
||||
Fix bug in ready check with `return_buffers` set to `true`.
|
||||
|
||||
Thanks to Dean Mao and Austin Chau.
|
||||
|
||||
## v0.5.5 - February 16, 2011
|
||||
|
||||
Add probe for server readiness.
|
||||
|
||||
When a Redis server starts up, it might take a while to load the dataset into memory.
|
||||
During this time, the server will accept connections, but will return errors for all non-INFO
|
||||
commands. Now node_redis will send an INFO command whenever it connects to a server.
|
||||
If the info command indicates that the server is not ready, the client will keep trying until
|
||||
the server is ready. Once it is ready, the client will emit a "ready" event as well as the
|
||||
"connect" event. The client will queue up all commands sent before the server is ready, just
|
||||
like it did before. When the server is ready, all offline/non-ready commands will be replayed.
|
||||
This should be backward compatible with previous versions.
|
||||
|
||||
To disable this ready check behavior, set `options.no_ready_check` when creating the client.
|
||||
|
||||
As a side effect of this change, the key/val params from the info command are available as
|
||||
`client.server_options`. Further, the version string is decomposed into individual elements
|
||||
in `client.server_options.versions`.
|
||||
|
||||
## v0.5.4 - February 11, 2011
|
||||
|
||||
Fix excess memory consumption from Queue backing store.
|
||||
|
||||
Thanks to Gustaf Sjöberg.
|
||||
|
||||
## v0.5.3 - February 5, 2011
|
||||
|
||||
Fix multi/exec error reply callback logic.
|
||||
|
||||
Thanks to Stella Laurenzo.
|
||||
|
||||
## v0.5.2 - January 18, 2011
|
||||
|
||||
Fix bug where unhandled error replies confuse the parser.
|
||||
|
||||
## v0.5.1 - January 18, 2011
|
||||
|
||||
Fix bug where subscribe commands would not handle redis-server startup error properly.
|
||||
|
||||
## v0.5.0 - December 29, 2010
|
||||
|
||||
Some bug fixes:
|
||||
|
||||
* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after
|
||||
a reconnect.
|
||||
* Changed error callback argument to be an actual Error object.
|
||||
|
||||
New feature:
|
||||
|
||||
* Add friendly syntax for HMSET using an object.
|
||||
|
||||
## v0.4.1 - December 8, 2010
|
||||
|
||||
Remove warning about missing hiredis. You probably do want it though.
|
||||
|
||||
## v0.4.0 - December 5, 2010
|
||||
|
||||
Support for multiple response parsers and hiredis C library from Pieter Noordhuis.
|
||||
Return Strings instead of Buffers by default.
|
||||
Empty nested mb reply bug fix.
|
||||
|
||||
## v0.3.9 - November 30, 2010
|
||||
|
||||
Fix parser bug on failed EXECs.
|
||||
|
||||
## v0.3.8 - November 10, 2010
|
||||
|
||||
Fix for null MULTI response when WATCH condition fails.
|
||||
|
||||
## v0.3.7 - November 9, 2010
|
||||
|
||||
Add "drain" and "idle" events.
|
||||
|
||||
## v0.3.6 - November 3, 2010
|
||||
|
||||
Add all known Redis commands from Redis master, even ones that are coming in 2.2 and beyond.
|
||||
|
||||
Send a friendlier "error" event message on stream errors like connection refused / reset.
|
||||
|
||||
## v0.3.5 - October 21, 2010
|
||||
|
||||
A few bug fixes.
|
||||
|
||||
* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts.
|
||||
* Only emit `end` once when connection goes away.
|
||||
* Fixed bug in `test.js` where driver finished before all tests completed.
|
||||
|
||||
## unversioned wasteland
|
||||
|
||||
See the git history for what happened before.
|
||||
9
networking/node_modules/socket.io/node_modules/redis/eval_test.js
generated
vendored
Normal file
9
networking/node_modules/socket.io/node_modules/redis/eval_test.js
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
var redis = require("./index"),
|
||||
client = redis.createClient();
|
||||
|
||||
redis.debug_mode = true;
|
||||
|
||||
client.eval("return 100.5", 0, function (err, res) {
|
||||
console.dir(err);
|
||||
console.dir(res);
|
||||
});
|
||||
5
networking/node_modules/socket.io/node_modules/redis/examples/auth.js
generated
vendored
Normal file
5
networking/node_modules/socket.io/node_modules/redis/examples/auth.js
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
// This command is magical. Client stashes the password and will issue on every connect.
|
||||
client.auth("somepass");
|
||||
33
networking/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js
generated
vendored
Normal file
33
networking/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
var redis = require("../index"),
|
||||
client = redis.createClient(null, null, {
|
||||
command_queue_high_water: 5,
|
||||
command_queue_low_water: 1
|
||||
}),
|
||||
remaining_ops = 100000, paused = false;
|
||||
|
||||
function op() {
|
||||
if (remaining_ops <= 0) {
|
||||
console.error("Finished.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
remaining_ops--;
|
||||
if (client.hset("test hash", "val " + remaining_ops, remaining_ops) === false) {
|
||||
console.log("Pausing at " + remaining_ops);
|
||||
paused = true;
|
||||
} else {
|
||||
process.nextTick(op);
|
||||
}
|
||||
}
|
||||
|
||||
client.on("drain", function () {
|
||||
if (paused) {
|
||||
console.log("Resuming at " + remaining_ops);
|
||||
paused = false;
|
||||
process.nextTick(op);
|
||||
} else {
|
||||
console.log("Got drain while not paused at " + remaining_ops);
|
||||
}
|
||||
});
|
||||
|
||||
op();
|
||||
24
networking/node_modules/socket.io/node_modules/redis/examples/extend.js
generated
vendored
Normal file
24
networking/node_modules/socket.io/node_modules/redis/examples/extend.js
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
// Extend the RedisClient prototype to add a custom method
|
||||
// This one converts the results from "INFO" into a JavaScript Object
|
||||
|
||||
redis.RedisClient.prototype.parse_info = function (callback) {
|
||||
this.info(function (err, res) {
|
||||
var lines = res.toString().split("\r\n").sort();
|
||||
var obj = {};
|
||||
lines.forEach(function (line) {
|
||||
var parts = line.split(':');
|
||||
if (parts[1]) {
|
||||
obj[parts[0]] = parts[1];
|
||||
}
|
||||
});
|
||||
callback(obj)
|
||||
});
|
||||
};
|
||||
|
||||
client.parse_info(function (info) {
|
||||
console.dir(info);
|
||||
client.quit();
|
||||
});
|
||||
32
networking/node_modules/socket.io/node_modules/redis/examples/file.js
generated
vendored
Normal file
32
networking/node_modules/socket.io/node_modules/redis/examples/file.js
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Read a file from disk, store it in Redis, then read it back from Redis.
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient(),
|
||||
fs = require("fs"),
|
||||
filename = "kids_in_cart.jpg";
|
||||
|
||||
// Get the file I use for testing like this:
|
||||
// curl http://ranney.com/kids_in_cart.jpg -o kids_in_cart.jpg
|
||||
// or just use your own file.
|
||||
|
||||
// Read a file from fs, store it in Redis, get it back from Redis, write it back to fs.
|
||||
fs.readFile(filename, function (err, data) {
|
||||
if (err) throw err
|
||||
console.log("Read " + data.length + " bytes from filesystem.");
|
||||
|
||||
client.set(filename, data, redis.print); // set entire file
|
||||
client.get(filename, function (err, reply) { // get entire file
|
||||
if (err) {
|
||||
console.log("Get error: " + err);
|
||||
} else {
|
||||
fs.writeFile("duplicate_" + filename, reply, function (err) {
|
||||
if (err) {
|
||||
console.log("Error on write: " + err)
|
||||
} else {
|
||||
console.log("File written.");
|
||||
}
|
||||
client.end();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
5
networking/node_modules/socket.io/node_modules/redis/examples/mget.js
generated
vendored
Normal file
5
networking/node_modules/socket.io/node_modules/redis/examples/mget.js
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
var client = require("redis").createClient();
|
||||
|
||||
client.mget(["sessions started", "sessions started", "foo"], function (err, res) {
|
||||
console.dir(res);
|
||||
});
|
||||
10
networking/node_modules/socket.io/node_modules/redis/examples/monitor.js
generated
vendored
Normal file
10
networking/node_modules/socket.io/node_modules/redis/examples/monitor.js
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
var client = require("../index").createClient(),
|
||||
util = require("util");
|
||||
|
||||
client.monitor(function (err, res) {
|
||||
console.log("Entering monitoring mode.");
|
||||
});
|
||||
|
||||
client.on("monitor", function (time, args) {
|
||||
console.log(time + ": " + util.inspect(args));
|
||||
});
|
||||
46
networking/node_modules/socket.io/node_modules/redis/examples/multi.js
generated
vendored
Normal file
46
networking/node_modules/socket.io/node_modules/redis/examples/multi.js
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
var redis = require("redis"),
|
||||
client = redis.createClient(), set_size = 20;
|
||||
|
||||
client.sadd("bigset", "a member");
|
||||
client.sadd("bigset", "another member");
|
||||
|
||||
while (set_size > 0) {
|
||||
client.sadd("bigset", "member " + set_size);
|
||||
set_size -= 1;
|
||||
}
|
||||
|
||||
// multi chain with an individual callback
|
||||
client.multi()
|
||||
.scard("bigset")
|
||||
.smembers("bigset")
|
||||
.keys("*", function (err, replies) {
|
||||
client.mget(replies, redis.print);
|
||||
})
|
||||
.dbsize()
|
||||
.exec(function (err, replies) {
|
||||
console.log("MULTI got " + replies.length + " replies");
|
||||
replies.forEach(function (reply, index) {
|
||||
console.log("Reply " + index + ": " + reply.toString());
|
||||
});
|
||||
});
|
||||
|
||||
client.mset("incr thing", 100, "incr other thing", 1, redis.print);
|
||||
|
||||
// start a separate multi command queue
|
||||
var multi = client.multi();
|
||||
multi.incr("incr thing", redis.print);
|
||||
multi.incr("incr other thing", redis.print);
|
||||
|
||||
// runs immediately
|
||||
client.get("incr thing", redis.print); // 100
|
||||
|
||||
// drains multi queue and runs atomically
|
||||
multi.exec(function (err, replies) {
|
||||
console.log(replies); // 101, 2
|
||||
});
|
||||
|
||||
// you can re-run the same transaction if you like
|
||||
multi.exec(function (err, replies) {
|
||||
console.log(replies); // 102, 3
|
||||
client.quit();
|
||||
});
|
||||
29
networking/node_modules/socket.io/node_modules/redis/examples/multi2.js
generated
vendored
Normal file
29
networking/node_modules/socket.io/node_modules/redis/examples/multi2.js
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
var redis = require("redis"),
|
||||
client = redis.createClient(), multi;
|
||||
|
||||
// start a separate command queue for multi
|
||||
multi = client.multi();
|
||||
multi.incr("incr thing", redis.print);
|
||||
multi.incr("incr other thing", redis.print);
|
||||
|
||||
// runs immediately
|
||||
client.mset("incr thing", 100, "incr other thing", 1, redis.print);
|
||||
|
||||
// drains multi queue and runs atomically
|
||||
multi.exec(function (err, replies) {
|
||||
console.log(replies); // 101, 2
|
||||
});
|
||||
|
||||
// you can re-run the same transaction if you like
|
||||
multi.exec(function (err, replies) {
|
||||
console.log(replies); // 102, 3
|
||||
client.quit();
|
||||
});
|
||||
|
||||
client.multi([
|
||||
["mget", "multifoo", "multibar", redis.print],
|
||||
["incr", "multifoo"],
|
||||
["incr", "multibar"]
|
||||
]).exec(function (err, replies) {
|
||||
console.log(replies.toString());
|
||||
});
|
||||
33
networking/node_modules/socket.io/node_modules/redis/examples/psubscribe.js
generated
vendored
Normal file
33
networking/node_modules/socket.io/node_modules/redis/examples/psubscribe.js
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
var redis = require("redis"),
|
||||
client1 = redis.createClient(),
|
||||
client2 = redis.createClient(),
|
||||
client3 = redis.createClient(),
|
||||
client4 = redis.createClient(),
|
||||
msg_count = 0;
|
||||
|
||||
redis.debug_mode = false;
|
||||
|
||||
client1.on("psubscribe", function (pattern, count) {
|
||||
console.log("client1 psubscribed to " + pattern + ", " + count + " total subscriptions");
|
||||
client2.publish("channeltwo", "Me!");
|
||||
client3.publish("channelthree", "Me too!");
|
||||
client4.publish("channelfour", "And me too!");
|
||||
});
|
||||
|
||||
client1.on("punsubscribe", function (pattern, count) {
|
||||
console.log("client1 punsubscribed from " + pattern + ", " + count + " total subscriptions");
|
||||
client4.end();
|
||||
client3.end();
|
||||
client2.end();
|
||||
client1.end();
|
||||
});
|
||||
|
||||
client1.on("pmessage", function (pattern, channel, message) {
|
||||
console.log("("+ pattern +")" + " client1 received message on " + channel + ": " + message);
|
||||
msg_count += 1;
|
||||
if (msg_count === 3) {
|
||||
client1.punsubscribe();
|
||||
}
|
||||
});
|
||||
|
||||
client1.psubscribe("channel*");
|
||||
41
networking/node_modules/socket.io/node_modules/redis/examples/pub_sub.js
generated
vendored
Normal file
41
networking/node_modules/socket.io/node_modules/redis/examples/pub_sub.js
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
var redis = require("redis"),
|
||||
client1 = redis.createClient(), msg_count = 0,
|
||||
client2 = redis.createClient();
|
||||
|
||||
redis.debug_mode = false;
|
||||
|
||||
// Most clients probably don't do much on "subscribe". This example uses it to coordinate things within one program.
|
||||
client1.on("subscribe", function (channel, count) {
|
||||
console.log("client1 subscribed to " + channel + ", " + count + " total subscriptions");
|
||||
if (count === 2) {
|
||||
client2.publish("a nice channel", "I am sending a message.");
|
||||
client2.publish("another one", "I am sending a second message.");
|
||||
client2.publish("a nice channel", "I am sending my last message.");
|
||||
}
|
||||
});
|
||||
|
||||
client1.on("unsubscribe", function (channel, count) {
|
||||
console.log("client1 unsubscribed from " + channel + ", " + count + " total subscriptions");
|
||||
if (count === 0) {
|
||||
client2.end();
|
||||
client1.end();
|
||||
}
|
||||
});
|
||||
|
||||
client1.on("message", function (channel, message) {
|
||||
console.log("client1 channel " + channel + ": " + message);
|
||||
msg_count += 1;
|
||||
if (msg_count === 3) {
|
||||
client1.unsubscribe();
|
||||
}
|
||||
});
|
||||
|
||||
client1.on("ready", function () {
|
||||
// if you need auth, do it here
|
||||
client1.incr("did a thing");
|
||||
client1.subscribe("a nice channel", "another one");
|
||||
});
|
||||
|
||||
client2.on("ready", function () {
|
||||
// if you need auth, do it here
|
||||
});
|
||||
17
networking/node_modules/socket.io/node_modules/redis/examples/simple.js
generated
vendored
Normal file
17
networking/node_modules/socket.io/node_modules/redis/examples/simple.js
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
client.on("error", function (err) {
|
||||
console.log("Redis connection error to " + client.host + ":" + client.port + " - " + err);
|
||||
});
|
||||
|
||||
client.set("string key", "string val", redis.print);
|
||||
client.hset("hash key", "hashtest 1", "some value", redis.print);
|
||||
client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
|
||||
client.hkeys("hash key", function (err, replies) {
|
||||
console.log(replies.length + " replies:");
|
||||
replies.forEach(function (reply, i) {
|
||||
console.log(" " + i + ": " + reply);
|
||||
});
|
||||
client.quit();
|
||||
});
|
||||
15
networking/node_modules/socket.io/node_modules/redis/examples/subqueries.js
generated
vendored
Normal file
15
networking/node_modules/socket.io/node_modules/redis/examples/subqueries.js
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Sending commands in response to other commands.
|
||||
// This example runs "type" against every key in the database
|
||||
//
|
||||
var client = require("redis").createClient();
|
||||
|
||||
client.keys("*", function (err, keys) {
|
||||
keys.forEach(function (key, pos) {
|
||||
client.type(key, function (err, keytype) {
|
||||
console.log(key + " is " + keytype);
|
||||
if (pos === (keys.length - 1)) {
|
||||
client.quit();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
19
networking/node_modules/socket.io/node_modules/redis/examples/subquery.js
generated
vendored
Normal file
19
networking/node_modules/socket.io/node_modules/redis/examples/subquery.js
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
var client = require("redis").createClient();
|
||||
|
||||
function print_results(obj) {
|
||||
console.dir(obj);
|
||||
}
|
||||
|
||||
// build a map of all keys and their types
|
||||
client.keys("*", function (err, all_keys) {
|
||||
var key_types = {};
|
||||
|
||||
all_keys.forEach(function (key, pos) { // use second arg of forEach to get pos
|
||||
client.type(key, function (err, type) {
|
||||
key_types[key] = type;
|
||||
if (pos === all_keys.length - 1) { // callbacks all run in order
|
||||
print_results(key_types);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
29
networking/node_modules/socket.io/node_modules/redis/examples/unix_socket.js
generated
vendored
Normal file
29
networking/node_modules/socket.io/node_modules/redis/examples/unix_socket.js
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
var redis = require("redis"),
|
||||
client = redis.createClient("/tmp/redis.sock"),
|
||||
profiler = require("v8-profiler");
|
||||
|
||||
client.on("connect", function () {
|
||||
console.log("Got Unix socket connection.")
|
||||
});
|
||||
|
||||
client.on("error", function (err) {
|
||||
console.log(err.message);
|
||||
});
|
||||
|
||||
client.set("space chars", "space value");
|
||||
|
||||
setInterval(function () {
|
||||
client.get("space chars");
|
||||
}, 100);
|
||||
|
||||
function done() {
|
||||
client.info(function (err, reply) {
|
||||
console.log(reply.toString());
|
||||
client.quit();
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
console.log("Taking snapshot.");
|
||||
var snap = profiler.takeSnapshot();
|
||||
}, 5000);
|
||||
31
networking/node_modules/socket.io/node_modules/redis/examples/web_server.js
generated
vendored
Normal file
31
networking/node_modules/socket.io/node_modules/redis/examples/web_server.js
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// A simple web server that generates dyanmic content based on responses from Redis
|
||||
|
||||
var http = require("http"), server,
|
||||
redis_client = require("redis").createClient();
|
||||
|
||||
server = http.createServer(function (request, response) {
|
||||
response.writeHead(200, {
|
||||
"Content-Type": "text/plain"
|
||||
});
|
||||
|
||||
var redis_info, total_requests;
|
||||
|
||||
redis_client.info(function (err, reply) {
|
||||
redis_info = reply; // stash response in outer scope
|
||||
});
|
||||
redis_client.incr("requests", function (err, reply) {
|
||||
total_requests = reply; // stash response in outer scope
|
||||
});
|
||||
redis_client.hincrby("ip", request.connection.remoteAddress, 1);
|
||||
redis_client.hgetall("ip", function (err, reply) {
|
||||
// This is the last reply, so all of the previous replies must have completed already
|
||||
response.write("This page was generated after talking to redis.\n\n" +
|
||||
"Redis info:\n" + redis_info + "\n" +
|
||||
"Total requests: " + total_requests + "\n\n" +
|
||||
"IP count: \n");
|
||||
Object.keys(reply).forEach(function (ip) {
|
||||
response.write(" " + ip + ": " + reply[ip] + "\n");
|
||||
});
|
||||
response.end();
|
||||
});
|
||||
}).listen(80);
|
||||
40
networking/node_modules/socket.io/node_modules/redis/generate_commands.js
generated
vendored
Normal file
40
networking/node_modules/socket.io/node_modules/redis/generate_commands.js
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
var http = require("http"),
|
||||
sys = require("sys"),
|
||||
fs = require("fs");
|
||||
|
||||
function prettyCurrentTime() {
|
||||
var date = new Date();
|
||||
return date.toLocaleString();
|
||||
}
|
||||
|
||||
function write_file(commands, path) {
|
||||
var file_contents, out_commands;
|
||||
|
||||
console.log("Writing " + Object.keys(commands).length + " commands to " + path);
|
||||
|
||||
file_contents = "// This file was generated by ./generate_commands.js on " + prettyCurrentTime() + "\n";
|
||||
|
||||
out_commands = Object.keys(commands).map(function (key) {
|
||||
return key.toLowerCase();
|
||||
});
|
||||
|
||||
file_contents += "module.exports = " + JSON.stringify(out_commands, null, " ") + ";\n";
|
||||
|
||||
fs.writeFile(path, file_contents);
|
||||
}
|
||||
|
||||
http.get({host: "redis.io", path: "/commands.json"}, function (res) {
|
||||
var body = "";
|
||||
|
||||
console.log("Response from redis.io/commands.json: " + res.statusCode);
|
||||
|
||||
res.on('data', function (chunk) {
|
||||
body += chunk;
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
write_file(JSON.parse(body), "lib/commands.js");
|
||||
});
|
||||
}).on('error', function (e) {
|
||||
console.log("Error fetching command list from redis.io: " + e.message);
|
||||
});
|
||||
860
networking/node_modules/socket.io/node_modules/redis/index.js
generated
vendored
Normal file
860
networking/node_modules/socket.io/node_modules/redis/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,860 @@
|
|||
/*global Buffer require exports console setTimeout */
|
||||
|
||||
var net = require("net"),
|
||||
util = require("./lib/util").util,
|
||||
Queue = require("./lib/queue").Queue,
|
||||
to_array = require("./lib/to_array"),
|
||||
events = require("events"),
|
||||
parsers = [], commands,
|
||||
default_port = 6379,
|
||||
default_host = "127.0.0.1";
|
||||
|
||||
// can set this to true to enable for all connections
|
||||
exports.debug_mode = false;
|
||||
|
||||
// hiredis might not be installed
|
||||
try {
|
||||
require("./lib/parser/hiredis");
|
||||
parsers.push(require("./lib/parser/hiredis"));
|
||||
} catch (err) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("hiredis parser not installed.");
|
||||
}
|
||||
}
|
||||
|
||||
parsers.push(require("./lib/parser/javascript"));
|
||||
|
||||
function RedisClient(stream, options) {
|
||||
this.stream = stream;
|
||||
this.options = options || {};
|
||||
|
||||
this.connected = false;
|
||||
this.ready = false;
|
||||
this.connections = 0;
|
||||
this.attempts = 1;
|
||||
this.should_buffer = false;
|
||||
this.command_queue_high_water = this.options.command_queue_high_water || 1000;
|
||||
this.command_queue_low_water = this.options.command_queue_low_water || 0;
|
||||
this.command_queue = new Queue(); // holds sent commands to de-pipeline them
|
||||
this.offline_queue = new Queue(); // holds commands issued but not able to be sent
|
||||
this.commands_sent = 0;
|
||||
this.retry_delay = 250; // inital reconnection delay
|
||||
this.current_retry_delay = this.retry_delay;
|
||||
this.retry_backoff = 1.7; // each retry waits current delay * retry_backoff
|
||||
this.subscriptions = false;
|
||||
this.monitoring = false;
|
||||
this.closing = false;
|
||||
this.server_info = {};
|
||||
this.auth_pass = null;
|
||||
|
||||
var parser_module, self = this;
|
||||
|
||||
if (self.options.parser) {
|
||||
if (! parsers.some(function (parser) {
|
||||
if (parser.name === self.options.parser) {
|
||||
parser_module = parser;
|
||||
if (exports.debug_mode) {
|
||||
console.log("Using parser module: " + parser_module.name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})) {
|
||||
throw new Error("Couldn't find named parser " + self.options.parser + " on this system");
|
||||
}
|
||||
} else {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Using default parser module: " + parsers[0].name);
|
||||
}
|
||||
parser_module = parsers[0];
|
||||
}
|
||||
|
||||
parser_module.debug_mode = exports.debug_mode;
|
||||
this.reply_parser = new parser_module.Parser({
|
||||
return_buffers: self.options.return_buffers || false
|
||||
});
|
||||
|
||||
// "reply error" is an error sent back by Redis
|
||||
this.reply_parser.on("reply error", function (reply) {
|
||||
self.return_error(new Error(reply));
|
||||
});
|
||||
this.reply_parser.on("reply", function (reply) {
|
||||
self.return_reply(reply);
|
||||
});
|
||||
// "error" is bad. Somehow the parser got confused. It'll try to reset and continue.
|
||||
this.reply_parser.on("error", function (err) {
|
||||
self.emit("error", new Error("Redis reply parser error: " + err.stack));
|
||||
});
|
||||
|
||||
this.stream.on("connect", function () {
|
||||
self.on_connect();
|
||||
});
|
||||
|
||||
this.stream.on("data", function (buffer_from_socket) {
|
||||
self.on_data(buffer_from_socket);
|
||||
});
|
||||
|
||||
this.stream.on("error", function (msg) {
|
||||
if (this.closing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var message = "Redis connection to " + self.host + ":" + self.port + " failed - " + msg.message;
|
||||
|
||||
if (exports.debug_mode) {
|
||||
console.warn(message);
|
||||
}
|
||||
self.offline_queue.forEach(function (args) {
|
||||
if (typeof args[2] === "function") {
|
||||
args[2](message);
|
||||
}
|
||||
});
|
||||
self.offline_queue = new Queue();
|
||||
|
||||
self.command_queue.forEach(function (args) {
|
||||
if (typeof args[2] === "function") {
|
||||
args[2](message);
|
||||
}
|
||||
});
|
||||
self.command_queue = new Queue();
|
||||
|
||||
self.connected = false;
|
||||
self.ready = false;
|
||||
|
||||
self.emit("error", new Error(message));
|
||||
// "error" events get turned into exceptions if they aren't listened for. If the user handled this error
|
||||
// then we should try to reconnect.
|
||||
self.connection_gone("error");
|
||||
});
|
||||
|
||||
this.stream.on("close", function () {
|
||||
self.connection_gone("close");
|
||||
});
|
||||
|
||||
this.stream.on("end", function () {
|
||||
self.connection_gone("end");
|
||||
});
|
||||
|
||||
this.stream.on("drain", function () {
|
||||
self.should_buffer = false;
|
||||
self.emit("drain");
|
||||
});
|
||||
|
||||
events.EventEmitter.call(this);
|
||||
}
|
||||
util.inherits(RedisClient, events.EventEmitter);
|
||||
exports.RedisClient = RedisClient;
|
||||
|
||||
RedisClient.prototype.do_auth = function () {
|
||||
var self = this;
|
||||
|
||||
if (exports.debug_mode) {
|
||||
console.log("Sending auth to " + self.host + ":" + self.port + " fd " + self.stream.fd);
|
||||
}
|
||||
self.send_anyway = true;
|
||||
self.send_command("auth", [this.auth_pass], function (err, res) {
|
||||
if (err) {
|
||||
if (err.toString().match("LOADING")) {
|
||||
// if redis is still loading the db, it will not authenticate and everything else will fail
|
||||
console.log("Redis still loading, trying to authenticate later");
|
||||
setTimeout(function () {
|
||||
self.do_auth();
|
||||
}, 2000); // TODO - magic number alert
|
||||
return;
|
||||
} else {
|
||||
return self.emit("error", "Auth error: " + err);
|
||||
}
|
||||
}
|
||||
if (res.toString() !== "OK") {
|
||||
return self.emit("error", "Auth failed: " + res.toString());
|
||||
}
|
||||
if (exports.debug_mode) {
|
||||
console.log("Auth succeeded " + self.host + ":" + self.port + " fd " + self.stream.fd);
|
||||
}
|
||||
if (self.auth_callback) {
|
||||
self.auth_callback(err, res);
|
||||
self.auth_callback = null;
|
||||
}
|
||||
|
||||
// now we are really connected
|
||||
self.emit("connect");
|
||||
if (self.options.no_ready_check) {
|
||||
self.ready = true;
|
||||
self.send_offline_queue();
|
||||
} else {
|
||||
self.ready_check();
|
||||
}
|
||||
});
|
||||
self.send_anyway = false;
|
||||
};
|
||||
|
||||
RedisClient.prototype.on_connect = function () {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Stream connected " + this.host + ":" + this.port + " fd " + this.stream.fd);
|
||||
}
|
||||
var self = this;
|
||||
|
||||
this.connected = true;
|
||||
this.ready = false;
|
||||
this.attempts = 0;
|
||||
this.connections += 1;
|
||||
this.command_queue = new Queue();
|
||||
this.emitted_end = false;
|
||||
this.retry_timer = null;
|
||||
this.current_retry_delay = this.retry_time;
|
||||
this.stream.setNoDelay();
|
||||
this.stream.setTimeout(0);
|
||||
|
||||
if (this.auth_pass) {
|
||||
this.do_auth();
|
||||
} else {
|
||||
this.emit("connect");
|
||||
|
||||
if (this.options.no_ready_check) {
|
||||
this.ready = true;
|
||||
this.send_offline_queue();
|
||||
} else {
|
||||
this.ready_check();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RedisClient.prototype.ready_check = function () {
|
||||
var self = this;
|
||||
|
||||
function send_info_cmd() {
|
||||
if (exports.debug_mode) {
|
||||
console.log("checking server ready state...");
|
||||
}
|
||||
|
||||
self.send_anyway = true; // secret flag to send_command to send something even if not "ready"
|
||||
self.info(function (err, res) {
|
||||
if (err) {
|
||||
return self.emit("error", "Ready check failed: " + err);
|
||||
}
|
||||
|
||||
var lines = res.toString().split("\r\n"), obj = {}, retry_time;
|
||||
|
||||
lines.forEach(function (line) {
|
||||
var parts = line.split(':');
|
||||
if (parts[1]) {
|
||||
obj[parts[0]] = parts[1];
|
||||
}
|
||||
});
|
||||
|
||||
obj.versions = [];
|
||||
obj.redis_version.split('.').forEach(function (num) {
|
||||
obj.versions.push(+num);
|
||||
});
|
||||
|
||||
// expose info key/vals to users
|
||||
self.server_info = obj;
|
||||
|
||||
if (!obj.loading || (obj.loading && obj.loading === "0")) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Redis server ready.");
|
||||
}
|
||||
self.ready = true;
|
||||
|
||||
self.send_offline_queue();
|
||||
self.emit("ready");
|
||||
} else {
|
||||
retry_time = obj.loading_eta_seconds * 1000;
|
||||
if (retry_time > 1000) {
|
||||
retry_time = 1000;
|
||||
}
|
||||
if (exports.debug_mode) {
|
||||
console.log("Redis server still loading, trying again in " + retry_time);
|
||||
}
|
||||
setTimeout(send_info_cmd, retry_time);
|
||||
}
|
||||
});
|
||||
self.send_anyway = false;
|
||||
}
|
||||
|
||||
send_info_cmd();
|
||||
};
|
||||
|
||||
RedisClient.prototype.send_offline_queue = function () {
|
||||
var command_obj, buffered_writes = 0;
|
||||
while (this.offline_queue.length > 0) {
|
||||
command_obj = this.offline_queue.shift();
|
||||
if (exports.debug_mode) {
|
||||
console.log("Sending offline command: " + command_obj.command);
|
||||
}
|
||||
buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback);
|
||||
}
|
||||
this.offline_queue = new Queue();
|
||||
// Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue
|
||||
|
||||
if (!buffered_writes) {
|
||||
this.should_buffer = false;
|
||||
this.emit("drain");
|
||||
}
|
||||
};
|
||||
|
||||
RedisClient.prototype.connection_gone = function (why) {
|
||||
var self = this;
|
||||
|
||||
// If a retry is already in progress, just let that happen
|
||||
if (this.retry_timer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that this may trigger another "close" or "end" event
|
||||
this.stream.destroy();
|
||||
|
||||
if (exports.debug_mode) {
|
||||
console.warn("Redis connection is gone from " + why + " event.");
|
||||
}
|
||||
this.connected = false;
|
||||
this.ready = false;
|
||||
this.subscriptions = false;
|
||||
this.monitoring = false;
|
||||
|
||||
// since we are collapsing end and close, users don't expect to be called twice
|
||||
if (! this.emitted_end) {
|
||||
this.emit("end");
|
||||
this.emitted_end = true;
|
||||
}
|
||||
|
||||
this.command_queue.forEach(function (args) {
|
||||
if (typeof args[2] === "function") {
|
||||
args[2]("Server connection closed");
|
||||
}
|
||||
});
|
||||
this.command_queue = new Queue();
|
||||
|
||||
// If this is a requested shutdown, then don't retry
|
||||
if (this.closing) {
|
||||
this.retry_timer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.current_retry_delay = this.retry_delay * this.retry_backoff;
|
||||
|
||||
if (exports.debug_mode) {
|
||||
console.log("Retry connection in " + this.current_retry_delay + " ms");
|
||||
}
|
||||
this.attempts += 1;
|
||||
this.emit("reconnecting", {
|
||||
delay: this.current_retry_delay,
|
||||
attempt: this.attempts
|
||||
});
|
||||
this.retry_timer = setTimeout(function () {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Retrying connection...");
|
||||
}
|
||||
self.stream.connect(self.port, self.host);
|
||||
self.retry_timer = null;
|
||||
}, this.current_retry_delay);
|
||||
};
|
||||
|
||||
RedisClient.prototype.on_data = function (data) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("net read " + this.host + ":" + this.port + " fd " + this.stream.fd + ": " + data.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
this.reply_parser.execute(data);
|
||||
} catch (err) {
|
||||
// This is an unexpected parser problem, an exception that came from the parser code itself.
|
||||
// Parser should emit "error" events if it notices things are out of whack.
|
||||
// Callbacks that throw exceptions will land in return_reply(), below.
|
||||
// TODO - it might be nice to have a different "error" event for different types of errors
|
||||
this.emit("error", err);
|
||||
}
|
||||
};
|
||||
|
||||
RedisClient.prototype.return_error = function (err) {
|
||||
var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength();
|
||||
|
||||
if (this.subscriptions === false && queue_len === 0) {
|
||||
this.emit("idle");
|
||||
this.command_queue = new Queue();
|
||||
}
|
||||
if (this.should_buffer && queue_len <= this.command_queue_low_water) {
|
||||
this.emit("drain");
|
||||
this.should_buffer = false;
|
||||
}
|
||||
|
||||
if (command_obj && typeof command_obj.callback === "function") {
|
||||
try {
|
||||
command_obj.callback(err);
|
||||
} catch (callback_err) {
|
||||
// if a callback throws an exception, re-throw it on a new stack so the parser can keep going
|
||||
process.nextTick(function () {
|
||||
throw callback_err;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log("node_redis: no callback to send error: " + err.message);
|
||||
// this will probably not make it anywhere useful, but we might as well throw
|
||||
process.nextTick(function () {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
RedisClient.prototype.return_reply = function (reply) {
|
||||
var command_obj = this.command_queue.shift(),
|
||||
obj, i, len, key, val, type, timestamp, args, queue_len = this.command_queue.getLength();
|
||||
|
||||
if (this.subscriptions === false && queue_len === 0) {
|
||||
this.emit("idle");
|
||||
this.command_queue = new Queue(); // explicitly reclaim storage from old Queue
|
||||
}
|
||||
if (this.should_buffer && queue_len <= this.command_queue_low_water) {
|
||||
this.emit("drain");
|
||||
this.should_buffer = false;
|
||||
}
|
||||
|
||||
if (command_obj && !command_obj.sub_command) {
|
||||
if (typeof command_obj.callback === "function") {
|
||||
// HGETALL special case replies with keyed Buffers
|
||||
if (reply && 'hgetall' === command_obj.command.toLowerCase()) {
|
||||
obj = {};
|
||||
for (i = 0, len = reply.length; i < len; i += 2) {
|
||||
key = reply[i].toString();
|
||||
val = reply[i + 1];
|
||||
obj[key] = val;
|
||||
}
|
||||
reply = obj;
|
||||
}
|
||||
|
||||
try {
|
||||
command_obj.callback(null, reply);
|
||||
} catch (err) {
|
||||
// if a callback throws an exception, re-throw it on a new stack so the parser can keep going
|
||||
process.nextTick(function () {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
} else if (exports.debug_mode) {
|
||||
console.log("no callback for reply: " + (reply && reply.toString && reply.toString()));
|
||||
}
|
||||
} else if (this.subscriptions || (command_obj && command_obj.sub_command)) {
|
||||
if (Array.isArray(reply)) {
|
||||
type = reply[0].toString();
|
||||
|
||||
if (type === "message") {
|
||||
this.emit("message", reply[1].toString(), reply[2]); // channel, message
|
||||
} else if (type === "pmessage") {
|
||||
this.emit("pmessage", reply[1].toString(), reply[2].toString(), reply[3]); // pattern, channel, message
|
||||
} else if (type === "subscribe" || type === "unsubscribe" || type === "psubscribe" || type === "punsubscribe") {
|
||||
if (reply[2] === 0) {
|
||||
this.subscriptions = false;
|
||||
if (this.debug_mode) {
|
||||
console.log("All subscriptions removed, exiting pub/sub mode");
|
||||
}
|
||||
}
|
||||
this.emit(type, reply[1].toString(), reply[2]); // channel, count
|
||||
} else {
|
||||
throw new Error("subscriptions are active but got unknown reply type " + type);
|
||||
}
|
||||
} else if (! this.closing) {
|
||||
throw new Error("subscriptions are active but got an invalid reply: " + reply);
|
||||
}
|
||||
} else if (this.monitoring) {
|
||||
len = reply.indexOf(" ");
|
||||
timestamp = reply.slice(0, len);
|
||||
// TODO - this de-quoting doesn't work correctly if you put JSON strings in your values.
|
||||
args = reply.slice(len + 1).match(/"[^"]+"/g).map(function (elem) {
|
||||
return elem.replace(/"/g, "");
|
||||
});
|
||||
this.emit("monitor", timestamp, args);
|
||||
} else {
|
||||
throw new Error("node_redis command queue state error. If you can reproduce this, please report it.");
|
||||
}
|
||||
};
|
||||
|
||||
// This Command constructor is ever so slightly faster than using an object literal
|
||||
function Command(command, args, sub_command, callback) {
|
||||
this.command = command;
|
||||
this.args = args;
|
||||
this.sub_command = sub_command;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
RedisClient.prototype.send_command = function (command, args, callback) {
|
||||
var arg, this_args, command_obj, i, il, elem_count, stream = this.stream, buffer_args, command_str = "", buffered_writes = 0;
|
||||
|
||||
if (typeof command !== "string") {
|
||||
throw new Error("First argument to send_command must be the command name string, not " + typeof command);
|
||||
}
|
||||
|
||||
if (Array.isArray(args)) {
|
||||
if (typeof callback === "function") {
|
||||
// probably the fastest way:
|
||||
// client.command([arg1, arg2], cb); (straight passthrough)
|
||||
// send_command(command, [arg1, arg2], cb);
|
||||
} else if (! callback) {
|
||||
// most people find this variable argument length form more convenient, but it uses arguments, which is slower
|
||||
// client.command(arg1, arg2, cb); (wraps up arguments into an array)
|
||||
// send_command(command, [arg1, arg2, cb]);
|
||||
// client.command(arg1, arg2); (callback is optional)
|
||||
// send_command(command, [arg1, arg2]);
|
||||
if (typeof args[args.length - 1] === "function") {
|
||||
callback = args[args.length - 1];
|
||||
args.length -= 1;
|
||||
}
|
||||
} else {
|
||||
throw new Error("send_command: last argument must be a callback or undefined");
|
||||
}
|
||||
} else {
|
||||
throw new Error("send_command: second argument must be an array");
|
||||
}
|
||||
|
||||
// if the last argument is an array, expand it out. This allows commands like this:
|
||||
// client.command(arg1, [arg2, arg3, arg4], cb);
|
||||
// and converts to:
|
||||
// client.command(arg1, arg2, arg3, arg4, cb);
|
||||
// which is convenient for some things like sadd
|
||||
if (Array.isArray(args[args.length - 1])) {
|
||||
args = args.slice(0, -1).concat(args[args.length - 1]);
|
||||
}
|
||||
|
||||
command_obj = new Command(command, args, false, callback);
|
||||
|
||||
if ((!this.ready && !this.send_anyway) || !stream.writable) {
|
||||
if (exports.debug_mode) {
|
||||
if (!stream.writable) {
|
||||
console.log("send command: stream is not writeable.");
|
||||
}
|
||||
|
||||
console.log("Queueing " + command + " for next server connection.");
|
||||
}
|
||||
this.offline_queue.push(command_obj);
|
||||
this.should_buffer = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (command === "subscribe" || command === "psubscribe" || command === "unsubscribe" || command === "punsubscribe") {
|
||||
if (this.subscriptions === false && exports.debug_mode) {
|
||||
console.log("Entering pub/sub mode from " + command);
|
||||
}
|
||||
command_obj.sub_command = true;
|
||||
this.subscriptions = true;
|
||||
} else if (command === "monitor") {
|
||||
this.monitoring = true;
|
||||
} else if (command === "quit") {
|
||||
this.closing = true;
|
||||
} else if (this.subscriptions === true) {
|
||||
throw new Error("Connection in pub/sub mode, only pub/sub commands may be used");
|
||||
}
|
||||
this.command_queue.push(command_obj);
|
||||
this.commands_sent += 1;
|
||||
|
||||
elem_count = 1;
|
||||
buffer_args = false;
|
||||
|
||||
elem_count += args.length;
|
||||
|
||||
// Always use "Multi bulk commands", but if passed any Buffer args, then do multiple writes, one for each arg
|
||||
// This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer.
|
||||
// Also, why am I putting user documentation in the library source code?
|
||||
|
||||
command_str = "*" + elem_count + "\r\n$" + command.length + "\r\n" + command + "\r\n";
|
||||
|
||||
for (i = 0, il = args.length, arg; i < il; i += 1) {
|
||||
if (Buffer.isBuffer(args[i])) {
|
||||
buffer_args = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! buffer_args) { // Build up a string and send entire command in one write
|
||||
for (i = 0, il = args.length, arg; i < il; i += 1) {
|
||||
arg = args[i];
|
||||
if (typeof arg !== "string") {
|
||||
arg = String(arg);
|
||||
}
|
||||
command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n";
|
||||
}
|
||||
if (exports.debug_mode) {
|
||||
console.log("send " + this.host + ":" + this.port + " fd " + this.stream.fd + ": " + command_str);
|
||||
}
|
||||
buffered_writes += !stream.write(command_str);
|
||||
} else {
|
||||
if (exports.debug_mode) {
|
||||
console.log("send command (" + command_str + ") has Buffer arguments");
|
||||
}
|
||||
buffered_writes += !stream.write(command_str);
|
||||
|
||||
for (i = 0, il = args.length, arg; i < il; i += 1) {
|
||||
arg = args[i];
|
||||
if (!(Buffer.isBuffer(arg) || arg instanceof String)) {
|
||||
arg = String(arg);
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(arg)) {
|
||||
if (arg.length === 0) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("send_command: using empty string for 0 length buffer");
|
||||
}
|
||||
buffered_writes += !stream.write("$0\r\n\r\n");
|
||||
} else {
|
||||
buffered_writes += !stream.write("$" + arg.length + "\r\n");
|
||||
buffered_writes += !stream.write(arg);
|
||||
buffered_writes += !stream.write("\r\n");
|
||||
if (exports.debug_mode) {
|
||||
console.log("send_command: buffer send " + arg.length + " bytes");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (exports.debug_mode) {
|
||||
console.log("send_command: string send " + Buffer.byteLength(arg) + " bytes: " + arg);
|
||||
}
|
||||
buffered_writes += !stream.write("$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exports.debug_mode) {
|
||||
console.log("send_command buffered_writes: " + buffered_writes, " should_buffer: " + this.should_buffer);
|
||||
}
|
||||
if (buffered_writes || this.command_queue.getLength() >= this.command_queue_high_water) {
|
||||
this.should_buffer = true;
|
||||
}
|
||||
return !this.should_buffer;
|
||||
};
|
||||
|
||||
RedisClient.prototype.end = function () {
|
||||
this.stream._events = {};
|
||||
this.connected = false;
|
||||
this.ready = false;
|
||||
return this.stream.end();
|
||||
};
|
||||
|
||||
function Multi(client, args) {
|
||||
this.client = client;
|
||||
this.queue = [["MULTI"]];
|
||||
if (Array.isArray(args)) {
|
||||
this.queue = this.queue.concat(args);
|
||||
}
|
||||
}
|
||||
|
||||
exports.Multi = Multi;
|
||||
|
||||
// take 2 arrays and return the union of their elements
|
||||
function set_union(seta, setb) {
|
||||
var obj = {};
|
||||
|
||||
seta.forEach(function (val) {
|
||||
obj[val] = true;
|
||||
});
|
||||
setb.forEach(function (val) {
|
||||
obj[val] = true;
|
||||
});
|
||||
return Object.keys(obj);
|
||||
}
|
||||
|
||||
// This static list of commands is updated from time to time. ./lib/commands.js can be updated with generate_commands.js
|
||||
commands = set_union(["get", "set", "setnx", "setex", "append", "strlen", "del", "exists", "setbit", "getbit", "setrange", "getrange", "substr",
|
||||
"incr", "decr", "mget", "rpush", "lpush", "rpushx", "lpushx", "linsert", "rpop", "lpop", "brpop", "brpoplpush", "blpop", "llen", "lindex",
|
||||
"lset", "lrange", "ltrim", "lrem", "rpoplpush", "sadd", "srem", "smove", "sismember", "scard", "spop", "srandmember", "sinter", "sinterstore",
|
||||
"sunion", "sunionstore", "sdiff", "sdiffstore", "smembers", "zadd", "zincrby", "zrem", "zremrangebyscore", "zremrangebyrank", "zunionstore",
|
||||
"zinterstore", "zrange", "zrangebyscore", "zrevrangebyscore", "zcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "hset", "hsetnx",
|
||||
"hget", "hmset", "hmget", "hincrby", "hdel", "hlen", "hkeys", "hvals", "hgetall", "hexists", "incrby", "decrby", "getset", "mset", "msetnx",
|
||||
"randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo", "save", "bgsave",
|
||||
"bgrewriteaof", "shutdown", "lastsave", "type", "multi", "exec", "discard", "sync", "flushdb", "flushall", "sort", "info", "monitor", "ttl",
|
||||
"persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch", "cluster",
|
||||
"restore", "migrate", "dump", "object", "client", "eval", "evalsha"], require("./lib/commands"));
|
||||
|
||||
commands.forEach(function (command) {
|
||||
RedisClient.prototype[command] = function (args, callback) {
|
||||
if (Array.isArray(args) && typeof callback === "function") {
|
||||
return this.send_command(command, args, callback);
|
||||
} else {
|
||||
return this.send_command(command, to_array(arguments));
|
||||
}
|
||||
};
|
||||
RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command];
|
||||
|
||||
Multi.prototype[command] = function () {
|
||||
this.queue.push([command].concat(to_array(arguments)));
|
||||
return this;
|
||||
};
|
||||
Multi.prototype[command.toUpperCase()] = Multi.prototype[command];
|
||||
});
|
||||
|
||||
// Stash auth for connect and reconnect. Send immediately if already connected.
|
||||
RedisClient.prototype.auth = function () {
|
||||
var args = to_array(arguments);
|
||||
this.auth_pass = args[0];
|
||||
this.auth_callback = args[1];
|
||||
if (exports.debug_mode) {
|
||||
console.log("Saving auth as " + this.auth_pass);
|
||||
}
|
||||
|
||||
if (this.connected) {
|
||||
this.send_command("auth", args);
|
||||
}
|
||||
};
|
||||
RedisClient.prototype.AUTH = RedisClient.prototype.auth;
|
||||
|
||||
RedisClient.prototype.hmget = function (arg1, arg2, arg3) {
|
||||
if (Array.isArray(arg2) && typeof arg3 === "function") {
|
||||
return this.send_command("hmget", [arg1].concat(arg2), arg3);
|
||||
} else if (Array.isArray(arg1) && typeof arg2 === "function") {
|
||||
return this.send_command("hmget", arg1, arg2);
|
||||
} else {
|
||||
return this.send_command("hmget", to_array(arguments));
|
||||
}
|
||||
};
|
||||
RedisClient.prototype.HMGET = RedisClient.prototype.hmget;
|
||||
|
||||
RedisClient.prototype.hmset = function (args, callback) {
|
||||
var tmp_args, tmp_keys, i, il, key;
|
||||
|
||||
if (Array.isArray(args) && typeof callback === "function") {
|
||||
return this.send_command("hmset", args, callback);
|
||||
}
|
||||
|
||||
args = to_array(arguments);
|
||||
if (typeof args[args.length - 1] === "function") {
|
||||
callback = args[args.length - 1];
|
||||
args.length -= 1;
|
||||
} else {
|
||||
callback = null;
|
||||
}
|
||||
|
||||
if (args.length === 2 && typeof args[0] === "string" && typeof args[1] === "object") {
|
||||
// User does: client.hmset(key, {key1: val1, key2: val2})
|
||||
tmp_args = [ args[0] ];
|
||||
tmp_keys = Object.keys(args[1]);
|
||||
for (i = 0, il = tmp_keys.length; i < il ; i++) {
|
||||
key = tmp_keys[i];
|
||||
tmp_args.push(key);
|
||||
tmp_args.push(args[1][key]);
|
||||
}
|
||||
args = tmp_args;
|
||||
}
|
||||
|
||||
return this.send_command("hmset", args, callback);
|
||||
};
|
||||
RedisClient.prototype.HMSET = RedisClient.prototype.hmset;
|
||||
|
||||
Multi.prototype.hmset = function () {
|
||||
var args = to_array(arguments), tmp_args;
|
||||
if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") {
|
||||
tmp_args = [ "hmset", args[0] ];
|
||||
Object.keys(args[1]).map(function (key) {
|
||||
tmp_args.push(key);
|
||||
tmp_args.push(args[1][key]);
|
||||
});
|
||||
if (args[2]) {
|
||||
tmp_args.push(args[2]);
|
||||
}
|
||||
args = tmp_args;
|
||||
} else {
|
||||
args.unshift("hmset");
|
||||
}
|
||||
|
||||
this.queue.push(args);
|
||||
return this;
|
||||
};
|
||||
Multi.prototype.HMSET = Multi.prototype.hmset;
|
||||
|
||||
Multi.prototype.exec = function (callback) {
|
||||
var self = this;
|
||||
|
||||
// drain queue, callback will catch "QUEUED" or error
|
||||
// TODO - get rid of all of these anonymous functions which are elegant but slow
|
||||
this.queue.forEach(function (args, index) {
|
||||
var command = args[0], obj;
|
||||
if (typeof args[args.length - 1] === "function") {
|
||||
args = args.slice(1, -1);
|
||||
} else {
|
||||
args = args.slice(1);
|
||||
}
|
||||
if (args.length === 1 && Array.isArray(args[0])) {
|
||||
args = args[0];
|
||||
}
|
||||
if (command === 'hmset' && typeof args[1] === 'object') {
|
||||
obj = args.pop();
|
||||
Object.keys(obj).forEach(function (key) {
|
||||
args.push(key);
|
||||
args.push(obj[key]);
|
||||
});
|
||||
}
|
||||
this.client.send_command(command, args, function (err, reply) {
|
||||
if (err) {
|
||||
var cur = self.queue[index];
|
||||
if (typeof cur[cur.length - 1] === "function") {
|
||||
cur[cur.length - 1](err);
|
||||
} else {
|
||||
throw new Error(err);
|
||||
}
|
||||
self.queue.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
|
||||
// TODO - make this callback part of Multi.prototype instead of creating it each time
|
||||
return this.client.send_command("EXEC", [], function (err, replies) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
callback(new Error(err));
|
||||
return;
|
||||
} else {
|
||||
throw new Error(err);
|
||||
}
|
||||
}
|
||||
|
||||
var i, il, j, jl, reply, args, obj, key, val;
|
||||
|
||||
if (replies) {
|
||||
for (i = 1, il = self.queue.length; i < il; i += 1) {
|
||||
reply = replies[i - 1];
|
||||
args = self.queue[i];
|
||||
|
||||
// Convert HGETALL reply to object
|
||||
if (reply && args[0].toLowerCase() === "hgetall") {
|
||||
obj = {};
|
||||
for (j = 0, jl = reply.length; j < jl; j += 2) {
|
||||
key = reply[j].toString();
|
||||
val = reply[j + 1];
|
||||
obj[key] = val;
|
||||
}
|
||||
replies[i - 1] = reply = obj;
|
||||
}
|
||||
|
||||
if (typeof args[args.length - 1] === "function") {
|
||||
args[args.length - 1](null, reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(null, replies);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
RedisClient.prototype.multi = function (args) {
|
||||
return new Multi(this, args);
|
||||
};
|
||||
RedisClient.prototype.MULTI = function (args) {
|
||||
return new Multi(this, args);
|
||||
};
|
||||
|
||||
exports.createClient = function (port_arg, host_arg, options) {
|
||||
var port = port_arg || default_port,
|
||||
host = host_arg || default_host,
|
||||
redis_client, net_client;
|
||||
|
||||
net_client = net.createConnection(port, host);
|
||||
|
||||
redis_client = new RedisClient(net_client, options);
|
||||
|
||||
redis_client.port = port;
|
||||
redis_client.host = host;
|
||||
|
||||
return redis_client;
|
||||
};
|
||||
|
||||
exports.print = function (err, reply) {
|
||||
if (err) {
|
||||
console.log("Error: " + err);
|
||||
} else {
|
||||
console.log("Reply: " + reply);
|
||||
}
|
||||
};
|
||||
126
networking/node_modules/socket.io/node_modules/redis/lib/commands.js
generated
vendored
Normal file
126
networking/node_modules/socket.io/node_modules/redis/lib/commands.js
generated
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
// This file was generated by ./generate_commands.js on Tue Jun 28 2011 22:37:02 GMT-0700 (PDT)
|
||||
module.exports = [
|
||||
"append",
|
||||
"auth",
|
||||
"bgrewriteaof",
|
||||
"bgsave",
|
||||
"blpop",
|
||||
"brpop",
|
||||
"brpoplpush",
|
||||
"config get",
|
||||
"config set",
|
||||
"config resetstat",
|
||||
"dbsize",
|
||||
"debug object",
|
||||
"debug segfault",
|
||||
"decr",
|
||||
"decrby",
|
||||
"del",
|
||||
"discard",
|
||||
"echo",
|
||||
"exec",
|
||||
"exists",
|
||||
"expire",
|
||||
"expireat",
|
||||
"flushall",
|
||||
"flushdb",
|
||||
"get",
|
||||
"getbit",
|
||||
"getrange",
|
||||
"getset",
|
||||
"hdel",
|
||||
"hexists",
|
||||
"hget",
|
||||
"hgetall",
|
||||
"hincrby",
|
||||
"hkeys",
|
||||
"hlen",
|
||||
"hmget",
|
||||
"hmset",
|
||||
"hset",
|
||||
"hsetnx",
|
||||
"hvals",
|
||||
"incr",
|
||||
"incrby",
|
||||
"info",
|
||||
"keys",
|
||||
"lastsave",
|
||||
"lindex",
|
||||
"linsert",
|
||||
"llen",
|
||||
"lpop",
|
||||
"lpush",
|
||||
"lpushx",
|
||||
"lrange",
|
||||
"lrem",
|
||||
"lset",
|
||||
"ltrim",
|
||||
"mget",
|
||||
"monitor",
|
||||
"move",
|
||||
"mset",
|
||||
"msetnx",
|
||||
"multi",
|
||||
"object",
|
||||
"persist",
|
||||
"ping",
|
||||
"psubscribe",
|
||||
"publish",
|
||||
"punsubscribe",
|
||||
"quit",
|
||||
"randomkey",
|
||||
"rename",
|
||||
"renamenx",
|
||||
"rpop",
|
||||
"rpoplpush",
|
||||
"rpush",
|
||||
"rpushx",
|
||||
"sadd",
|
||||
"save",
|
||||
"scard",
|
||||
"sdiff",
|
||||
"sdiffstore",
|
||||
"select",
|
||||
"set",
|
||||
"setbit",
|
||||
"setex",
|
||||
"setnx",
|
||||
"setrange",
|
||||
"shutdown",
|
||||
"sinter",
|
||||
"sinterstore",
|
||||
"sismember",
|
||||
"slaveof",
|
||||
"smembers",
|
||||
"smove",
|
||||
"sort",
|
||||
"spop",
|
||||
"srandmember",
|
||||
"srem",
|
||||
"strlen",
|
||||
"subscribe",
|
||||
"sunion",
|
||||
"sunionstore",
|
||||
"sync",
|
||||
"ttl",
|
||||
"type",
|
||||
"unsubscribe",
|
||||
"unwatch",
|
||||
"watch",
|
||||
"zadd",
|
||||
"zcard",
|
||||
"zcount",
|
||||
"zincrby",
|
||||
"zinterstore",
|
||||
"zrange",
|
||||
"zrangebyscore",
|
||||
"zrank",
|
||||
"zrem",
|
||||
"zremrangebyrank",
|
||||
"zremrangebyscore",
|
||||
"zrevrange",
|
||||
"zrevrangebyscore",
|
||||
"zrevrank",
|
||||
"zscore",
|
||||
"zunionstore"
|
||||
];
|
||||
41
networking/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js
generated
vendored
Normal file
41
networking/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*global Buffer require exports console setTimeout */
|
||||
|
||||
var events = require("events"),
|
||||
util = require("../util").util,
|
||||
hiredis = require("hiredis");
|
||||
|
||||
exports.debug_mode = false;
|
||||
exports.name = "hiredis";
|
||||
|
||||
function HiredisReplyParser(options) {
|
||||
this.name = exports.name;
|
||||
this.options = options || {};
|
||||
this.reset();
|
||||
events.EventEmitter.call(this);
|
||||
}
|
||||
|
||||
util.inherits(HiredisReplyParser, events.EventEmitter);
|
||||
|
||||
exports.Parser = HiredisReplyParser;
|
||||
|
||||
HiredisReplyParser.prototype.reset = function () {
|
||||
this.reader = new hiredis.Reader({
|
||||
return_buffers: this.options.return_buffers || false
|
||||
});
|
||||
};
|
||||
|
||||
HiredisReplyParser.prototype.execute = function (data) {
|
||||
var reply;
|
||||
this.reader.feed(data);
|
||||
try {
|
||||
while ((reply = this.reader.get()) !== undefined) {
|
||||
if (reply && reply.constructor === Error) {
|
||||
this.emit("reply error", reply);
|
||||
} else {
|
||||
this.emit("reply", reply);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.emit("error", err);
|
||||
}
|
||||
};
|
||||
316
networking/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js
generated
vendored
Normal file
316
networking/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js
generated
vendored
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
/*global Buffer require exports console setTimeout */
|
||||
|
||||
// TODO - incorporate these V8 pro tips:
|
||||
// pre-allocate Arrays if length is known in advance
|
||||
// do not use delete
|
||||
// use numbers for parser state
|
||||
|
||||
var events = require("events"),
|
||||
util = require("../util").util;
|
||||
|
||||
exports.debug_mode = false;
|
||||
exports.name = "javascript";
|
||||
|
||||
function RedisReplyParser(options) {
|
||||
this.name = exports.name;
|
||||
this.options = options || {};
|
||||
this.reset();
|
||||
events.EventEmitter.call(this);
|
||||
}
|
||||
|
||||
util.inherits(RedisReplyParser, events.EventEmitter);
|
||||
|
||||
exports.Parser = RedisReplyParser;
|
||||
|
||||
// Buffer.toString() is quite slow for small strings
|
||||
function small_toString(buf, len) {
|
||||
var tmp = "", i;
|
||||
|
||||
for (i = 0; i < len; i += 1) {
|
||||
tmp += String.fromCharCode(buf[i]);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Reset parser to it's original state.
|
||||
RedisReplyParser.prototype.reset = function () {
|
||||
this.return_buffer = new Buffer(16384); // for holding replies, might grow
|
||||
this.return_string = "";
|
||||
this.tmp_string = ""; // for holding size fields
|
||||
|
||||
this.multi_bulk_length = 0;
|
||||
this.multi_bulk_replies = null;
|
||||
this.multi_bulk_pos = 0;
|
||||
this.multi_bulk_nested_length = 0;
|
||||
this.multi_bulk_nested_replies = null;
|
||||
|
||||
this.states = {
|
||||
TYPE: 1,
|
||||
SINGLE_LINE: 2,
|
||||
MULTI_BULK_COUNT: 3,
|
||||
INTEGER_LINE: 4,
|
||||
BULK_LENGTH: 5,
|
||||
ERROR_LINE: 6,
|
||||
BULK_DATA: 7,
|
||||
UNKNOWN_TYPE: 8,
|
||||
FINAL_CR: 9,
|
||||
FINAL_LF: 10,
|
||||
MULTI_BULK_COUNT_LF: 11
|
||||
};
|
||||
|
||||
this.state = this.states.TYPE;
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.parser_error = function (message) {
|
||||
this.emit("error", message);
|
||||
this.reset();
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
var pos = 0, bd_tmp, bd_str, i, il, states = this.states;
|
||||
//, state_times = {}, start_execute = new Date(), start_switch, end_switch, old_state;
|
||||
//start_switch = new Date();
|
||||
|
||||
while (pos < incoming_buf.length) {
|
||||
// old_state = this.state;
|
||||
// console.log("execute: " + this.state + ", " + pos + "/" + incoming_buf.length + ", " + String.fromCharCode(incoming_buf[pos]));
|
||||
|
||||
switch (this.state) {
|
||||
case states.TYPE:
|
||||
this.type = incoming_buf[pos];
|
||||
pos += 1;
|
||||
|
||||
switch (this.type) {
|
||||
case 43: // +
|
||||
this.state = states.SINGLE_LINE;
|
||||
this.return_buffer.end = 0;
|
||||
this.return_string = "";
|
||||
break;
|
||||
case 42: // *
|
||||
this.state = states.MULTI_BULK_COUNT;
|
||||
this.tmp_string = "";
|
||||
break;
|
||||
case 58: // :
|
||||
this.state = states.INTEGER_LINE;
|
||||
this.return_buffer.end = 0;
|
||||
this.return_string = "";
|
||||
break;
|
||||
case 36: // $
|
||||
this.state = states.BULK_LENGTH;
|
||||
this.tmp_string = "";
|
||||
break;
|
||||
case 45: // -
|
||||
this.state = states.ERROR_LINE;
|
||||
this.return_buffer.end = 0;
|
||||
this.return_string = "";
|
||||
break;
|
||||
default:
|
||||
this.state = states.UNKNOWN_TYPE;
|
||||
}
|
||||
break;
|
||||
case states.INTEGER_LINE:
|
||||
if (incoming_buf[pos] === 13) {
|
||||
this.send_reply(+small_toString(this.return_buffer, this.return_buffer.end));
|
||||
this.state = states.FINAL_LF;
|
||||
} else {
|
||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
||||
this.return_buffer.end += 1;
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case states.ERROR_LINE:
|
||||
if (incoming_buf[pos] === 13) {
|
||||
this.send_error(this.return_buffer.toString("ascii", 0, this.return_buffer.end));
|
||||
this.state = states.FINAL_LF;
|
||||
} else {
|
||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
||||
this.return_buffer.end += 1;
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case states.SINGLE_LINE:
|
||||
if (incoming_buf[pos] === 13) {
|
||||
this.send_reply(this.return_string);
|
||||
this.state = states.FINAL_LF;
|
||||
} else {
|
||||
this.return_string += String.fromCharCode(incoming_buf[pos]);
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case states.MULTI_BULK_COUNT:
|
||||
if (incoming_buf[pos] === 13) { // \r
|
||||
this.state = states.MULTI_BULK_COUNT_LF;
|
||||
} else {
|
||||
this.tmp_string += String.fromCharCode(incoming_buf[pos]);
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case states.MULTI_BULK_COUNT_LF:
|
||||
if (incoming_buf[pos] === 10) { // \n
|
||||
if (this.multi_bulk_length) { // nested multi-bulk
|
||||
this.multi_bulk_nested_length = this.multi_bulk_length;
|
||||
this.multi_bulk_nested_replies = this.multi_bulk_replies;
|
||||
this.multi_bulk_nested_pos = this.multi_bulk_pos;
|
||||
}
|
||||
this.multi_bulk_length = +this.tmp_string;
|
||||
this.multi_bulk_pos = 0;
|
||||
this.state = states.TYPE;
|
||||
if (this.multi_bulk_length < 0) {
|
||||
this.send_reply(null);
|
||||
this.multi_bulk_length = 0;
|
||||
} else if (this.multi_bulk_length === 0) {
|
||||
this.multi_bulk_pos = 0;
|
||||
this.multi_bulk_replies = null;
|
||||
this.send_reply([]);
|
||||
} else {
|
||||
this.multi_bulk_replies = new Array(this.multi_bulk_length);
|
||||
}
|
||||
} else {
|
||||
this.parser_error(new Error("didn't see LF after NL reading multi bulk count"));
|
||||
return;
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case states.BULK_LENGTH:
|
||||
if (incoming_buf[pos] === 13) { // \r
|
||||
this.state = states.BULK_LF;
|
||||
} else {
|
||||
this.tmp_string += String.fromCharCode(incoming_buf[pos]);
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case states.BULK_LF:
|
||||
if (incoming_buf[pos] === 10) { // \n
|
||||
this.bulk_length = +this.tmp_string;
|
||||
if (this.bulk_length === -1) {
|
||||
this.send_reply(null);
|
||||
this.state = states.TYPE;
|
||||
} else if (this.bulk_length === 0) {
|
||||
this.send_reply(new Buffer(""));
|
||||
this.state = states.FINAL_CR;
|
||||
} else {
|
||||
this.state = states.BULK_DATA;
|
||||
if (this.bulk_length > this.return_buffer.length) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Growing return_buffer from " + this.return_buffer.length + " to " + this.bulk_length);
|
||||
}
|
||||
this.return_buffer = new Buffer(this.bulk_length);
|
||||
}
|
||||
this.return_buffer.end = 0;
|
||||
}
|
||||
} else {
|
||||
this.parser_error(new Error("didn't see LF after NL while reading bulk length"));
|
||||
return;
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case states.BULK_DATA:
|
||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
||||
this.return_buffer.end += 1;
|
||||
pos += 1;
|
||||
if (this.return_buffer.end === this.bulk_length) {
|
||||
bd_tmp = new Buffer(this.bulk_length);
|
||||
// When the response is small, Buffer.copy() is a lot slower.
|
||||
if (this.bulk_length > 10) {
|
||||
this.return_buffer.copy(bd_tmp, 0, 0, this.bulk_length);
|
||||
} else {
|
||||
for (i = 0, il = this.bulk_length; i < il; i += 1) {
|
||||
bd_tmp[i] = this.return_buffer[i];
|
||||
}
|
||||
}
|
||||
this.send_reply(bd_tmp);
|
||||
this.state = states.FINAL_CR;
|
||||
}
|
||||
break;
|
||||
case states.FINAL_CR:
|
||||
if (incoming_buf[pos] === 13) { // \r
|
||||
this.state = states.FINAL_LF;
|
||||
pos += 1;
|
||||
} else {
|
||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final CR"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case states.FINAL_LF:
|
||||
if (incoming_buf[pos] === 10) { // \n
|
||||
this.state = states.TYPE;
|
||||
pos += 1;
|
||||
} else {
|
||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final LF"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.parser_error(new Error("invalid state " + this.state));
|
||||
}
|
||||
// end_switch = new Date();
|
||||
// if (state_times[old_state] === undefined) {
|
||||
// state_times[old_state] = 0;
|
||||
// }
|
||||
// state_times[old_state] += (end_switch - start_switch);
|
||||
// start_switch = end_switch;
|
||||
}
|
||||
// console.log("execute ran for " + (Date.now() - start_execute) + " ms, on " + incoming_buf.length + " Bytes. ");
|
||||
// Object.keys(state_times).forEach(function (state) {
|
||||
// console.log(" " + state + ": " + state_times[state]);
|
||||
// });
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.send_error = function (reply) {
|
||||
if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) {
|
||||
// TODO - can this happen? Seems like maybe not.
|
||||
this.add_multi_bulk_reply(reply);
|
||||
} else {
|
||||
this.emit("reply error", reply);
|
||||
}
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.send_reply = function (reply) {
|
||||
if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) {
|
||||
if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
|
||||
this.add_multi_bulk_reply(reply.toString("utf8"));
|
||||
} else {
|
||||
this.add_multi_bulk_reply(reply);
|
||||
}
|
||||
} else {
|
||||
if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
|
||||
this.emit("reply", reply.toString("utf8"));
|
||||
} else {
|
||||
this.emit("reply", reply);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.add_multi_bulk_reply = function (reply) {
|
||||
if (this.multi_bulk_replies) {
|
||||
this.multi_bulk_replies[this.multi_bulk_pos] = reply;
|
||||
this.multi_bulk_pos += 1;
|
||||
if (this.multi_bulk_pos < this.multi_bulk_length) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.multi_bulk_replies = reply;
|
||||
}
|
||||
|
||||
if (this.multi_bulk_nested_length > 0) {
|
||||
this.multi_bulk_nested_replies[this.multi_bulk_nested_pos] = this.multi_bulk_replies;
|
||||
this.multi_bulk_nested_pos += 1;
|
||||
|
||||
this.multi_bulk_length = 0;
|
||||
this.multi_bulk_replies = null;
|
||||
this.multi_bulk_pos = 0;
|
||||
|
||||
if (this.multi_bulk_nested_length === this.multi_bulk_nested_pos) {
|
||||
this.emit("reply", this.multi_bulk_nested_replies);
|
||||
this.multi_bulk_nested_length = 0;
|
||||
this.multi_bulk_nested_pos = 0;
|
||||
this.multi_bulk_nested_replies = null;
|
||||
}
|
||||
} else {
|
||||
this.emit("reply", this.multi_bulk_replies);
|
||||
this.multi_bulk_length = 0;
|
||||
this.multi_bulk_replies = null;
|
||||
this.multi_bulk_pos = 0;
|
||||
}
|
||||
};
|
||||
58
networking/node_modules/socket.io/node_modules/redis/lib/queue.js
generated
vendored
Normal file
58
networking/node_modules/socket.io/node_modules/redis/lib/queue.js
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
var to_array = require("./to_array");
|
||||
|
||||
// Queue class adapted from Tim Caswell's pattern library
|
||||
// http://github.com/creationix/pattern/blob/master/lib/pattern/queue.js
|
||||
|
||||
function Queue() {
|
||||
this.tail = [];
|
||||
this.head = to_array(arguments);
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
Queue.prototype.shift = function () {
|
||||
if (this.offset === this.head.length) {
|
||||
var tmp = this.head;
|
||||
tmp.length = 0;
|
||||
this.head = this.tail;
|
||||
this.tail = tmp;
|
||||
this.offset = 0;
|
||||
if (this.head.length === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return this.head[this.offset++]; // sorry, JSLint
|
||||
};
|
||||
|
||||
Queue.prototype.push = function (item) {
|
||||
return this.tail.push(item);
|
||||
};
|
||||
|
||||
Queue.prototype.forEach = function (fn, thisv) {
|
||||
var array = this.head.slice(this.offset), i, il;
|
||||
|
||||
array.push.apply(array, this.tail);
|
||||
|
||||
if (thisv) {
|
||||
for (i = 0, il = array.length; i < il; i += 1) {
|
||||
fn.call(thisv, array[i], i, array);
|
||||
}
|
||||
} else {
|
||||
for (i = 0, il = array.length; i < il; i += 1) {
|
||||
fn(array[i], i, array);
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
Queue.prototype.getLength = function () {
|
||||
return this.head.length - this.offset + this.tail.length;
|
||||
};
|
||||
|
||||
Object.defineProperty(Queue.prototype, 'length', {
|
||||
get: function () {
|
||||
return this.getLength();
|
||||
}
|
||||
});
|
||||
|
||||
exports.Queue = Queue;
|
||||
12
networking/node_modules/socket.io/node_modules/redis/lib/to_array.js
generated
vendored
Normal file
12
networking/node_modules/socket.io/node_modules/redis/lib/to_array.js
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
function to_array(args) {
|
||||
var len = args.length,
|
||||
arr = new Array(len), i;
|
||||
|
||||
for (i = 0; i < len; i += 1) {
|
||||
arr[i] = args[i];
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
module.exports = to_array;
|
||||
6
networking/node_modules/socket.io/node_modules/redis/lib/util.js
generated
vendored
Normal file
6
networking/node_modules/socket.io/node_modules/redis/lib/util.js
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
if (process.versions.node.match(/^0.3/)) {
|
||||
exports.util = require("util");
|
||||
} else {
|
||||
// This module is called "sys" in 0.2.x
|
||||
exports.util = require("sys");
|
||||
}
|
||||
135
networking/node_modules/socket.io/node_modules/redis/multi_bench.js
generated
vendored
Normal file
135
networking/node_modules/socket.io/node_modules/redis/multi_bench.js
generated
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
var redis = require("./index"),
|
||||
num_clients = parseInt(process.argv[2], 10) || 50,
|
||||
active_clients = 0,
|
||||
clients = new Array(num_clients),
|
||||
num_requests = 20000,
|
||||
issued_requests = 0,
|
||||
latency = new Array(num_requests),
|
||||
tests = [],
|
||||
test_start, parser_logged = false,
|
||||
client_options = {
|
||||
return_buffers: false
|
||||
};
|
||||
|
||||
redis.debug_mode = false;
|
||||
|
||||
tests.push({
|
||||
descr: "PING",
|
||||
command: ["ping"]
|
||||
});
|
||||
|
||||
tests.push({
|
||||
descr: "SET",
|
||||
command: ["set", "foo_rand000000000000", "bar"]
|
||||
});
|
||||
|
||||
tests.push({
|
||||
descr: "GET",
|
||||
command: ["get", "foo_rand000000000000"]
|
||||
});
|
||||
|
||||
tests.push({
|
||||
descr: "INCR",
|
||||
command: ["incr", "counter_rand000000000000"]
|
||||
});
|
||||
|
||||
tests.push({
|
||||
descr: "LPUSH",
|
||||
command: ["lpush", "mylist", new Array(8).join("-")]
|
||||
});
|
||||
|
||||
tests.push({
|
||||
descr: "LRANGE (10 elements)",
|
||||
command: ["lrange", "mylist", "0", "9"]
|
||||
});
|
||||
|
||||
tests.push({
|
||||
descr: "LRANGE (100 elements)",
|
||||
command: ["lrange", "mylist", "0", "99"]
|
||||
});
|
||||
|
||||
function create_clients(callback) {
|
||||
if (active_clients === num_clients) {
|
||||
// common case is all clients are already created
|
||||
console.log("create_clients: all clients already created " + num_clients);
|
||||
callback();
|
||||
} else {
|
||||
var client, connected = active_clients;
|
||||
|
||||
while (active_clients < num_clients) {
|
||||
client = clients[active_clients++] = redis.createClient(6379, "127.0.0.1", client_options);
|
||||
if (! parser_logged) {
|
||||
console.log("Using reply parser " + client.reply_parser.name);
|
||||
parser_logged = true;
|
||||
}
|
||||
client.on("connect", function () {
|
||||
// Fire callback when all clients are connected
|
||||
connected += 1;
|
||||
if (connected === num_clients) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
// TODO - need to check for client disconnect
|
||||
client.on("error", function (msg) {
|
||||
console.log("Connect problem:" + msg.stack);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function issue_request(client, test, cmd, args) {
|
||||
var i = issued_requests++;
|
||||
latency[i] = Date.now();
|
||||
|
||||
client[cmd](args, function() {
|
||||
latency[i] = Date.now() - latency[i];
|
||||
if (issued_requests < num_requests) {
|
||||
issue_request(client, test, cmd, args);
|
||||
} else {
|
||||
client.end();
|
||||
if (--active_clients == 0)
|
||||
test_complete(test);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function test_run(test) {
|
||||
create_clients(function() {
|
||||
var i = num_clients,
|
||||
cmd = test.command[0],
|
||||
args = test.command.slice(1);
|
||||
|
||||
test_start = Date.now();
|
||||
issued_requests = 0;
|
||||
while(i-- && issued_requests < num_requests) {
|
||||
issue_request(clients[i], test, cmd, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function test_complete(test) {
|
||||
var min, max, sum, avg;
|
||||
var total_time = Date.now() - test_start;
|
||||
var op_rate = (issued_requests / (total_time / 1000.0)).toFixed(2);
|
||||
var i;
|
||||
|
||||
latency.sort();
|
||||
min = latency[0];
|
||||
max = latency[issued_requests-1];
|
||||
for (sum = 0, i = 0; i < issued_requests; i++)
|
||||
sum += latency[i];
|
||||
avg = (sum / issued_requests).toFixed(3);
|
||||
|
||||
console.log(test.descr + ": " + issued_requests + " ops " + op_rate + " ops/sec " + min + "/" + max + "/" + avg);
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
function next() {
|
||||
var test = tests.shift();
|
||||
if (test) {
|
||||
test_run(test);
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
67
networking/node_modules/socket.io/node_modules/redis/package.json
generated
vendored
Normal file
67
networking/node_modules/socket.io/node_modules/redis/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"name": "redis",
|
||||
"version": "0.6.7",
|
||||
"description": "Redis client library",
|
||||
"author": {
|
||||
"name": "Matt Ranney",
|
||||
"email": "mjr@ranney.com"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Rick Olson"
|
||||
},
|
||||
{
|
||||
"name": "Tim-Smart"
|
||||
},
|
||||
{
|
||||
"name": "TJ Holowaychuk"
|
||||
},
|
||||
{
|
||||
"name": "Orion Henry"
|
||||
},
|
||||
{
|
||||
"name": "Hank Sims"
|
||||
},
|
||||
{
|
||||
"name": "Aivo Paas"
|
||||
},
|
||||
{
|
||||
"name": "Paul Carey"
|
||||
},
|
||||
{
|
||||
"name": "Pieter Noordhuis"
|
||||
},
|
||||
{
|
||||
"name": "Andy Ray"
|
||||
},
|
||||
{
|
||||
"name": "Vladimir Dronnikov"
|
||||
},
|
||||
{
|
||||
"name": "Dave Hoover"
|
||||
}
|
||||
],
|
||||
"main": "./index.js",
|
||||
"scripts": {
|
||||
"test": "node ./test.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/mranney/node_redis.git"
|
||||
},
|
||||
"_id": "redis@0.6.7",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.4",
|
||||
"_nodeVersion": "v0.6.12",
|
||||
"_defaultsLoaded": true,
|
||||
"dist": {
|
||||
"shasum": "3313a943bacf1c0e958c315ce4578ef429a646c3"
|
||||
},
|
||||
"_from": "redis@0.6.7"
|
||||
}
|
||||
3
networking/node_modules/socket.io/node_modules/redis/simple_test.js
generated
vendored
Normal file
3
networking/node_modules/socket.io/node_modules/redis/simple_test.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
var client = require("./index").createClient();
|
||||
|
||||
client.hmset("test hash", "key 1", "val 1", "key 2", "val 2");
|
||||
1248
networking/node_modules/socket.io/node_modules/redis/test.js
generated
vendored
Normal file
1248
networking/node_modules/socket.io/node_modules/redis/test.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue