Opera works! Fix message event drops/reorders.
Instead of relying on FABridge AS -> JS event delivery, we just use the events to notify JS of pending data. The message handler then calls the AS readSocketData routine which sends back an array of the pending WebSocket frames. There is still a minor bug somewhere that happens after the first connect where the web-socket-js throws an "INVALID_STATE_ERR: Web Socket connection has not been established". But, Opera is now usable and we should be able to drop the packet sequence numbering and re-ordering code. Another minor issue to better support Opera is to move JS script includes to the <head> of the page instead of after the body.
This commit is contained in:
parent
1eba7b4279
commit
a93c955538
10
README.md
10
README.md
|
@ -90,9 +90,9 @@ I only currently test under Linux. Here are the current results:
|
|||
full-color images are slow.
|
||||
* Arora 0.50: Works. Broken putImageData so large full-color images
|
||||
are slow.
|
||||
* Opera 10.60: Works. Uses flash WebSockets emulator. Large full-color
|
||||
images are slow.
|
||||
|
||||
* Opera 10.10: Unusable: drops web-socket-js events.
|
||||
* Opera 10.60: Broken: throws "WRONG_ARGUMENTS_ERR" on connect.
|
||||
* Konqueror 4.2.2: Broken: flash WebSockets emulator never connects.
|
||||
|
||||
|
||||
|
@ -105,11 +105,13 @@ structure and style.
|
|||
At a minimum you must include the `vnc.js` and `default_controls.js`
|
||||
scripts and call their load() functions. For example:
|
||||
|
||||
<head>
|
||||
<script src='include/vnc.js'></script>
|
||||
<script src="include/default_controls.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id='vnc'>Loading</div>
|
||||
</body>
|
||||
<script src='include/vnc.js'></script>
|
||||
<script src="include/default_controls.js"></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
DefaultControls.load('vnc');
|
||||
|
|
|
@ -2,7 +2,8 @@ Short Term:
|
|||
|
||||
- Test on IE 9 preview 3.
|
||||
|
||||
- Support Opera 10.60 (WebSocket frames dropped).
|
||||
- Track down "INVALID_STATE_ERR" when reconnecting using
|
||||
web-socket-js.
|
||||
|
||||
- Possibly support IE <= 8.0 using excanvas or fxcanvas:
|
||||
http://excanvas.sourceforge.net/
|
||||
|
|
|
@ -48,6 +48,7 @@ public class WebSocket extends EventDispatcher {
|
|||
private var origin:String;
|
||||
private var protocol:String;
|
||||
private var buffer:ByteArray = new ByteArray();
|
||||
private var dataQueue:Array;
|
||||
private var headerState:int = 0;
|
||||
private var readyState:int = CONNECTING;
|
||||
private var bufferedAmount:int = 0;
|
||||
|
@ -61,6 +62,7 @@ public class WebSocket extends EventDispatcher {
|
|||
headers:String = null) {
|
||||
this.main = main;
|
||||
initNoiseChars();
|
||||
dataQueue = [];
|
||||
this.url = url;
|
||||
var m:Array = url.match(/^(\w+):\/\/([^\/:]+)(:(\d+))?(\/.*)?$/);
|
||||
if (!m) main.fatal("SYNTAX_ERR: invalid url: " + url);
|
||||
|
@ -270,30 +272,10 @@ public class WebSocket extends EventDispatcher {
|
|||
onError("data must start with \\x00");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
var data:String = "", byte:uint;
|
||||
while (buffer.bytesAvailable > 1) {
|
||||
byte = buffer[buffer.position];
|
||||
if (byte === 0x00) {
|
||||
// readUTFBytes mishandles 0x00
|
||||
data = data + "\x00";
|
||||
buffer.position++;
|
||||
} else if (byte === 0xff) {
|
||||
// End of WebSocket frame
|
||||
//ExternalInterface.call("console.log", "[WebSocket] early 0xff found");
|
||||
break;
|
||||
} else if ((byte & 0x80) === 0x00) {
|
||||
// One UTF-8 input byte to one output byte
|
||||
data = data + buffer.readUTFBytes(1);
|
||||
} else {
|
||||
// Assume two UTF-8 input bytes to one output byte
|
||||
data = data + buffer.readUTFBytes(2);
|
||||
}
|
||||
}
|
||||
*/
|
||||
var data:String = buffer.readUTFBytes(pos - 1);
|
||||
main.log("received: " + data);
|
||||
dispatchEvent(new WebSocketMessageEvent("message", encodeURIComponent(data)));
|
||||
dataQueue.push(encodeURIComponent(data));
|
||||
dispatchEvent(new WebSocketMessageEvent("message", data.length.toString()));
|
||||
buffer.readByte();
|
||||
makeBufferCompact();
|
||||
pos = -1;
|
||||
|
@ -301,6 +283,15 @@ public class WebSocket extends EventDispatcher {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function readSocketData():Array {
|
||||
var q:Array = dataQueue;
|
||||
if (dataQueue.length > 0) {
|
||||
// Reset to empty
|
||||
dataQueue = [];
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
private function validateHeader(headerStr:String):Boolean {
|
||||
var lines:Array = headerStr.split(/\r\n/);
|
||||
|
|
|
@ -52,20 +52,24 @@
|
|||
});
|
||||
|
||||
self.__flash.addEventListener("message", function(fe) {
|
||||
var data = decodeURIComponent(fe.getData());
|
||||
try {
|
||||
if (self.onmessage) {
|
||||
var e;
|
||||
if (window.MessageEvent) {
|
||||
e = document.createEvent("MessageEvent");
|
||||
e.initMessageEvent("message", false, false, data, null, null, window, null);
|
||||
} else { // IE
|
||||
e = {data: data};
|
||||
var i, arr, data;
|
||||
arr = self.__flash.readSocketData();
|
||||
for (i=0; i < arr.length; i++) {
|
||||
data = decodeURIComponent(arr[i]);
|
||||
try {
|
||||
if (self.onmessage) {
|
||||
var e;
|
||||
if (window.MessageEvent) {
|
||||
e = document.createEvent("MessageEvent");
|
||||
e.initMessageEvent("message", false, false, data, null, null, window, null);
|
||||
} else { // IE
|
||||
e = {data: data};
|
||||
}
|
||||
self.onmessage(e);
|
||||
}
|
||||
self.onmessage(e);
|
||||
} catch (e) {
|
||||
console.error(e.toString());
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e.toString());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
12
vnc.html
12
vnc.html
|
@ -5,18 +5,18 @@ noVNC example: simple example using default controls
|
|||
<head>
|
||||
<title>VNC Client</title>
|
||||
<link rel="stylesheet" href="include/plain.css">
|
||||
<!--
|
||||
<script type='text/javascript'
|
||||
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
||||
-->
|
||||
<script src="include/vnc.js"></script>
|
||||
<script src="include/default_controls.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id='vnc'>Loading</div>
|
||||
</body>
|
||||
|
||||
<!--
|
||||
<script type='text/javascript'
|
||||
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
||||
-->
|
||||
<script src="include/vnc.js"></script>
|
||||
<script src="include/default_controls.js"></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
DefaultControls.load('vnc');
|
||||
|
|
|
@ -8,6 +8,11 @@ Connect parameters are provided in query string:
|
|||
<head>
|
||||
<title>VNC Client</title>
|
||||
<link rel="stylesheet" href="include/plain.css">
|
||||
<!--
|
||||
<script type='text/javascript'
|
||||
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
||||
-->
|
||||
<script src="include/vnc.js"></script>
|
||||
</head>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
|
@ -27,7 +32,6 @@ Connect parameters are provided in query string:
|
|||
</div>
|
||||
</body>
|
||||
|
||||
<script src="include/vnc.js"></script>
|
||||
<script>
|
||||
function setPassword() {
|
||||
RFB.sendPassword($('password_input').value);
|
||||
|
|
Loading…
Reference in New Issue