Permalink
Browse files

Merge branch 'master' of http://github.com/gimite/web-socket-js

Conflicts:
	WebSocketMain.swf
	WebSocketMainInsecure.zip
  • Loading branch information...
2 parents 7772f79 + 20f8374 commit e9b99e680a03f7155ce3e66d20f6935000ff1d0f @Vagabond committed Jan 11, 2011
View
Binary file not shown.
View
Binary file not shown.
View
@@ -24,11 +24,7 @@ import com.hurlant.crypto.tls.TLSEngine;
import com.hurlant.crypto.tls.TLSSecurityParameters;
import com.gsolo.encryption.MD5;
-[Event(name="message", type="flash.events.Event")]
-[Event(name="open", type="flash.events.Event")]
-[Event(name="close", type="flash.events.Event")]
-[Event(name="error", type="flash.events.Event")]
-[Event(name="stateChange", type="WebSocketStateEvent")]
+[Event(name="event", type="flash.events.Event")]
public class WebSocket extends EventDispatcher {
private static var CONNECTING:int = 0;
@@ -49,10 +45,9 @@ 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 eventQueue:Array = [];
private var headerState:int = 0;
private var readyState:int = CONNECTING;
- private var bufferedAmount:int = 0;
private var headers:String;
private var noiseChars:Array;
private var expectedDigest:String;
@@ -120,23 +115,19 @@ public class WebSocket extends EventDispatcher {
socket.flush();
main.log("sent: " + data);
return -1;
- } else if (readyState == CLOSED) {
+ } else if (readyState == CLOSING || readyState == CLOSED) {
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(data);
- bufferedAmount += bytes.length; // not sure whether it should include \x00 and \xff
- // We use return value to let caller know bufferedAmount because we cannot fire
- // stateChange event here which causes weird error:
- // > You are trying to call recursively into the Flash Player which is not allowed.
- return bufferedAmount;
+ return bytes.length; // not sure whether it should include \x00 and \xff
} else {
- main.fatal("INVALID_STATE_ERR: invalid state");
+ main.fatal("invalid state");
return 0;
}
}
public function close():void {
main.log("close");
- dataQueue = [];
+ eventQueue = [];
try {
if (readyState == OPEN) {
socket.writeByte(0xff);
@@ -151,14 +142,6 @@ public class WebSocket extends EventDispatcher {
// We do something equivalent in JavaScript WebSocket#close instead.
}
- public function getReadyState():int {
- return readyState;
- }
-
- public function getBufferedAmount():int {
- return bufferedAmount;
- }
-
private function onSocketConnect(event:Event):void {
main.log("connected");
socketTimeout.stop();
@@ -168,7 +151,6 @@ public class WebSocket extends EventDispatcher {
tlsSocket.startTLS(rawSocket, host, tlsConfig);
}
- dataQueue = [];
var hostValue:String = host + (port == 80 ? "" : ":" + port);
var cookie:String = "";
if (main.getCallerHost() == host) {
@@ -205,8 +187,7 @@ public class WebSocket extends EventDispatcher {
private function onSocketClose(event:Event):void {
main.log("closed");
readyState = CLOSED;
- notifyStateChange();
- dispatchEvent(new Event("close"));
+ fireEvent({type: "close"}, true);
}
private function onSocketIoError(event:IOErrorEvent):void {
@@ -236,8 +217,7 @@ public class WebSocket extends EventDispatcher {
if (state == CLOSED) return;
main.error(message);
close();
- notifyStateChange();
- dispatchEvent(new Event(state == CONNECTING ? "close" : "error"));
+ fireEvent({type: state == CONNECTING ? "close" : "error"}, true);
}
private function onSocketData(event:ProgressEvent):void {
@@ -254,17 +234,15 @@ public class WebSocket extends EventDispatcher {
headerState = 0;
}
if (headerState == 4) {
- buffer.position = 0;
- var headerStr:String = buffer.readUTFBytes(pos + 1);
+ var headerStr:String = readUTFBytes(buffer, 0, pos + 1);
main.log("response header:\n" + headerStr);
if (!validateHeader(headerStr)) return;
removeBufferBefore(pos + 1);
pos = -1;
}
} else if (headerState == 4) {
if (pos == 15) {
- buffer.position = 0;
- var replyDigest:String = readBytes(buffer, 16);
+ var replyDigest:String = readBytes(buffer, 0, 16);
main.log("reply digest: " + replyDigest);
if (replyDigest != expectedDigest) {
onError("digest doesn't match: " + replyDigest + " != " + expectedDigest);
@@ -274,39 +252,33 @@ public class WebSocket extends EventDispatcher {
removeBufferBefore(pos + 1);
pos = -1;
readyState = OPEN;
- notifyStateChange();
- dispatchEvent(new Event("open"));
+ fireEvent({type: "open"}, true);
}
} else {
if (buffer[pos] == 0xff && pos > 0) {
if (buffer[0] != 0x00) {
onError("data must start with \\x00");
return;
}
- buffer.position = 1;
- var data:String = buffer.readUTFBytes(pos - 1);
+ var data:String = readUTFBytes(buffer, 1, pos - 1);
main.log("received: " + data);
- dataQueue.push(encodeURIComponent(data));
- dispatchEvent(new Event("message"));
+ fireEvent({type: "message", data: encodeURIComponent(data)}, false);
removeBufferBefore(pos + 1);
pos = -1;
} else if (pos == 1 && buffer[0] == 0xff && buffer[1] == 0x00) { // closing
main.log("received closing packet");
removeBufferBefore(pos + 1);
pos = -1;
close();
- notifyStateChange();
- dispatchEvent(new Event("close"));
+ fireEvent({type: "close"}, true);
}
}
}
}
- public function readSocketData():Array {
- var q:Array = dataQueue;
- if (dataQueue.length > 0) {
- dataQueue = [];
- }
+ public function receiveEvents():Array {
+ var q:Array = eventQueue;
+ eventQueue = [];
return q;
}
@@ -369,8 +341,12 @@ public class WebSocket extends EventDispatcher {
buffer = nextBuffer;
}
- private function notifyStateChange():void {
- dispatchEvent(new WebSocketStateEvent("stateChange", readyState, bufferedAmount));
+ private function fireEvent(event:Object, stateChanged:Boolean):void {
+ if (stateChanged) {
+ event.readyState = readyState;
+ }
+ eventQueue.push(event);
+ dispatchEvent(new Event("event"));
}
private function initNoiseChars():void {
@@ -440,7 +416,8 @@ public class WebSocket extends EventDispatcher {
// Reads specified number of bytes from buffer, and returns it as special format String
// where bytes[i] is i-th byte (not i-th character).
- private function readBytes(buffer:ByteArray, numBytes:int):String {
+ private function readBytes(buffer:ByteArray, start:int, numBytes:int):String {
+ buffer.position = start;
var bytes:String = "";
for (var i:int = 0; i < numBytes; ++i) {
// & 0xff is to make \x80-\xff positive number.
@@ -449,6 +426,20 @@ public class WebSocket extends EventDispatcher {
return bytes;
}
+ private function readUTFBytes(buffer:ByteArray, start:int, numBytes:int):String {
+ buffer.position = start;
+ var data:String = "";
+ for(var i:int = start; i < start + numBytes; ++i) {
+ // Workaround of a bug of ByteArray#readUTFBytes() that bytes after "\x00" is discarded.
+ if (buffer[i] == 0x00) {
+ data += buffer.readUTFBytes(i - buffer.position) + "\x00";
+ buffer.position = i + 1;
+ }
+ }
+ data += buffer.readUTFBytes(start + numBytes - buffer.position);
+ return data;
+ }
+
private function randomInt(min:uint, max:uint):uint {
return min + Math.floor(Math.random() * (Number(max) - min + 1));
}
View
@@ -19,24 +19,14 @@ import bridge.FABridge;
public class WebSocketMain extends Sprite {
- private var policyLoaded:Boolean = false;
private var callerUrl:String;
private var debug:Boolean = false;
+ private var manualPolicyFileLoaded:Boolean = false;
public function WebSocketMain() {
-
- // This is to avoid "You are trying to call recursively into the Flash Player ..."
- // error which (I heard) happens when you pass bunch of messages.
- // This workaround was written here:
- // http://www.themorphicgroup.com/blog/2009/02/14/fabridge-error-you-are-trying-to-call-recursively-into-the-flash-player-which-is-not-allowed/
- FABridge.EventsToCallLater["flash.events::Event"] = "true";
- FABridge.EventsToCallLater["WebSocketMessageEvent"] = "true";
- FABridge.EventsToCallLater["WebSocketStateEvent"] = "true";
-
var fab:FABridge = new FABridge();
fab.rootObject = this;
//log("Flash initialized");
-
}
public function setCallerUrl(url:String):void {
@@ -51,7 +41,9 @@ public class WebSocketMain extends Sprite {
url:String, protocol:String,
proxyHost:String = null, proxyPort:int = 0,
headers:String = null):WebSocket {
- loadPolicyFile(null);
+ if (!manualPolicyFileLoaded) {
+ loadDefaultPolicyFile(url);
+ }
return new WebSocket(this, url, protocol, proxyHost, proxyPort, headers);
}
@@ -64,14 +56,16 @@ public class WebSocketMain extends Sprite {
return URLUtil.getServerName(this.callerUrl);
}
- public function loadPolicyFile(url:String):void {
- if (policyLoaded && !url) return;
- if (!url) {
- url = "xmlsocket://" + URLUtil.getServerName(this.callerUrl) + ":843";
- }
- log("policy file: " + url);
- Security.loadPolicyFile(url);
- policyLoaded = true;
+ private function loadDefaultPolicyFile(wsUrl:String):void {
+ var policyUrl:String = "xmlsocket://" + URLUtil.getServerName(wsUrl) + ":843";
+ log("policy file: " + policyUrl);
+ Security.loadPolicyFile(policyUrl);
+ }
+
+ public function loadManualPolicyFile(policyUrl:String):void {
+ log("policy file: " + policyUrl);
+ Security.loadPolicyFile(policyUrl);
+ manualPolicyFileLoaded = true;
}
public function log(message:String):void {
@@ -1,32 +0,0 @@
-// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
-// License: New BSD License
-// Reference: http://dev.w3.org/html5/websockets/
-// Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-31
-
-package {
-
-import flash.display.*;
-import flash.events.*;
-import flash.external.*;
-import flash.net.*;
-import flash.system.*;
-import flash.utils.*;
-import mx.core.*;
-import mx.controls.*;
-import mx.events.*;
-import mx.utils.*;
-
-public class WebSocketStateEvent extends Event {
-
- public var readyState:int;
- public var bufferedAmount:int;
-
- public function WebSocketStateEvent(type:String, readyState:int, bufferedAmount:int) {
- super(type);
- this.readyState = readyState;
- this.bufferedAmount = bufferedAmount;
- }
-
-}
-
-}
Oops, something went wrong.

0 comments on commit e9b99e6

Please sign in to comment.