Add server-side support for watching dgamelaunch games.

This commit is contained in:
John "Elwin" Edwards 2015-01-13 20:30:10 -05:00
parent 56024418c3
commit 7332b95a30

View file

@ -297,6 +297,8 @@ function DglSession(filename) {
return; return;
} }
ss.rpos += 12; ss.rpos += 12;
/* Update timestamp, to within 1 second. */
ss.lasttime = new Date(1000 * buf.readUInt32LE(0));
var datalen = buf.readUInt32LE(8); var datalen = buf.readUInt32LE(8);
//tslog("Allocating %d bytes", datalen); //tslog("Allocating %d bytes", datalen);
if (datalen > 16384) { if (datalen > 16384) {
@ -315,6 +317,11 @@ function DglSession(filename) {
ss.reading = false; ss.reading = false;
/* Process the data */ /* Process the data */
ss.framepush(buf); ss.framepush(buf);
var wmsg = JSON.stringify({"t": "d", "d": buf.toString("hex")});
for (var i = 0; i < ss.watchers.length; i++) {
if (ss.watchers[i].connected)
ss.watchers[i].sendUTF(wmsg);
}
ss.emit("data", buf); ss.emit("data", buf);
//tslog("DGL %s: %d bytes", ss.tag(), buf.length); //tslog("DGL %s: %d bytes", ss.tag(), buf.length);
/* Recurse. */ /* Recurse. */
@ -339,7 +346,7 @@ function DglSession(filename) {
ss.emit('open', true); ss.emit('open', true);
tslog("DGL %s: open", ss.tag()); tslog("DGL %s: open", ss.tag());
ss.readchunk(); ss.readchunk();
ss.watcher = fs.watch(ss.ttyrec, function (ev, finame) { ss.recwatcher = fs.watch(ss.ttyrec, function (ev, finame) {
if (ev == "change") if (ev == "change")
ss.readchunk(); ss.readchunk();
}); });
@ -350,13 +357,40 @@ function DglSession(filename) {
return this.gname + "/" + this.pname; return this.gname + "/" + this.pname;
}; };
this.close = function () { this.close = function () {
this.watcher.close() this.recwatcher.close()
/* Ensure all data is handled before quitting. */ /* Ensure all data is handled before quitting. */
this.readchunk(); this.readchunk();
var connlist = this.watchers;
this.watchers = [];
for (var i = 0; i < connlist.length; i++) {
if (connlist[i].connected)
connlist[i].close();
}
fs.close(this.fd); fs.close(this.fd);
this.emit("close"); this.emit("close");
tslog("DGL %s: closed", ss.tag()); tslog("DGL %s: closed", ss.tag());
}; };
this.watchers = [];
/* Attach a watcher. */
this.attach = function (wsReq) {
var conn = wsReq.accept(null, wsReq.origin);
conn.sendUTF(JSON.stringify({
"t": "w", "w": this.w, "h": this.h, "p": this.pname,
"g": this.gname
}));
conn.sendUTF(JSON.stringify({"t": "d",
"d": this.framebuf.toString("hex", 0, this.frameoff)}));
conn.on('close', function () {
/* 'this' is the connection when triggered */
var n = ss.watchers.indexOf(this);
if (n >= 0) {
ss.watchers.splice(n, 1);
tslog("A WebSocket watcher has left DGL game %s", ss.tag());
}
});
this.watchers.push(conn);
};
this.lasttime = new Date();
} }
DglSession.prototype = new events.EventEmitter(); DglSession.prototype = new events.EventEmitter();
@ -790,6 +824,7 @@ function getStatus(callback) {
gamedesc["p"] = sessions[tag].pname; gamedesc["p"] = sessions[tag].pname;
gamedesc["g"] = sessions[tag].game.uname; gamedesc["g"] = sessions[tag].game.uname;
gamedesc["i"] = now - sessions[tag].lasttime; gamedesc["i"] = now - sessions[tag].lasttime;
gamedesc["w"] = sessions[tag].watchers.length;
statusinfo["g"].push(gamedesc); statusinfo["g"].push(gamedesc);
} }
statusinfo["dgl"] = []; statusinfo["dgl"] = [];
@ -798,7 +833,8 @@ function getStatus(callback) {
var slash = tag.search('/'); var slash = tag.search('/');
dglinfo["g"] = tag.slice(0, slash); dglinfo["g"] = tag.slice(0, slash);
dglinfo["p"] = tag.slice(slash + 1); dglinfo["p"] = tag.slice(slash + 1);
dglinfo["i"] = -1; dglinfo["i"] = now - dglgames[tag].lasttime;
dglinfo["w"] = dglgames[tag].watchers.length;
statusinfo["dgl"].push(dglinfo); statusinfo["dgl"].push(dglinfo);
} }
callback(statusinfo); callback(statusinfo);
@ -1022,13 +1058,20 @@ function wsHandler(wsRequest) {
var watchmatch = wsRequest.resource.match(/^\/watch\/(.*)$/); var watchmatch = wsRequest.resource.match(/^\/watch\/(.*)$/);
var playmatch = wsRequest.resource.match(/^\/play\//); var playmatch = wsRequest.resource.match(/^\/play\//);
if (watchmatch !== null) { if (watchmatch !== null) {
if (!(watchmatch[1] in sessions)) { if (watchmatch[1] in sessions) {
var tsession = sessions[watchmatch[1]];
tsession.attach(wsRequest);
tslog("Game %s is being watched via WebSockets", tsession.tag());
}
else if (watchmatch[1] in dglgames) {
var dsession = dglgames[watchmatch[1]];
dsession.attach(wsRequest);
tslog("DGL game %s is being watched via WebSockets", dsession.tag());
}
else {
wsRequest.reject(404, errorcodes[7]); wsRequest.reject(404, errorcodes[7]);
return; return;
} }
var tsession = sessions[watchmatch[1]];
tsession.attach(wsRequest);
tslog("Game %s is being watched via WebSockets", tsession.tag());
} }
else if (playmatch !== null) { else if (playmatch !== null) {
wsStartGame(wsRequest); wsStartGame(wsRequest);
@ -1077,16 +1120,21 @@ function pushStatus() {
gamedesc["p"] = sessions[tag].pname; gamedesc["p"] = sessions[tag].pname;
gamedesc["g"] = sessions[tag].game.uname; gamedesc["g"] = sessions[tag].game.uname;
gamedesc["i"] = delta; gamedesc["i"] = delta;
gamedesc["w"] = sessions[tag].watchers.length;
statusinfo["g"].push(gamedesc); statusinfo["g"].push(gamedesc);
} }
} }
for (var tag in dglgames) { for (var tag in dglgames) {
var dglinfo = {}; var delta = now - dglgames[tag].lasttime;
var slash = tag.search('/'); if (delta < 60000) {
dglinfo["g"] = tag.slice(0, slash); var dglinfo = {};
dglinfo["p"] = tag.slice(slash + 1); var slash = tag.search('/');
dglinfo["i"] = -1; dglinfo["g"] = tag.slice(0, slash);
statusinfo["dgl"].push(dglinfo); dglinfo["p"] = tag.slice(slash + 1);
dglinfo["i"] = delta;
dglinfo["w"] = dglgames[tag].watchers.length;
statusinfo["dgl"].push(dglinfo);
}
} }
gamemux.emit('list', statusinfo); gamemux.emit('list', statusinfo);
} }