diff webtty.js @ 153:c4a32007d2dc

WebTTY: remove polling. Communication now uses WebSockets only.
author John "Elwin" Edwards
date Mon, 27 Jan 2014 16:02:27 -0800
parents 789c094675f4
children 5372f1f97cf5
line wrap: on
line diff
--- a/webtty.js	Sun Jan 26 19:56:02 2014 -0800
+++ b/webtty.js	Mon Jan 27 16:02:27 2014 -0800
@@ -11,7 +11,7 @@
 
 var serveStaticRoot = fs.realpathSync(".");
 var sessions = {};
-var sessionsWS = {};
+var nsessid = 0;
 
 var env_dontuse = {"TMUX": true, "TMUX_PANE": true};
 
@@ -79,94 +79,11 @@
       ss.conn.sendUTF(JSON.stringify({"t": "q"}));
     }
   };
+  sessions[nsessid++] = this;
   this.conn.sendUTF(JSON.stringify({"t": "l", "w": w, "h": h}));
   console.log("New WebSocket connection.");
 }
 
-function TermSession(sessid, h, w) {
-  /* Set up the sizes. */
-  w = Math.floor(Number(w));
-  if (!(w > 0 && w < 256))
-    w = 80;
-  this.w = w;
-  h = Math.floor(Number(h));
-  if (!(h > 0 && h < 256))
-    h = 25;
-  this.h = h;
-  /* Customize the environment. */
-  var childenv = {};
-  for (var key in process.env) {
-    if (!(key in env_dontuse))
-      childenv[key] = process.env[key];
-  }
-  var spawnopts = {"env": childenv, "cwd": process.env["HOME"], 
-                   "rows": this.h, "cols": this.w};
-  this.term = pty.spawn("bash", [], spawnopts);
-  var ss = this;
-  /* Eventually we'll need to make sure the sessid isn't in use yet. */
-  this.sessid = sessid;
-  this.alive = true;
-  this.data = []; // Buffer for the process' output.
-  this.nsend = 0; // Number to use for the next message sent.
-  this.nrecv = 0; // Number expected on the next message received.
-  this.msgQ = []; // Queue for messages that arrived out of order.
-  this.term.on("data", function (buf) {
-    ss.data.push(buf);
-  });
-  this.term.on("exit", function () {
-    ss.alive = false;
-    /* Wait for all the data to get collected */
-    setTimeout(ss.cleanup, 1000);
-  });
-  this.write = function (data, n) {
-    if (!this.alive) {
-      /* Throw some kind of exception? */
-      return;
-    }
-    if (n !== this.nrecv) {
-      console.log("Session " + this.sessid + ": Expected message " + this.nrecv + ", got " + n);
-    }
-    this.nrecv = n + 1;
-    this.term.write(data);
-  };
-  this.read = function () {
-    if (this.data.length == 0)
-      return null;
-    var pos = 0;
-    var i = 0;
-    for (i = 0; i < this.data.length; i++)
-      pos += Buffer.byteLength(this.data[i]);
-    var nbuf = new Buffer(pos);
-    var tptr;
-    pos = 0;
-    while (this.data.length > 0) {
-      tptr = new Buffer(this.data.shift());
-      tptr.copy(nbuf, pos);
-      pos += tptr.length;
-    }
-    return nbuf;
-  };
-  this.close = function () {
-    if (this.alive)
-      this.term.kill('SIGHUP');
-  };
-  this.cleanup = function () {
-    /* Call this when the child is dead. */
-    if (this.alive)
-      return;
-    /* Give the client a chance to read any leftover data. */
-    if (ss.data.length > 0)
-      setTimeout(ss.remove, 8000);
-    else
-      ss.remove();
-  };
-  this.remove = function () {
-    delete sessions[ss.sessid];
-    console.log("Session " + this.sessid + " removed.");
-  };
-  sessions[sessid] = this;
-}
-
 function randkey() {
   rnum = Math.floor(Math.random() * 65536 * 65536);
   hexstr = rnum.toString(16);
@@ -226,45 +143,6 @@
   return jsonobj;
 }
 
-function login(req, res, formdata) {
-  var resheaders = {'Content-Type': 'text/plain'};
-  var sessid = randkey();
-  /* The TermSession constructor will check these thoroughly too, but 
-   * you can't be too suspicious of client-supplied data. */
-  var w = 80;
-  var h = 25;
-  var t;
-  if ("w" in formdata) {
-    t = Math.floor(Number(formdata["w"]));
-    if (t > 0 && t < 256)
-      w = t;
-  }
-  if ("h" in formdata) {
-    t = Math.floor(Number(formdata["h"]));
-    if (t > 0 && t < 256)
-      h = t;
-  }
-  var nsession = new TermSession(sessid, h, w);
-  resheaders["Set-Cookie"] = "ID=" + sessid;
-  res.writeHead(200, resheaders);
-  var logindict = {"login": true, "id": sessid, "w": w, "h": h};
-  res.write(JSON.stringify(logindict));
-  res.end();
-  console.log("Started new session with key " + sessid + ", pid " + nsession.term.pid);
-  return;
-}
-
-function findTermSession(req) {
-  var cookies = getCookies(req);
-  if ("id" in cookies) {
-    var sessid = cookies["id"];
-    if (sessid in sessions) {
-      return sessions[sessid];
-    }
-  }
-  return null;
-}
-
 function serveStatic(req, res, fname) {
   var nname = path.normalize(fname);
   if (nname == "" || nname == "/")
@@ -306,27 +184,6 @@
   return;
 }
 
-function readFeed(res, term) {
-  res.writeHead(200, { "Content-Type": "text/plain" });
-  if (term) {
-    var answer = {};
-    var result = term.read();
-    if (result == null) {
-      answer["t"] = "n";
-    }
-    else {
-      answer["t"] = "d";
-      answer["d"] = result.toString("hex");
-      answer["n"] = term.nsend++;
-    }
-    res.write(JSON.stringify(answer));
-    res.end();
-  }
-  else {
-    sendError(res, 1);
-  }
-}
-
 var errorcodes = [ "Generic Error", "Not logged in", "Invalid data" ];
 
 function sendError(res, ecode) {
@@ -353,55 +210,14 @@
   /* This will send the response once the whole request is here. */
   function respond() {
     var target = url.parse(req.url).pathname;
-    var cterm = findTermSession(req);
-    /* First figure out if the client is POSTing to a command interface. */
+    /* Currently only static files and WebSockets are needed. */
     if (req.method == 'POST') {
       formdata = getFormValues(reqbody);
-      if (target == '/feed') {
-        if (!cterm) {
-          sendError(res, 1);
-          return;
-        }
-        if (formdata["t"] == "q") {
-          /* The client wants to quit. */
-          // FIXME need to send a message back to the client
-          cterm.close();
-        }
-        else if (formdata["t"] == "d" && typeof(formdata["d"]) == "string") {
-          /* process the keys */
-          hexstr = formdata["d"].replace(/[^0-9a-f]/gi, "");
-          if (hexstr.length % 2 != 0) {
-            sendError(res, 2);
-            return;
-          }
-          keybuf = new Buffer(hexstr, "hex");
-          cterm.write(keybuf, formdata["n"]);
-        }
-        readFeed(res, cterm);
-      }
-      else if (target == "/login") {
-        login(req, res, formdata);
-      }
-      else {
-        res.writeHead(405, resheaders);
-        res.end();
-      }
+      res.writeHead(405, resheaders);
+      res.end();
     }
     else if (req.method == 'GET' || req.method == 'HEAD') {
-      if (target == '/feed') {
-        if (!cterm) {
-          sendError(res, 1);
-          return;
-        }
-        readFeed(res, cterm);
-      }
-      /* Default page, create a new term */
-      /* FIXME New term not created anymore, is a special case still needed? */
-      else if (target == '/') {
-        serveStatic(req, res, "/");
-      }
-      else /* Go look for it in the filesystem */
-        serveStatic(req, res, target);
+      serveStatic(req, res, target);
     }
     else { /* Some other method */
       res.writeHead(501, resheaders);
@@ -411,7 +227,6 @@
     return;
   }
   req.on('end', respond);
-
 }
 
 process.on("exit", function () {