changeset 104:7d444ba4739e

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.
author John "Elwin" Edwards <elwin@sdf.org>
date Fri, 13 Jul 2012 22:26:20 -0700
parents f30495f7ede8
children a9371002aecc
files rlgwebd.js
diffstat 1 files changed, 49 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/rlgwebd.js	Fri Jul 13 09:17:05 2012 -0700
+++ b/rlgwebd.js	Fri Jul 13 22:26:20 2012 -0700
@@ -62,6 +62,7 @@
 var clients = {};
 var allowlogin = true;
 var nextsession = 0;
+var gamemux = new events.EventEmitter();
 
 /* Constructor.  A TermSession handles a pty and the game running on it.
  *   game: (String) Name of the game to launch.
@@ -118,6 +119,7 @@
   tslog("%s playing %s (index %d, pid %d)", this.pname, this.game.uname, 
             this.sessid, this.term.pid);
   this.emit('open', true, this.sessid);
+  gamemux.emit('begin', this.sessid, this.pname, this.game.uname);
   /* Set up the lockfile and ttyrec */
   var ts = timestamp();
   var progressdir = "/dgldir/inprogress-" + this.game.uname;
@@ -177,6 +179,7 @@
     var id = ss.sessid;
     delete sessions[id];
     tslog("Game %s ended.", id);
+    gamemux.emit('end', id);
   });
   this.close = function () {
     this.term.kill('SIGHUP');
@@ -1062,15 +1065,54 @@
 }
 
 function wsHandler(wsRequest) {
-  var urlmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/);
-  if (urlmatch !== null && urlmatch[1] && Number(urlmatch[1]) in sessions) {
-    var tsession = sessions[Number(urlmatch[1])];
+  var watchmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/);
+  if (watchmatch !== null) {
+    if (watchmatch[1] && Number(watchmatch[1]) in sessions) {
+      var tsession = sessions[Number(watchmatch[1])];
+      var conn = wsRequest.accept(null, wsRequest.origin);
+      new wsWatcher(conn, tsession);
+      tslog("Game %d is being watched via WebSockets", tsession.sessid);
+    }
+    else
+      wsRequest.reject(404, errorcodes[7]);
+  }
+  else if (wsRequest.resource == "/status") {
     var conn = wsRequest.accept(null, wsRequest.origin);
-    new wsWatcher(conn, tsession);
-    tslog("Game %d is being watched via WebSockets", tsession.sessid);
+    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, errorcodes[7]);
+    wsRequest.reject(404, "No such resource.");
+}
+
+function pushStatus() {
+  getStatus(function(info) {
+    info["t"] = "t";
+    gamemux.emit('list', info);
+  });
 }
 
 function shutdown () {
@@ -1154,5 +1196,6 @@
   wsServer = new WebSocketServer({"httpServer": httpServer});
   wsServer.on("request", wsHandler);
   tslog('WebSockets are online'); 
+  setInterval(pushStatus, 4000);
 });