commit 9bcfc6f7a6ea6a94faed9becb1311ea94443727d Author: Nate Hardison nate@rescomp-09-154551.stanford.edu Date: Wed May 4 18:25:39 2011 -0700
Initial version of AS Connector that communicates with Cirrus server and facilitator --- Connector.as | 137 ++++++++++++++++++++++++++++- Makefile | 2 +- RTMFPRelay.as | 235 +++++++------------------------------------------- RTMFPRelayReactor.as | 13 +++ Utils.as | 24 +++++ 5 files changed, 203 insertions(+), 208 deletions(-)
diff --git a/Connector.as b/Connector.as index f362dd3..fc18692 100644 --- a/Connector.as +++ b/Connector.as @@ -16,9 +16,27 @@ package import flash.utils.setInterval; import flash.utils.setTimeout;
- public class Connector extends RTMFPRelay { + import RTMFPRelay; + import RTMFPRelayReactor; + import Utils; + + public class Connector extends Sprite implements RTMFPRelayReactor { + + /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a + crossdomain policy. */ + private const DEFAULT_TOR_ADDR:Object = { + host: "173.255.221.44", + port: 9001 + };
private var output_text:TextField; + + // Socket to Tor relay. + private var s_t:Socket; + // Socket to facilitator. + private var s_f:Socket; + // RTMFP data relay + private var relay:RTMFPRelay;
private var fac_addr:Object; private var tor_addr:Object; @@ -33,10 +51,70 @@ package addChild(output_text);
puts("Starting."); + // Wait until the query string parameters are loaded. this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete); }
+ private function facilitator_is(host:String, port:int):void + { + if (s_f != null && s_f.connected) { + puts("Error: already connected to Facilitator!"); + return; + } + + s_f = new Socket(); + + s_f.addEventListener(Event.CONNECT, function (e:Event):void { + puts("Facilitator: connected."); + onConnectionEvent(); + }); + s_f.addEventListener(Event.CLOSE, function (e:Event):void { + puts("Facilitator: closed connection."); + }); + s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void { + puts("Facilitator: I/O error: " + e.text + "."); + }); + s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void { + puts("Facilitator: security error: " + e.text + "."); + }); + + puts("Facilitator: connecting to " + host + ":" + port + "."); + s_f.connect(host, port); + } + + private function tor_relay_is(host:String, port:int):void + { + if (s_t != null && s_t.connected) { + puts("Error: already connected to Tor relay!"); + return; + } + + s_t = new Socket(); + + s_t.addEventListener(Event.CONNECT, function (e:Event):void { + puts("Tor: connected."); + onConnectionEvent(); + }); + s_t.addEventListener(Event.CLOSE, function (e:Event):void { + puts("Tor: closed."); + }); + s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void { + puts("Tor: I/O error: " + e.text + "."); + }); + s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void { + puts("Tor: security error: " + e.text + "."); + }); + + puts("Tor: connecting to " + host + ":" + port + "."); + s_t.connect(host, port); + } + + private function puts(s:String):void + { + output_text.appendText(s + "\n"); + output_text.scrollV = output_text.maxScrollV; + }
private function loaderinfo_complete(e:Event):void { @@ -45,8 +123,61 @@ package
puts("Parameters loaded.");
- + fac_spec = this.loaderInfo.parameters["facilitator"]; + if (!fac_spec) { + puts("Error: no "facilitator" specification provided."); + return; + } + puts("Facilitator spec: "" + fac_spec + """); + fac_addr = Utils.parse_addr_spec(fac_spec); + if (!fac_addr) { + puts("Error: Facilitator spec must be in the form "host:port"."); + return; + } + + relay = new RTMFPRelay(this); + + tor_addr = DEFAULT_TOR_ADDR; + tor_relay_is(tor_addr.host, tor_addr.port); + facilitator_is(fac_addr.host, fac_addr.port); } - + + public function onConnectionEvent():void + { + if (s_f != null && s_f.connected && s_t != null && s_t.connected && + relay != null && relay.connected) { + s_f.writeUTFBytes("POST / HTTP/1.1\r\n\r\nclient=%3A"+ relay.cirrus_id + "\r\n"); + } + } + + public function onIOErrorEvent(event:IOErrorEvent):void + { + puts("Cirrus: I/O error: " + event.text + "."); + } + + public function onNetStatusEvent(event:NetStatusEvent):void + { + switch (event.info.code) { + case "NetConnection.Connect.Success" : + puts("Cirrus: connected with ID " + relay.cirrus_id + "."); + onConnectionEvent(); + break; + case "NetStream.Connect.Success" : + puts("Peer: connected."); + break; + case "NetStream.Publish.BadName" : + puts(event.info.code); + break; + case "NetStream.Connect.Closed" : + puts(event.info.code); + break; + } + } + + public function onSecurityErrorEvent(event:SecurityErrorEvent):void + { + puts("Cirrus: security error: " + event.text + "."); + } + } }
\ No newline at end of file diff --git a/Makefile b/Makefile index baf0e94..92047fb 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ MXMLC ?= mxmlc
-TARGETS = swfcat.swf Proxy.swf +TARGETS = swfcat.swf Connector.swf
all: $(TARGETS)
diff --git a/RTMFPRelay.as b/RTMFPRelay.as index 27b3208..a33ebbf 100644 --- a/RTMFPRelay.as +++ b/RTMFPRelay.as @@ -15,8 +15,6 @@ package import flash.utils.clearInterval; import flash.utils.setInterval; import flash.utils.setTimeout; - - import Utils;
public class RTMFPRelay extends Sprite { @@ -24,15 +22,8 @@ package private static const CIRRUS_DEV_KEY:String = RTMFP::CIRRUS_KEY; /* The name of the "media" to pass between peers */ - public static const DATA:String = "data"; + private static const DATA:String = "data"; - protected var output_text:TextField; - - // Socket to Tor relay. - private var s_t:Socket; - // Socket to facilitator. - private var s_f:Socket; - /* Connection to the Cirrus rendezvous service */ private var cirrus_conn:NetConnection; @@ -42,231 +33,67 @@ package /* Data streams to be established with peer */ private var send_stream:NetStream; private var recv_stream:NetStream; + + private var notifiee:RTMFPRelayReactor;
- private var fac_addr:Object; - private var tor_addr:Object; - - private function puts(s:String):void - { - output_text.appendText(s + "\n"); - output_text.scrollV = output_text.maxScrollV; - } - - public function RTMFPRelay() - { - output_text = new TextField(); - output_text.width = 400; - output_text.height = 300; - output_text.background = true; - output_text.backgroundColor = 0x001f0f; - output_text.textColor = 0x44CC44; - addChild(output_text); - - puts("Starting."); - - cirrus_conn = new NetConnection(); - cirrus_conn.addEventListener(NetStatusEvent.NET_STATUS, function (e:NetStatusEvent):void { - puts("Cirrus: connected."); - }); - cirrus_conn.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void { - puts("Cirrus: I/O error: " + e.text + "."); - }); - - cirrus_conn.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityError):void { - puts("Cirrus: security error: " + e.text + "."); - }); + public function RTMFPRelay(notifiee:RTMFPRelayReactor) + { + this.notifiee = notifiee; + + cirrus_conn = new NetConnection(); + cirrus_conn.addEventListener(NetStatusEvent.NET_STATUS, notifiee.onNetStatusEvent); + cirrus_conn.addEventListener(IOErrorEvent.IO_ERROR, notifiee.onIOErrorEvent); + cirrus_conn.addEventListener(SecurityErrorEvent.SECURITY_ERROR, notifiee.onSecurityErrorEvent); - cirrus_conn.connect(CIRRUS_ADDRESS + "/" + CIRRUS_DEV_KEY); - - - // Wait until the query string parameters are loaded. - this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete); + cirrus_conn.connect(CIRRUS_ADDRESS + "/" + CIRRUS_DEV_KEY); }
- public function data_is(data:ByteArray):void + public function get cirrus_id():String { + if (cirrus_conn != null && cirrus_conn.connected) { + return cirrus_conn.nearID; + }
- + return null; }
- public function facilitator_is(host:String, port:String):void + public function get connected():Boolean + { + return (cirrus_conn != null && cirrus_conn.connected); + } + + public function data_is(data:ByteArray):void { - if (s_f != null && s_f.connected) { - - return; - }
- s_f = new Socket();
- s_f.addEventListener(Event.CONNECT, function (e:Event):void { - puts("Facilitator: connected."); - }); - s_f.addEventListener(Event.CLOSE, function (e:Event):void { - puts("Facilitator: closed connection."); - }); - s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void { - puts("Facilitator: I/O error: " + e.text + "."); - }); - s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void { - puts("Facilitator: security error: " + e.text + "."); - }); - - puts("Facilitator: connecting to " + host + ":" + port + "."); - s_f.connect(host, port); }
- public function peer(peer_id:String):String + public function get peer():String { return this.peer_id; }
- public function peer_is(peer_id:String):void + public function set peer(peer_id:String):void { if (peer_id == null) { - puts("Error: Client ID doesn't exist."); - return; + throw new Error("Peer ID is null.") } else if (peer_id == cirrus_conn.nearID) { - puts("Error: Client ID is our ID."); - return; + throw new Error("Peer ID cannot be the same as our ID."); } else if (this.peer_id == peer_id) { - + throw new Error("Already connected to peer " + peer_id + "."); } else if (this.recv_stream != null) { - puts("Error: already set up with a peer!"); - return; + throw new Error("Cannot connect to a second peer."); }
this.peer_id = peer_id;
send_stream = new NetStream(cirrus_conn, NetStream.DIRECT_CONNECTIONS); - send_stream.addEventListener(NetStatusEvent.NET_STATUS, net_status_event_handler); + send_stream.addEventListener(NetStatusEvent.NET_STATUS, notifiee.onNetStatusEvent); send_stream.publish(DATA);
recv_stream = new NetStream(cirrus_conn, peer_id); - recv_stream.addEventListener(NetStatusEvent.NET_STATUS, net_status_event_handler); + recv_stream.addEventListener(NetStatusEvent.NET_STATUS, notifiee.onNetStatusEvent); recv_stream.play(DATA); } - - public function tor_relay_is(host:String, port:String):void - { - if (s_t != null && s_t.connected) { - puts("Error: already connected to Tor relay!"); - return; - } - - s_t = new Socket(); - - s_t.addEventListener(Event.CONNECT, function (e:Event):void { - puts("Tor: connected."); - }); - s_t.addEventListener(Event.CLOSE, function (e:Event):void { - puts("Tor: closed."); - }); - s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void { - puts("Tor: I/O error: " + e.text + "."); - }); - s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void { - puts("Tor: security error: " + e.text + "."); - }); - - puts("Tor: connecting to " + host + ":" + port + "."); - s_t.connect(host, port); - } - - private function loaderinfo_complete(e:Event):void - { - var fac_spec:String; - var tor_spec:String; - - puts("Parameters loaded."); - fac_spec = this.loaderInfo.parameters["facilitator"]; - if (!fac_spec) { - puts("Error: no "facilitator" specification provided."); - return; - } - puts("Facilitator spec: "" + fac_spec + """); - fac_addr = parse_addr_spec(fac_spec); - if (!fac_addr) { - puts("Error: Facilitator spec must be in the form "host:port"."); - return; - } - - tor_addr = DEFAULT_TOR_ADDR; - - go(); - } - - private function fac_connected(e:Event):void - { - - - s_f.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void { - var client_spec:String; - var client_addr:Object; - - client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8"); - puts("Facilitator: got "" + client_spec + """); - - /*client_addr = parse_addr_spec(client_spec); - if (!client_addr) { - puts("Error: Client spec must be in the form "host:port"."); - return; - } - if (client_addr.host == "0.0.0.0" && client_addr.port == 0) { - puts("Error: Facilitator has no clients."); - return; - }*/ - - /* Now we have a client, so start up a connection to the Cirrus rendezvous point */ - - }); - - s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n"); - } - - private function net_status_event_handler(e:NetStatusEvent):void - { - switch (e.info.code) { - case "NetConnection.Connect.Success" : - // Cirrus is now connected - cirrus_connected(e); - } - - } - - private function cirrus_connected(e:Event):void - { - - - - } - - /*private function client_connected(e:Event):void - { - puts("Client: connected."); - - s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void { - var bytes:ByteArray = new ByteArray(); - s_t.readBytes(bytes, 0, e.bytesLoaded); - puts("Tor: read " + bytes.length + "."); - s_c.writeBytes(bytes); - }); - s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void { - var bytes:ByteArray = new ByteArray(); - s_c.readBytes(bytes, 0, e.bytesLoaded); - puts("Client: read " + bytes.length + "."); - s_t.writeBytes(bytes); - }); - }*/ - - private function close_connections():void - { - if (s_t.connected) s_t.close(); - if (s_f.connected) s_f.close(); - if (cirrus.connected) cirrus.close(); - if (send_stream != null) send_stream.close(); - if (recv_stream != null) recv_stream.close(); - } - - } } diff --git a/RTMFPRelayReactor.as b/RTMFPRelayReactor.as new file mode 100644 index 0000000..5c84779 --- /dev/null +++ b/RTMFPRelayReactor.as @@ -0,0 +1,13 @@ +package { + + import flash.events.IOErrorEvent; + import flash.events.NetStatusEvent; + import flash.events.SecurityErrorEvent; + + public interface RTMFPRelayReactor { + function onIOErrorEvent(event:IOErrorEvent):void; + function onNetStatusEvent(event:NetStatusEvent):void; + function onSecurityErrorEvent(event:SecurityErrorEvent):void + } + +} \ No newline at end of file diff --git a/Utils.as b/Utils.as new file mode 100644 index 0000000..75ed44c --- /dev/null +++ b/Utils.as @@ -0,0 +1,24 @@ +package { + + public class Utils { + + /* Parse an address in the form "host:port". Returns an Object with + keys "host" (String) and "port" (int). Returns null on error. */ + public static function parse_addr_spec(spec:String):Object + { + var parts:Array; + var addr:Object; + + parts = spec.split(":", 2); + if (parts.length != 2 || !parseInt(parts[1])) + return null; + addr = {} + addr.host = parts[0]; + addr.port = parseInt(parts[1]); + + return addr; + } + + } + +} \ No newline at end of file