Issue #15: noVNC falls behind.
noVNC was never processing more than one framebufferUpdate message per onmessage event. If noVNC receives an incomplete framebufferUpdate and then receives the rest of the framebufferUpdate plus another complete framebufferUpdate, then it will fall permanently behind. If there is more to process after a completed framebufferUpdate, then execute normal_msg again. All the render routines must return false if there is not enough data in the receive queue to process their current update, and true otherwise.
This commit is contained in:
parent
11304584ca
commit
42b2246c1a
|
|
@ -509,7 +509,7 @@ normal_msg: function () {
|
||||||
}
|
}
|
||||||
switch (msg_type) {
|
switch (msg_type) {
|
||||||
case 0: // FramebufferUpdate
|
case 0: // FramebufferUpdate
|
||||||
ret = RFB.framebufferUpdate();
|
ret = RFB.framebufferUpdate(); // false means need more data
|
||||||
break;
|
break;
|
||||||
case 1: // SetColourMapEntries
|
case 1: // SetColourMapEntries
|
||||||
Util.Debug("SetColourMapEntries");
|
Util.Debug("SetColourMapEntries");
|
||||||
|
|
@ -587,7 +587,13 @@ framebufferUpdate: function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((FBU.rects > 0) && (RQ.length >= FBU.bytes)) {
|
while (FBU.rects > 0) {
|
||||||
|
if (RFB.state !== "normal") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (RQ.length < FBU.bytes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (FBU.bytes === 0) {
|
if (FBU.bytes === 0) {
|
||||||
if (RQ.length < 12) {
|
if (RQ.length < 12) {
|
||||||
//Util.Debug(" waiting for rect header bytes");
|
//Util.Debug(" waiting for rect header bytes");
|
||||||
|
|
@ -624,6 +630,7 @@ framebufferUpdate: function() {
|
||||||
last_bytes = RQ.length;
|
last_bytes = RQ.length;
|
||||||
last_rects = FBU.rects;
|
last_rects = FBU.rects;
|
||||||
|
|
||||||
|
// false ret means need more data
|
||||||
ret = RFB.encHandlers[FBU.encoding]();
|
ret = RFB.encHandlers[FBU.encoding]();
|
||||||
|
|
||||||
now = (new Date()).getTime();
|
now = (new Date()).getTime();
|
||||||
|
|
@ -662,8 +669,6 @@ framebufferUpdate: function() {
|
||||||
timing.fbu_rt_start = 0;
|
timing.fbu_rt_start = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RFB.state !== "normal") { return true; }
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
@ -684,7 +689,7 @@ display_raw: function () {
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (FBU.bytes - RQ.length) + " RAW bytes");
|
// (FBU.bytes - RQ.length) + " RAW bytes");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
cur_y = FBU.y + (FBU.height - FBU.lines);
|
cur_y = FBU.y + (FBU.height - FBU.lines);
|
||||||
cur_height = Math.min(FBU.lines,
|
cur_height = Math.min(FBU.lines,
|
||||||
|
|
@ -699,6 +704,7 @@ display_raw: function () {
|
||||||
FBU.rects -= 1;
|
FBU.rects -= 1;
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
display_copy_rect: function () {
|
display_copy_rect: function () {
|
||||||
|
|
@ -709,13 +715,14 @@ display_copy_rect: function () {
|
||||||
if (RQ.length < 4) {
|
if (RQ.length < 4) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (FBU.bytes - RQ.length) + " COPYRECT bytes");
|
// (FBU.bytes - RQ.length) + " COPYRECT bytes");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
old_x = RQ.shift16();
|
old_x = RQ.shift16();
|
||||||
old_y = RQ.shift16();
|
old_y = RQ.shift16();
|
||||||
Canvas.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height);
|
Canvas.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height);
|
||||||
FBU.rects -= 1;
|
FBU.rects -= 1;
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
display_rre: function () {
|
display_rre: function () {
|
||||||
|
|
@ -725,7 +732,7 @@ display_rre: function () {
|
||||||
if (RQ.length < 4 + RFB.fb_Bpp) {
|
if (RQ.length < 4 + RFB.fb_Bpp) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (4 + RFB.fb_Bpp - RQ.length) + " RRE bytes");
|
// (4 + RFB.fb_Bpp - RQ.length) + " RRE bytes");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
FBU.subrects = RQ.shift32();
|
FBU.subrects = RQ.shift32();
|
||||||
color = RQ.shiftBytes(RFB.fb_Bpp); // Background
|
color = RQ.shiftBytes(RFB.fb_Bpp); // Background
|
||||||
|
|
@ -751,6 +758,7 @@ display_rre: function () {
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
}
|
}
|
||||||
//Util.Debug("<< display_rre, FBU.bytes: " + FBU.bytes);
|
//Util.Debug("<< display_rre, FBU.bytes: " + FBU.bytes);
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
display_hextile: function() {
|
display_hextile: function() {
|
||||||
|
|
@ -771,14 +779,14 @@ display_hextile: function() {
|
||||||
FBU.bytes = 1;
|
FBU.bytes = 1;
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
//Util.Debug(" waiting for HEXTILE subencoding byte");
|
//Util.Debug(" waiting for HEXTILE subencoding byte");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
subencoding = RQ[0]; // Peek
|
subencoding = RQ[0]; // Peek
|
||||||
if (subencoding > 30) { // Raw
|
if (subencoding > 30) { // Raw
|
||||||
RFB.updateState('failed',
|
RFB.updateState('failed',
|
||||||
"Disconnected: illegal hextile subencoding " + subencoding);
|
"Disconnected: illegal hextile subencoding " + subencoding);
|
||||||
//Util.Debug("RQ.slice(0,30):" + RQ.slice(0,30));
|
//Util.Debug("RQ.slice(0,30):" + RQ.slice(0,30));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
subrects = 0;
|
subrects = 0;
|
||||||
cur_tile = FBU.total_tiles - FBU.tiles;
|
cur_tile = FBU.total_tiles - FBU.tiles;
|
||||||
|
|
@ -805,7 +813,7 @@ display_hextile: function() {
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
/* Wait for subrects byte */
|
/* Wait for subrects byte */
|
||||||
//Util.Debug(" waiting for hextile subrects header byte");
|
//Util.Debug(" waiting for hextile subrects header byte");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
subrects = RQ[FBU.bytes-1]; // Peek
|
subrects = RQ[FBU.bytes-1]; // Peek
|
||||||
if (subencoding & 0x10) { // SubrectsColoured
|
if (subencoding & 0x10) { // SubrectsColoured
|
||||||
|
|
@ -827,7 +835,7 @@ display_hextile: function() {
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (FBU.bytes - RQ.length) + " hextile bytes");
|
// (FBU.bytes - RQ.length) + " hextile bytes");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We know the encoding and have a whole tile */
|
/* We know the encoding and have a whole tile */
|
||||||
|
|
@ -889,6 +897,7 @@ display_hextile: function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Util.Debug("<< display_hextile");
|
//Util.Debug("<< display_hextile");
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -904,7 +913,7 @@ display_tight_png: function() {
|
||||||
FBU.bytes = 1; // compression-control byte
|
FBU.bytes = 1; // compression-control byte
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
Util.Debug(" waiting for TIGHT compression-control byte");
|
Util.Debug(" waiting for TIGHT compression-control byte");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'compact length' header and data size
|
// Get 'compact length' header and data size
|
||||||
|
|
@ -938,7 +947,7 @@ display_tight_png: function() {
|
||||||
|
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Util.Debug(" RQ.slice(0,20): " + RFB.RQ.slice(0,20) + " (" + RFB.RQ.length + ")");
|
//Util.Debug(" RQ.slice(0,20): " + RFB.RQ.slice(0,20) + " (" + RFB.RQ.length + ")");
|
||||||
|
|
@ -957,7 +966,7 @@ display_tight_png: function() {
|
||||||
FBU.bytes = 1 + clength[0] + clength[1]; // ctl + clength size + jpeg-data
|
FBU.bytes = 1 + clength[0] + clength[1]; // ctl + clength size + jpeg-data
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have everything, render it
|
// We have everything, render it
|
||||||
|
|
@ -976,6 +985,7 @@ display_tight_png: function() {
|
||||||
//Util.Debug(" ending RQ.length: " + RQ.length);
|
//Util.Debug(" ending RQ.length: " + RQ.length);
|
||||||
//Util.Debug(" ending RQ.slice(0,20): " + RQ.slice(0,20));
|
//Util.Debug(" ending RQ.slice(0,20): " + RQ.slice(0,20));
|
||||||
//Util.Debug("<< display_tight_png");
|
//Util.Debug("<< display_tight_png");
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
extract_data_uri : function (arr) {
|
extract_data_uri : function (arr) {
|
||||||
|
|
@ -1013,6 +1023,7 @@ set_desktopsize : function () {
|
||||||
RFB.FBU.rects -= 1;
|
RFB.FBU.rects -= 1;
|
||||||
|
|
||||||
Util.Debug("<< set_desktopsize");
|
Util.Debug("<< set_desktopsize");
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
set_cursor: function () {
|
set_cursor: function () {
|
||||||
|
|
@ -1042,6 +1053,7 @@ set_cursor: function () {
|
||||||
RFB.FBU.rects -= 1;
|
RFB.FBU.rects -= 1;
|
||||||
|
|
||||||
//Util.Debug("<< set_cursor");
|
//Util.Debug("<< set_cursor");
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
set_jpeg_quality : function () {
|
set_jpeg_quality : function () {
|
||||||
|
|
@ -1238,16 +1250,15 @@ handle_message: function () {
|
||||||
RFB.disconnect();
|
RFB.disconnect();
|
||||||
break;
|
break;
|
||||||
case 'normal':
|
case 'normal':
|
||||||
RFB.normal_msg();
|
while ((RFB.state === 'normal') && (RFB.RQ.length > 0)) {
|
||||||
/*
|
if (RFB.normal_msg()) {
|
||||||
while (RFB.RQ.length > 0) {
|
// true means we can continue processing
|
||||||
if (RFB.normal_msg() && RFB.state === 'normal') {
|
Util.Debug("More data to process");
|
||||||
Util.Debug("More to process");
|
|
||||||
} else {
|
} else {
|
||||||
|
// false means we need more data
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
RFB.init_msg();
|
RFB.init_msg();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue