Mercurial > hg > rlgwebd
diff rlgwebd.js @ 47:27b7f0c8b9f0
RLG-Web: make login sessions time out.
After enough inactivity, log the user out automatically.
author | John "Elwin" Edwards <elwin@sdf.org> |
---|---|
date | Sat, 09 Jun 2012 21:20:14 -0700 |
parents | c4efc7522e7b |
children | 423ef87ddc9b |
line wrap: on
line diff
--- a/rlgwebd.js Sat Jun 09 17:00:25 2012 -0700 +++ b/rlgwebd.js Sat Jun 09 21:20:14 2012 -0700 @@ -59,7 +59,7 @@ * been authenticated. */ /* TODO take a callback, or emit success/err events. */ -function TermSession(game, user, dims) { +function TermSession(game, user, dims, lkey) { /* First make sure starting the game will work. */ if (game in games) { this.game = games[game]; @@ -69,6 +69,7 @@ return null; } this.player = String(user); + this.key = lkey; /* This order seems to best avoid race conditions... */ this.alive = false; this.sessid = randkey(2); @@ -361,6 +362,14 @@ fs.fstat(session.record.fd, function (err, stats) { if (!err && now - stats.mtime > playtimeout) { tslog("Reaping %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); + if (now - logins[session.key].ts > playtimeout) + logins[session.key].ts = new Date(now - playtimeout); + } + /* Shut it down. */ session.close(); } }); @@ -368,6 +377,35 @@ for (var sessid in sessions) { reapcheck(sessions[sessid]); } + /* HELPME this is about as clever as I can code, so I can't tell whether + * there are any bugs. */ + for (var lkey in logins) { + if (logins[lkey].sessions.length == 0) { + /* A login with no current games can be killed for inactivity. */ + if (now - logins[lkey].ts > playtimeout * 4) { + tslog("Login for %s (key %s) timed out", logins[lkey].name, lkey); + delete logins[lkey]; + } + } + else { + /* Check for games that have terminated normally, and update + * the timestamp. */ + 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) { + logins[lkey].ts = new Date(now); + for (var j = 0; j < expired.length; j++) { + targarray.splice(targarray.indexOf(expired[j], 1)); + } + } + } + } } function login(req, res, formdata) { @@ -400,7 +438,7 @@ var lkey = randkey(2); while (lkey in logins) lkey = randkey(2); - logins[lkey] = {"name": username, "ts": new Date()}; + logins[lkey] = {"name": username, "ts": new Date(), "sessions": []}; res.writeHead(200, {'Content-Type': 'application/json'}); var reply = {"t": "l", "k": lkey, "u": username}; res.write(JSON.stringify(reply)); @@ -452,7 +490,7 @@ return; } // Game starting has been approved. - var nsession = new TermSession(gname, username, dims); + var nsession = new TermSession(gname, username, dims, lkey); if (nsession) { res.writeHead(200, {'Content-Type': 'application/json'}); var reply = {"t": "l", "id": nsession.sessid, "w": nsession.w, "h": @@ -461,6 +499,7 @@ res.end(); tslog("%s playing %s (key %s, pid %d)", username, gname, nsession.sessid, nsession.child.pid); + logins[lkey].sessions.push(nsession.sessid); } else { sendError(res, 5, "Failed to open TTY"); @@ -506,7 +545,7 @@ var lkey = randkey(2); while (lkey in logins) lkey = randkey(2); - logins[lkey] = {"name": uname, "ts": new Date()}; + logins[lkey] = {"name": uname, "ts": new Date(), "sessions": []}; var reply = {"t": "r", "k": lkey, "u": uname}; res.writeHead(200, {'Content-Type': 'application/json'}); res.write(JSON.stringify(reply));