RLG-Web server: send status events over WebSockets.

A WebSocket connection to /status will be sent periodic listings, along
with notifications of the beginning and end of games.
This commit is contained in:
John "Elwin" Edwards 2012-07-13 22:26:20 -07:00
parent 4174840c3e
commit bec02aea9e

View file

@ -62,6 +62,7 @@ var sessions = {};
var clients = {}; var clients = {};
var allowlogin = true; var allowlogin = true;
var nextsession = 0; var nextsession = 0;
var gamemux = new events.EventEmitter();
/* Constructor. A TermSession handles a pty and the game running on it. /* Constructor. A TermSession handles a pty and the game running on it.
* game: (String) Name of the game to launch. * game: (String) Name of the game to launch.
@ -118,6 +119,7 @@ function TermSession(game, lkey, dims, handlers) {
tslog("%s playing %s (index %d, pid %d)", this.pname, this.game.uname, tslog("%s playing %s (index %d, pid %d)", this.pname, this.game.uname,
this.sessid, this.term.pid); this.sessid, this.term.pid);
this.emit('open', true, this.sessid); this.emit('open', true, this.sessid);
gamemux.emit('begin', this.sessid, this.pname, this.game.uname);
/* Set up the lockfile and ttyrec */ /* Set up the lockfile and ttyrec */
var ts = timestamp(); var ts = timestamp();
var progressdir = "/dgldir/inprogress-" + this.game.uname; var progressdir = "/dgldir/inprogress-" + this.game.uname;
@ -177,6 +179,7 @@ function TermSession(game, lkey, dims, handlers) {
var id = ss.sessid; var id = ss.sessid;
delete sessions[id]; delete sessions[id];
tslog("Game %s ended.", id); tslog("Game %s ended.", id);
gamemux.emit('end', id);
}); });
this.close = function () { this.close = function () {
this.term.kill('SIGHUP'); this.term.kill('SIGHUP');
@ -1062,15 +1065,54 @@ function webHandler(req, res) {
} }
function wsHandler(wsRequest) { function wsHandler(wsRequest) {
var urlmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/); var watchmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/);
if (urlmatch !== null && urlmatch[1] && Number(urlmatch[1]) in sessions) { if (watchmatch !== null) {
var tsession = sessions[Number(urlmatch[1])]; if (watchmatch[1] && Number(watchmatch[1]) in sessions) {
var tsession = sessions[Number(watchmatch[1])];
var conn = wsRequest.accept(null, wsRequest.origin); var conn = wsRequest.accept(null, wsRequest.origin);
new wsWatcher(conn, tsession); new wsWatcher(conn, tsession);
tslog("Game %d is being watched via WebSockets", tsession.sessid); tslog("Game %d is being watched via WebSockets", tsession.sessid);
} }
else else
wsRequest.reject(404, errorcodes[7]); wsRequest.reject(404, errorcodes[7]);
}
else if (wsRequest.resource == "/status") {
var conn = wsRequest.accept(null, wsRequest.origin);
var tell = function () {
getStatus(function (info) {
info["t"] = "t";
conn.sendUTF(JSON.stringify(info));
});
}
var beginH = function (n, name, game) {
conn.sendUTF(JSON.stringify({"t": "b", "n": n, "p": name, "g": game}));
};
var listH = function (list) {
conn.sendUTF(JSON.stringify(list));
};
var endH = function (n) {
conn.sendUTF(JSON.stringify({"t": "e", "n": n}));
};
gamemux.on('begin', beginH);
gamemux.on('list', listH);
gamemux.on('end', endH);
conn.on('message', tell);
conn.on('close', function () {
gamemux.removeListener('begin', beginH);
gamemux.removeListener('list', listH);
gamemux.removeListener('end', endH);
});
tell();
}
else
wsRequest.reject(404, "No such resource.");
}
function pushStatus() {
getStatus(function(info) {
info["t"] = "t";
gamemux.emit('list', info);
});
} }
function shutdown () { function shutdown () {
@ -1154,5 +1196,6 @@ ctlServer.listen(ctlsocket, function () {
wsServer = new WebSocketServer({"httpServer": httpServer}); wsServer = new WebSocketServer({"httpServer": httpServer});
wsServer.on("request", wsHandler); wsServer.on("request", wsHandler);
tslog('WebSockets are online'); tslog('WebSockets are online');
setInterval(pushStatus, 4000);
}); });