# HG changeset patch # User John "Elwin" Edwards # 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();