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:
Joel Martin
2010-07-01 09:53:38 -05:00
parent 1eba7b4279
commit a93c955538
6 changed files with 48 additions and 46 deletions
+13 -22
View File
@@ -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/);
+16 -12
View File
@@ -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());
}
});