RLG-Web: begin converting to WebSockets.

Use WebSockets for watching, if the browser supports it.  Functionality
is not complete yet.
This commit is contained in:
John "Elwin" Edwards 2012-07-12 22:16:15 -07:00
parent e143ac7d20
commit aee00a29d5
2 changed files with 88 additions and 1 deletions

View file

@ -11,6 +11,7 @@ var events = require('events');
var child_process = require('child_process');
var daemon = require(path.join(localModules, "daemon"));
var pty = require(path.join(localModules, "pty.js"));
var WebSocketServer = require(path.join(localModules, "websocket")).server;
/* Configuration variables */
// These first two files are NOT in the chroot.
@ -130,6 +131,8 @@ function TermSession(game, lkey, dims, handlers) {
* with a complete screen. */
this.framebuf = new Buffer(1024);
this.frameoff = 0;
/* List of WebSockets watching the game. */
this.watchsocks = [];
logins[lkey].sessions.push(this.sessid);
/* END setup */
function ttyrec_chunk(datastr) {
@ -168,6 +171,22 @@ function TermSession(game, lkey, dims, handlers) {
this.write = function(data) {
this.term.write(data);
};
// WebSocket watchers.
this.addWS = function (conn) {
this.watchsocks.push(conn);
};
this.removeWS = function (conn) {
var i = this.watchsocks.indexOf(conn);
if (i >= 0) {
if (conn.connected)
conn.close();
this.watchsocks.splice(i, 1);
return true;
}
else
return false;
};
// Teardown.
this.term.on("exit", function () {
fs.unlink(ss.lock);
ss.record.end();
@ -354,6 +373,27 @@ function Player(gamename, lkey, dims, callback) {
this.session = new TermSession(gamename, lkey, dims, handlers);
}
// Also known as WebSocketAndTermSessionClosureGlueFactory
function wsWatcher(conn, session) {
var ss = this; // is this even needed?
var dataH = function(buf) {
conn.sendUTF(JSON.stringify({"t": "d", "d": buf.toString("hex")}));
};
var exitH = function() {
if (conn.connected)
conn.close();
}
session.on('data', dataH);
session.on('exit', exitH);
conn.on('close', function(code, desc) {
session.removeListener('data', dataH);
session.removeListener('exit', exitH);
tslog("A WebSocket watcher has left game %d", session.sessid);
});
conn.sendUTF(JSON.stringify({"t": "d",
"d": session.framebuf.toString("hex", 0, session.frameoff)}));
}
/* Some functions which check whether a player is currently playing or
* has a saved game. Maybe someday they will provide information on
* the game. */
@ -1029,6 +1069,18 @@ function webHandler(req, res) {
}
function wsHandler(wsRequest) {
var urlmatch = wsRequest.resource.match(/^\/watch\/([0-9]*)$/);
if (urlmatch !== null && urlmatch[1] && Number(urlmatch[1]) in sessions) {
var tsession = sessions[Number(urlmatch[1])];
var conn = wsRequest.accept(null, wsRequest.origin);
new wsWatcher(conn, tsession);
tslog("Game %d is being watched via WebSockets", tsession.sessid);
}
else
wsRequest.reject(404, errorcodes[7]);
}
function shutdown () {
httpServer.close();
httpServer.removeAllListeners('request');
@ -1066,6 +1118,7 @@ if (process.getuid() != 0) {
}
var httpServer; // declare here so shutdown() can find it
var wsServer;
/* This could be nonblocking, but nothing else can start yet anyway. */
if (fs.existsSync(ctlsocket)) {
@ -1106,5 +1159,8 @@ ctlServer.listen(ctlsocket, function () {
httpServer.listen(httpPort);
tslog('rlgwebd running on port %d', httpPort);
setInterval(reaper, playtimeout / 4);
wsServer = new WebSocketServer({"httpServer": httpServer});
wsServer.on("request", wsHandler);
tslog('WebSockets are online');
});