changeset 14:155f3c104759

shterm.js: Client-side message ordering Make sure data from the server is written to the terminal emulator in the correct order. Out-of-order messages are stored in a queue until their turn comes.
author John "Elwin" Edwards <elwin@sdf.org>
date Tue, 15 May 2012 09:30:12 -0700
parents bf7c26d0b66d
children 7466927c17a5
files shterm.js
diffstat 1 files changed, 36 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/shterm.js	Sun May 13 20:50:13 2012 -0700
+++ b/shterm.js	Tue May 15 09:30:12 2012 -0700
@@ -2,8 +2,9 @@
  * is running a shell via the webtty.js server.
  */
 
-/* The number of the next packet to send. */
-var nsend = 0;
+var nsend = 0; // The number of the next packet to send.
+var nrecv = 0; // The next packet expected.
+var msgQ = []; // Queue for out-of-order messages.
 
 // A state machine that keeps track of polling the server.
 var ajaxstate = {
@@ -116,6 +117,35 @@
   return;
 }
 
+function processMsg(response) {
+  if (response.t != "d" || typeof(response.d) != "string")
+    return;
+  if (response.n === nrecv) {
+    writeData(response.d);
+    nrecv++;
+    var next;
+    /* msgQ must be shifted every time nrecv is incremented, but the process
+     * stops whenever an empty space, corresponding to an unarrived message,
+     * is encountered.
+     */
+    while ((next = msgQ.shift()) !== undefined) {
+      writeData(next.d);
+      nrecv++;
+    }
+  }
+  else if (response.n > nrecv) {
+    /* The current message comes after one still missing.  Queue this one
+     * for later use.
+     */
+    debug(1, "Got packet " + response.n + ", expected " + nrecv);
+    msgQ[response.n - nrecv - 1] = response;
+  }
+  else {
+    /* This message's number was encountered previously. */
+    debug(1, "Discarding packet " + response.n + ", expected " + nrecv);
+  }
+}
+
 function getData() {
   if (!termemu.alive)
     return;
@@ -134,8 +164,7 @@
       else if (response.t == "n")
         ajaxstate.gotnothing();
       else if (response.t == "d") {
-        writeData(response.d);
-        debug(1, "Got packet " + response.n);
+        processMsg(response);
         ajaxstate.gotdata();
       }
       return;
@@ -162,8 +191,8 @@
       return;
     /* It is a data message */
     if (response.d) {
-      writeData(response.d);
-      debug(1, "Got packet " + response.n);
+      processMsg(response);
+      //debug(1, "Got packet " + response.n);
     }
     ajaxstate.posted();
     return;
@@ -316,6 +345,7 @@
         termemu.resize(logindict.h, logindict.w);
         termemu.alive = true;
         nsend = 0;
+        nrecv = 0;
 	setTitle("Logged in");
         debug(1, "Logged in with id " + logindict.id);
         getData();