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:
parent
012c86faa8
commit
e0a70e4b0e
1 changed files with 42 additions and 26 deletions
68
rlgwebd.js
68
rlgwebd.js
|
|
@ -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)) {
|
||||
sendError(res, 4, null);
|
||||
tslog("%s is already playing %s", username, gname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 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] */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue