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 } |