/flash-src/src/net/gimite/websocket/WebSocketMain.as
ActionScript | 166 lines | 131 code | 23 blank | 12 comment | 12 complexity | 2e052987ea658e7005e2c089728e0906 MD5 | raw file
1// Copyright: Hiroshi Ichikawa <http://gimite.net/en/> 2// License: New BSD License 3 4package net.gimite.websocket { 5 6import flash.display.Sprite; 7import flash.external.ExternalInterface; 8import flash.system.Security; 9import flash.utils.setTimeout; 10 11import mx.utils.URLUtil; 12 13/** 14 * Provides JavaScript API of WebSocket. 15 */ 16public class WebSocketMain extends Sprite implements IWebSocketLogger{ 17 18 private var callerUrl:String; 19 private var debug:Boolean = false; 20 private var manualPolicyFileLoaded:Boolean = false; 21 private var webSockets:Array = []; 22 private var eventQueue:Array = []; 23 24 public function WebSocketMain() { 25 ExternalInterface.addCallback("setCallerUrl", setCallerUrl); 26 ExternalInterface.addCallback("setDebug", setDebug); 27 ExternalInterface.addCallback("create", create); 28 ExternalInterface.addCallback("send", send); 29 ExternalInterface.addCallback("close", close); 30 ExternalInterface.addCallback("loadManualPolicyFile", loadManualPolicyFile); 31 ExternalInterface.addCallback("receiveEvents", receiveEvents); 32 ExternalInterface.call("WebSocket.__onFlashInitialized"); 33 } 34 35 public function setCallerUrl(url:String):void { 36 callerUrl = url; 37 } 38 39 public function setDebug(val:Boolean):void { 40 debug = val; 41 if (val) { 42 log("debug enabled"); 43 } 44 } 45 46 private function loadDefaultPolicyFile(wsUrl:String):void { 47 var policyUrl:String = "xmlsocket://" + URLUtil.getServerName(wsUrl) + ":843"; 48 log("policy file: " + policyUrl); 49 Security.loadPolicyFile(policyUrl); 50 } 51 52 public function loadManualPolicyFile(policyUrl:String):void { 53 log("policy file: " + policyUrl); 54 Security.loadPolicyFile(policyUrl); 55 manualPolicyFileLoaded = true; 56 } 57 58 public function log(message:String):void { 59 if (debug) { 60 ExternalInterface.call("WebSocket.__log", encodeURIComponent("[WebSocket] " + message)); 61 } 62 } 63 64 public function error(message:String):void { 65 ExternalInterface.call("WebSocket.__error", encodeURIComponent("[WebSocket] " + message)); 66 } 67 68 private function parseEvent(event:WebSocketEvent):Object { 69 var webSocket:WebSocket = event.target as WebSocket; 70 var eventObj:Object = {}; 71 eventObj.type = event.type; 72 eventObj.webSocketId = webSocket.getId(); 73 eventObj.readyState = webSocket.getReadyState(); 74 eventObj.protocol = webSocket.getAcceptedProtocol(); 75 if (event.message !== null) { 76 eventObj.message = event.message; 77 } 78 if (event.wasClean) { 79 eventObj.wasClean = event.wasClean; 80 } 81 if (event.code) { 82 eventObj.code = event.code; 83 } 84 if (event.reason !== null) { 85 eventObj.reason = event.reason; 86 } 87 return eventObj; 88 } 89 90 public function create( 91 webSocketId:int, 92 url:String, protocols:Array, 93 proxyHost:String = null, proxyPort:int = 0, 94 headers:String = null):void { 95 if (!manualPolicyFileLoaded) { 96 loadDefaultPolicyFile(url); 97 } 98 var newSocket:WebSocket = new WebSocket( 99 webSocketId, url, protocols, getOrigin(), proxyHost, proxyPort, 100 getCookie(url), headers, this); 101 newSocket.addEventListener("open", onSocketEvent); 102 newSocket.addEventListener("close", onSocketEvent); 103 newSocket.addEventListener("error", onSocketEvent); 104 newSocket.addEventListener("message", onSocketEvent); 105 webSockets[webSocketId] = newSocket; 106 } 107 108 public function send(webSocketId:int, encData:String):int { 109 var webSocket:WebSocket = webSockets[webSocketId]; 110 return webSocket.send(encData); 111 } 112 113 public function close(webSocketId:int):void { 114 var webSocket:WebSocket = webSockets[webSocketId]; 115 webSocket.close(); 116 } 117 118 public function receiveEvents():Object { 119 var result:Object = eventQueue; 120 eventQueue = []; 121 return result; 122 } 123 124 private function getOrigin():String { 125 return (URLUtil.getProtocol(this.callerUrl) + "://" + 126 URLUtil.getServerNameWithPort(this.callerUrl)).toLowerCase(); 127 } 128 129 private function getCookie(url:String):String { 130 if (URLUtil.getServerName(url).toLowerCase() == 131 URLUtil.getServerName(this.callerUrl).toLowerCase()) { 132 return ExternalInterface.call("function(){return document.cookie}"); 133 } else { 134 return ""; 135 } 136 } 137 138 /** 139 * Socket event handler. 140 */ 141 public function onSocketEvent(event:WebSocketEvent):void { 142 var eventObj:Object = parseEvent(event); 143 eventQueue.push(eventObj); 144 processEvents(); 145 } 146 147 /** 148 * Process our event queue. If javascript is unresponsive, set 149 * a timeout and try again. 150 */ 151 public function processEvents():void { 152 if (eventQueue.length == 0) return; 153 try { 154 if (!ExternalInterface.call("WebSocket.__onFlashEvent")) { 155 setTimeout(processEvents, 500); 156 } 157 } catch(e:SecurityError){ 158 trace( 159 "Caught SecurityError when trying to processEvents. " + 160 "This may happen when the window is going to be closed."); 161 } 162 } 163 164} 165 166}