diff --git a/include/rfb.js b/include/rfb.js index d1e7f153..8ddd27c9 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -99,9 +99,6 @@ var that = {}, // Public API interface fb_height = 0, fb_name = "", - cuttext = 'none', // ServerCutText wait state - cuttext_length = 0, - scan_imgQ_rate = 100, last_req_time = 0, rre_chunk_sz = 100, @@ -204,6 +201,27 @@ function rQshiftBytes(len) { return rQ.slice(rQi-len, rQi); } +// Check to see if we must wait for 'num' bytes (default to FBU.bytes) +// to be available in the receive queue. Return true if we need to +// wait (and possibly print a debug message), otherwise false. +function rQwait(msg, num, goback) { + if (typeof num !== 'number') { num = FBU.bytes; } + var rQlen = rQ.length - rQi; // Skip rQlen() function call + if (rQlen < num) { + if (goback) { + if (rQi < goback) { + throw("rQwait cannot backup " + goback + " bytes"); + } + rQi -= goback; + } + //Util.Debug(" waiting for " + (num-rQlen) + + // " " + msg + " byte(s)"); + return true; // true means need more data + } + return false; +} + + // // Setup routines // @@ -299,8 +317,6 @@ function init_ws() { init_vars = function() { /* Reset state */ - cuttext = 'none'; - cuttext_length = 0; rQ = []; rQi = 0; sQ = ""; @@ -670,7 +686,7 @@ function mouseMove(x, y) { init_msg = function() { //Util.Debug(">> init_msg [rfb_state '" + rfb_state + "']"); - var strlen, reason, reason_len, sversion, cversion, + var strlen, reason, length, sversion, cversion, i, types, num_types, challenge, response, bpp, depth, big_endian, true_color, name_length; @@ -724,11 +740,7 @@ init_msg = function() { case 'Security' : if (rfb_version >= 3.7) { num_types = rQ[rQi++]; - if (rQlen() < num_types) { - rQi--; - Util.Debug(" waiting for security types"); - return; - } + if (rQwait("security type", num_types, 1)) { return false; } if (num_types === 0) { strlen = rQshift32(); reason = rQshiftStr(strlen); @@ -752,10 +764,7 @@ init_msg = function() { send_array([rfb_auth_scheme]); } else { - if (rQlen() < 4) { - Util.Debug(" waiting for security scheme bytes"); - return; - } + if (rQwait("security scheme", 4)) { return false; } rfb_auth_scheme = rQshift32(); } updateState('Authentication', @@ -767,10 +776,7 @@ init_msg = function() { //Util.Debug("Security auth scheme: " + rfb_auth_scheme); switch (rfb_auth_scheme) { case 0: // connection failed - if (rQlen() < 4) { - Util.Debug(" waiting for auth reason bytes"); - return; - } + if (rQwait("auth reason", 4)) { return false; } strlen = rQshift32(); reason = rQshiftStr(strlen); updateState('failed', @@ -784,10 +790,7 @@ init_msg = function() { updateState('password', "Password Required"); return; } - if (rQlen() < 16) { - Util.Debug(" waiting for auth challenge bytes"); - return; - } + if (rQwait("auth challenge", 16)) { return false; } challenge = rQshiftBytes(16); //Util.Debug("Password: " + rfb_password); //Util.Debug("Challenge: " + challenge + @@ -819,11 +822,9 @@ init_msg = function() { break; case 1: // failed if (rfb_version >= 3.8) { - reason_len = rQshift32(); - if (rQlen() < reason_len) { - Util.Debug(" waiting for SecurityResult reason bytes"); - rQi -= 8; // Unshift the status and length - return; + length = rQshift32(); + if (rQwait("SecurityResult reason", length, 8)) { + return false; } reason = rQshiftStr(reason_len); updateState('failed', reason); @@ -901,13 +902,11 @@ init_msg = function() { normal_msg = function() { //Util.Debug(">> normal_msg"); - var ret = true, msg_type, + var ret = true, msg_type, length, c, first_colour, num_colours, red, green, blue; if (FBU.rects > 0) { msg_type = 0; - } else if (cuttext !== 'none') { - msg_type = 3; } else { msg_type = rQ[rQi++]; } @@ -937,25 +936,12 @@ normal_msg = function() { break; case 3: // ServerCutText Util.Debug("ServerCutText"); - Util.Debug("rQ:" + rQ.slice(0,20)); - if (cuttext === 'none') { - cuttext = 'header'; - } - if (cuttext === 'header') { - if (rQlen() < 7) { - //Util.Debug("waiting for ServerCutText header"); - return false; - } - rQshiftBytes(3); // Padding - cuttext_length = rQshift32(); - } - cuttext = 'bytes'; - if (rQlen() < cuttext_length) { - //Util.Debug("waiting for ServerCutText bytes"); - return false; - } - conf.clipboardReceive(that, rQshiftStr(cuttext_length)); - cuttext = 'none'; + if (rQwait("ServerCutText header", 7, 1)) { return false; } + rQshiftBytes(3); // Padding + length = rQshift32(); + if (rQwait("ServerCutText", length, 8)) { return false; } + + conf.clipboardReceive(that, rQshiftStr(length)); break; default: updateState('failed', @@ -972,13 +958,12 @@ framebufferUpdate = function() { if (FBU.rects === 0) { //Util.Debug("New FBU: rQ.slice(0,20): " + rQ.slice(0,20)); - if (rQlen() < 3) { + if (rQwait("FBU header", 3)) { if (rQi === 0) { rQ.unshift(0); // FBU msg_type } else { rQi -= 1; } - //Util.Debug(" waiting for FBU header bytes"); return false; } rQi++; @@ -996,15 +981,9 @@ framebufferUpdate = function() { if (rfb_state !== "normal") { return false; } - if (rQlen() < FBU.bytes) { - //Util.Debug(" waiting for " + (FBU.bytes - rQlen()) + " FBU bytes"); - return false; - } + if (rQwait("FBU")) { return false; } if (FBU.bytes === 0) { - if (rQlen() < 12) { - //Util.Debug(" waiting for rect header bytes"); - return false; - } + if (rQwait("rect header", 12)) { return false; } /* New FramebufferUpdate */ hdr = rQshiftBytes(12); @@ -1092,11 +1071,7 @@ encHandlers.RAW = function display_raw() { FBU.lines = FBU.height; } FBU.bytes = FBU.width * fb_Bpp; // At least a line - if (rQlen() < FBU.bytes) { - //Util.Debug(" waiting for " + - // (FBU.bytes - rQlen()) + " RAW bytes"); - return false; - } + if (rQwait("RAW")) { return false; } cur_y = FBU.y + (FBU.height - FBU.lines); cur_height = Math.min(FBU.lines, Math.floor(rQlen()/(FBU.width * fb_Bpp))); @@ -1119,11 +1094,7 @@ encHandlers.COPYRECT = function display_copy_rect() { var old_x, old_y; - if (rQlen() < 4) { - //Util.Debug(" waiting for " + - // (FBU.bytes - rQlen()) + " COPYRECT bytes"); - return false; - } + if (rQwait("COPYRECT", 4)) { return false; } old_x = rQshift16(); old_y = rQshift16(); canvas.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height); @@ -1137,11 +1108,7 @@ encHandlers.RRE = function display_rre() { var color, x, y, width, height, chunk; if (FBU.subrects === 0) { - if (rQlen() < 4 + fb_Bpp) { - //Util.Debug(" waiting for " + - // (4 + fb_Bpp - rQlen()) + " RRE bytes"); - return false; - } + if (rQwait("RRE", 4+fb_Bpp)) { return false; } FBU.subrects = rQshift32(); color = rQshiftBytes(fb_Bpp); // Background canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color); @@ -1184,10 +1151,7 @@ encHandlers.HEXTILE = function display_hextile() { /* FBU.bytes comes in as 1, rQlen() at least 1 */ while (FBU.tiles > 0) { FBU.bytes = 1; - if (rQlen() < FBU.bytes) { - //Util.Debug(" waiting for HEXTILE subencoding byte"); - return false; - } + if (rQwait("HEXTILE subencoding")) { return false; } //Util.Debug(" 2 rQ length: " + rQlen() + " rQ[rQi]: " + rQ[rQi] + " rQ.slice(rQi,rQi+20): " + rQ.slice(rQi,rQi+20) + ", FBU.rects: " + FBU.rects + ", FBU.tiles: " + FBU.tiles); subencoding = rQ[rQi]; // Peek if (subencoding > 30) { // Raw @@ -1218,11 +1182,7 @@ encHandlers.HEXTILE = function display_hextile() { } if (subencoding & 0x08) { // AnySubrects FBU.bytes += 1; // Since we aren't shifting it off - if (rQlen() < FBU.bytes) { - /* Wait for subrects byte */ - //Util.Debug(" waiting for hextile subrects header byte"); - return false; - } + if (rQwait("hextile subrects header")) { return false; } subrects = rQ[rQi + FBU.bytes-1]; // Peek if (subencoding & 0x10) { // SubrectsColoured FBU.bytes += subrects * (fb_Bpp + 2); @@ -1243,11 +1203,7 @@ encHandlers.HEXTILE = function display_hextile() { " last:" + rQ.slice(FBU.bytes-10, FBU.bytes) + " next:" + rQ.slice(FBU.bytes-1, FBU.bytes+10)); */ - if (rQlen() < FBU.bytes) { - //Util.Debug(" waiting for " + - // (FBU.bytes - rQlen()) + " hextile bytes"); - return false; - } + if (rQwait("hextile")) { return false; } /* We know the encoding and have a whole tile */ FBU.subencoding = rQ[rQi]; @@ -1320,10 +1276,7 @@ encHandlers.TIGHT_PNG = function display_tight_png() { //Util.Debug(" starting rQ.slice(rQi,rQi+20): " + rQ.slice(rQi,rQi+20) + " (" + rQlen() + ")"); FBU.bytes = 1; // compression-control byte - if (rQlen() < FBU.bytes) { - Util.Debug(" waiting for TIGHT compression-control byte"); - return false; - } + if (rQwait("TIGHT compression-control")) { return false; } // Get 'compact length' header and data size getCLength = function (arr, offset) { @@ -1354,10 +1307,7 @@ encHandlers.TIGHT_PNG = function display_tight_png() { case "png": FBU.bytes += 3; break; // max clength } - if (rQlen() < FBU.bytes) { - Util.Debug(" waiting for TIGHT " + cmode + " bytes"); - return false; - } + if (rQwait("TIGHT " + cmode)) { return false; } //Util.Debug(" rQ.slice(0,20): " + rQ.slice(0,20) + " (" + rQlen() + ")"); //Util.Debug(" cmode: " + cmode); @@ -1373,10 +1323,7 @@ encHandlers.TIGHT_PNG = function display_tight_png() { case "png": clength = getCLength(rQ, rQi+1); FBU.bytes = 1 + clength[0] + clength[1]; // ctl + clength size + jpeg-data - if (rQlen() < FBU.bytes) { - Util.Debug(" waiting for TIGHT " + cmode + " bytes"); - return false; - } + if (rQwait("TIGHT " + cmode)) { return false; } // We have everything, render it //Util.Debug(" png, rQlen(): " + rQlen() + ", clength[0]: " + clength[0] + ", clength[1]: " + clength[1]); @@ -1446,11 +1393,8 @@ encHandlers.Cursor = function set_cursor() { pixelslength = w * h * fb_Bpp; masklength = Math.floor((w + 7) / 8) * h; - if (rQlen() < (pixelslength + masklength)) { - //Util.Debug("waiting for cursor encoding bytes"); - FBU.bytes = pixelslength + masklength; - return false; - } + FBU.bytes = pixelslength + masklength; + if (rQwait("cursor encoding")) { return false; } //Util.Debug(" set_cursor, x: " + x + ", y: " + y + ", w: " + w + ", h: " + h);