RLG-Web server: add playing through WebSockets.
Games can be played with a WebSocket connection to /play/<game>?key=<loginkey>&w=<cols>&h=<rows>
This commit is contained in:
parent
185ea6a9ef
commit
d11eb5e22a
1 changed files with 102 additions and 4 deletions
106
rlgwebd.js
106
rlgwebd.js
|
|
@ -182,7 +182,8 @@ function TermSession(game, lkey, dims, handlers) {
|
|||
gamemux.emit('end', id);
|
||||
});
|
||||
this.close = function () {
|
||||
this.term.kill('SIGHUP');
|
||||
if (this.sessid in sessions)
|
||||
this.term.kill('SIGHUP');
|
||||
};
|
||||
}
|
||||
TermSession.prototype = new events.EventEmitter();
|
||||
|
|
@ -385,6 +386,93 @@ function wsWatcher(conn, session) {
|
|||
"d": session.framebuf.toString("hex", 0, session.frameoff)}));
|
||||
}
|
||||
|
||||
function wsPlay(wsReq, game, lkey, dims) {
|
||||
var conn;
|
||||
var session;
|
||||
/* Listeners on the WebSocket */
|
||||
function messageH(message) {
|
||||
var parsedMsg = getMsgWS(message);
|
||||
if (parsedMsg.t == 'q') {
|
||||
session.close();
|
||||
}
|
||||
else if (parsedMsg.t == 'd') {
|
||||
var hexstr = parsedMsg.d.replace(/[^0-9a-f]/gi, "");
|
||||
if (hexstr.length % 2 != 0) {
|
||||
hexstr = hexstr.slice(0, -1);
|
||||
}
|
||||
var keybuf = new Buffer(hexstr, "hex");
|
||||
session.write(keybuf);
|
||||
}
|
||||
}
|
||||
function closeH() {
|
||||
session.close();
|
||||
}
|
||||
/* These listen on the TermSession. */
|
||||
function openH(success, id) {
|
||||
if (success) {
|
||||
var reply = {"t": "s", "id": id, "w": sessions[id].w, "h":
|
||||
sessions[id].h, "p": sessions[id].pname, "g": game};
|
||||
conn = wsReq.accept(null, wsReq.origin);
|
||||
conn.sendUTF(JSON.stringify(reply));
|
||||
conn.on('message', messageH);
|
||||
conn.on('close', closeH);
|
||||
}
|
||||
else {
|
||||
wsReq.reject(500, errorcodes[5]);
|
||||
tslog("Unable to allocate TTY for %s", game);
|
||||
}
|
||||
}
|
||||
function dataH(chunk) {
|
||||
var msg = {};
|
||||
msg.t = "d";
|
||||
msg.d = chunk.toString("hex");
|
||||
conn.sendUTF(JSON.stringify(msg));
|
||||
}
|
||||
function exitH() {
|
||||
if (conn.connected)
|
||||
conn.sendUTF(JSON.stringify({"t": "q"}));
|
||||
conn.close();
|
||||
session.removeListener('open', openH);
|
||||
session.removeListener('data', dataH);
|
||||
session.removeListener('exit', exitH);
|
||||
}
|
||||
var handlers = {'open': openH, 'data': dataH, 'exit': exitH};
|
||||
session = new TermSession(game, lkey, dims, handlers);
|
||||
}
|
||||
|
||||
function wsStart(wsReq) {
|
||||
var playmatch = wsReq.resourceURL.pathname.match(/^\/play\/([^\/]*)$/);
|
||||
if (!playmatch[1] || !(playmatch[1] in games)) {
|
||||
wsReq.reject(404, errorcodes[2]);
|
||||
return;
|
||||
}
|
||||
var gname = playmatch[1];
|
||||
if (!allowlogin) {
|
||||
wsReq.reject(404, errorcodes[6]);
|
||||
return;
|
||||
}
|
||||
if (!("key" in wsReq.resourceURL.query)) {
|
||||
wsReq.reject(404, "No key given.");
|
||||
return;
|
||||
}
|
||||
var lkey = wsReq.resourceURL.query["key"];
|
||||
if (!(lkey in logins)) {
|
||||
wsReq.reject(404, errorcodes[1]);
|
||||
return;
|
||||
}
|
||||
var pname = logins[lkey].name;
|
||||
var dims = [wsReq.resourceURL.query.h, wsReq.resourceURL.query.w];
|
||||
function progcallback(err, fname) {
|
||||
if (fname) {
|
||||
wsReq.reject(404, errorcodes[4]);
|
||||
tslog("%s is already playing %s", pname, gname);
|
||||
}
|
||||
else
|
||||
wsPlay(wsReq, gname, lkey, dims);
|
||||
};
|
||||
checkprogress(pname, games[gname], progcallback, []);
|
||||
}
|
||||
|
||||
/* Some functions which check whether a player is currently playing or
|
||||
* has a saved game. Maybe someday they will provide information on
|
||||
* the game. */
|
||||
|
|
@ -530,6 +618,12 @@ function getMsg(posttext) {
|
|||
return jsonobj;
|
||||
}
|
||||
|
||||
function getMsgWS(msgObj) {
|
||||
if (msgObj.type != "utf8")
|
||||
return {};
|
||||
return getMsg(msgObj.utf8Data);
|
||||
}
|
||||
|
||||
function reaper() {
|
||||
var now = new Date();
|
||||
function reapcheck(session) {
|
||||
|
|
@ -1007,12 +1101,12 @@ function webHandler(req, res) {
|
|||
return;
|
||||
}
|
||||
/* process the keys */
|
||||
hexstr = formdata.d.replace(/[^0-9a-f]/gi, "");
|
||||
var hexstr = formdata.d.replace(/[^0-9a-f]/gi, "");
|
||||
if (hexstr.length % 2 != 0) {
|
||||
sendError(res, 2, "incomplete byte", true);
|
||||
return;
|
||||
}
|
||||
keybuf = new Buffer(hexstr, "hex");
|
||||
var keybuf = new Buffer(hexstr, "hex");
|
||||
client.write(keybuf, formdata.n);
|
||||
}
|
||||
readFeed(client, res);
|
||||
|
|
@ -1066,6 +1160,7 @@ function webHandler(req, res) {
|
|||
|
||||
function wsHandler(wsRequest) {
|
||||
var watchmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/);
|
||||
var playmatch = wsRequest.resource.match(/^\/play\//);
|
||||
if (watchmatch !== null) {
|
||||
if (watchmatch[1] && Number(watchmatch[1]) in sessions) {
|
||||
var tsession = sessions[Number(watchmatch[1])];
|
||||
|
|
@ -1076,7 +1171,10 @@ function wsHandler(wsRequest) {
|
|||
else
|
||||
wsRequest.reject(404, errorcodes[7]);
|
||||
}
|
||||
else if (wsRequest.resource == "/status") {
|
||||
else if (playmatch !== null) {
|
||||
wsStart(wsRequest);
|
||||
}
|
||||
else if (wsRequest.resourceURL.pathname == "/status") {
|
||||
var conn = wsRequest.accept(null, wsRequest.origin);
|
||||
var tell = function () {
|
||||
getStatus(function (info) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue