# HG changeset patch # User John "Elwin" Edwards # Date 1339302014 25200 # Node ID 27b7f0c8b9f08f64e1dc5c6f6182967e424459cf # Parent 59ecd99845ebdd3504529a651d0c0f3b1c2ba32b RLG-Web: make login sessions time out. After enough inactivity, log the user out automatically. diff -r 59ecd99845eb -r 27b7f0c8b9f0 rlgterm.js --- a/rlgterm.js Sat Jun 09 17:00:25 2012 -0700 +++ b/rlgterm.js Sat Jun 09 21:20:14 2012 -0700 @@ -164,6 +164,9 @@ else if (msgDict.t == "E") { if (msgDict.c == 1 || msgDict.c == 6 || msgDict.c == 7) { gameover(); + if (msgDict.c == 1) { + logout(); + } } debug(1, "Server error: " + msgDict.s); } @@ -496,6 +499,9 @@ } else if (reply.t == 'E') { debug(1, "Could not start game: " + reply.s); + if (reply.c == 1) { + logout(); + } } }; req.open('POST', '/play', true); @@ -551,6 +557,12 @@ return; } +function logout() { + lcred = null; + lname = null; + setmode("login"); +} + function stop() { if (!termemu.sessid) return; diff -r 59ecd99845eb -r 27b7f0c8b9f0 rlgwebd.js --- 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));