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.
This commit is contained in:
John "Elwin" Edwards 2012-05-15 09:30:12 -07:00
parent 090e02ed59
commit c7995adad5

View file

@ -2,8 +2,9 @@
* is running a shell via the webtty.js server. * is running a shell via the webtty.js server.
*/ */
/* The number of the next packet to send. */ var nsend = 0; // The number of the next packet to send.
var nsend = 0; 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. // A state machine that keeps track of polling the server.
var ajaxstate = { var ajaxstate = {
@ -116,6 +117,35 @@ function writeData(hexstr) {
return; 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() { function getData() {
if (!termemu.alive) if (!termemu.alive)
return; return;
@ -134,8 +164,7 @@ function getData() {
else if (response.t == "n") else if (response.t == "n")
ajaxstate.gotnothing(); ajaxstate.gotnothing();
else if (response.t == "d") { else if (response.t == "d") {
writeData(response.d); processMsg(response);
debug(1, "Got packet " + response.n);
ajaxstate.gotdata(); ajaxstate.gotdata();
} }
return; return;
@ -162,8 +191,8 @@ function postResponseHandler() {
return; return;
/* It is a data message */ /* It is a data message */
if (response.d) { if (response.d) {
writeData(response.d); processMsg(response);
debug(1, "Got packet " + response.n); //debug(1, "Got packet " + response.n);
} }
ajaxstate.posted(); ajaxstate.posted();
return; return;
@ -316,6 +345,7 @@ function login(h, w) {
termemu.resize(logindict.h, logindict.w); termemu.resize(logindict.h, logindict.w);
termemu.alive = true; termemu.alive = true;
nsend = 0; nsend = 0;
nrecv = 0;
setTitle("Logged in"); setTitle("Logged in");
debug(1, "Logged in with id " + logindict.id); debug(1, "Logged in with id " + logindict.id);
getData(); getData();