# HG changeset patch
# User John "Elwin" Edwards <elwin@sdf.org>
# Date 1337099412 25200
# Node ID 155f3c104759c92ebfc3c9c86ec80b9077742542
# Parent bf7c26d0b66d2c2b7a7d702e92f4df3b5cd8ceb4
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.
diff -r bf7c26d0b66d -r 155f3c104759 shterm.js
--- 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();