# HG changeset patch # User John "Elwin" Edwards # Date 1420324755 18000 # Node ID ed837da65e5f6234ccbcb45c20dcd4d02f02ab76 # Parent a613380ffdc29dc44743c4525f60eb9d2ed11d42 RLGWebD: Clean up code related to session timestamps. TermSessions now store the timestamp of the latest data. This removes the need to use fstat() to calculate idle times. The reaper() function is removed. It may be useful to find another way to remove old login keys. diff -r a613380ffdc2 -r ed837da65e5f rlgwebd.js --- a/rlgwebd.js Sat Jan 03 15:23:04 2015 -0500 +++ b/rlgwebd.js Sat Jan 03 17:39:15 2015 -0500 @@ -19,7 +19,6 @@ var chrootDir = "/var/dgl/"; var dropToUser = "rodney"; var serveStaticRoot = "/var/www/"; // inside the chroot -var playtimeout = 3600000; // Idle time before games are autosaved, in ms /* Data on the games available. */ var games = { @@ -122,7 +121,8 @@ this.emit('open', true, this.game.uname, this.pname); gamemux.emit('begin', this.game.uname, this.pname); /* Set up the lockfile and ttyrec */ - var ts = timestamp(); + this.lasttime = new Date(); + var ts = timestamp(this.lasttime); var progressdir = path.join("/dgldir/inprogress", this.game.uname); this.lock = path.join(progressdir, this.pname + ":node:" + ts + ".ttyrec"); var lmsg = this.term.pid.toString() + '\n' + this.h + '\n' + this.w + '\n'; @@ -134,15 +134,14 @@ * with a complete screen. */ this.framebuf = new Buffer(1024); this.frameoff = 0; - logins[lkey].sessions.push(this.game.uname + "/" + this.pname); /* END setup */ function ttyrec_chunk(datastr) { - var ts = new Date(); + ss.lasttime = new Date(); var buf = new Buffer(datastr); var chunk = new Buffer(buf.length + 12); /* TTYREC headers */ - chunk.writeUInt32LE(Math.floor(ts.getTime() / 1000), 0); - chunk.writeUInt32LE(1000 * (ts.getTime() % 1000), 4); + chunk.writeUInt32LE(Math.floor(ss.lasttime.getTime() / 1000), 0); + chunk.writeUInt32LE(1000 * (ss.lasttime.getTime() % 1000), 4); chunk.writeUInt32LE(buf.length, 8); buf.copy(chunk, 12); ss.record.write(chunk); @@ -373,8 +372,10 @@ } /* A few utility functions */ -function timestamp() { - dd = new Date(); +function timestamp(dd) { + if (!(dd instanceof Date)) { + dd = new Date(); + } sd = dd.toISOString(); sd = sd.slice(0, sd.indexOf(".")); return sd.replace("T", "."); @@ -457,47 +458,6 @@ return getMsg(msgObj.utf8Data); } -/* FIXME sessid removal */ -function reaper() { - return; // TODO figure out if this function is useful - var now = new Date(); - function reapcheck(session) { - fs.fstat(session.record.fd, function (err, stats) { - if (!err && now - stats.mtime > playtimeout) { - tslog("Reaping session %s", session.sessid); - /* Dissociate it with its login name. */ - var sn = logins[session.key].sessions.indexOf(session.sessid); - if (sn >= 0) { - logins[session.key].sessions.splice(sn, 1); - } - /* Shut it down. */ - session.close(); - } - }); - } - for (var sessid in sessions) { - reapcheck(sessions[sessid]); - } - for (var lkey in logins) { - if (logins[lkey].sessions.length > 0) { - /* Check for games that have terminated normally, and remove them. */ - var expired = []; - var targarray = logins[lkey].sessions; - /* Let's not find out what happens if you modify an array - * you're iterating through. */ - for (var i = 0; i < targarray.length; i++) { - if (!(targarray[i] in sessions)) - expired.push(targarray[i]); - } - if (expired.length > 0) { - for (var j = 0; j < expired.length; j++) { - targarray.splice(targarray.indexOf(expired[j]), 1); - } - } - } - } -} - function login(req, res, formdata) { if (!allowlogin) { sendError(res, 6, null, false); @@ -528,7 +488,7 @@ var lkey = randkey(2); while (lkey in logins) lkey = randkey(2); - logins[lkey] = {"name": username, "ts": new Date(), "sessions": []}; + logins[lkey] = {"name": username, "ts": new Date()}; res.writeHead(200, {'Content-Type': 'application/json'}); var reply = {"t": "l", "k": lkey, "u": username}; res.write(JSON.stringify(reply)); @@ -579,7 +539,7 @@ var lkey = randkey(2); while (lkey in logins) lkey = randkey(2); - logins[lkey] = {"name": uname, "ts": new Date(), "sessions": []}; + logins[lkey] = {"name": uname, "ts": new Date()}; var reply = {"t": "r", "k": lkey, "u": uname}; res.writeHead(200, {'Content-Type': 'application/json'}); res.write(JSON.stringify(reply)); @@ -732,54 +692,23 @@ return; } -/* TODO simplify by storing timestamps instead of callin stat() */ +/* Currently, this doesn't do anything blocking, but keep the callback */ function getStatus(callback) { var now = new Date(); var statusinfo = {"s": allowlogin, "g": []}; - function idleset(n, idletime) { - if (n >= 0 && n < statusinfo.g.length) { - statusinfo.g[n].i = idletime; - } - for (var j = 0; j < statusinfo.g.length; j++) { - if (!("i" in statusinfo.g[j])) - return; - } - callback(statusinfo); - } for (var tag in sessions) { var gamedesc = {}; gamedesc["tag"] = tag; gamedesc["p"] = sessions[tag].pname; gamedesc["g"] = sessions[tag].game.uname; + gamedesc["i"] = now - sessions[tag].lasttime; statusinfo["g"].push(gamedesc); } statusinfo["dgl"] = []; for (var tag in dglgames) { statusinfo["dgl"].push(tag); } - if (statusinfo.g.length == 0) { - callback(statusinfo); - return; - } - function makecallback(i) { - return function (err, stats) { - if (err) - idleset(i, null); - else - idleset(i, now - stats.mtime); - } - } - for (var i = 0; i < statusinfo.g.length; i++) { - /* fd sometimes isn't a number, presumably when the file isn't open yet. */ - /* FIXME sessid -> tag */ - var tag = statusinfo.g[i].tag; - if (tag in sessions && typeof(sessions[tag].record.fd) == 'number') { - fs.fstat(sessions[tag].record.fd, makecallback(i)); - } - else { - idleset(i, null); - } - } + callback(statusinfo); } function statusmsg(req, res) { @@ -1134,7 +1063,6 @@ httpServer = http.createServer(webHandler); httpServer.listen(httpPort); tslog('rlgwebd running on port %d', httpPort); - setInterval(reaper, playtimeout / 4); wsServer = new WebSocketServer({"httpServer": httpServer}); wsServer.on("request", wsHandler); tslog('WebSockets are online');