1 // Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
2 // License: New BSD License
3 // Reference: http://dev.w3.org/html5/websockets/
4 // Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
8 import flash.display.Sprite;
9 import flash.external.ExternalInterface;
10 import flash.system.Security;
11 import flash.utils.setTimeout;
13 import mx.utils.URLUtil;
16 * Provides JavaScript API of WebSocket.
18 public class WebSocketMain extends Sprite implements IWebSocketLogger{
20 private var callerUrl:String;
21 private var debug:Boolean = false;
22 private var manualPolicyFileLoaded:Boolean = false;
23 private var webSockets:Array = [];
24 private var eventQueue:Array = [];
26 public function WebSocketMain() {
27 ExternalInterface.addCallback("setCallerUrl", setCallerUrl);
28 ExternalInterface.addCallback("setDebug", setDebug);
29 ExternalInterface.addCallback("create", create);
30 ExternalInterface.addCallback("send", send);
31 ExternalInterface.addCallback("close", close);
32 ExternalInterface.addCallback("loadManualPolicyFile", loadManualPolicyFile);
33 ExternalInterface.addCallback("receiveEvents", receiveEvents);
34 ExternalInterface.call("WebSocket.__onFlashInitialized");
37 public function setCallerUrl(url:String):void {
41 public function setDebug(val:Boolean):void {
45 private function loadDefaultPolicyFile(wsUrl:String):void {
46 var policyUrl:String = "xmlsocket://" + URLUtil.getServerName(wsUrl) + ":843";
47 log("policy file: " + policyUrl);
48 Security.loadPolicyFile(policyUrl);
51 public function loadManualPolicyFile(policyUrl:String):void {
52 log("policy file: " + policyUrl);
53 Security.loadPolicyFile(policyUrl);
54 manualPolicyFileLoaded = true;
57 public function log(message:String):void {
59 ExternalInterface.call("WebSocket.__log", encodeURIComponent("[WebSocket] " + message));
63 public function error(message:String):void {
64 ExternalInterface.call("WebSocket.__error", encodeURIComponent("[WebSocket] " + message));
67 private function parseEvent(event:WebSocketEvent):Object {
68 var webSocket:WebSocket = event.target as WebSocket;
69 var eventObj:Object = {};
70 eventObj.type = event.type;
71 eventObj.webSocketId = webSocket.getId();
72 eventObj.readyState = webSocket.getReadyState();
73 eventObj.protocol = webSocket.getAcceptedProtocol();
74 if (event.message !== null) {
75 eventObj.message = event.message;
80 public function create(
82 url:String, protocols:Array,
83 proxyHost:String = null, proxyPort:int = 0,
84 headers:String = null):void {
85 if (!manualPolicyFileLoaded) {
86 loadDefaultPolicyFile(url);
88 var newSocket:WebSocket = new WebSocket(
89 webSocketId, url, protocols, getOrigin(), proxyHost, proxyPort,
90 getCookie(url), headers, this);
91 newSocket.addEventListener("open", onSocketEvent);
92 newSocket.addEventListener("close", onSocketEvent);
93 newSocket.addEventListener("error", onSocketEvent);
94 newSocket.addEventListener("message", onSocketEvent);
95 webSockets[webSocketId] = newSocket;
98 public function send(webSocketId:int, encData:String):int {
99 var webSocket:WebSocket = webSockets[webSocketId];
100 return webSocket.send(encData);
103 public function close(webSocketId:int):void {
104 var webSocket:WebSocket = webSockets[webSocketId];
108 public function receiveEvents():Object {
109 var result:Object = eventQueue;
114 private function getOrigin():String {
115 return (URLUtil.getProtocol(this.callerUrl) + "://" +
116 URLUtil.getServerNameWithPort(this.callerUrl)).toLowerCase();
119 private function getCookie(url:String):String {
120 if (URLUtil.getServerName(url).toLowerCase() ==
121 URLUtil.getServerName(this.callerUrl).toLowerCase()) {
122 return ExternalInterface.call("function(){return document.cookie}");
129 * Socket event handler.
131 public function onSocketEvent(event:WebSocketEvent):void {
132 var eventObj:Object = parseEvent(event);
133 eventQueue.push(eventObj);
138 * Process our event queue. If javascript is unresponsive, set
139 * a timeout and try again.
141 public function processEvents():void {
142 if (eventQueue.length == 0) return;
143 if (!ExternalInterface.call("WebSocket.__onFlashEvent")) {
144 setTimeout(processEvents, 500);