Skip to content

Instantly share code, notes, and snippets.

@joshterrill
Forked from anonymous/app.js
Created March 15, 2014 20:23
Show Gist options
  • Save joshterrill/9573422 to your computer and use it in GitHub Desktop.
Save joshterrill/9573422 to your computer and use it in GitHub Desktop.
var express = require("express"),
http = require("http"),
async = require("async"),
sockjs = require("sockjs"),
uuid = require("uuid"),
url = require("url"),
redis = require("redis"); // for pubsub and to persist data if your app restarts
var app = express(),
redisClient = redis.createClient(),
pubsubClient = redis.createClient();
app.use(app.router);
var settings = {
port: 80
prefix: "/sockets"
};
app.get("/", function(req, res){
var id = uuid.v4();
redisClient.set(id, 0, function(error){
if(error){
console.log("Error creating room in redis!", error);
res.render(500, "500.html"); // send them a page with an internal server error message
}else{
res.redirect("/" + id);
}
});
});
app.get("/:id", function(req, res){
res.render("chat.html"); // send them a page with sockjs and the chat interface
});
var server = http.createServer(app),
socketServer = sockjs.createServer();
socketServer.installHandlers(server, {
prefix: settings.prefix, // can be anything, just make sure the client also implements this
});
/*
When a socket attempts to connect from the client side have the socket append the path suffix to the connection url as a GET parameter
For example, if the client is at the url http://yourapp.com/12345 then in the browser the sockjs initialization would look like:
var sock = new SockJS('http://yourapp.com/your_prefix_to_match_settings.prefix?room=12345')
*/
var sockets = {};
pubsubClient.on("message", function(channel, message){
if(typeof message === "object")
message = JSON.stringify(message);
if(sockets[channel]){
async.each(Object.keys(sockets[channel]), function(sid, callback){
sockets[channel][sid].write(message);
callback();
}, function(error){
// there shouldn't be any errors here...
});
}
});
sockets.on("connection", function(socket){
var room = url.parse(socket.url, true).query.room;
if(room){
redisClient.incr(room, function(error, members){
if(error){
console.log("Error incrementing room member count!", error);
// TODO maybe close the client too?
}else{
socket.sid = uuid.v4();
if(members === 1){
pubsubClient.subscribe(room);
sockets[room] = {};
}
sockets[room][socket.sid] = socket;
}
});
}else{
// no room found, kill the connection
return socket.end();
}
socket.on("data", function(message){
// assume the messages are stringified json from the client
pubsubClient.publish(room, message);
});
socket.on("close", function(){
delete sockets[room][socket.sid];
redisClient.incrby(room, -1, function(error, members){
if(error)
console.log("Error decrementing room member counter!", error);
else if(members === 0)
delete sockets[room];
});
});
});
server.listen(settings.port, function(){
console.log("Server started");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment