summaryrefslogtreecommitdiff
path: root/flash-src/WebSocketMain.as
blob: 22d42f5270ff662a349eacd6a1673e2456069c13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// 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-76

package {

import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.system.Security;
import flash.utils.setTimeout;

import mx.utils.URLUtil;

/**
  * Provides JavaScript API of WebSocket.
  */
public class WebSocketMain extends Sprite implements IWebSocketWrapper{
  
  private var callerUrl:String;
  private var debug:Boolean = false;
  private var manualPolicyFileLoaded:Boolean = false;
  private var webSockets:Array = [];
  private var eventQueue:Array = [];
  
  public function WebSocketMain() {
    ExternalInterface.addCallback("setCallerUrl", setCallerUrl);
    ExternalInterface.addCallback("setDebug", setDebug);
    ExternalInterface.addCallback("create", create);
    ExternalInterface.addCallback("send", send);
    ExternalInterface.addCallback("close", close);
    ExternalInterface.addCallback("loadManualPolicyFile", loadManualPolicyFile);
    ExternalInterface.addCallback("receiveEvents", receiveEvents);
    ExternalInterface.call("WebSocket.__onFlashInitialized");
  }
  
  /*************
   * Initialization / Utility methods
   */
  
  public function setCallerUrl(url:String):void {
    callerUrl = url;
  }
  
  public function setDebug(val:Boolean):void {
    debug = val;
  }
  
  public function getOrigin():String {
    return (URLUtil.getProtocol(this.callerUrl) + "://" +
      URLUtil.getServerNameWithPort(this.callerUrl)).toLowerCase();
  }
  
  public function getCallerHost():String {
    return URLUtil.getServerName(this.callerUrl);
  }
  
  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 {
    if (debug) {
      ExternalInterface.call("WebSocket.__log", encodeURIComponent("[WebSocket] " + message));
    }
  }
  
  public function error(message:String):void {
    ExternalInterface.call("WebSocket.__error", encodeURIComponent("[WebSocket] " + message));
  }
  
  private function parseEvent(event:WebSocketEvent):Object {
    var webSocket:WebSocket = event.target as WebSocket;
    var eventObj:Object = {};
    eventObj.type = event.type;
    eventObj.webSocketId = webSocket.getId();
    eventObj.readyState = webSocket.getReadyState();
    if (event.message !== null) {
      eventObj.message = event.message;
    }
    return eventObj;
  }
  
  /**
   * Socket interface
   */
  public function create(
    webSocketId:int,
    url:String, protocol:String,
    proxyHost:String = null, proxyPort:int = 0,
    headers:String = null):void {
    if (!manualPolicyFileLoaded) {
      loadDefaultPolicyFile(url);
    }
    var newSocket:WebSocket = new WebSocket(
        this, webSocketId, url, protocol, proxyHost, proxyPort, headers);
    newSocket.addEventListener("open", onSocketEvent);
    newSocket.addEventListener("close", onSocketEvent);
    newSocket.addEventListener("error", onSocketEvent);
    newSocket.addEventListener("message", onSocketEvent);
    webSockets[webSocketId] = newSocket;
  }
  
  public function send(webSocketId:int, encData:String):int {
    var webSocket:WebSocket = webSockets[webSocketId];
    return webSocket.send(encData);
  }
  
  public function close(webSocketId:int):void {
    var webSocket:WebSocket = webSockets[webSocketId];
    webSocket.close();
  }
  
  public function receiveEvents():Object {
    var result:Object = eventQueue;
    eventQueue = [];
    return result;
  }
  
  /****************
   * Socket event handler
   */
  public function onSocketEvent(event:WebSocketEvent):void {
    var eventObj:Object = parseEvent(event);
    eventQueue.push(eventObj);
    processEvents();
  }
  
  /**
   * Process our event queue.  If javascript is unresponsive, set
   * a timeout and try again.
   */
  public function processEvents():void {
    if (eventQueue.length == 0) return;
    if (!ExternalInterface.call("WebSocket.__onFlashEvent")) {
      setTimeout(processEvents, 500);
    }
  }
  
}

}