Status/error refactor. Fix firefox bugs.
- All state/status updates go through updateState routine which updates the status line also. - Old firefox (and opera) don't support canvas createImageData, so use getImageData as replacement. - Add console.warn and console.error stubs so that firefox without firebug doesn't crap out. - If no WebSockets then error if no flash or if URL is location (flash will refuse to load the object for security reasons).
This commit is contained in:
parent
07f6ca751d
commit
8759ea6f90
2
TODO
2
TODO
@ -1,7 +1,5 @@
|
|||||||
- Make packet sequence number optional based on WebSockets 'path'.
|
- Make packet sequence number optional based on WebSockets 'path'.
|
||||||
|
|
||||||
- Better status and error feedback.
|
|
||||||
|
|
||||||
- Add WSS/https/SSL support to page and wsproxy.py
|
- Add WSS/https/SSL support to page and wsproxy.py
|
||||||
|
|
||||||
- Make C version of wsproxy.py
|
- Make C version of wsproxy.py
|
||||||
|
@ -8,6 +8,11 @@
|
|||||||
</canvas>
|
</canvas>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
||||||
|
-->
|
||||||
|
|
||||||
<script src="include/mootools.js"></script>
|
<script src="include/mootools.js"></script>
|
||||||
<script src="include/util.js"></script>
|
<script src="include/util.js"></script>
|
||||||
<script src="canvas.js"></script>
|
<script src="canvas.js"></script>
|
||||||
|
@ -121,7 +121,8 @@ draw: function () {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Test array image data */
|
/* Test array image data */
|
||||||
var img = Canvas.ctx.createImageData(50, 50);
|
//var img = Canvas.ctx.createImageData(50, 50);
|
||||||
|
var img = Canvas.ctx.getImageData(0, 0, 50, 50);
|
||||||
for (y=0; y< 50; y++) {
|
for (y=0; y< 50; y++) {
|
||||||
for (x=0; x< 50; x++) {
|
for (x=0; x< 50; x++) {
|
||||||
img.data[(y*50 + x)*4 + 0] = 255 - parseInt((255 / 50) * y);
|
img.data[(y*50 + x)*4 + 0] = 255 - parseInt((255 / 50) * y);
|
||||||
@ -134,7 +135,8 @@ draw: function () {
|
|||||||
},
|
},
|
||||||
|
|
||||||
rgbxImage: function(x, y, width, height, arr) {
|
rgbxImage: function(x, y, width, height, arr) {
|
||||||
var img = Canvas.ctx.createImageData(width, height);
|
/* Old firefox and Opera don't support createImageData */
|
||||||
|
var img = Canvas.ctx.getImageData(0, 0, width, height);
|
||||||
for (var i=0; i < (width * height); i++) {
|
for (var i=0; i < (width * height); i++) {
|
||||||
img.data[i*4 + 0] = arr[i*4 + 0];
|
img.data[i*4 + 0] = arr[i*4 + 0];
|
||||||
img.data[i*4 + 1] = arr[i*4 + 1];
|
img.data[i*4 + 1] = arr[i*4 + 1];
|
||||||
|
@ -2,6 +2,8 @@ if ((!window.console) || (! /__debug__$/i.test(document.location.href))) {
|
|||||||
// non-debug mode, an empty function
|
// non-debug mode, an empty function
|
||||||
window.console = window.console || {};
|
window.console = window.console || {};
|
||||||
window.console.log = function(message) {};
|
window.console.log = function(message) {};
|
||||||
|
window.console.warn = function(message) {};
|
||||||
|
window.console.error = function(message) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function dirObj(obj, depth, parent) {
|
function dirObj(obj, depth, parent) {
|
||||||
|
34
vnc.html
34
vnc.html
@ -7,11 +7,11 @@
|
|||||||
Host: <input id='host' style='width:100'>
|
Host: <input id='host' style='width:100'>
|
||||||
Port: <input id='port' style='width:50'>
|
Port: <input id='port' style='width:50'>
|
||||||
Password: <input id='password' type='password' style='width:80'>
|
Password: <input id='password' type='password' style='width:80'>
|
||||||
<input id='connectButton' type='button' value='Connect' style='width:100px'
|
<input id='connectButton' type='button' value='Loading'
|
||||||
onclick="RFB.connect();">
|
style='width:100px' disabled>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<div id='status'>Disconnected</div>
|
<div id='status'>Loading</div>
|
||||||
<canvas id="vnc" width="640" height="20"
|
<canvas id="vnc" width="640" height="20"
|
||||||
style="border-style: dotted; border-width: 1px;">
|
style="border-style: dotted; border-width: 1px;">
|
||||||
Canvas not supported.
|
Canvas not supported.
|
||||||
@ -27,6 +27,11 @@
|
|||||||
onblur="RFB.clipboardFocus=false;"></textarea>
|
onblur="RFB.clipboardFocus=false;"></textarea>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
||||||
|
-->
|
||||||
|
|
||||||
<script src="include/mootools.js"></script>
|
<script src="include/mootools.js"></script>
|
||||||
<script src="include/base64.js"></script>
|
<script src="include/base64.js"></script>
|
||||||
<script src="include/des.js"></script>
|
<script src="include/des.js"></script>
|
||||||
@ -50,15 +55,26 @@
|
|||||||
console.log("onload");
|
console.log("onload");
|
||||||
if (native_ws) {
|
if (native_ws) {
|
||||||
console.log("Using native WebSockets");
|
console.log("Using native WebSockets");
|
||||||
|
RFB.updateState('disconnected', 'Disconnected');
|
||||||
} else {
|
} else {
|
||||||
console.log("Using web-socket-js flash bridge");
|
console.log("Using web-socket-js flash bridge");
|
||||||
WebSocket.__swfLocation = "web-socket-js/WebSocketMain.swf";
|
if ((! Browser.Plugins.Flash) ||
|
||||||
RFB.force_copy = true;
|
(Browser.Plugins.Flash.version < 9)) {
|
||||||
|
RFB.updateState('failed', "WebSockets or Adobe Flash is required");
|
||||||
|
} else if (location.href.substr(0, 7) == "file://") {
|
||||||
|
RFB.updateState('failed', "'file://' URL is incompatible with Adobe Flash");
|
||||||
|
} else {
|
||||||
|
WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf";
|
||||||
|
RFB.force_copy = true;
|
||||||
|
RFB.updateState('disconnected', 'Disconnected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (RFB.state == 'disconnected') {
|
||||||
|
var url = document.location.href;
|
||||||
|
$('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
|
||||||
|
$('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
|
||||||
|
$('password').value = (url.match(/password=([^&#]*)/) || ['',''])[1];
|
||||||
}
|
}
|
||||||
var url = document.location.href;
|
|
||||||
$('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
|
|
||||||
$('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
|
|
||||||
$('password').value = (url.match(/password=([^&#]*)/) || ['',''])[1];
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
156
vnc.js
156
vnc.js
@ -86,7 +86,7 @@ sendID : null,
|
|||||||
force_copy : false,
|
force_copy : false,
|
||||||
|
|
||||||
version : "RFB 003.003\n",
|
version : "RFB 003.003\n",
|
||||||
state : 'ProtocolVersion',
|
state : 'disconnected',
|
||||||
cuttext : 'none', // ServerCutText wait state
|
cuttext : 'none', // ServerCutText wait state
|
||||||
ct_length : 0,
|
ct_length : 0,
|
||||||
clipboardFocus: false,
|
clipboardFocus: false,
|
||||||
@ -113,28 +113,24 @@ rre_chunk : 100,
|
|||||||
|
|
||||||
/* RFB/VNC initialisation */
|
/* RFB/VNC initialisation */
|
||||||
init_msg: function () {
|
init_msg: function () {
|
||||||
console.log(">> init_msg: " + RFB.state);
|
console.log(">> init_msg");
|
||||||
|
|
||||||
switch (RFB.state) {
|
switch (RFB.state) {
|
||||||
|
|
||||||
case 'ProtocolVersion' :
|
case 'ProtocolVersion' :
|
||||||
if (RQ.length != 12) {
|
if (RQ.length != 12) {
|
||||||
console.log("Invalid protocol version from server");
|
updateStatus('failed', "Disconnected: invalid RFB protocol version received");
|
||||||
//RFB.state = 'reset';
|
|
||||||
RFB.state = 'failed';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var server_version = RQ.shiftStr(12);
|
var server_version = RQ.shiftStr(12);
|
||||||
console.log("Server ProtocolVersion: " + server_version.substr(0,11));
|
console.log("Server ProtocolVersion: " + server_version.substr(0,11));
|
||||||
console.log("Sending ProtocolVersion: " + RFB.version.substr(0,11));
|
|
||||||
RFB.send_string(RFB.version);
|
RFB.send_string(RFB.version);
|
||||||
RFB.state = 'Authentication';
|
RFB.updateState('Authentication', "Sent ProtocolVersion: " + RFB.version.substr(0,11));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Authentication' :
|
case 'Authentication' :
|
||||||
if (RQ.length < 4) {
|
if (RQ.length < 4) {
|
||||||
console.log("Invalid auth frame");
|
RFB.updateState('reset', "Invalid auth frame");
|
||||||
RFB.state = 'reset';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var scheme = RQ.shift32();
|
var scheme = RQ.shift32();
|
||||||
@ -143,65 +139,55 @@ init_msg: function () {
|
|||||||
case 0: // connection failed
|
case 0: // connection failed
|
||||||
var strlen = RQ.shift32();
|
var strlen = RQ.shift32();
|
||||||
var reason = RQ.shiftStr(strlen);
|
var reason = RQ.shiftStr(strlen);
|
||||||
console.log("auth failed: " + reason);
|
RFB.updateState('failed', "Disconnected: auth failure: " + reason);
|
||||||
RFB.state = "failed";
|
|
||||||
return;
|
return;
|
||||||
case 1: // no authentication
|
case 1: // no authentication
|
||||||
RFB.send_array([RFB.shared]); // ClientInitialisation
|
RFB.send_array([RFB.shared]); // ClientInitialisation
|
||||||
RFB.state = "ServerInitialisation";
|
RFB.updateState('ServerInitialisation');
|
||||||
break;
|
break;
|
||||||
case 2: // VNC authentication
|
case 2: // VNC authentication
|
||||||
var challenge = RQ.shiftBytes(16);
|
var challenge = RQ.shiftBytes(16);
|
||||||
console.log("Password: " + RFB.password);
|
console.log("Password: " + RFB.password);
|
||||||
console.log("Challenge: " + challenge + "(" + challenge.length + ")");
|
console.log("Challenge: " + challenge + "(" + challenge.length + ")");
|
||||||
passwd = RFB.passwdTwiddle(RFB.password);
|
passwd = RFB.passwdTwiddle(RFB.password);
|
||||||
//console.log("passwd: " + passwd + "(" + passwd.length + ")");
|
|
||||||
response = des(passwd, challenge, 1);
|
response = des(passwd, challenge, 1);
|
||||||
//console.log("reponse: " + response + "(" + response.length + ")");
|
|
||||||
|
|
||||||
RFB.send_array(response);
|
RFB.send_array(response);
|
||||||
RFB.state = "SecurityResult";
|
RFB.updateState('SecurityResult');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log("Unsupported auth scheme");
|
RFB.updateState('failed', "Disconnected: unsupported auth scheme " + scheme);
|
||||||
RFB.state = "failed";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'SecurityResult' :
|
case 'SecurityResult' :
|
||||||
if (RQ.length != 4) {
|
if (RQ.length != 4) {
|
||||||
console.log("Invalid server auth response");
|
RFB.updateState('reset', "Invalid VNC auth response");
|
||||||
RFB.state = 'reset';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var resp = RQ.shift32();
|
var resp = RQ.shift32();
|
||||||
switch (resp) {
|
switch (resp) {
|
||||||
case 0: // OK
|
case 0: // OK
|
||||||
console.log("Authentication OK");
|
RFB.updateState('ServerInitialisation', "Authentication OK");
|
||||||
break;
|
break;
|
||||||
case 1: // failed
|
case 1: // failed
|
||||||
console.log("Authentication failed");
|
RFB.updateState('reset', "Authentication failed");
|
||||||
RFB.state = "reset";
|
|
||||||
return;
|
return;
|
||||||
case 2: // too-many
|
case 2: // too-many
|
||||||
console.log("Too many authentication attempts");
|
RFB.updateState('failed', "Disconnected: too many auth attempts");
|
||||||
RFB.state = "failed";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RFB.send_array([RFB.shared]); // ClientInitialisation
|
RFB.send_array([RFB.shared]); // ClientInitialisation
|
||||||
RFB.state = "ServerInitialisation";
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ServerInitialisation' :
|
case 'ServerInitialisation' :
|
||||||
if (RQ.length < 24) {
|
if (RQ.length < 24) {
|
||||||
console.log("Invalid server initialisation");
|
RFB.updateState('reset', "Invalid server initialisation");
|
||||||
RFB.state = 'reset';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Screen size */
|
/* Screen size */
|
||||||
//console.log("RQ: " + RQ);
|
|
||||||
RFB.fb_width = RQ.shift16();
|
RFB.fb_width = RQ.shift16();
|
||||||
RFB.fb_height = RQ.shift16();
|
RFB.fb_height = RQ.shift16();
|
||||||
|
|
||||||
@ -223,9 +209,6 @@ init_msg: function () {
|
|||||||
var name_length = RQ.shift32();
|
var name_length = RQ.shift32();
|
||||||
RFB.fb_name = RQ.shiftStr(name_length);
|
RFB.fb_name = RQ.shiftStr(name_length);
|
||||||
|
|
||||||
console.log("Name: " + RFB.fb_name);
|
|
||||||
$('status').innerHTML = "Connected to: " + RFB.fb_name;
|
|
||||||
|
|
||||||
Canvas.init('vnc', RFB.fb_width, RFB.fb_height,
|
Canvas.init('vnc', RFB.fb_width, RFB.fb_height,
|
||||||
RFB.keyDown, RFB.keyUp,
|
RFB.keyDown, RFB.keyUp,
|
||||||
RFB.mouseDown, RFB.mouseUp, RFB.mouseMove);
|
RFB.mouseDown, RFB.mouseUp, RFB.mouseMove);
|
||||||
@ -239,10 +222,10 @@ init_msg: function () {
|
|||||||
/* Start pushing/polling */
|
/* Start pushing/polling */
|
||||||
RFB.checkEvents.delay(RFB.check_rate);
|
RFB.checkEvents.delay(RFB.check_rate);
|
||||||
|
|
||||||
RFB.state = 'normal';
|
RFB.updateState('normal', "Connected to: " + RFB.fb_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
console.log("<< init_msg (" + RFB.state + ")");
|
console.log("<< init_msg");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -293,8 +276,7 @@ normal_msg: function () {
|
|||||||
case 2: msg += "(RRE)"; break;
|
case 2: msg += "(RRE)"; break;
|
||||||
case 5: msg += "(HEXTILE " + FBU.tiles + " tiles)"; break;
|
case 5: msg += "(HEXTILE " + FBU.tiles + " tiles)"; break;
|
||||||
default:
|
default:
|
||||||
console.log("Unsupported encoding " + FBU.encoding);
|
RFB.updateState('failed', "Disconnected: unsupported encoding " + FBU.encoding);
|
||||||
RFB.state = "failed";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
msg += ", RQ.length: " + RQ.length
|
msg += ", RQ.length: " + RQ.length
|
||||||
@ -302,18 +284,15 @@ normal_msg: function () {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("> RQ.length: " + RQ.length + ", arr[0..30]: " + RQ.slice(0,30));
|
|
||||||
switch (FBU.encoding) {
|
switch (FBU.encoding) {
|
||||||
case 0: ret = RFB.display_raw(); break; // Raw
|
case 0: ret = RFB.display_raw(); break; // Raw
|
||||||
case 1: ret = RFB.display_copy_rect(); break; // Copy-Rect
|
case 1: ret = RFB.display_copy_rect(); break; // Copy-Rect
|
||||||
case 2: ret = RFB.display_rre(); break; // RRE
|
case 2: ret = RFB.display_rre(); break; // RRE
|
||||||
case 5: ret = RFB.display_hextile(); break; // hextile
|
case 5: ret = RFB.display_hextile(); break; // hextile
|
||||||
}
|
}
|
||||||
//console.log("< RQ.length: " + RQ.length + ", FBU.bytes: " + FBU.bytes);
|
|
||||||
if (RFB.state != "normal") return true;
|
if (RFB.state != "normal") return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("Finished frame buffer update");
|
|
||||||
break;
|
break;
|
||||||
case 1: // SetColourMapEntries
|
case 1: // SetColourMapEntries
|
||||||
console.log("SetColourMapEntries (unsupported)");
|
console.log("SetColourMapEntries (unsupported)");
|
||||||
@ -348,9 +327,8 @@ normal_msg: function () {
|
|||||||
RFB.cuttext = 'none';
|
RFB.cuttext = 'none';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Illegal server message type: " + msg_type);
|
RFB.updateState('failed', "Disconnected: illegal server message type " + msg_type);
|
||||||
console.log("RQ.slice(0,30):" + RQ.slice(0,30));
|
console.log("RQ.slice(0,30):" + RQ.slice(0,30));
|
||||||
RFB.state = "failed";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//console.log("<< normal_msg");
|
//console.log("<< normal_msg");
|
||||||
@ -374,7 +352,6 @@ display_raw: function () {
|
|||||||
}
|
}
|
||||||
var cur_y = FBU.y + (FBU.height - FBU.lines);
|
var cur_y = FBU.y + (FBU.height - FBU.lines);
|
||||||
var cur_height = Math.min(FBU.lines, Math.floor(RQ.length/(FBU.width * RFB.fb_Bpp)));
|
var cur_height = Math.min(FBU.lines, Math.floor(RQ.length/(FBU.width * RFB.fb_Bpp)));
|
||||||
//console.log("cur_y:" + cur_y + ", cur_height:" + cur_height);
|
|
||||||
Canvas.rgbxImage(FBU.x, cur_y, FBU.width, cur_height, RQ);
|
Canvas.rgbxImage(FBU.x, cur_y, FBU.width, cur_height, RQ);
|
||||||
RQ.shiftBytes(FBU.width * cur_height * RFB.fb_Bpp);
|
RQ.shiftBytes(FBU.width * cur_height * RFB.fb_Bpp);
|
||||||
FBU.lines -= cur_height;
|
FBU.lines -= cur_height;
|
||||||
@ -409,7 +386,6 @@ display_rre: function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FBU.subrects = RQ.shift32();
|
FBU.subrects = RQ.shift32();
|
||||||
//console.log(">> display_rre " + "(" + FBU.subrects + " subrects)");
|
|
||||||
var color = RQ.shiftBytes(RFB.fb_Bpp); // Background
|
var color = RQ.shiftBytes(RFB.fb_Bpp); // Background
|
||||||
Canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color);
|
Canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color);
|
||||||
}
|
}
|
||||||
@ -435,7 +411,7 @@ display_rre: function () {
|
|||||||
},
|
},
|
||||||
|
|
||||||
display_hextile: function() {
|
display_hextile: function() {
|
||||||
//console.log(">> display_hextile, tiles: " + FBU.tiles + ", arr.length: " + RQ.length + ", bytes: " + FBU.bytes);
|
//console.log(">> display_hextile");
|
||||||
var subencoding, subrects, cur_tile, tile_x, x, w, tile_y, y, h;
|
var subencoding, subrects, cur_tile, tile_x, x, w, tile_y, y, h;
|
||||||
|
|
||||||
if (FBU.tiles == 0) {
|
if (FBU.tiles == 0) {
|
||||||
@ -454,9 +430,8 @@ display_hextile: function() {
|
|||||||
}
|
}
|
||||||
subencoding = RQ[0]; // Peek
|
subencoding = RQ[0]; // Peek
|
||||||
if (subencoding > 30) { // Raw
|
if (subencoding > 30) { // Raw
|
||||||
console.error("Illegal subencoding " + subencoding);
|
RFB.updateState('failed', "Disconnected: illegal hextile subencoding " + subencoding);
|
||||||
console.log("RQ.slice(0,30):" + RQ.slice(0,30));
|
console.log("RQ.slice(0,30):" + RQ.slice(0,30));
|
||||||
RFB.state = "failed";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
subrects = 0;
|
subrects = 0;
|
||||||
@ -496,7 +471,6 @@ display_hextile: function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//console.log(" tile:" + cur_tile + "/" + (FBU.total_tiles - 1) + ", subencoding:" + subencoding + "(last: " + FBU.lastsubencoding + "), subrects:" + subrects + ", tile:" + tile_x + "," + tile_y + " [" + x + "," + y + "]@" + w + "x" + h + ", d.length:" + RQ.length + ", bytes:" + FBU.bytes + " last:" + RQ.slice(FBU.bytes-10, FBU.bytes) + " next:" + RQ.slice(FBU.bytes-1, FBU.bytes+10));
|
//console.log(" tile:" + cur_tile + "/" + (FBU.total_tiles - 1) + ", subencoding:" + subencoding + "(last: " + FBU.lastsubencoding + "), subrects:" + subrects + ", tile:" + tile_x + "," + tile_y + " [" + x + "," + y + "]@" + w + "x" + h + ", d.length:" + RQ.length + ", bytes:" + FBU.bytes + " last:" + RQ.slice(FBU.bytes-10, FBU.bytes) + " next:" + RQ.slice(FBU.bytes-1, FBU.bytes+10));
|
||||||
//console.log(" arr[0..30]: " + RQ.slice(0,30));
|
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQ.length < FBU.bytes) {
|
||||||
//console.log(" waiting for " + (FBU.bytes - RQ.length) + " hextile bytes");
|
//console.log(" waiting for " + (FBU.bytes - RQ.length) + " hextile bytes");
|
||||||
return;
|
return;
|
||||||
@ -519,12 +493,10 @@ display_hextile: function() {
|
|||||||
if (FBU.subencoding & 0x02) { // Background
|
if (FBU.subencoding & 0x02) { // Background
|
||||||
FBU.background = RQ.slice(idx, idx + RFB.fb_Bpp);
|
FBU.background = RQ.slice(idx, idx + RFB.fb_Bpp);
|
||||||
idx += RFB.fb_Bpp;
|
idx += RFB.fb_Bpp;
|
||||||
//console.log(" background: " + FBU.background);
|
|
||||||
}
|
}
|
||||||
if (FBU.subencoding & 0x04) { // Foreground
|
if (FBU.subencoding & 0x04) { // Foreground
|
||||||
FBU.foreground = RQ.slice(idx, idx + RFB.fb_Bpp);
|
FBU.foreground = RQ.slice(idx, idx + RFB.fb_Bpp);
|
||||||
idx += RFB.fb_Bpp;
|
idx += RFB.fb_Bpp;
|
||||||
//console.log(" foreground: " + FBU.foreground);
|
|
||||||
}
|
}
|
||||||
Canvas.fillRect(x, y, w, h, FBU.background);
|
Canvas.fillRect(x, y, w, h, FBU.background);
|
||||||
if (FBU.subencoding & 0x08) { // AnySubrects
|
if (FBU.subencoding & 0x08) { // AnySubrects
|
||||||
@ -562,7 +534,7 @@ display_hextile: function() {
|
|||||||
FBU.rects --;
|
FBU.rects --;
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("<< display_hextile, rects:" + FBU.rects, " d:" + RQ.slice(0,40));
|
//console.log("<< display_hextile");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -642,7 +614,6 @@ keyEvent: function (keysym, down) {
|
|||||||
arr.push8(down);
|
arr.push8(down);
|
||||||
arr.push16(0);
|
arr.push16(0);
|
||||||
arr.push32(keysym);
|
arr.push32(keysym);
|
||||||
//console.log("keyEvent array: " + arr);
|
|
||||||
//console.log("<< keyEvent");
|
//console.log("<< keyEvent");
|
||||||
return arr;
|
return arr;
|
||||||
},
|
},
|
||||||
@ -813,6 +784,42 @@ clipboardClear: function () {
|
|||||||
RFB.clipboardPasteFrom();
|
RFB.clipboardPasteFrom();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateState: function(state, statusMsg) {
|
||||||
|
var s = $('status');
|
||||||
|
var c = $('connectButton');
|
||||||
|
var func = function(msg) { console.log(msg) };
|
||||||
|
switch (state) {
|
||||||
|
case 'failed':
|
||||||
|
func = function(msg) { console.error(msg) };
|
||||||
|
c.disabled = true;
|
||||||
|
s.style.fontColor = "#880000";
|
||||||
|
break;
|
||||||
|
case 'normal':
|
||||||
|
c.value = "Disconnect";
|
||||||
|
c.onclick = RFB.disconnect;
|
||||||
|
c.disabled = false;
|
||||||
|
s.style.fontColor = "#000000";
|
||||||
|
break;
|
||||||
|
case 'disconnected':
|
||||||
|
c.value = "Connect";
|
||||||
|
c.onclick = RFB.connect;
|
||||||
|
c.disabled = false;
|
||||||
|
s.style.fontColor = "#000000";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
func = function(msg) { console.warn(msg) };
|
||||||
|
c.disabled = true;
|
||||||
|
s.style.fontColor = "#444400";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RFB.state = state;
|
||||||
|
var cmsg = typeof(statusMsg) != 'undefined' ? (" Msg: " + statusMsg) : "";
|
||||||
|
func("New state '" + state + "'." + cmsg);
|
||||||
|
if (typeof(statusMsg) != 'undefined') {
|
||||||
|
s.innerHTML = statusMsg;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup routines
|
* Setup routines
|
||||||
@ -825,20 +832,17 @@ init_ws: function () {
|
|||||||
console.log("connecting to " + uri);
|
console.log("connecting to " + uri);
|
||||||
RFB.ws = new WebSocket(uri);
|
RFB.ws = new WebSocket(uri);
|
||||||
RFB.ws.onmessage = function(e) {
|
RFB.ws.onmessage = function(e) {
|
||||||
//console.log(">> WebSockets.onmessage");
|
//console.log(">> WebSocket.onmessage");
|
||||||
|
|
||||||
//console.log(e.data);
|
|
||||||
var offset = e.data.indexOf(":") + 1;
|
var offset = e.data.indexOf(":") + 1;
|
||||||
var seq_num = parseInt(e.data.substr(0, offset-1));
|
var seq_num = parseInt(e.data.substr(0, offset-1));
|
||||||
//console.log("RQ_seq_num:" + RQ_seq_num + ", seq_num:" + seq_num);
|
|
||||||
if (RQ_seq_num == seq_num) {
|
if (RQ_seq_num == seq_num) {
|
||||||
RQ = RQ.concat(Base64.decode(e.data, offset));
|
RQ = RQ.concat(Base64.decode(e.data, offset));
|
||||||
RQ_seq_num++;
|
RQ_seq_num++;
|
||||||
} else {
|
} else {
|
||||||
console.warn("sequence number mismatch RQ_seq_num:" + RQ_seq_num + ", seq_num:" + seq_num);
|
console.warn("sequence number mismatch RQ_seq_num:" + RQ_seq_num + ", seq_num:" + seq_num);
|
||||||
if (RQ_reorder.length > 20) {
|
if (RQ_reorder.length > 20) {
|
||||||
console.log("Re-order queue too long");
|
RFB.updateState('failed', "Re-order queue too long");
|
||||||
RFB.state = 'failed';
|
|
||||||
} else {
|
} else {
|
||||||
RQ_reorder = RQ_reorder.concat(e.data.substr(0));
|
RQ_reorder = RQ_reorder.concat(e.data.substr(0));
|
||||||
var i = 0;
|
var i = 0;
|
||||||
@ -862,8 +866,8 @@ init_ws: function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (RFB.state) {
|
switch (RFB.state) {
|
||||||
case 'closed':
|
case 'disconnected':
|
||||||
console.log("onmessage while closed");
|
console.error("WebSocket.onmessage while disconnected");
|
||||||
break;
|
break;
|
||||||
case 'reset':
|
case 'reset':
|
||||||
/* close and reset connection */
|
/* close and reset connection */
|
||||||
@ -890,11 +894,11 @@ init_ws: function () {
|
|||||||
RFB.init_msg();
|
RFB.init_msg();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//console.log("<< WebSockets.onmessage");
|
//console.log("<< WebSocket.onmessage");
|
||||||
};
|
};
|
||||||
RFB.ws.onopen = function(e) {
|
RFB.ws.onopen = function(e) {
|
||||||
console.log(">> WebSockets.onopen");
|
console.log(">> WebSocket.onopen");
|
||||||
RFB.state = "ProtocolVersion";
|
RFB.updateState('ProtocolVersion', "Starting VNC handshake");
|
||||||
RFB.sendID = setInterval(function() {
|
RFB.sendID = setInterval(function() {
|
||||||
/*
|
/*
|
||||||
* Send updates either at a rate of one update every 50ms,
|
* Send updates either at a rate of one update every 50ms,
|
||||||
@ -909,18 +913,20 @@ init_ws: function () {
|
|||||||
console.log("Delaying send");
|
console.log("Delaying send");
|
||||||
}
|
}
|
||||||
}, 50);
|
}, 50);
|
||||||
console.log("<< WebSockets.onopen");
|
console.log("<< WebSocket.onopen");
|
||||||
};
|
};
|
||||||
RFB.ws.onclose = function(e) {
|
RFB.ws.onclose = function(e) {
|
||||||
console.log(">> WebSockets.onclose");
|
console.log(">> WebSocket.onclose");
|
||||||
clearInterval(RFB.sendID);
|
clearInterval(RFB.sendID);
|
||||||
RFB.state = "closed";
|
if (RFB.state != 'disconnected') {
|
||||||
console.log("<< WebSockets.onclose");
|
RFB.updateState('disconnected', 'VNC disconnected');
|
||||||
|
}
|
||||||
|
console.log("<< WebSocket.onclose");
|
||||||
};
|
};
|
||||||
RFB.ws.onerror = function(e) {
|
RFB.ws.onerror = function(e) {
|
||||||
console.log(">> WebSockets.onerror");
|
console.error(">> WebSocket.onerror");
|
||||||
console.log(" " + e);
|
console.error(" " + e);
|
||||||
console.log("<< WebSockets.onerror");
|
console.error("<< WebSocket.onerror");
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("<< init_ws");
|
console.log("<< init_ws");
|
||||||
@ -954,21 +960,20 @@ connect: function () {
|
|||||||
|
|
||||||
RFB.init_vars();
|
RFB.init_vars();
|
||||||
|
|
||||||
if (RFB.ws) {
|
if ((RFB.ws) && (RFB.ws.readyState == WebSocket.OPEN)) {
|
||||||
RFB.ws.close();
|
RFB.ws.close();
|
||||||
}
|
}
|
||||||
RFB.init_ws();
|
RFB.init_ws();
|
||||||
|
|
||||||
$('connectButton').value = "Disconnect";
|
RFB.updateState('ProtocolVersion');
|
||||||
$('connectButton').onclick = RFB.disconnect;
|
|
||||||
console.log("<< connect");
|
console.log("<< connect");
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
disconnect: function () {
|
disconnect: function () {
|
||||||
console.log(">> disconnect");
|
console.log(">> disconnect");
|
||||||
if (RFB.ws) {
|
if ((RFB.ws) && (RFB.ws.readyState == WebSocket.OPEN)) {
|
||||||
RFB.state = "closed";
|
RFB.updateState('closed');
|
||||||
RFB.ws.close();
|
RFB.ws.close();
|
||||||
}
|
}
|
||||||
if (Canvas.ctx) {
|
if (Canvas.ctx) {
|
||||||
@ -977,9 +982,8 @@ disconnect: function () {
|
|||||||
Canvas.clear();
|
Canvas.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$('connectButton').value = "Connect";
|
|
||||||
$('connectButton').onclick = RFB.connect;
|
RFB.updateState('disconnected', 'Disconnected');
|
||||||
$('status').innerHTML = "Disconnected";
|
|
||||||
console.log("<< disconnect");
|
console.log("<< disconnect");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user