-
-
Save joshterrill/9573422 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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