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);
|
gamemux.emit('end', id);
|
||||||
});
|
});
|
||||||
this.close = function () {
|
this.close = function () {
|
||||||
this.term.kill('SIGHUP');
|
if (this.sessid in sessions)
|
||||||
|
this.term.kill('SIGHUP');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
TermSession.prototype = new events.EventEmitter();
|
TermSession.prototype = new events.EventEmitter();
|
||||||
|
|
@ -385,6 +386,93 @@ function wsWatcher(conn, session) {
|
||||||
"d": session.framebuf.toString("hex", 0, session.frameoff)}));
|
"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
|
/* Some functions which check whether a player is currently playing or
|
||||||
* has a saved game. Maybe someday they will provide information on
|
* has a saved game. Maybe someday they will provide information on
|
||||||
* the game. */
|
* the game. */
|
||||||
|
|
@ -530,6 +618,12 @@ function getMsg(posttext) {
|
||||||
return jsonobj;
|
return jsonobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMsgWS(msgObj) {
|
||||||
|
if (msgObj.type != "utf8")
|
||||||
|
return {};
|
||||||
|
return getMsg(msgObj.utf8Data);
|
||||||
|
}
|
||||||
|
|
||||||
function reaper() {
|
function reaper() {
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
function reapcheck(session) {
|
function reapcheck(session) {
|
||||||
|
|
@ -1007,12 +1101,12 @@ function webHandler(req, res) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* process the keys */
|
/* 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) {
|
if (hexstr.length % 2 != 0) {
|
||||||
sendError(res, 2, "incomplete byte", true);
|
sendError(res, 2, "incomplete byte", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keybuf = new Buffer(hexstr, "hex");
|
var keybuf = new Buffer(hexstr, "hex");
|
||||||
client.write(keybuf, formdata.n);
|
client.write(keybuf, formdata.n);
|
||||||
}
|
}
|
||||||
readFeed(client, res);
|
readFeed(client, res);
|
||||||
|
|
@ -1066,6 +1160,7 @@ function webHandler(req, res) {
|
||||||
|
|
||||||
function wsHandler(wsRequest) {
|
function wsHandler(wsRequest) {
|
||||||
var watchmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/);
|
var watchmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/);
|
||||||
|
var playmatch = wsRequest.resource.match(/^\/play\//);
|
||||||
if (watchmatch !== null) {
|
if (watchmatch !== null) {
|
||||||
if (watchmatch[1] && Number(watchmatch[1]) in sessions) {
|
if (watchmatch[1] && Number(watchmatch[1]) in sessions) {
|
||||||
var tsession = sessions[Number(watchmatch[1])];
|
var tsession = sessions[Number(watchmatch[1])];
|
||||||
|
|
@ -1076,7 +1171,10 @@ function wsHandler(wsRequest) {
|
||||||
else
|
else
|
||||||
wsRequest.reject(404, errorcodes[7]);
|
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 conn = wsRequest.accept(null, wsRequest.origin);
|
||||||
var tell = function () {
|
var tell = function () {
|
||||||
getStatus(function (info) {
|
getStatus(function (info) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue