diff --git a/rlgwebd.js b/rlgwebd.js index cc43dc7..6756e97 100755 --- a/rlgwebd.js +++ b/rlgwebd.js @@ -19,7 +19,6 @@ var httpPort = 8080; 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 @@ function TermSession(game, lkey, dims, handlers) { 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 @@ function TermSession(game, lkey, dims, handlers) { * 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 @@ function playerstatus(user, callback) { } /* 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 @@ function getMsgWS(msgObj) { 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 @@ function login(req, res, formdata) { 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 @@ function register(req, res, formdata) { 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 @@ function serveStatic(req, res, fname) { 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 @@ ctlServer.listen(ctlsocket, function () { 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');