Mercurial > hg > rlgwebd
comparison shterm.js @ 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 | 7a50b4412fea |
comparison
equal
deleted
inserted
replaced
| 13:bf7c26d0b66d | 14:155f3c104759 |
|---|---|
| 1 /* shterm.js: browser-side JavaScript to handle I/O for termemu.js when it | 1 /* shterm.js: browser-side JavaScript to handle I/O for termemu.js when it |
| 2 * is running a shell via the webtty.js server. | 2 * is running a shell via the webtty.js server. |
| 3 */ | 3 */ |
| 4 | 4 |
| 5 /* The number of the next packet to send. */ | 5 var nsend = 0; // The number of the next packet to send. |
| 6 var nsend = 0; | 6 var nrecv = 0; // The next packet expected. |
| 7 var msgQ = []; // Queue for out-of-order messages. | |
| 7 | 8 |
| 8 // A state machine that keeps track of polling the server. | 9 // A state machine that keeps track of polling the server. |
| 9 var ajaxstate = { | 10 var ajaxstate = { |
| 10 state: 0, | 11 state: 0, |
| 11 timerID: null, | 12 timerID: null, |
| 114 } | 115 } |
| 115 termemu.write(codes); | 116 termemu.write(codes); |
| 116 return; | 117 return; |
| 117 } | 118 } |
| 118 | 119 |
| 120 function processMsg(response) { | |
| 121 if (response.t != "d" || typeof(response.d) != "string") | |
| 122 return; | |
| 123 if (response.n === nrecv) { | |
| 124 writeData(response.d); | |
| 125 nrecv++; | |
| 126 var next; | |
| 127 /* msgQ must be shifted every time nrecv is incremented, but the process | |
| 128 * stops whenever an empty space, corresponding to an unarrived message, | |
| 129 * is encountered. | |
| 130 */ | |
| 131 while ((next = msgQ.shift()) !== undefined) { | |
| 132 writeData(next.d); | |
| 133 nrecv++; | |
| 134 } | |
| 135 } | |
| 136 else if (response.n > nrecv) { | |
| 137 /* The current message comes after one still missing. Queue this one | |
| 138 * for later use. | |
| 139 */ | |
| 140 debug(1, "Got packet " + response.n + ", expected " + nrecv); | |
| 141 msgQ[response.n - nrecv - 1] = response; | |
| 142 } | |
| 143 else { | |
| 144 /* This message's number was encountered previously. */ | |
| 145 debug(1, "Discarding packet " + response.n + ", expected " + nrecv); | |
| 146 } | |
| 147 } | |
| 148 | |
| 119 function getData() { | 149 function getData() { |
| 120 if (!termemu.alive) | 150 if (!termemu.alive) |
| 121 return; | 151 return; |
| 122 var datareq = new XMLHttpRequest(); | 152 var datareq = new XMLHttpRequest(); |
| 123 datareq.onreadystatechange = function () { | 153 datareq.onreadystatechange = function () { |
| 132 } | 162 } |
| 133 } | 163 } |
| 134 else if (response.t == "n") | 164 else if (response.t == "n") |
| 135 ajaxstate.gotnothing(); | 165 ajaxstate.gotnothing(); |
| 136 else if (response.t == "d") { | 166 else if (response.t == "d") { |
| 137 writeData(response.d); | 167 processMsg(response); |
| 138 debug(1, "Got packet " + response.n); | |
| 139 ajaxstate.gotdata(); | 168 ajaxstate.gotdata(); |
| 140 } | 169 } |
| 141 return; | 170 return; |
| 142 } | 171 } |
| 143 }; | 172 }; |
| 160 } | 189 } |
| 161 else if (response.t != "d") | 190 else if (response.t != "d") |
| 162 return; | 191 return; |
| 163 /* It is a data message */ | 192 /* It is a data message */ |
| 164 if (response.d) { | 193 if (response.d) { |
| 165 writeData(response.d); | 194 processMsg(response); |
| 166 debug(1, "Got packet " + response.n); | 195 //debug(1, "Got packet " + response.n); |
| 167 } | 196 } |
| 168 ajaxstate.posted(); | 197 ajaxstate.posted(); |
| 169 return; | 198 return; |
| 170 } | 199 } |
| 171 } | 200 } |
| 314 if (logindict.login) { | 343 if (logindict.login) { |
| 315 /* Success */ | 344 /* Success */ |
| 316 termemu.resize(logindict.h, logindict.w); | 345 termemu.resize(logindict.h, logindict.w); |
| 317 termemu.alive = true; | 346 termemu.alive = true; |
| 318 nsend = 0; | 347 nsend = 0; |
| 348 nrecv = 0; | |
| 319 setTitle("Logged in"); | 349 setTitle("Logged in"); |
| 320 debug(1, "Logged in with id " + logindict.id); | 350 debug(1, "Logged in with id " + logindict.id); |
| 321 getData(); | 351 getData(); |
| 322 return; | 352 return; |
| 323 } | 353 } |
