rlgwebd.js: refactor some game-starting code.

Separate things like checking for games in progress, starting a new
game, and figuring out where the lockfile and ttyrec should go.  This
allows e.g. the games-in-progress check to be used to create status
messages.  It also keeps the argument list for the TermSession
constructor to a sensible size.
This commit is contained in:
John "Elwin" Edwards 2012-06-08 18:11:47 -07:00
parent 012c86faa8
commit e0a70e4b0e

View file

@ -54,7 +54,8 @@ var allowlogin = true;
* adds itself to the sessions dict. It currently assumes the user has
* been authenticated.
*/
function TermSession(game, user, files, dims) {
/* TODO take a callback, or emit success/err events. */
function TermSession(game, user, dims) {
/* First make sure starting the game will work. */
if (game in games) {
this.game = games[game];
@ -63,7 +64,7 @@ function TermSession(game, user, files, dims) {
// TODO: throw an exception instead
return null;
}
this.player = user;
this.player = String(user);
/* This order seems to best avoid race conditions... */
this.alive = false;
this.sessid = randkey(2);
@ -97,10 +98,15 @@ function TermSession(game, user, files, dims) {
var ss = this;
this.alive = true;
this.data = [];
this.lock = files[0];
fs.writeFile(this.lock, this.child.pid.toString() + '\n' + this.w + '\n' +
this.h + '\n', "utf8");
this.record = fs.createWriteStream(files[1], { mode: 0664 });
/* Set up the lockfile and ttyrec */
var ts = timestamp();
var progressdir = "/dgldir/inprogress-" + this.game.uname;
this.lock = path.join(progressdir, this.player + ":node:" + ts + ".ttyrec");
var lmsg = this.child.pid.toString() + '\n' + this.w + '\n' + this.h + '\n';
fs.writeFile(this.lock, lmsg, "utf8");
var ttyrec = path.join("/dgldir/ttyrec", this.player, this.game.uname,
ts + ".ttyrec");
this.record = fs.createWriteStream(ttyrec, { mode: 0664 });
/* END setup */
function ttyrec_chunk(buf) {
var ts = new Date();
@ -219,6 +225,27 @@ function TermSession(game, user, files, dims) {
};
}
function checkprogress(user, game, callback, args) {
var progressdir = "/dgldir/inprogress-" + game.uname;
fs.readdir(progressdir, function(err, files) {
if (err) {
args.unshift(err, null);
callback.apply(null, args);
return;
}
var fre = RegExp("^" + user + ":");
for (var i = 0; i < files.length; i++) {
if (files[i].match(fre)) {
args.shift(null, files[i]);
callback.apply(null, args);
return;
}
}
args.shift(null, false);
callback.apply(null, args);
});
}
/* A few utility functions */
function timestamp() {
dd = new Date();
@ -374,28 +401,16 @@ function startgame(req, res, formdata) {
tslog("Request for nonexistant game \"%s\"", gname);
return;
}
// check for an existing game
var progressdir = "/dgldir/inprogress-" + games[gname].uname;
fs.readdir(progressdir, function(err, files) {
if (!err) {
var fre = RegExp("^" + username + ":");
for (var i = 0; i < files.length; i++) {
if (files[i].match(fre)) {
// A callback to pass to the game-in-progress checker.
var launch = function(err, fname) {
if (fname) {
sendError(res, 4, null);
tslog("%s is already playing %s", username, gname);
return;
}
}
}
// Game starting has been approved.
var ts = timestamp();
var lockfile = path.join(progressdir, username + ":node:" + ts + ".ttyrec");
var ttyrec = path.join("/dgldir/ttyrec", username, gname, ts + ".ttyrec");
var nsession = new TermSession(gname, username, [lockfile, ttyrec], dims);
var nsession = new TermSession(gname, username, dims);
if (nsession) {
/* Technically there's a race condition for the "lock"file, but since
* it requires the user deliberately starting two games at similar times,
* it's not too serious. We can't get O_EXCL in Node anyway. */
res.writeHead(200, {'Content-Type': 'application/json'});
var reply = {"t": "l", "id": nsession.sessid, "w": nsession.w, "h":
nsession.h};
@ -408,7 +423,8 @@ function startgame(req, res, formdata) {
sendError(res, 5, "Failed to open TTY");
tslog("Unable to allocate TTY for %s", gname);
}
});
}
checkprogress(username, games[gname], launch, []);
}
/* Sets things up for a new user, like dgamelaunch's commands[register] */