tor-commits
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2011
- 14 participants
- 716 discussions
commit 4914ab8f0d65f577dd41e64d0cb105b84e50acb0
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 09:47:50 2011 -0700
rm return_of_the_rtmfpcat.as.
---
return_of_the_rtmfpcat.as | 794 ---------------------------------------------
1 files changed, 0 insertions(+), 794 deletions(-)
diff --git a/return_of_the_rtmfpcat.as b/return_of_the_rtmfpcat.as
deleted file mode 100644
index 7095c09..0000000
--- a/return_of_the_rtmfpcat.as
+++ /dev/null
@@ -1,794 +0,0 @@
-/* Meow! */
-package
-{
- import flash.display.Sprite;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
- import flash.text.TextField;
- import flash.text.TextFormat;
- import flash.net.Socket;
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.IOErrorEvent;
- import flash.events.NetStatusEvent;
- import flash.events.ProgressEvent;
- import flash.events.SecurityErrorEvent;
- import flash.utils.ByteArray;
- import flash.utils.clearTimeout;
- import flash.utils.setTimeout;
- import flash.utils.clearInterval;
- import flash.utils.setInterval;
- import flash.utils.setTimeout;
- import flash.net.NetConnection;
-
- public class return_of_the_rtmfpcat extends Sprite
- {
- /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
- crossdomain policy. */
- private const DEFAULT_TOR_PROXY_ADDR:Object = {
- host: "173.255.221.44",
- port: 9001
- };
-
- /* Tor application running on the client. */
- private const DEFAULT_TOR_CLIENT_ADDR:Object = {
- host: "127.0.0.1",
- port: 3333
- };
-
- /* Nate's facilitator -- also serving a crossdomain policy */
- //private const DEFAULT_FACILITATOR_ADDR:Object = {
- // host: "128.12.179.80",
- // port: 9002
- //};
-
- /* David's facilitator. */
- private const DEFAULT_FACILITATOR_ADDR:Object = {
- host: "127.0.0.1",
- port: 9002
- };
-
- /* Cirrus server information. */
- private const DEFAULT_CIRRUS_ADDRESS:String = "rtmfp://p2p.rtmfp.net";
- private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
-
- private static const DEFAULT_CIRCON_TIMEOUT:uint = 4000;
-
- private static const DEFAULT_PEER_CON_TIMEOUT:uint = 4000;
-
- /* Maximum connections. */
- private const DEFAULT_MAXIMUM_RCP_PAIRS:uint = 1;
-
- /* Milliseconds. */
- private const FACILITATOR_POLL_INTERVAL:int = 10000;
-
- private var max_rcp_pairs:uint;
-
- /* TextField for debug output. */
- private var output_text:TextField;
-
- /* Are we the proxy or the client? */
- private var proxy_mode:Boolean;
-
- /* Facilitator address */
- private var fac_addr:Object;
-
- /* Tor address. If we're a proxy, then this address is a relay.
- * If we're running on the client, then this address is the Tor
- * client application. */
- private var tor_addr:Object;
-
- /* Cirrus address */
- private var cir_addr:String;
-
- /* Cirrus key */
- private var cir_key:String;
-
- /* Connection to the Cirrus rendezvous service */
- private var circon:NetConnection;
-
- /* Cirrus connection timeout ID. */
- private var circon_timeo_id:int;
-
- /* Number of connected RTMFPConnectionPairs. */
- private var rcp_pairs:uint;
- private var rcp_pairs_total:uint;
-
- private var rtmfp_data_counter:uint;
-
- /* Keep track of facilitator polling timer. */
- private var fac_poll_timeo_id:uint;
-
- /* Badge with a client counter */
- [Embed(source="badge.png")]
- private var BadgeImage:Class;
- private var tot_client_count_tf:TextField;
- private var tot_client_count_fmt:TextFormat;
- private var cur_client_count_tf:TextField;
- private var cur_client_count_fmt:TextFormat;
-
- /* Put a string to the screen. */
- public function puts(s:String):void
- {
- output_text.appendText(s + "\n");
- output_text.scrollV = output_text.maxScrollV;
- }
-
- public function update_client_count():void
- {
- /* Update total client count. */
- if (String(rcp_pairs_total).length == 1)
- tot_client_count_tf.text = "0" + String(rcp_pairs_total);
- else
- tot_client_count_tf.text = String(rcp_pairs_total);
-
- /* Update current client count. */
- cur_client_count_tf.text = "";
- for(var i:Number=0; i<rcp_pairs; i++)
- cur_client_count_tf.appendText(".");;
- }
-
- public function return_of_the_rtmfpcat()
- {
- // Absolute positioning.
- stage.scaleMode = StageScaleMode.NO_SCALE;
- stage.align = StageAlign.TOP_LEFT;
-
- output_text = new TextField();
- output_text.width = stage.stageWidth;
- output_text.height = stage.stageHeight;
- output_text.background = true;
- output_text.backgroundColor = 0x001f0f;
- output_text.textColor = 0x44cc44;
-
- /* Setup client counter for badge. */
- tot_client_count_fmt = new TextFormat();
- tot_client_count_fmt.color = 0xFFFFFF;
- tot_client_count_fmt.align = "center";
- tot_client_count_fmt.font = "courier-new";
- tot_client_count_fmt.bold = true;
- tot_client_count_fmt.size = 10;
- tot_client_count_tf = new TextField();
- tot_client_count_tf.width = 20;
- tot_client_count_tf.height = 17;
- tot_client_count_tf.background = false;
- tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
- tot_client_count_tf.x=47;
- tot_client_count_tf.y=0;
-
- cur_client_count_fmt = new TextFormat();
- cur_client_count_fmt.color = 0xFFFFFF;
- cur_client_count_fmt.align = "center";
- cur_client_count_fmt.font = "courier-new";
- cur_client_count_fmt.bold = true;
- cur_client_count_fmt.size = 10;
- cur_client_count_tf = new TextField();
- cur_client_count_tf.width = 20;
- cur_client_count_tf.height = 17;
- cur_client_count_tf.background = false;
- cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
- cur_client_count_tf.x=47;
- cur_client_count_tf.y=6;
-
- /* Update the client counter on badge. */
- update_client_count();
-
- /* Initialize connection pair count. */
- rcp_pairs = 0;
-
- /* Unique counter for RTMFP data publishing. */
- rtmfp_data_counter = 0;
-
- puts("Meow!");
- puts("Starting.");
- // Wait until the query string parameters are loaded.
- this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
- }
-
- private function loaderinfo_complete(e:Event):void
- {
- var fac_spec:String;
- var tor_spec:String;
-
- puts("Parameters loaded.");
-
- proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
-
- if(this.loaderInfo.parameters["debug"] != null)
- addChild(output_text);
-
- addChild(new BadgeImage());
- /* Tried unsuccessfully to add counter to badge. */
- /* For now, need two addChilds :( */
- addChild(tot_client_count_tf);
- addChild(cur_client_count_tf);
-
-
- fac_spec = this.loaderInfo.parameters["facilitator"];
- if (fac_spec) {
- 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;
- }
- } else {
- fac_addr = DEFAULT_FACILITATOR_ADDR;
- }
-
- tor_spec = this.loaderInfo.parameters["tor"];
- if (tor_spec) {
- puts("Tor spec: \"" + tor_spec + "\"");
- tor_addr = parse_addr_spec(tor_spec);
- if (!tor_addr) {
- puts("Error: Tor spec must be in the form \"host:port\".");
- return;
- }
- } else {
- if (proxy_mode)
- tor_addr = DEFAULT_TOR_PROXY_ADDR;
- else
- tor_addr = DEFAULT_TOR_CLIENT_ADDR;
- }
-
- if(this.loaderInfo.parameters["cirrus_server"])
- cir_addr = this.loaderInfo.parameters["cirrus_server"];
- else
- cir_addr = DEFAULT_CIRRUS_ADDRESS;
-
- if(this.loaderInfo.parameters["cirrus_key"])
- cir_key = this.loaderInfo.parameters["cirrus_key"];
- else
- cir_key = DEFAULT_CIRRUS_KEY;
-
- if(this.loaderInfo.parameters["max_con"])
- max_rcp_pairs = this.loaderInfo.parameters["max_con"];
- else
- max_rcp_pairs = DEFAULT_MAXIMUM_RCP_PAIRS;
-
- if(this.loaderInfo.parameters["start"])
- rtmfp_data_counter = this.loaderInfo.parameters["start"];
-
- main();
- }
-
- /* The main logic begins here, after start-up issues are taken care of. */
- private function main():void
- {
- puts("Making connection to cirrus server.");
- circon = new NetConnection();
- circon.addEventListener(NetStatusEvent.NET_STATUS, circon_netstatus_event);
- circon.addEventListener(IOErrorEvent.IO_ERROR, function (e:Event):void {
- puts("Cirrus connection had an IOErrorEvent.IO_ERROR event");
- });
- circon.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:Event):void {
- puts("Cirrus connection had a SecurityErrorEvent.SECURITY_ERROR");
- });
- circon.connect(cir_addr + "/" + cir_key);
- circon_timeo_id = setInterval(circon_timeout, DEFAULT_CIRCON_TIMEOUT);
- }
-
- private function circon_netstatus_event(event:NetStatusEvent):void
- {
- switch (event.info.code) {
- case "NetConnection.Connect.Success" :
- puts("Cirrus server connection established.");
- puts("Got id " + circon.nearID + ".");
- clearInterval(circon_timeo_id);
-
- if(proxy_mode) {
- poll_for_id();
- } else {
- puts("Setting up listening RTMFPConnectionPair");
- var rcp:RTMFPConnectionPair = new RTMFPConnectionPair(circon, tor_addr, output_text);
- rcp.addEventListener(Event.CONNECT, rcp_connect_event);
- rcp.addEventListener(Event.CLOSE, rcp_close_event);
- rcp.listen(String(rtmfp_data_counter));
-
- var reg_str:String = circon.nearID + ":" + String(rtmfp_data_counter);
- puts("Registering " + reg_str + " with facilitator");
- register_id(reg_str, fac_addr);
- rtmfp_data_counter++;
- }
-
- break;
- }
- }
-
- private function poll_for_id():void
- {
- puts("Facilitator: got " + rcp_pairs + " connections... polling for another");
-
- var s_f:Socket = new Socket();
- s_f.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("Facilitator: connected to " + fac_addr.host + ":" + fac_addr.port + ".");
- s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
- });
- s_f.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("Facilitator: connection closed.");
- });
- s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- puts("Facilitator: I/O error: " + e.text + ".");
- });
- s_f.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- var client:String = s_f.readMultiByte(e.bytesLoaded, "utf-8");
- puts("Facilitator: got \"" + client + "\"");
- if (client != "Registration list empty") {
- puts("Connecting to " + client + ".");
-
- var client_id:String = client.split(":")[0];
- var client_data:String = client.split(":")[1];
-
- clearTimeout(fac_poll_timeo_id);
-
- var rcp:RTMFPConnectionPair = new RTMFPConnectionPair(circon, tor_addr, output_text);
- rcp.addEventListener(Event.CONNECT, rcp_connect_event);
- rcp.addEventListener(Event.UNLOAD, function (e:Event):void {
- /* Failed to connect to peer... continue loop. */
- puts("RTMFPConnectionPair: Timed out connecting to peer!");
- if(rcp_pairs < max_rcp_pairs)
- poll_for_id();
- });
- rcp.addEventListener(Event.CLOSE, rcp_close_event);
- rcp.connect(client_id, client_data, DEFAULT_PEER_CON_TIMEOUT);
- } else {
- /* Need to clear any outstanding timers to ensure
- * that only one timer ever runs. */
- clearTimeout(fac_poll_timeo_id);
- if(rcp_pairs < max_rcp_pairs)
- fac_poll_timeo_id = setTimeout(poll_for_id, FACILITATOR_POLL_INTERVAL);
- }
- });
- s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- puts("Facilitator: security error: " + e.text + ".");
- });
-
- s_f.connect(fac_addr.host, fac_addr.port);
-
- }
-
- private function rcp_connect_event(e:Event):void
- {
- puts("RTMFPConnectionPair connected");
-
- rcp_pairs++;
- rcp_pairs_total++;
-
- /* Update the client count on the badge. */
- update_client_count();
-
- if(proxy_mode) {
- if(rcp_pairs < max_rcp_pairs) {
- poll_for_id();
- }
- } else {
- /* Setup listening RTMFPConnectionPair. */
- if(rcp_pairs < max_rcp_pairs) {
- puts("Setting up listening RTMFPConnectionPair");
- var rcp:RTMFPConnectionPair = new RTMFPConnectionPair(circon, tor_addr, output_text);
- rcp.addEventListener(Event.CONNECT, rcp_connect_event);
- rcp.addEventListener(Event.CLOSE, rcp_close_event);
- rcp.listen(String(rtmfp_data_counter));
- var reg_str:String = circon.nearID + ":" + String(rtmfp_data_counter);
- puts("Registering " + reg_str + " with facilitator");
- register_id(reg_str, fac_addr);
- rtmfp_data_counter++;
- }
- }
- }
-
- private function rcp_close_event(e:Event):void
- {
- puts("RTMFPConnectionPair closed");
-
- rcp_pairs--;
-
- /* Update the client count on the badge. */
- update_client_count();
-
- /* FIXME: Do I need to unregister the event listeners so
- * that the system can garbage collect the rcp object? */
- if(proxy_mode) {
- if(rcp_pairs < max_rcp_pairs) {
- poll_for_id();
- }
- } else {
- if(rcp_pairs < max_rcp_pairs) {
- puts("Setting up listening RTMFPConnectionPair");
- var rcp:RTMFPConnectionPair = new RTMFPConnectionPair(circon, tor_addr, output_text);
- rcp.addEventListener(Event.CONNECT, rcp_connect_event);
- rcp.addEventListener(Event.CLOSE, rcp_close_event);
- rcp.listen(String(rtmfp_data_counter));
- var reg_str:String = circon.nearID + ":" + String(rtmfp_data_counter);
- puts("Registering " + reg_str + " with facilitator");
- register_id(reg_str, fac_addr);
- rtmfp_data_counter++;
- }
- }
- }
-
- private function register_id(id:String, fac_addr:Object):void
- {
- var s_f:Socket = new Socket();
- s_f.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("Facilitator: connected to " + fac_addr.host + ":" + fac_addr.port + ".");
- puts("Facilitator: Registering id " + id);
- s_f.writeUTFBytes("POST / HTTP/1.0\r\n\r\nclient=" + id + "\r\n");
- });
- s_f.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("Facilitator: connection closed.");
- });
- 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 + ".");
- });
-
- s_f.connect(fac_addr.host, fac_addr.port);
- }
-
- private function circon_timeout():void
- {
- puts("Cirrus server connection timed out!");
- }
-
- /* Parse an address in the form "host:port". Returns an Object with
- keys "host" (String) and "port" (int). Returns null on error. */
- private 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;
- }
- }
-}
-
-import flash.display.Sprite;
-import flash.events.Event;
-import flash.events.EventDispatcher;
-import flash.events.IOErrorEvent;
-import flash.events.ProgressEvent;
-import flash.events.SecurityErrorEvent;
-import flash.events.NetStatusEvent;
-import flash.net.Socket;
-import flash.utils.ByteArray;
-import flash.utils.clearTimeout;
-import flash.utils.getTimer;
-import flash.utils.setTimeout;
-import flash.net.NetConnection;
-import flash.net.NetStream;
-import flash.text.TextField;
-
-class RTMFPSocket extends EventDispatcher
-{
- /* The name of the "media" to pass between peers. */
- private var data:String;
-
- /* Connection to the Cirrus rendezvous service.
- * RTMFPSocket is established using this service. */
- private var circon:NetConnection;
-
- /* Unidirectional streams composing socket. */
- private var send_stream:NetStream;
- private var recv_stream:NetStream;
-
- /* Keeps the state of our connectedness. */
- public var connected:Boolean;
-
- private var connect_timeo_id:uint;
-
- private var output_text:TextField;
-
- /* Put a string to the screen. */
- public function puts(s:String):void
- {
- output_text.appendText(s + "\n");
- output_text.scrollV = output_text.maxScrollV;
- }
-
- public function RTMFPSocket(circon:NetConnection, output_text:TextField)
- {
- this.circon = circon;
- this.output_text = output_text;
- connected = false;
-
- circon.addEventListener(NetStatusEvent.NET_STATUS, circon_netstatus_event);
- circon.addEventListener(IOErrorEvent.IO_ERROR, function (e:Event):void {
- puts("RTMFPSocket: Cirrus connection had an IOErrorEvent.IO_ERROR event");
- });
- circon.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:Event):void {
- puts("RTMFPSocket: Cirrus connection had a SecurityErrorEvent.SECURITY_ERROR");
- });
- }
-
- public function listen(data:String):void
- {
- this.data = data;
-
- send_stream = new NetStream(circon, NetStream.DIRECT_CONNECTIONS);
- var client:Object = new Object();
- client.onPeerConnect = send_stream_peer_connect;
- send_stream.client = client;
- send_stream.publish(data);
- }
-
- private function connect_timeout():void
- {
- puts("RTMFPSocket: Timed out connecting to peer");
- close();
- /* OK this is not so nice, because I wanted an Event.TIMEOUT event, but flash gives us none such event :( */
- dispatchEvent(new Event(Event.UNLOAD));
- }
-
- public function connect(clientID:String, data:String, timeout:uint):void
- {
- puts("RTMFPSocket: connecting to peer...");
-
- connect_timeo_id = setTimeout(connect_timeout, timeout);
-
- this.data = data;
-
- send_stream = new NetStream(circon, NetStream.DIRECT_CONNECTIONS);
- var client:Object = new Object();
- client.onPeerConnect = function (peer:NetStream):Boolean {
- clearTimeout(connect_timeo_id);
- puts("RTMFPSocket: connected to peer");
- connected = true;
- dispatchEvent(new Event(Event.CONNECT));
- peer.send("setPeerConnectAcknowledged");
- return true;
- };
- send_stream.client = client;
- send_stream.publish(data);
-
- recv_stream = new NetStream(circon, clientID);
- var client_rtmfp:RTMFPSocketClient = new RTMFPSocketClient();
- client_rtmfp.addEventListener(ProgressEvent.SOCKET_DATA, function (event:ProgressEvent):void {
- dispatchEvent(event);
- }, false, 0, true);
- client_rtmfp.addEventListener(RTMFPSocketClient.PEER_CONNECT_ACKNOWLEDGED, function (event:Event):void {
- /* Empty... here for symmetry. */
- }, false, 0, true);
-
- recv_stream.client = client_rtmfp;
- recv_stream.play(data);
- }
-
- private function send_stream_peer_connect(peer:NetStream):Boolean
- {
- puts("RTMFPSocket: peer connecting...");
- recv_stream = new NetStream(circon, peer.farID);
- var client:RTMFPSocketClient = new RTMFPSocketClient();
- client.addEventListener(ProgressEvent.SOCKET_DATA, function (event:ProgressEvent):void {
- dispatchEvent(event);
- }, false, 0, true);
- client.addEventListener(RTMFPSocketClient.PEER_CONNECT_ACKNOWLEDGED, function (event:Event):void {
- puts("RTMFPSocket: peer connected");
- connected = true;
- dispatchEvent(new Event(Event.CONNECT));
- }, false, 0, true);
- recv_stream.client = client;
- recv_stream.play(data);
-
- peer.send("setPeerConnectAcknowledged");
-
- return true;
- }
-
- private function circon_netstatus_event(event:NetStatusEvent):void
- {
- switch (event.info.code) {
- case "NetStream.Connect.Closed" :
- puts("RTMFPSocket: NetStream connection was closed");
-
- if(connected)
- {
- send_stream.close();
- recv_stream.close();
- connected = false;
- dispatchEvent(new Event(Event.CLOSE));
- }
-
- break;
- }
- }
-
-
- public function readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void
- {
- recv_stream.client.bytes.readBytes(bytes, offset, length);
- }
-
- public function writeBytes(bytes:ByteArray):void
- {
- send_stream.send("dataAvailable", bytes);
- }
-
- public function close():void
- {
- puts("RTMFPSocket: closing...");
- send_stream.close();
- recv_stream.close();
- connected = false;
- }
-}
-
-[Event(name="peerConnectAcknowledged", type="flash.events.Event")]
-dynamic class RTMFPSocketClient extends EventDispatcher
-{
- public static const PEER_CONNECT_ACKNOWLEDGED:String = "peerConnectAcknowledged";
-
- private var _bytes:ByteArray;
- private var _peerID:String;
- private var _peerConnectAcknowledged:Boolean;
-
- public function RTMFPSocketClient()
- {
- super();
- _bytes = new ByteArray();
- _peerID = null;
- _peerConnectAcknowledged = false;
- }
-
- public function get bytes():ByteArray
- {
- return _bytes;
- }
-
- public function dataAvailable(bytes:ByteArray):void
- {
- this._bytes.clear();
- bytes.readBytes(this._bytes);
- dispatchEvent(new ProgressEvent(ProgressEvent.SOCKET_DATA, false, false, this._bytes.bytesAvailable, this._bytes.length));
- }
-
- public function get peerConnectAcknowledged():Boolean
- {
- return _peerConnectAcknowledged;
- }
-
- public function setPeerConnectAcknowledged():void
- {
- _peerConnectAcknowledged = true;
- dispatchEvent(new Event(PEER_CONNECT_ACKNOWLEDGED));
- }
-
- public function get peerID():String
- {
- return _peerID;
- }
-
- public function set peerID(id:String):void
- {
- _peerID = id;
- }
-
-}
-
-class RTMFPConnectionPair extends EventDispatcher
-{
- private var circon:NetConnection;
-
- private var tor_addr:Object;
-
- private var s_r:RTMFPSocket;
-
- private var s_t:Socket;
-
- private var output_text:TextField;
-
- /* Put a string to the screen. */
- public function puts(s:String):void
- {
- output_text.appendText(s + "\n");
- output_text.scrollV = output_text.maxScrollV;
- }
-
- public function RTMFPConnectionPair(circon:NetConnection, tor_addr:Object, output_text:TextField)
- {
- this.circon = circon;
- this.tor_addr = tor_addr;
- this.output_text = output_text;
- }
-
- public function connect(clientID:String, rtmfp_data:String, timeout:uint):void
- {
- s_r = new RTMFPSocket(circon, output_text);
- s_r.addEventListener(Event.CONNECT, rtmfp_connect_event);
- s_r.addEventListener(Event.UNLOAD, function (e:Event):void {
- dispatchEvent(new Event(Event.UNLOAD));
- });
- s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- /* It's possible that we receive data before we're connected
- * to the tor-side of the connection. In this case we want
- * to buffer the data. */
- if(!s_t.connected) {
- puts("MASSIVE ATTACK!");
- } else {
- var bytes:ByteArray = new ByteArray();
- s_r.readBytes(bytes, 0, e.bytesLoaded);
- puts("RTMFPConnectionPair: RTMFP: read " + bytes.length + " bytes.");
- s_t.writeBytes(bytes);
- }
- });
- s_r.addEventListener(Event.CLOSE, rtmfp_close_event);
- s_r.connect(clientID, rtmfp_data, timeout);
- }
-
- public function listen(rtmfp_data:String):void
- {
- s_r = new RTMFPSocket(circon, output_text);
- s_r.addEventListener(Event.CONNECT, rtmfp_connect_event);
- s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- /* It's possible that we receive data before we're connected
- * to the tor-side of the connection. In this case we want
- * to buffer the data. */
- if(!s_t.connected) {
- puts("MASSIVE ATTACK!");
- } else {
- var bytes:ByteArray = new ByteArray();
- s_r.readBytes(bytes, 0, e.bytesLoaded);
- puts("RTMFPConnectionPair: RTMFP: read " + bytes.length + " bytes.");
- s_t.writeBytes(bytes);
- }
- });
-
- s_r.addEventListener(Event.CLOSE, rtmfp_close_event);
- s_r.listen(rtmfp_data);
- }
-
- private function rtmfp_connect_event(e:Event):void
- {
- puts("RTMFPConnectionPair: RTMFPSocket side connected!");
- puts("RTMFPConnectionPair: setting up tor side connection...");
-
- /* Setup tor connection linked to RTMFPSocket. */
- s_t = new Socket();
- s_t.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("RTMFPConnectionPair: Tor: connected to " + tor_addr.host + ":" + tor_addr.port + ".");
- dispatchEvent(new Event(Event.CONNECT));
- });
- s_t.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("RTMFPConnectionPair: Tor: closed connection.");
- /* Close other side of connection pair if it is open and
- * dispatch close event. */
- if(s_r.connected)
- s_r.close();
- dispatchEvent(new Event(Event.CLOSE));
- });
- s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- var bytes:ByteArray = new ByteArray();
- s_t.readBytes(bytes, 0, e.bytesLoaded);
- puts("RTMFPConnectionPair: Tor: read " + bytes.length + " bytes.");
- s_r.writeBytes(bytes);
- });
- s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- puts("RTMFPConnectionPair: Tor: I/O error: " + e.text + ".");
- });
- s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- puts("RTMFPConnectionPair: Tor: security error: " + e.text + ".");
- });
-
- s_t.connect(tor_addr.host, tor_addr.port);
- }
-
- private function rtmfp_close_event(e:Event):void
- {
- puts("RTMFPConnectionPair: RTMFPSocket closed connection");
- /* Close other side of connection pair if it is open and dispatch
- * close event. */
- if(s_t.connected)
- s_t.close();
- dispatchEvent(new Event(Event.CLOSE));
- }
-
-}
1
0
commit 147a34c11d54b7b4470c8d65448cb38d5c3bbf2b
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 09:48:21 2011 -0700
Rearrange Makefile.
---
Makefile | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 72f5162..6c11397 100644
--- a/Makefile
+++ b/Makefile
@@ -4,10 +4,10 @@ TARGETS = swfcat.swf
all: $(TARGETS)
+swfcat.swf: *.as badge.png
+
%.swf: %.as
$(MXMLC) -output $@ -static-link-runtime-shared-libraries -define=RTMFP::CIRRUS_KEY,\"$(CIRRUS_KEY)\" $<
-swfcat.swf: *.as badge.png
-
clean:
rm -f $(TARGETS)
1
0

[flashproxy/master] Switching swfcat.as to point to David's facilitator by default instead of Nate's
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit c16f7d998686c84d30b4f6e4177659e3845888b7
Author: Nate Hardison <hardison(a)stanford.edu>
Date: Thu Jun 9 17:59:57 2011 -0700
Switching swfcat.as to point to David's facilitator by default instead of Nate's
---
swfcat.as | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index 627a3cd..1bb2ff5 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -27,9 +27,9 @@ package
private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
- /* Nate's facilitator -- serves a crossdomain policy */
+ /* David's facilitator. */
private const DEFAULT_FACILITATOR_ADDR:Object = {
- host: "128.12.179.80",
+ host: "173.255.221.44",
port: 9002
};
1
0
commit f2e878f6e17965b338094c0eb28106b4ae55633f
Merge: c16f7d9 dd7cfb9
Author: David Fifield <david(a)bamsoftware.com>
Date: Fri Jun 10 06:41:33 2011 -0700
Merge branch 'master' into rtmfp
Conflicts:
README
facilitator.py
swfcat.as
FacilitatorSocket.as | 39 +++++------
ProxyPair.as | 27 +++++----
README | 16 +++--
SQSProxyPair.as | 17 +----
TCPProxyPair.as | 17 +----
connector.py | 2 +-
design.txt | 28 ++++----
events/FacilitatorSocketEvent.as | 4 +-
facilitator.py | 130 +++++++++++++++++++++++++-------------
swfcat.as | 30 +--------
10 files changed, 157 insertions(+), 153 deletions(-)
diff --cc FacilitatorSocket.as
index 3930fea,0000000..70325c1
mode 100644,000000..100644
--- a/FacilitatorSocket.as
+++ b/FacilitatorSocket.as
@@@ -1,103 -1,0 +1,100 @@@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.HTTPStatusEvent;
+ import flash.events.IOErrorEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.URLLoader;
+ import flash.net.URLLoaderDataFormat;
+ import flash.net.URLRequest;
+ import flash.net.URLRequestMethod;
+ import flash.net.URLVariables;
+
+ import events.FacilitatorSocketEvent;
+
+ [Event(name=FacilitatorSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATION_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATION_RECEIVED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATIONS_EMPTY, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ public class FacilitatorSocket extends EventDispatcher
+ {
+ private var host:String;
+ private var port:uint;
+
+ public function FacilitatorSocket(host:String, port:uint)
+ {
+ this.host = host;
+ this.port = port;
+ }
+
+ public function get_registration():void
+ {
+ make_request(URLRequestMethod.GET);
+ }
+
+ public function post_registration(registration_data:String):void
+ {
+ var data:URLVariables = new URLVariables();
+ data.client = registration_data;
+ make_request(URLRequestMethod.POST, data);
+ }
+
+ private function fail():void
+ {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_FAILED));
+ }
+
+ private function make_request(method:String, data:URLVariables = null):void
+ {
- var request:URLRequest = new URLRequest(url)
++ var request:URLRequest;
++ var loader:URLLoader;
++
++ loader = new URLLoader();
++ /* Get the x-www-form-encoded-values. */
++ loader.dataFormat = URLLoaderDataFormat.VARIABLES;
++ loader.addEventListener(Event.COMPLETE, on_complete_event);
++ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
++ loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
++
++ request = new URLRequest(url);
+ request.data = data;
+ request.method = method;
-
- var url_loader:URLLoader = new URLLoader();
- url_loader = new URLLoader();
- url_loader.dataFormat = URLLoaderDataFormat.VARIABLES;
-
- url_loader.addEventListener(Event.COMPLETE, on_complete_event);
- url_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, on_http_status_event);
- url_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
- url_loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
-
- url_loader.load(request);
++ loader.load(request);
+ }
+
+ private function on_complete_event(event:Event):void
+ {
+ try {
+ var client_id:String = event.target.data.client;
- if (client_id == "Registration list empty") {
++ var relay_addr:String = event.target.data.relay;
++ if (client_id == "") {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY));
+ } else {
- dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id));
++ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id, relay_addr));
+ }
+ } catch (e:Error) {
+ /* error is thrown for POST when we don't care about
+ the response anyways */
+ }
+
+ event.target.close()
+ }
+
- private function on_http_status_event(event:HTTPStatusEvent):void
- {
- /* empty for now */
- }
-
+ private function on_io_error_event(event:IOErrorEvent):void
+ {
+ fail();
+ }
+
+ private function on_security_error_event(event:SecurityErrorEvent):void
+ {
+ fail();
+ }
+
+ private function get url():String
+ {
- return "http://" + host + ":" + port;
++ return "http://" + encodeURIComponent(host)
++ + ":" + encodeURIComponent(port.toString()) + "/";
+ }
+ }
- }
++}
diff --cc ProxyPair.as
index 75ae901,0000000..6ca60ef
mode 100644,000000..100644
--- a/ProxyPair.as
+++ b/ProxyPair.as
@@@ -1,273 -1,0 +1,276 @@@
+package
+{
+ import flash.errors.IllegalOperationError;
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
++ import flash.events.TextEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+ import flash.utils.clearTimeout;
+ import flash.utils.setTimeout;
+
+ import swfcat;
+
+ public class ProxyPair extends EventDispatcher
+ {
+ private var ui:swfcat;
+
+ protected var client_addr:Object;
+
+ /* Not defined here: subclasses should define their own
+ * protected var client_socket:Object;
+ */
+
+ private var c2r_schedule:Array;
+
+ private var relay_addr:Object;
+ private var relay_socket:Socket;
+ private var r2c_schedule:Array;
+
+ // Bytes per second. Set to undefined to disable limit.
+ private const RATE_LIMIT:Number = undefined; //10000;
+ // Seconds.
+ private const RATE_LIMIT_HISTORY:Number = 5.0;
+
+ private var rate_limit:RateLimit;
+
+ // Callback id.
+ private var flush_id:uint;
+
+ public function ProxyPair(self:ProxyPair, ui:swfcat)
+ {
+ if (self != this) {
+ //only a subclass can pass a valid reference to self
+ throw new IllegalOperationError("ProxyPair cannot be instantiated directly.");
+ }
+
+ this.ui = ui;
+ this.c2r_schedule = new Array();
+ this.r2c_schedule = new Array();
+
+ if (RATE_LIMIT)
+ rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
+ else
+ rate_limit = new RateUnlimit();
+
+ setup_relay_socket();
+
+ /* client_socket setup should be taken */
+ /* care of in the subclass constructor */
+ }
+
+ public function close():void
+ {
+ if (relay_socket != null && relay_socket.connected) {
+ relay_socket.close();
+ }
+
+ /* subclasses should override to close */
+ /* their client_socket according to impl. */
+ }
+
+ public function get connected():Boolean
+ {
+ return (relay_socket != null && relay_socket.connected);
+
+ /* subclasses should override to check */
+ /* connectivity of their client_socket. */
+ }
+
+ public function set client(client_addr:Object):void
+ {
+ /* subclasses should override to */
+ /* connect the client_socket here */
+ }
+
+ public function set relay(relay_addr:Object):void
+ {
+ this.relay_addr = relay_addr;
+ log("Relay: connecting to " + relay_addr.host + ":" + relay_addr.port + ".");
+ relay_socket.connect(relay_addr.host, relay_addr.port);
+ }
+
+ protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ /* No-op: must be overridden by subclasses */
+ }
++
++ protected function socket_error(message:String):Function
++ {
++ return function(e:Event):void {
++ if (e is TextEvent)
++ log(message + ": " + (e as TextEvent).text + ".");
++ else
++ log(message + ".");
++ close();
++ };
++ }
+
+ private function setup_relay_socket():void
+ {
+ relay_socket = new Socket();
+ relay_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Relay: connected to " + relay_addr.host + ":" + relay_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
- relay_socket.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Relay: closed connection.");
- close();
- });
- relay_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Relay: I/O error: " + e.text + ".");
- close();
- });
- relay_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Relay: security error: " + e.text + ".");
- close();
- });
++ relay_socket.addEventListener(Event.CLOSE, socket_error("Relay: closed"));
++ relay_socket.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Relay: I/O error"))
++ relay_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Relay: security error"))
+ relay_socket.addEventListener(ProgressEvent.SOCKET_DATA, relay_to_client);
+ }
+
+ protected function client_to_relay(e:ProgressEvent):void
+ {
+ c2r_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ private function relay_to_client(e:ProgressEvent):void
+ {
+ r2c_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ /* Send as much data as the rate limit currently allows. */
+ private function flush():void
+ {
+ if (flush_id)
+ clearTimeout(flush_id);
+ flush_id = undefined;
+
+ if (!connected)
+ /* Can't do anything until connected. */
+ return;
+
+ while (!rate_limit.is_limited() && (c2r_schedule.length > 0 || r2c_schedule.length > 0)) {
+ var num_bytes:uint;
+
+ if (c2r_schedule.length > 0) {
+ num_bytes = c2r_schedule.shift();
+ transfer_bytes(null, relay_socket, num_bytes);
+ rate_limit.update(num_bytes);
+ }
+
+ if (r2c_schedule.length > 0) {
+ num_bytes = r2c_schedule.shift();
+ transfer_bytes(relay_socket, null, num_bytes);
+ rate_limit.update(num_bytes);
+ }
+ }
+
+ /* Call again when safe, if necessary. */
+ if (c2r_schedule.length > 0 || r2c_schedule.length > 0)
+ flush_id = setTimeout(flush, rate_limit.when() * 1000);
+ }
+
+ /* Helper function to write output to the
+ * swfcat console. Set as protected for
+ * subclasses */
+ protected function log(s:String):void
+ {
+ ui.puts(s);
+ }
+ }
+}
+
+import flash.utils.getTimer;
+
+class RateLimit
+{
+ public function RateLimit()
+ {
+ }
+
+ public function update(n:Number):Boolean
+ {
+ return true;
+ }
+
+ public function when():Number
+ {
+ return 0.0;
+ }
+
+ public function is_limited():Boolean
+ {
+ return false;
+ }
+}
+
+class RateUnlimit extends RateLimit
+{
+ public function RateUnlimit()
+ {
+ }
+
+ public override function update(n:Number):Boolean
+ {
+ return true;
+ }
+
+ public override function when():Number
+ {
+ return 0.0;
+ }
+
+ public override function is_limited():Boolean
+ {
+ return false;
+ }
+}
+
+class BucketRateLimit extends RateLimit
+{
+ private var amount:Number;
+ private var capacity:Number;
+ private var time:Number;
+ private var last_update:uint;
+
+ public function BucketRateLimit(capacity:Number, time:Number)
+ {
+ this.amount = 0.0;
+ /* capacity / time is the rate we are aiming for. */
+ this.capacity = capacity;
+ this.time = time;
+ this.last_update = getTimer();
+ }
+
+ private function age():void
+ {
+ var now:uint;
+ var delta:Number;
+
+ now = getTimer();
+ delta = (now - last_update) / 1000.0;
+ last_update = now;
+
+ amount -= delta * capacity / time;
+ if (amount < 0.0)
+ amount = 0.0;
+ }
+
+ public override function update(n:Number):Boolean
+ {
+ age();
+ amount += n;
+
+ return amount <= capacity;
+ }
+
+ public override function when():Number
+ {
+ age();
+ return (amount - capacity) / (capacity / time);
+ }
+
+ public override function is_limited():Boolean
+ {
+ age();
+ return amount > capacity;
+ }
+}
diff --cc README
index 05cd676,b4b1d0e..0e2a0eb
--- a/README
+++ b/README
@@@ -102,26 -81,25 +102,30 @@@ changing pool of addresses
== Design notes
- The Tor relay address is hardcoded in rtmfpcat.as. It could be any relay,
- with the caveat that the server also has to serve a crossdomain policy.
+ Any Tor relay can be used, as long as it also serves a crossdomain
+ policy.
- Client rtmfpcats register with the facilitator by sending an HTTP-like message:
-The Tor client needs to be able to listen for an incoming connection,
-which generally means not being behind NAT.
-
+ Clients register with the facilitator by sending an HTTP message:
POST / HTTP/1.0\r\n
\r\n
- client=:9000
+ client=<CIRRUS-CLIENT-ID>
+
+The <CIRRUS-CLIENT-ID> is returned by Adobe's developer Cirrus server
+as soon as the rtfmpcat can connect to it. Each rtmfpcat needs to connect
+to a server like this to get one of these client IDs, since the Cirrus
+server uses these to coordinate RTMFP connections (including NAT punching).
+The need to communicate with a Cirrus server in addition to a facilitator is
+one of the major weaknesses of this design.
+
- The proxy rtmfpcat gets a client id using something like HTTP:
+ The Flash proxy also gets a client address over HTTP:
GET / HTTP/1.0\r\n
\r\n
- The server sends back an id specification (no HTTP header):
- 51ae8ed56c3705e4ad3755cdd3328c27720984778bfff71d9ec9f2647331d39b
+ The server sends back address specifications of a client and a relay in
+ an HTTP respose.
+ HTTP/1.0 200 OK\r\n
+ Server: BaseHTTP/0.3 Python/2.5.2\r\n
+ \r\n
- client=1.2.3.4%3A9000&relay=9.9.9.9:9001
++ client=<CIRRUS-CLIENT-ID>&relay=9.9.9.9:9001
== ActionScript programming
diff --cc SQSProxyPair.as
index 54f763d,0000000..20a6a65
mode 100644,000000..100644
--- a/SQSProxyPair.as
+++ b/SQSProxyPair.as
@@@ -1,86 -1,0 +1,77 @@@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+
+ public class SQSProxyPair extends ProxyPair
+ {
+ private var client_socket:Socket;
+
+ public function SQSProxyPair(ui:swfcat)
+ {
+ super(this, ui);
+
+ log("Starting SQS proxy pair");
+ setup_client_socket();
+ }
+
+ override public function set client(client_addr:Object):void
+ {
+ this.client_addr = client_addr;
+ log("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
+ client_socket.connect(client_addr.host, client_addr.port);
+ }
+
+ override public function close():void
+ {
+ super.close();
+ if (client_socket != null && client_socket.connected) {
+ client_socket.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ override public function get connected():Boolean
+ {
+ return (super.connected && client_socket != null && client_socket.connected);
+ }
+
+ override protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ var bytes:ByteArray = new ByteArray();
+
+ if (src == null) {
+ src = client_socket;
+ }
+
+ if (dst == null) {
+ dst = client_socket;
+ }
+
+ Socket(src).readBytes(bytes, 0, num_bytes);
+ log("SQSProxyPair: transferring " + num_bytes + " bytes.");
+ Socket(dst).writeBytes(bytes);
+ }
+
+ private function setup_client_socket():void
+ {
+ client_socket = new Socket();
+
+ client_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Client: connected to " + client_addr.host + ":" + client_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
- client_socket.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Client: closed.");
- close();
- });
- client_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Client: I/O error: " + e.text + ".");
- close();
- });
- client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Client: security error: " + e.text + ".");
- close();
- });
++ client_socket.addEventListener(Event.CLOSE, socket_error("Client: closed"));
++ client_socket.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Client: I/O error"));
++ client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Client: security error"))
+ client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+ }
+ }
- }
++}
diff --cc TCPProxyPair.as
index b81af3e,0000000..de18dd6
mode 100644,000000..100644
--- a/TCPProxyPair.as
+++ b/TCPProxyPair.as
@@@ -1,86 -1,0 +1,77 @@@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+
+ public class TCPProxyPair extends ProxyPair
+ {
+ private var client_socket:Socket;
+
+ public function TCPProxyPair(ui:swfcat)
+ {
+ super(this, ui);
+
+ log("Starting TCP proxy pair");
+ setup_client_socket();
+ }
+
+ override public function set client(client_addr:Object):void
+ {
+ this.client_addr = client_addr;
+ log("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
+ client_socket.connect(client_addr.host, client_addr.port);
+ }
+
+ override public function close():void
+ {
+ super.close();
+ if (client_socket != null && client_socket.connected) {
+ client_socket.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ override public function get connected():Boolean
+ {
+ return (super.connected && client_socket != null && client_socket.connected);
+ }
+
+ override protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ var bytes:ByteArray = new ByteArray();
+
+ if (src == null) {
+ src = client_socket;
+ }
+
+ if (dst == null) {
+ dst = client_socket;
+ }
+
+ Socket(src).readBytes(bytes, 0, num_bytes);
+ log("TCPProxyPair: transferring " + num_bytes + " bytes.");
+ Socket(dst).writeBytes(bytes);
+ }
+
+ private function setup_client_socket():void
+ {
+ client_socket = new Socket();
+
+ client_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Client: connected to " + client_addr.host + ":" + client_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
- client_socket.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Client: closed.");
- close();
- });
- client_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Client: I/O error: " + e.text + ".");
- close();
- });
- client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Client: security error: " + e.text + ".");
- close();
- });
++ client_socket.addEventListener(Event.CLOSE, socket_error("Client: closed"));
++ client_socket.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Client: I/O error"));
++ client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Client: security error"))
+ client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+ }
+ }
- }
++}
diff --cc events/FacilitatorSocketEvent.as
index 9fc478b,0000000..5787309
mode 100644,000000..100644
--- a/events/FacilitatorSocketEvent.as
+++ b/events/FacilitatorSocketEvent.as
@@@ -1,22 -1,0 +1,24 @@@
+package events
+{
+ import flash.events.Event;
+
+ public class FacilitatorSocketEvent extends Event
+ {
+ public static const CONNECT_CLOSED:String = "connectClosed";
+ public static const CONNECT_FAILED:String = "connectFailed";
+ public static const CONNECT_SUCCESS:String = "connectSuccess";
+ public static const REGISTRATION_RECEIVED:String = "registrationReceived";
+ public static const REGISTRATION_FAILED:String = "registrationFailed";
+ public static const REGISTRATIONS_EMPTY:String = "registrationsEmpty";
+
+ public var client:String;
++ public var relay:String;
+
- public function FacilitatorSocketEvent(type:String, client:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
++ public function FacilitatorSocketEvent(type:String, client:String = null, relay:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
+ {
+ super(type, bubbles, cancelable);
+ this.client = client;
++ this.relay = relay;
+ }
+ }
+}
diff --cc swfcat.as
index 1bb2ff5,4aa430b..dd2396d
--- a/swfcat.as
+++ b/swfcat.as
@@@ -5,64 -5,33 +5,56 @@@ packag
import flash.display.StageScaleMode;
import flash.text.TextField;
import flash.text.TextFormat;
- import flash.net.Socket;
- import flash.net.URLLoader;
- import flash.net.URLLoaderDataFormat;
- import flash.net.URLRequest;
import flash.events.Event;
- import flash.events.IOErrorEvent;
- import flash.events.ProgressEvent;
- import flash.events.SecurityErrorEvent;
- import flash.utils.ByteArray;
import flash.utils.setTimeout;
+ import FacilitatorSocket;
+ import events.FacilitatorSocketEvent;
+
+ import ProxyPair;
+ import RTMFPProxyPair;
+ import SQSProxyPair;
+ import TCPProxyPair;
+
+ import rtmfp.CirrusSocket;
+ import rtmfp.events.CirrusSocketEvent;
+
public class swfcat extends Sprite
{
+ /* Adobe's Cirrus server for RTMFP connections.
+ The Cirrus key is defined at compile time by
+ reading from the CIRRUS_KEY environment var. */
+ private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
+ private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
+
- /* David's facilitator. */
private const DEFAULT_FACILITATOR_ADDR:Object = {
- host: "173.255.221.44",
+ host: "tor-facilitator.bamsoftware.com",
port: 9002
};
-
- private const MAX_NUM_PROXY_PAIRS:uint = 1;
-
- // Milliseconds.
- private const FACILITATOR_POLL_INTERVAL:int = 10000;
-
- // Bytes per second. Set to undefined to disable limit.
- public const RATE_LIMIT:Number = undefined;
- // Seconds.
- private const RATE_LIMIT_HISTORY:Number = 5.0;
+
+ /* Default Tor client to use in case of RTMFP connection */
+ private const DEFAULT_TOR_CLIENT_ADDR:Object = {
+ host: "127.0.0.1",
+ port: 9002
+ };
+
- /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
- crossdomain policy. */
- private const DEFAULT_TOR_RELAY_ADDR:Object = {
- host: "173.255.221.44",
- port: 9001
- };
-
+ /* Poll facilitator every 10 sec */
+ private const DEFAULT_FAC_POLL_INTERVAL:uint = 10000;
+
+ // Socket to Cirrus server
+ private var s_c:CirrusSocket;
+ // Socket to facilitator.
+ private var s_f:FacilitatorSocket;
+ // Handle local-remote traffic
+ private var p_p:ProxyPair;
+
+ private var client_id:String;
+ private var proxy_pair_factory:Function;
+
+ private var proxy_pairs:Array;
+
+ private var debug_mode:Boolean;
+ private var proxy_mode:Boolean;
/* TextField for debug output. */
private var output_text:TextField;
@@@ -97,57 -133,24 +89,39 @@@
private function loaderinfo_complete(e:Event):void
{
var fac_spec:String;
+ var relay_spec:String;
- puts("Parameters loaded.");
-
- if (this.loaderInfo.parameters["debug"])
+ debug_mode = (this.loaderInfo.parameters["debug"] != null)
+ proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
+ if (proxy_mode && !debug_mode) {
+ badge = new InternetFreedomBadge(this);
+ badge.display();
+ } else {
+ output_text = new TextField();
+ output_text.width = stage.stageWidth;
+ output_text.height = stage.stageHeight;
+ output_text.background = true;
+ output_text.backgroundColor = 0x001f0f;
+ output_text.textColor = 0x44cc44;
addChild(output_text);
- else {
- addChild(new BadgeImage());
- /* Tried unsuccessfully to add counter to badge. */
- /* For now, need two addChilds :( */
- addChild(tot_client_count_tf);
- addChild(cur_client_count_tf);
}
-
- fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
- if (!fac_addr) {
- puts("Error: Facilitator spec must be in the form \"host:port\".");
- return;
+
+ puts("Starting: parameters loaded.");
+
+ /* TODO: use this to have multiple proxies going at once */
+ proxy_pairs = new Array();
+
+ fac_spec = this.loaderInfo.parameters["facilitator"];
+ if (fac_spec) {
+ 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;
+ }
+ } else {
+ fac_addr = DEFAULT_FACILITATOR_ADDR;
}
-
- /* TODO: modify this for the client so that it can specify
- a relay for the proxy to use */
- relay_spec = this.loaderInfo.parameters["relay"];
- if (relay_spec) {
- puts("Relay spec: \"" + relay_spec + "\"");
- relay_addr = parse_addr_spec(relay_spec);
- if (!relay_addr) {
- puts("Error: Relay spec must be in the form \"host:port\".");
- return;
- }
- } else {
- if (proxy_mode) {
- relay_addr = DEFAULT_TOR_RELAY_ADDR;
- } else {
- relay_addr = DEFAULT_TOR_CLIENT_ADDR;
- }
- }
main();
}
@@@ -155,132 -158,98 +129,134 @@@
/* The main logic begins here, after start-up issues are taken care of. */
private function main():void
{
- var fac_url:String;
- var loader:URLLoader;
-
- if (num_proxy_pairs >= MAX_NUM_PROXY_PAIRS) {
- setTimeout(main, FACILITATOR_POLL_INTERVAL);
- return;
+ if (proxy_mode) {
+ establish_facilitator_connection();
+ } else {
+ establish_cirrus_connection();
}
+ }
- loader = new URLLoader();
- /* Get the x-www-form-urlencoded values. */
- loader.dataFormat = URLLoaderDataFormat.VARIABLES;
- loader.addEventListener(Event.COMPLETE, fac_complete);
- loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- puts("Facilitator: I/O error: " + e.text + ".");
+ private function establish_cirrus_connection():void
+ {
+ s_c = new CirrusSocket();
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_SUCCESS, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: connected with id " + s_c.id + ".");
+ if (proxy_mode) {
+ start_proxy_pair();
+ s_c.send_hello(client_id);
+ } else {
+ establish_facilitator_connection();
+ }
});
- loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- puts("Facilitator: security error: " + e.text + ".");
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
+ puts("Error: failed to connect to Cirrus.");
});
-
- fac_url = "http://" + encodeURIComponent(fac_addr.host)
- + ":" + encodeURIComponent(fac_addr.port) + "/";
- puts("Facilitator: connecting to " + fac_url + ".");
- loader.load(new URLRequest(fac_url));
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: closed connection.");
+ });
+ s_c.addEventListener(CirrusSocketEvent.HELLO_RECEIVED, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: received hello from peer " + e.peer);
+
+ /* don't bother if we already have a proxy going */
+ if (p_p != null && p_p.connected) {
+ return;
+ }
+
+ /* if we're in proxy mode, we should have already set
+ up a proxy pair */
+ if (!proxy_mode) {
++ relay_addr = DEFAULT_TOR_CLIENT_ADDR;
+ proxy_pair_factory = rtmfp_proxy_pair_factory;
+ start_proxy_pair();
+ s_c.send_hello(e.peer);
+ } else if (!debug_mode && badge != null) {
+ badge.total_proxy_pairs++;
+ badge.num_proxy_pairs++;
+ }
+
+ p_p.client = {peer: e.peer, stream: e.stream};
+ });
+
+ s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
}
- private function fac_complete(e:Event):void
+ private function establish_facilitator_connection():void
{
- var loader:URLLoader;
- var client_spec:String;
- var client_addr:Object;
- var relay_spec:String;
- var relay_addr:Object;
- var proxy_pair:Object;
-
- setTimeout(main, FACILITATOR_POLL_INTERVAL);
-
- loader = e.target as URLLoader;
- client_spec = loader.data.client;
- if (client_spec == "") {
- puts("No clients.");
- return;
- } else if (!client_spec) {
- puts("Error: missing \"client\" in response.");
- return;
- }
- relay_spec = loader.data.relay;
- if (!relay_spec) {
- puts("Error: missing \"relay\" in response.");
- return;
- }
- puts("Facilitator: got client:\"" + client_spec + "\" "
- + "relay:\"" + relay_spec + "\".");
-
- client_addr = parse_addr_spec(client_spec);
- if (!client_addr) {
- puts("Error: Client spec must be in the form \"host:port\".");
- return;
- }
- relay_addr = parse_addr_spec(relay_spec);
- if (!client_addr) {
- puts("Error: Relay spec must be in the form \"host:port\".");
- return;
+ s_f = new FacilitatorSocket(fac_addr.host, fac_addr.port);
+ s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
+ puts("Facilitator: connect failed.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+
+ if (proxy_mode) {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void {
+ var client_addr:Object = parse_addr_spec(e.client);
++ relay_addr = parse_addr_spec(e.relay);
+ if (client_addr == null) {
+ puts("Facilitator: got registration " + e.client);
+ proxy_pair_factory = rtmfp_proxy_pair_factory;
+ if (s_c == null || !s_c.connected) {
+ client_id = e.client;
+ establish_cirrus_connection();
+ } else {
+ start_proxy_pair();
+ s_c.send_hello(e.client);
+ }
+ } else {
+ proxy_pair_factory = tcp_proxy_pair_factory;
+ start_proxy_pair();
+ p_p.client = client_addr;
+ }
+ });
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATIONS_EMPTY, function (e:Event):void {
+ puts("Facilitator: no registrations available.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+ puts("Facilitator: getting registration.");
+ s_f.get_registration();
+ } else {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
+ puts("Facilitator: registration failed.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+ puts("Facilitator: posting registration.");
+ s_f.post_registration(s_c.id);
}
-
- num_proxy_pairs++;
- total_proxy_pairs++;
- /* Update the client count on the badge. */
- update_client_count();
-
- proxy_pair = new ProxyPair(this, client_addr, relay_addr);
- proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
- proxy_pair.log("Complete.");
-
- num_proxy_pairs--;
- /* Update the client count on the badge. */
- update_client_count();
+ }
+
+ private function start_proxy_pair():void
+ {
+ p_p = proxy_pair_factory();
+ p_p.addEventListener(Event.CONNECT, function (e:Event):void {
+ puts("ProxyPair: connected!");
});
- proxy_pair.connect();
-
+ p_p.addEventListener(Event.CLOSE, function (e:Event):void {
+ puts("ProxyPair: connection closed.");
+ p_p = null;
+ if (proxy_mode && !debug_mode && badge != null) {
+ badge.num_proxy_pairs--;
+ }
+ establish_facilitator_connection();
+ });
+ p_p.relay = relay_addr;
+ }
+
+ private function rtmfp_proxy_pair_factory():ProxyPair
+ {
+ return new RTMFPProxyPair(this, s_c, s_c.local_stream_name);
+ }
+
+ // currently is the same as TCPProxyPair
+ // could be interesting to see how this works
+ // can't imagine it will work terribly well...
+ private function sqs_proxy_pair_factory():ProxyPair
+ {
+ return new SQSProxyPair(this);
+ }
+
+ private function tcp_proxy_pair_factory():ProxyPair
+ {
+ return new TCPProxyPair(this);
}
/* Parse an address in the form "host:port". Returns an Object with
1
0
commit e9b53ee59b7bc95ea93df01b8f0b4f62ba92e3b2
Author: David Fifield <david(a)bamsoftware.com>
Date: Thu Jun 9 07:14:25 2011 -0700
Make swfcat.swf depend on *.as.
---
Makefile | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
index 4e22e1d..c98c0ee 100644
--- a/Makefile
+++ b/Makefile
@@ -7,5 +7,7 @@ all: $(TARGETS)
%.swf: %.as badge.png
$(MXMLC) -output $@ -static-link-runtime-shared-libraries -define=RTMFP::CIRRUS_KEY,\"$(CIRRUS_KEY)\" $<
+swfcat.swf: *.as badge.png
+
clean:
rm -f $(TARGETS)
1
0

[flashproxy/master] The generic mxmlc rule should not depend on badge.png.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 07db15b16690f5c9855b81969300b7034c215c7e
Author: David Fifield <david(a)bamsoftware.com>
Date: Thu Jun 9 07:23:16 2011 -0700
The generic mxmlc rule should not depend on badge.png.
That's specific to swfcat.
---
Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Makefile b/Makefile
index c98c0ee..72f5162 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ TARGETS = swfcat.swf
all: $(TARGETS)
-%.swf: %.as badge.png
+%.swf: %.as
$(MXMLC) -output $@ -static-link-runtime-shared-libraries -define=RTMFP::CIRRUS_KEY,\"$(CIRRUS_KEY)\" $<
swfcat.swf: *.as badge.png
1
0

12 Jun '11
commit 53fcd931929eba516e39aea4b17cc524b0fa8c78
Author: David Fifield <david(a)bamsoftware.com>
Date: Thu Jun 9 07:15:17 2011 -0700
Fix a global search-and-replace error.
RATE_LIMIT_HISrelayY -> RATE_LIMIT_HISTORY
---
ProxyPair.as | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/ProxyPair.as b/ProxyPair.as
index aef4e2e..75ae901 100644
--- a/ProxyPair.as
+++ b/ProxyPair.as
@@ -32,7 +32,7 @@ package
// Bytes per second. Set to undefined to disable limit.
private const RATE_LIMIT:Number = undefined; //10000;
// Seconds.
- private const RATE_LIMIT_HISrelayY:Number = 5.0;
+ private const RATE_LIMIT_HISTORY:Number = 5.0;
private var rate_limit:RateLimit;
@@ -51,7 +51,7 @@ package
this.r2c_schedule = new Array();
if (RATE_LIMIT)
- rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISrelayY, RATE_LIMIT_HISrelayY);
+ rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
else
rate_limit = new RateUnlimit();
@@ -270,4 +270,4 @@ class BucketRateLimit extends RateLimit
age();
return amount > capacity;
}
-}
\ No newline at end of file
+}
1
0

[flashproxy/master] Merged rtmfpcat with swfcat, now proxy can help TCP and RTMFP clients
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 1d66a5de55e165334cbdd35ad5d38cf4157d9a2a
Author: Nate Hardison <nate(a)rescomp-09-154551.stanford.edu>
Date: Wed Jun 8 23:56:03 2011 -0700
Merged rtmfpcat with swfcat, now proxy can help TCP and RTMFP clients
---
Makefile | 6 +-
ProxyPair.as | 273 +++++++++++++++++++
RTMFPProxyPair.as | 101 +++++++
TCPProxyPair.as | 86 ++++++
connector.py | 4 +-
facilitator.py | 7 +-
rtmfp/ProxyPair.as | 279 -------------------
rtmfp/RTMFPSocket.as | 2 +-
rtmfpcat.as | 353 ------------------------
swfcat.as | 723 ++++++++++++++++++++------------------------------
10 files changed, 756 insertions(+), 1078 deletions(-)
diff --git a/Makefile b/Makefile
index 3595385..4e22e1d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,10 @@
MXMLC ?= mxmlc
-TARGETS = rtmfpcat.swf
+TARGETS = swfcat.swf
all: $(TARGETS)
-swfcat.swf: badge.png
-
-%.swf: %.as
+%.swf: %.as badge.png
$(MXMLC) -output $@ -static-link-runtime-shared-libraries -define=RTMFP::CIRRUS_KEY,\"$(CIRRUS_KEY)\" $<
clean:
diff --git a/ProxyPair.as b/ProxyPair.as
new file mode 100644
index 0000000..aef4e2e
--- /dev/null
+++ b/ProxyPair.as
@@ -0,0 +1,273 @@
+package
+{
+ import flash.errors.IllegalOperationError;
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+ import flash.utils.clearTimeout;
+ import flash.utils.setTimeout;
+
+ import swfcat;
+
+ public class ProxyPair extends EventDispatcher
+ {
+ private var ui:swfcat;
+
+ protected var client_addr:Object;
+
+ /* Not defined here: subclasses should define their own
+ * protected var client_socket:Object;
+ */
+
+ private var c2r_schedule:Array;
+
+ private var relay_addr:Object;
+ private var relay_socket:Socket;
+ private var r2c_schedule:Array;
+
+ // Bytes per second. Set to undefined to disable limit.
+ private const RATE_LIMIT:Number = undefined; //10000;
+ // Seconds.
+ private const RATE_LIMIT_HISrelayY:Number = 5.0;
+
+ private var rate_limit:RateLimit;
+
+ // Callback id.
+ private var flush_id:uint;
+
+ public function ProxyPair(self:ProxyPair, ui:swfcat)
+ {
+ if (self != this) {
+ //only a subclass can pass a valid reference to self
+ throw new IllegalOperationError("ProxyPair cannot be instantiated directly.");
+ }
+
+ this.ui = ui;
+ this.c2r_schedule = new Array();
+ this.r2c_schedule = new Array();
+
+ if (RATE_LIMIT)
+ rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISrelayY, RATE_LIMIT_HISrelayY);
+ else
+ rate_limit = new RateUnlimit();
+
+ setup_relay_socket();
+
+ /* client_socket setup should be taken */
+ /* care of in the subclass constructor */
+ }
+
+ public function close():void
+ {
+ if (relay_socket != null && relay_socket.connected) {
+ relay_socket.close();
+ }
+
+ /* subclasses should override to close */
+ /* their client_socket according to impl. */
+ }
+
+ public function get connected():Boolean
+ {
+ return (relay_socket != null && relay_socket.connected);
+
+ /* subclasses should override to check */
+ /* connectivity of their client_socket. */
+ }
+
+ public function set client(client_addr:Object):void
+ {
+ /* subclasses should override to */
+ /* connect the client_socket here */
+ }
+
+ public function set relay(relay_addr:Object):void
+ {
+ this.relay_addr = relay_addr;
+ log("Relay: connecting to " + relay_addr.host + ":" + relay_addr.port + ".");
+ relay_socket.connect(relay_addr.host, relay_addr.port);
+ }
+
+ protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ /* No-op: must be overridden by subclasses */
+ }
+
+ private function setup_relay_socket():void
+ {
+ relay_socket = new Socket();
+ relay_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Relay: connected to " + relay_addr.host + ":" + relay_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
+ relay_socket.addEventListener(Event.CLOSE, function (e:Event):void {
+ log("Relay: closed connection.");
+ close();
+ });
+ relay_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
+ log("Relay: I/O error: " + e.text + ".");
+ close();
+ });
+ relay_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ log("Relay: security error: " + e.text + ".");
+ close();
+ });
+ relay_socket.addEventListener(ProgressEvent.SOCKET_DATA, relay_to_client);
+ }
+
+ protected function client_to_relay(e:ProgressEvent):void
+ {
+ c2r_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ private function relay_to_client(e:ProgressEvent):void
+ {
+ r2c_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ /* Send as much data as the rate limit currently allows. */
+ private function flush():void
+ {
+ if (flush_id)
+ clearTimeout(flush_id);
+ flush_id = undefined;
+
+ if (!connected)
+ /* Can't do anything until connected. */
+ return;
+
+ while (!rate_limit.is_limited() && (c2r_schedule.length > 0 || r2c_schedule.length > 0)) {
+ var num_bytes:uint;
+
+ if (c2r_schedule.length > 0) {
+ num_bytes = c2r_schedule.shift();
+ transfer_bytes(null, relay_socket, num_bytes);
+ rate_limit.update(num_bytes);
+ }
+
+ if (r2c_schedule.length > 0) {
+ num_bytes = r2c_schedule.shift();
+ transfer_bytes(relay_socket, null, num_bytes);
+ rate_limit.update(num_bytes);
+ }
+ }
+
+ /* Call again when safe, if necessary. */
+ if (c2r_schedule.length > 0 || r2c_schedule.length > 0)
+ flush_id = setTimeout(flush, rate_limit.when() * 1000);
+ }
+
+ /* Helper function to write output to the
+ * swfcat console. Set as protected for
+ * subclasses */
+ protected function log(s:String):void
+ {
+ ui.puts(s);
+ }
+ }
+}
+
+import flash.utils.getTimer;
+
+class RateLimit
+{
+ public function RateLimit()
+ {
+ }
+
+ public function update(n:Number):Boolean
+ {
+ return true;
+ }
+
+ public function when():Number
+ {
+ return 0.0;
+ }
+
+ public function is_limited():Boolean
+ {
+ return false;
+ }
+}
+
+class RateUnlimit extends RateLimit
+{
+ public function RateUnlimit()
+ {
+ }
+
+ public override function update(n:Number):Boolean
+ {
+ return true;
+ }
+
+ public override function when():Number
+ {
+ return 0.0;
+ }
+
+ public override function is_limited():Boolean
+ {
+ return false;
+ }
+}
+
+class BucketRateLimit extends RateLimit
+{
+ private var amount:Number;
+ private var capacity:Number;
+ private var time:Number;
+ private var last_update:uint;
+
+ public function BucketRateLimit(capacity:Number, time:Number)
+ {
+ this.amount = 0.0;
+ /* capacity / time is the rate we are aiming for. */
+ this.capacity = capacity;
+ this.time = time;
+ this.last_update = getTimer();
+ }
+
+ private function age():void
+ {
+ var now:uint;
+ var delta:Number;
+
+ now = getTimer();
+ delta = (now - last_update) / 1000.0;
+ last_update = now;
+
+ amount -= delta * capacity / time;
+ if (amount < 0.0)
+ amount = 0.0;
+ }
+
+ public override function update(n:Number):Boolean
+ {
+ age();
+ amount += n;
+
+ return amount <= capacity;
+ }
+
+ public override function when():Number
+ {
+ age();
+ return (amount - capacity) / (capacity / time);
+ }
+
+ public override function is_limited():Boolean
+ {
+ age();
+ return amount > capacity;
+ }
+}
\ No newline at end of file
diff --git a/RTMFPProxyPair.as b/RTMFPProxyPair.as
new file mode 100644
index 0000000..346d63c
--- /dev/null
+++ b/RTMFPProxyPair.as
@@ -0,0 +1,101 @@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.ProgressEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+
+ import rtmfp.CirrusSocket;
+ import rtmfp.RTMFPSocket;
+ import rtmfp.events.RTMFPSocketEvent;
+
+ public class RTMFPProxyPair extends ProxyPair
+ {
+ private var cirrus_socket:CirrusSocket;
+ private var client_socket:RTMFPSocket;
+ private var listen_stream:String;
+
+ public function RTMFPProxyPair(ui:swfcat, cirrus_socket:CirrusSocket, listen_stream:String)
+ {
+ super(this, ui);
+
+ log("Starting RTMFP proxy pair on stream " + listen_stream);
+
+ this.cirrus_socket = cirrus_socket;
+ this.listen_stream = listen_stream;
+
+ setup_client_socket();
+ }
+
+ override public function set client(client_addr:Object):void
+ {
+ this.client_addr = client_addr;
+ log("Client: connecting to " + client_addr.peer + " on stream " + client_addr.stream + ".");
+ client_socket.connect(client_addr.peer, client_addr.stream);
+ }
+
+ override public function close():void
+ {
+ super.close();
+ if (client_socket != null && client_socket.connected) {
+ client_socket.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ override public function get connected():Boolean
+ {
+ return (super.connected && client_socket != null && client_socket.connected);
+ }
+
+ override protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ var bytes:ByteArray = new ByteArray();
+
+ if (src == null) {
+ src = client_socket;
+ RTMFPSocket(src).readBytes(bytes, 0, num_bytes);
+ log("RTMFPProxyPair: read " + num_bytes + " bytes from client, writing to relay.");
+ Socket(dst).writeBytes(bytes);
+ }
+
+ if (dst == null) {
+ dst = client_socket;
+ Socket(src).readBytes(bytes, 0, num_bytes);
+ log("RTMFPProxyPair: read " + num_bytes + " bytes from relay, writing to client.");
+ RTMFPSocket(dst).writeBytes(bytes);
+ }
+ }
+
+ private function setup_client_socket():void
+ {
+ client_socket = new RTMFPSocket(cirrus_socket);
+ client_socket.addEventListener(RTMFPSocketEvent.CONNECT_FAILED, function (e:RTMFPSocketEvent):void {
+ log("Client: connection failed to " + client_addr.peer + " on stream " + client_addr.stream + ".");
+ });
+ client_socket.addEventListener(RTMFPSocketEvent.CONNECT_SUCCESS, function (e:RTMFPSocketEvent):void {
+ log("Client: connected to " + client_addr.peer + " on stream " + client_addr.stream + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
+ client_socket.addEventListener(RTMFPSocketEvent.PEER_CONNECTED, function (e:RTMFPSocketEvent):void {
+ log("Peer connected.");
+ });
+ client_socket.addEventListener(RTMFPSocketEvent.PEER_DISCONNECTED, function (e:RTMFPSocketEvent):void {
+ log("Client: disconnected from " + client_addr.peer + ".");
+ close();
+ });
+ client_socket.addEventListener(RTMFPSocketEvent.PLAY_STARTED, function (e:RTMFPSocketEvent):void {
+ log("Play started.");
+ });
+ client_socket.addEventListener(RTMFPSocketEvent.PUBLISH_STARTED, function (e:RTMFPSocketEvent):void {
+ log("Publishing started.");
+ });
+ client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+
+ client_socket.listen(listen_stream);
+ }
+ }
+}
\ No newline at end of file
diff --git a/TCPProxyPair.as b/TCPProxyPair.as
new file mode 100644
index 0000000..b81af3e
--- /dev/null
+++ b/TCPProxyPair.as
@@ -0,0 +1,86 @@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+
+ public class TCPProxyPair extends ProxyPair
+ {
+ private var client_socket:Socket;
+
+ public function TCPProxyPair(ui:swfcat)
+ {
+ super(this, ui);
+
+ log("Starting TCP proxy pair");
+ setup_client_socket();
+ }
+
+ override public function set client(client_addr:Object):void
+ {
+ this.client_addr = client_addr;
+ log("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
+ client_socket.connect(client_addr.host, client_addr.port);
+ }
+
+ override public function close():void
+ {
+ super.close();
+ if (client_socket != null && client_socket.connected) {
+ client_socket.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ override public function get connected():Boolean
+ {
+ return (super.connected && client_socket != null && client_socket.connected);
+ }
+
+ override protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ var bytes:ByteArray = new ByteArray();
+
+ if (src == null) {
+ src = client_socket;
+ }
+
+ if (dst == null) {
+ dst = client_socket;
+ }
+
+ Socket(src).readBytes(bytes, 0, num_bytes);
+ log("TCPProxyPair: transferring " + num_bytes + " bytes.");
+ Socket(dst).writeBytes(bytes);
+ }
+
+ private function setup_client_socket():void
+ {
+ client_socket = new Socket();
+
+ client_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Client: connected to " + client_addr.host + ":" + client_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
+ client_socket.addEventListener(Event.CLOSE, function (e:Event):void {
+ log("Client: closed.");
+ close();
+ });
+ client_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
+ log("Client: I/O error: " + e.text + ".");
+ close();
+ });
+ client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ log("Client: security error: " + e.text + ".");
+ close();
+ });
+ client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+ }
+ }
+}
\ No newline at end of file
diff --git a/connector.py b/connector.py
index a683de0..d20a5b6 100755
--- a/connector.py
+++ b/connector.py
@@ -13,7 +13,7 @@ import urllib
import xml.sax.saxutils
DEFAULT_REMOTE_ADDRESS = "127.0.0.1"
-DEFAULT_REMOTE_PORT = 3333
+DEFAULT_REMOTE_PORT = 9002
DEFAULT_LOCAL_ADDRESS = "127.0.0.1"
DEFAULT_LOCAL_PORT = 9001
DEFAULT_FACILITATOR_PORT = 9002
@@ -281,7 +281,7 @@ def register():
spec = format_addr((None, options.remote_addr[1]))
log(u"Registering \"%s\" with %s." % (spec, format_addr(options.facilitator_addr)))
http = httplib.HTTPConnection(*options.facilitator_addr)
- http.request("POST", "/", urllib.urlencode({"client": spec}))
+ http.request("POST", "/", urllib.urlencode({"client": spec}), {"Content-Type":"application/x-www-form-urlencoded"})
http.close()
return True
diff --git a/facilitator.py b/facilitator.py
index 0ea86a1..d6c598d 100755
--- a/facilitator.py
+++ b/facilitator.py
@@ -11,6 +11,7 @@ import sys
import threading
import time
import urllib
+import xml.sax.saxutils
DEFAULT_ADDRESS = "0.0.0.0"
DEFAULT_PORT = 9002
@@ -216,10 +217,6 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
environ = {'REQUEST_METHOD' : 'POST',
'CONTENT_TYPE' : self.headers['Content-Type']})
- if self.path == "/crossdomain.xml":
- self.send_crossdomain()
- return
-
client_specs = data["client"]
if client_specs is None or client_specs.value is None:
log(u"client %s missing \"client\" param" % format_addr(self.client_address))
@@ -257,7 +254,7 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
crossdomain = """\
<cross-domain-policy>
<allow-access-from domain="*" to-ports="%s"/>
-</cross-domain-policy>\r\n""" % (address[1])
+</cross-domain-policy>\r\n""" % xml.sax.saxutils.escape(str(address[1]))
self.send_response(200)
self.send_header('Content-Type', 'application/xml')
self.send_header('Content-Length', str(len(crossdomain)))
diff --git a/rtmfp/ProxyPair.as b/rtmfp/ProxyPair.as
deleted file mode 100644
index 159abde..0000000
--- a/rtmfp/ProxyPair.as
+++ /dev/null
@@ -1,279 +0,0 @@
-package rtmfp
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.IOErrorEvent;
- import flash.events.ProgressEvent;
- import flash.events.SecurityErrorEvent;
- import flash.net.Socket;
- import flash.utils.ByteArray;
- import flash.utils.clearTimeout;
- import flash.utils.setTimeout;
-
- import rtmfp.CirrusSocket;
- import rtmfp.RTMFPSocket;
- import rtmfp.events.RTMFPSocketEvent;
-
- public class ProxyPair extends EventDispatcher
- {
- private var ui:rtmfpcat;
-
- private var s_p:RTMFPSocket;
- private var s_r:Socket;
-
- private var relay_host:String;
- private var relay_port:uint;
-
- private var p2r_schedule:Array;
- private var r2p_schedule:Array;
-
- // Bytes per second. Set to undefined to disable limit.
- public const RATE_LIMIT:Number = 10000;
- // Seconds.
- private const RATE_LIMIT_HISrelayY:Number = 5.0;
-
- private var rate_limit:RateLimit;
-
- // Callback id.
- private var flush_id:uint;
-
- public function ProxyPair(ui:rtmfpcat, s_c:CirrusSocket, relay_host:String, relay_port:uint)
- {
- this.ui = ui;
- this.relay_host = relay_host;
- this.relay_port = relay_port;
-
- this.p2r_schedule = new Array();
- this.r2p_schedule = new Array();
-
- if (RATE_LIMIT)
- rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISrelayY, RATE_LIMIT_HISrelayY);
- else
- rate_limit = new RateUnlimit();
-
- setup_rtmfp_socket(s_c);
- setup_relay_socket();
- }
-
- public function close():void
- {
- if (s_p.connected) {
- s_p.close();
- }
- if (s_r.connected) {
- s_r.close();
- }
- dispatchEvent(new Event(Event.CLOSE));
- }
-
- public function connect(peer:String, stream:String):void
- {
- s_p.connect(peer, stream);
- }
-
- public function get connected():Boolean
- {
- return (s_p.connected && s_r.connected);
- }
-
- public function listen(stream:String):void
- {
- s_p.listen(stream);
- }
-
- private function setup_rtmfp_socket(s_c:CirrusSocket):void
- {
- s_p = new RTMFPSocket(s_c);
- s_p.addEventListener(RTMFPSocketEvent.CONNECT_FAILED, function (e:RTMFPSocketEvent):void {
- ui.puts("Peering failed.");
- });
- s_p.addEventListener(RTMFPSocketEvent.CONNECT_SUCCESS, function (e:RTMFPSocketEvent):void {
- ui.puts("Peering success.");
- s_r.connect(relay_host, relay_port);
- });
- s_p.addEventListener(RTMFPSocketEvent.PEER_CONNECTED, function (e:RTMFPSocketEvent):void {
- ui.puts("Peer connected.");
- });
- s_p.addEventListener(RTMFPSocketEvent.PEER_DISCONNECTED, function (e:RTMFPSocketEvent):void {
- ui.puts("Peer disconnected.");
- close();
- });
- s_p.addEventListener(RTMFPSocketEvent.PLAY_STARTED, function (e:RTMFPSocketEvent):void {
- ui.puts("Play started.");
- });
- s_p.addEventListener(RTMFPSocketEvent.PUBLISH_STARTED, function (e:RTMFPSocketEvent):void {
- ui.puts("Publishing started.");
- });
- s_p.addEventListener(ProgressEvent.SOCKET_DATA, proxy_to_relay);
- }
-
- private function setup_relay_socket():void
- {
- s_r = new Socket();
- s_r.addEventListener(Event.CONNECT, function (e:Event):void {
- ui.puts("Relay: connected to " + relay_host + ":" + relay_port + ".");
- dispatchEvent(new Event(Event.CONNECT));
- });
- s_r.addEventListener(Event.CLOSE, function (e:Event):void {
- ui.puts("Relay: closed connection.");
- close();
- });
- s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- ui.puts("Relay: I/O error: " + e.text + ".");
- close();
- });
- s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- ui.puts("Relay: security error: " + e.text + ".");
- close();
- });
- s_r.addEventListener(ProgressEvent.SOCKET_DATA, relay_to_proxy);
- }
-
- private function relay_to_proxy(e:ProgressEvent):void
- {
- r2p_schedule.push(e.bytesLoaded);
- flush();
- }
-
- private function proxy_to_relay(e:ProgressEvent):void
- {
- p2r_schedule.push(e.bytesLoaded);
- flush();
- }
-
- /* Send as much data as the rate limit currently allows. */
- private function flush():void
- {
- if (flush_id)
- clearTimeout(flush_id);
- flush_id = undefined;
-
- if (!(s_p.connected && s_r.connected))
- /* Can't do anything until both sockets are connected. */
- return;
-
- while (!rate_limit.is_limited() && (p2r_schedule.length > 0 || r2p_schedule.length > 0)) {
- var numBytes:uint;
- var bytes:ByteArray;
-
- if (p2r_schedule.length > 0) {
- numBytes = p2r_schedule.shift();
- bytes = new ByteArray();
- s_p.readBytes(bytes, 0, numBytes);
- ui.puts("ProxyPair: RTMFP: read " + bytes.length + " bytes.");
- s_r.writeBytes(bytes);
- rate_limit.update(numBytes);
- }
- if (r2p_schedule.length > 0) {
- numBytes = r2p_schedule.shift();
- bytes = new ByteArray();
- s_r.readBytes(bytes, 0, numBytes);
- ui.puts("ProxyPair: Relay: read " + bytes.length + " bytes.");
- s_p.writeBytes(bytes);
- rate_limit.update(numBytes);
- }
- }
-
- /* Call again when safe, if necessary. */
- if (p2r_schedule.length > 0 || r2p_schedule.length > 0)
- flush_id = setTimeout(flush, rate_limit.when() * 1000);
- }
- }
-}
-
-import flash.utils.getTimer;
-
-class RateLimit
-{
- public function RateLimit()
- {
- }
-
- public function update(n:Number):Boolean
- {
- return true;
- }
-
- public function when():Number
- {
- return 0.0;
- }
-
- public function is_limited():Boolean
- {
- return false;
- }
-}
-
-class RateUnlimit extends RateLimit
-{
- public function RateUnlimit()
- {
- }
-
- public override function update(n:Number):Boolean
- {
- return true;
- }
-
- public override function when():Number
- {
- return 0.0;
- }
-
- public override function is_limited():Boolean
- {
- return false;
- }
-}
-
-class BucketRateLimit extends RateLimit
-{
- private var amount:Number;
- private var capacity:Number;
- private var time:Number;
- private var last_update:uint;
-
- public function BucketRateLimit(capacity:Number, time:Number)
- {
- this.amount = 0.0;
- /* capacity / time is the rate we are aiming for. */
- this.capacity = capacity;
- this.time = time;
- this.last_update = getTimer();
- }
-
- private function age():void
- {
- var now:uint;
- var delta:Number;
-
- now = getTimer();
- delta = (now - last_update) / 1000.0;
- last_update = now;
-
- amount -= delta * capacity / time;
- if (amount < 0.0)
- amount = 0.0;
- }
-
- public override function update(n:Number):Boolean
- {
- age();
- amount += n;
-
- return amount <= capacity;
- }
-
- public override function when():Number
- {
- age();
- return (amount - capacity) / (capacity / time);
- }
-
- public override function is_limited():Boolean
- {
- age();
- return amount > capacity;
- }
-}
\ No newline at end of file
diff --git a/rtmfp/RTMFPSocket.as b/rtmfp/RTMFPSocket.as
index bcbee67..4efe702 100644
--- a/rtmfp/RTMFPSocket.as
+++ b/rtmfp/RTMFPSocket.as
@@ -48,7 +48,7 @@ package rtmfp
/* Tears down this RTMFPSocket, closing both its streams.
To be used when destroying this object. */
- public function close():void
+ public function close():void
{
if (send_stream != null) {
s_c.connection.removeEventListener(NetStatusEvent.NET_STATUS, on_stream_disconnection_event);
diff --git a/rtmfpcat.as b/rtmfpcat.as
deleted file mode 100644
index 1876ef9..0000000
--- a/rtmfpcat.as
+++ /dev/null
@@ -1,353 +0,0 @@
-package
-{
- import flash.display.Sprite;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
- import flash.text.TextField;
- import flash.text.TextFormat;
- import flash.events.Event;
- import flash.utils.setTimeout;
-
- import rtmfp.CirrusSocket;
- import rtmfp.FacilitatorSocket;
- import rtmfp.ProxyPair;
- import rtmfp.events.CirrusSocketEvent;
- import rtmfp.events.FacilitatorSocketEvent;
-
- public class rtmfpcat extends Sprite
- {
- /* Adobe's Cirrus server and Nate's key */
- private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
- private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
-
- /* Nate's facilitator -- serves a crossdomain policy */
- private const DEFAULT_FACILITATOR_ADDR:Object = {
- host: "128.12.179.80",
- port: 9002
- };
-
- private const DEFAULT_TOR_CLIENT_ADDR:Object = {
- host: "127.0.0.1",
- port: 3333
- };
-
- /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
- crossdomain policy. */
- private const DEFAULT_TOR_RELAY_ADDR:Object = {
- host: "173.255.221.44",
- port: 9001
- };
-
- /* Poll facilitator every 10 sec */
- private const DEFAULT_FAC_POLL_INTERVAL:uint = 10000;
-
- // Socket to Cirrus server
- private var s_c:CirrusSocket;
- // Socket to facilitator.
- private var s_f:FacilitatorSocket;
- // Handle local-remote traffic
- private var p_p:ProxyPair;
-
- private var proxy_pairs:Array;
-
- private var debug_mode:Boolean;
- private var proxy_mode:Boolean;
-
- /* TextField for debug output. */
- private var output_text:TextField;
-
- /* Badge for display */
- private var badge:InternetFreedomBadge;
-
- private var fac_addr:Object;
- private var relay_addr:Object;
-
- public function rtmfpcat()
- {
- proxy_mode = false;
- debug_mode = false;
-
- // Absolute positioning.
- stage.scaleMode = StageScaleMode.NO_SCALE;
- stage.align = StageAlign.TOP_LEFT;
-
- // Wait until the query string parameters are loaded.
- this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
- }
-
- public function puts(s:String):void
- {
- if (output_text != null) {
- output_text.appendText(s + "\n");
- output_text.scrollV = output_text.maxScrollV;
- }
- }
-
- private function loaderinfo_complete(e:Event):void
- {
- var fac_spec:String;
- var relay_spec:String;
-
- debug_mode = (this.loaderInfo.parameters["debug"] != null)
- proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
- if (proxy_mode && !debug_mode) {
- badge = new InternetFreedomBadge(this);
- badge.display();
- } else {
- output_text = new TextField();
- output_text.width = stage.stageWidth;
- output_text.height = stage.stageHeight;
- output_text.background = true;
- output_text.backgroundColor = 0x001f0f;
- output_text.textColor = 0x44cc44;
- addChild(output_text);
- }
-
- puts("Starting: parameters loaded.");
-
- /* TODO: use this to have multiple proxies going at once */
- proxy_pairs = new Array();
-
- fac_spec = this.loaderInfo.parameters["facilitator"];
- if (fac_spec) {
- 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;
- }
- } else {
- fac_addr = DEFAULT_FACILITATOR_ADDR;
- }
-
- relay_spec = this.loaderInfo.parameters["relay"];
- if (relay_spec) {
- puts("Relay spec: \"" + relay_spec + "\"");
- relay_addr = parse_addr_spec(relay_spec);
- if (!relay_addr) {
- puts("Error: Relay spec must be in the form \"host:port\".");
- return;
- }
- } else {
- if (proxy_mode) {
- relay_addr = DEFAULT_TOR_RELAY_ADDR;
- } else {
- relay_addr = DEFAULT_TOR_CLIENT_ADDR;
- }
- }
-
- main();
- }
-
- /* The main logic begins here, after start-up issues are taken care of. */
- private function main():void
- {
- establish_cirrus_connection();
- }
-
- private function establish_cirrus_connection():void
- {
- s_c = new CirrusSocket();
- s_c.addEventListener(CirrusSocketEvent.CONNECT_SUCCESS, function (e:CirrusSocketEvent):void {
- puts("Cirrus: connected with id " + s_c.id + ".");
- establish_facilitator_connection();
- });
- s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
- puts("Error: failed to connect to Cirrus.");
- });
- s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
- puts("Cirrus: closed connection.");
- });
-
- s_c.addEventListener(CirrusSocketEvent.HELLO_RECEIVED, function (e:CirrusSocketEvent):void {
- puts("Cirrus: received hello from peer " + e.peer);
-
- /* don't bother if we already have a proxy going */
- if (p_p != null && p_p.connected) {
- return;
- }
-
- /* if we're in proxy mode, we should have already set
- up a proxy pair */
- if (!proxy_mode) {
- start_proxy_pair();
- s_c.send_hello(e.peer);
- } else if (!debug_mode && badge != null) {
- badge.total_proxy_pairs++;
- badge.num_proxy_pairs++;
- }
- p_p.connect(e.peer, e.stream);
- });
-
- s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
- }
-
- private function establish_facilitator_connection():void
- {
- s_f = new FacilitatorSocket(fac_addr.host, fac_addr.port);
- s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
- puts("Facilitator: connect failed.");
- setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
- });
-
- if (proxy_mode) {
- s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void {
- puts("Facilitator: got registration " + e.client);
- start_proxy_pair();
- s_c.send_hello(e.client);
- });
- s_f.addEventListener(FacilitatorSocketEvent.REGISTRATIONS_EMPTY, function (e:Event):void {
- puts("Facilitator: no registrations available.");
- setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
- });
- puts("Facilitator: getting registration.");
- s_f.get_registration();
- } else {
- s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
- puts("Facilitator: registration failed.");
- setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
- });
- puts("Facilitator: posting registration.");
- s_f.post_registration(s_c.id);
- }
- }
-
- private function start_proxy_pair():void
- {
- puts("Starting proxy pair on stream " + s_c.local_stream_name);
- p_p = new ProxyPair(this, s_c, relay_addr.host, relay_addr.port);
- p_p.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("ProxyPair: connected!");
- });
- p_p.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("ProxyPair: connection closed.");
- p_p = null;
- if (proxy_mode && !debug_mode && badge != null) {
- badge.num_proxy_pairs--;
- }
- establish_facilitator_connection();
- });
- p_p.listen(s_c.local_stream_name);
- }
-
- /* Parse an address in the form "host:port". Returns an Object with
- keys "host" (String) and "port" (int). Returns null on error. */
- private 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;
- }
- }
-}
-
-import flash.text.TextField;
-import flash.text.TextFormat;
-
-class InternetFreedomBadge {
-
- private var ui:rtmfpcat;
-
- private var _num_proxy_pairs:uint;
- private var _total_proxy_pairs:uint;
-
- [Embed(source="badge.png")]
- private var BadgeImage:Class;
- private var tot_client_count_tf:TextField;
- private var tot_client_count_fmt:TextFormat;
- private var cur_client_count_tf:TextField;
- private var cur_client_count_fmt:TextFormat;
-
- public function InternetFreedomBadge(ui:rtmfpcat)
- {
- this.ui = ui;
- _num_proxy_pairs = 0;
- _total_proxy_pairs = 0;
-
- /* Setup client counter for badge. */
- tot_client_count_fmt = new TextFormat();
- tot_client_count_fmt.color = 0xFFFFFF;
- tot_client_count_fmt.align = "center";
- tot_client_count_fmt.font = "courier-new";
- tot_client_count_fmt.bold = true;
- tot_client_count_fmt.size = 10;
- tot_client_count_tf = new TextField();
- tot_client_count_tf.width = 20;
- tot_client_count_tf.height = 17;
- tot_client_count_tf.background = false;
- tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
- tot_client_count_tf.x=47;
- tot_client_count_tf.y=0;
-
- cur_client_count_fmt = new TextFormat();
- cur_client_count_fmt.color = 0xFFFFFF;
- cur_client_count_fmt.align = "center";
- cur_client_count_fmt.font = "courier-new";
- cur_client_count_fmt.bold = true;
- cur_client_count_fmt.size = 10;
- cur_client_count_tf = new TextField();
- cur_client_count_tf.width = 20;
- cur_client_count_tf.height = 17;
- cur_client_count_tf.background = false;
- cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
- cur_client_count_tf.x=47;
- cur_client_count_tf.y=6;
-
- /* Update the client counter on badge. */
- update_client_count();
- }
-
- public function display():void
- {
- ui.addChild(new BadgeImage());
- /* Tried unsuccessfully to add counter to badge. */
- /* For now, need two addChilds :( */
- ui.addChild(tot_client_count_tf);
- ui.addChild(cur_client_count_tf);
- }
-
- public function get num_proxy_pairs():uint
- {
- return _num_proxy_pairs;
- }
-
- public function set num_proxy_pairs(amount:uint):void
- {
- _num_proxy_pairs = amount;
- update_client_count();
- }
-
- public function get total_proxy_pairs():uint
- {
- return _total_proxy_pairs;
- }
-
- public function set total_proxy_pairs(amount:uint):void
- {
- _total_proxy_pairs = amount;
- /* note: doesn't update, so be sure to update this
- before you update num_proxy_pairs! */
- }
-
- private function update_client_count():void
- {
- /* Update total client count. */
- if (String(total_proxy_pairs).length == 1)
- tot_client_count_tf.text = "0" + String(total_proxy_pairs);
- else
- tot_client_count_tf.text = String(total_proxy_pairs);
-
- /* Update current client count. */
- cur_client_count_tf.text = "";
- for(var i:Number = 0; i < num_proxy_pairs; i++)
- cur_client_count_tf.appendText(".");
- }
-}
diff --git a/swfcat.as b/swfcat.as
index 05da498..7729d2c 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -5,251 +5,268 @@ package
import flash.display.StageScaleMode;
import flash.text.TextField;
import flash.text.TextFormat;
- import flash.net.Socket;
import flash.events.Event;
- import flash.events.IOErrorEvent;
- import flash.events.ProgressEvent;
- import flash.events.SecurityErrorEvent;
- import flash.utils.ByteArray;
import flash.utils.setTimeout;
+ import rtmfp.CirrusSocket;
+ import rtmfp.FacilitatorSocket;
+ import rtmfp.events.CirrusSocketEvent;
+ import rtmfp.events.FacilitatorSocketEvent;
+
public class swfcat extends Sprite
{
+ /* Adobe's Cirrus server and Nate's key */
+ private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
+ private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
+
+ /* Nate's facilitator -- serves a crossdomain policy */
+ private const DEFAULT_FACILITATOR_ADDR:Object = {
+ host: "128.12.179.80",
+ port: 9002
+ };
+
+ private const DEFAULT_TOR_CLIENT_ADDR:Object = {
+ host: "127.0.0.1",
+ port: 9002
+ };
+
/* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
crossdomain policy. */
- private const DEFAULT_RELAY_ADDR:Object = {
+ private const DEFAULT_TOR_RELAY_ADDR:Object = {
host: "173.255.221.44",
port: 9001
};
- private const DEFAULT_FACILITATOR_ADDR:Object = {
- host: "173.255.221.44",
- port: 9002
- };
-
- private const MAX_NUM_PROXY_PAIRS:uint = 1;
-
- // Milliseconds.
- private const FACILITATOR_POLL_INTERVAL:int = 10000;
-
- // Bytes per second. Set to undefined to disable limit.
- public const RATE_LIMIT:Number = undefined;
- // Seconds.
- private const RATE_LIMIT_HISTORY:Number = 5.0;
+
+ /* Poll facilitator every 10 sec */
+ private const DEFAULT_FAC_POLL_INTERVAL:uint = 10000;
+ // Socket to Cirrus server
+ private var s_c:CirrusSocket;
// Socket to facilitator.
- private var s_f:Socket;
+ private var s_f:FacilitatorSocket;
+ // Handle local-remote traffic
+ private var p_p:ProxyPair;
+
+ private var client_id:String;
+ private var proxy_pair_factory:Function;
+
+ private var proxy_pairs:Array;
+
+ private var debug_mode:Boolean;
+ private var proxy_mode:Boolean;
/* TextField for debug output. */
private var output_text:TextField;
+
+ /* Badge for display */
+ private var badge:InternetFreedomBadge;
private var fac_addr:Object;
private var relay_addr:Object;
- /* Number of proxy pairs currently connected (up to
- MAX_NUM_PROXY_PAIRS). */
- private var num_proxy_pairs:int = 0;
- /* Number of proxy pairs ever connected. */
- private var total_proxy_pairs:int = 0;
-
- public var rate_limit:RateLimit;
-
- /* Badge with a client counter */
- [Embed(source="badge.png")]
- private var BadgeImage:Class;
- private var tot_client_count_tf:TextField;
- private var tot_client_count_fmt:TextFormat;
- private var cur_client_count_tf:TextField;
- private var cur_client_count_fmt:TextFormat;
-
- public function puts(s:String):void
- {
- output_text.appendText(s + "\n");
- output_text.scrollV = output_text.maxScrollV;
- }
-
- public function update_client_count():void
- {
- /* Update total client count. */
- if (String(total_proxy_pairs).length == 1)
- tot_client_count_tf.text = "0" + String(total_proxy_pairs);
- else
- tot_client_count_tf.text = String(total_proxy_pairs);
-
- /* Update current client count. */
- cur_client_count_tf.text = "";
- for(var i:Number=0; i<num_proxy_pairs; i++)
- cur_client_count_tf.appendText(".");;
- }
-
public function swfcat()
{
+ proxy_mode = false;
+ debug_mode = false;
+
// Absolute positioning.
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
-
- output_text = new TextField();
- output_text.width = stage.stageWidth;
- output_text.height = stage.stageHeight;
- output_text.background = true;
- output_text.backgroundColor = 0x001f0f;
- output_text.textColor = 0x44cc44;
-
- /* Setup client counter for badge. */
- tot_client_count_fmt = new TextFormat();
- tot_client_count_fmt.color = 0xFFFFFF;
- tot_client_count_fmt.align = "center";
- tot_client_count_fmt.font = "courier-new";
- tot_client_count_fmt.bold = true;
- tot_client_count_fmt.size = 10;
- tot_client_count_tf = new TextField();
- tot_client_count_tf.width = 20;
- tot_client_count_tf.height = 17;
- tot_client_count_tf.background = false;
- tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
- tot_client_count_tf.x=47;
- tot_client_count_tf.y=0;
-
- cur_client_count_fmt = new TextFormat();
- cur_client_count_fmt.color = 0xFFFFFF;
- cur_client_count_fmt.align = "center";
- cur_client_count_fmt.font = "courier-new";
- cur_client_count_fmt.bold = true;
- cur_client_count_fmt.size = 10;
- cur_client_count_tf = new TextField();
- cur_client_count_tf.width = 20;
- cur_client_count_tf.height = 17;
- cur_client_count_tf.background = false;
- cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
- cur_client_count_tf.x=47;
- cur_client_count_tf.y=6;
-
-
- /* Update the client counter on badge. */
- update_client_count();
-
- if (RATE_LIMIT)
- rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
- else
- rate_limit = new RateUnlimit();
-
- puts("Starting.");
+
// Wait until the query string parameters are loaded.
this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
}
+
+ public function puts(s:String):void
+ {
+ if (output_text != null) {
+ output_text.appendText(s + "\n");
+ output_text.scrollV = output_text.maxScrollV;
+ }
+ }
private function loaderinfo_complete(e:Event):void
{
var fac_spec:String;
-
- puts("Parameters loaded.");
-
- if (this.loaderInfo.parameters["debug"])
+ var relay_spec:String;
+
+ debug_mode = (this.loaderInfo.parameters["debug"] != null)
+ proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
+ if (proxy_mode && !debug_mode) {
+ badge = new InternetFreedomBadge(this);
+ badge.display();
+ } else {
+ output_text = new TextField();
+ output_text.width = stage.stageWidth;
+ output_text.height = stage.stageHeight;
+ output_text.background = true;
+ output_text.backgroundColor = 0x001f0f;
+ output_text.textColor = 0x44cc44;
addChild(output_text);
- else {
- addChild(new BadgeImage());
- /* Tried unsuccessfully to add counter to badge. */
- /* For now, need two addChilds :( */
- addChild(tot_client_count_tf);
- addChild(cur_client_count_tf);
}
-
- fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
- if (!fac_addr) {
- puts("Error: Facilitator spec must be in the form \"host:port\".");
- return;
+
+ puts("Starting: parameters loaded.");
+
+ /* TODO: use this to have multiple proxies going at once */
+ proxy_pairs = new Array();
+
+ fac_spec = this.loaderInfo.parameters["facilitator"];
+ if (fac_spec) {
+ 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;
+ }
+ } else {
+ fac_addr = DEFAULT_FACILITATOR_ADDR;
}
- relay_addr = get_param_addr("relay", DEFAULT_RELAY_ADDR);
- if (!relay_addr) {
- puts("Error: Relay spec must be in the form \"host:port\".");
- return;
+
+ relay_spec = this.loaderInfo.parameters["relay"];
+ if (relay_spec) {
+ puts("Relay spec: \"" + relay_spec + "\"");
+ relay_addr = parse_addr_spec(relay_spec);
+ if (!relay_addr) {
+ puts("Error: Relay spec must be in the form \"host:port\".");
+ return;
+ }
+ } else {
+ if (proxy_mode) {
+ relay_addr = DEFAULT_TOR_RELAY_ADDR;
+ } else {
+ relay_addr = DEFAULT_TOR_CLIENT_ADDR;
+ }
}
main();
}
- /* Get an address structure from the given movie parameter, or the given
- default. Returns null on error. */
- private function get_param_addr(param:String, default_addr:Object):Object
- {
- var spec:String, addr:Object;
-
- spec = this.loaderInfo.parameters[param];
- if (spec)
- return parse_addr_spec(spec);
- else
- return default_addr;
- }
-
/* The main logic begins here, after start-up issues are taken care of. */
private function main():void
{
- if (num_proxy_pairs >= MAX_NUM_PROXY_PAIRS) {
- setTimeout(main, FACILITATOR_POLL_INTERVAL);
- return;
+ if (proxy_mode) {
+ establish_facilitator_connection();
+ } else {
+ establish_cirrus_connection();
}
+ }
- s_f = new Socket();
-
- s_f.addEventListener(Event.CONNECT, fac_connected);
- s_f.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("Facilitator: closed connection.");
- setTimeout(main, FACILITATOR_POLL_INTERVAL);
+ private function establish_cirrus_connection():void
+ {
+ s_c = new CirrusSocket();
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_SUCCESS, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: connected with id " + s_c.id + ".");
+ if (proxy_mode) {
+ start_proxy_pair();
+ s_c.send_hello(client_id);
+ } else {
+ establish_facilitator_connection();
+ }
});
- s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- puts("Facilitator: I/O error: " + e.text + ".");
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
+ puts("Error: failed to connect to Cirrus.");
});
- s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- puts("Facilitator: security error: " + e.text + ".");
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: closed connection.");
});
-
- puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
- s_f.connect(fac_addr.host, fac_addr.port);
+ s_c.addEventListener(CirrusSocketEvent.HELLO_RECEIVED, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: received hello from peer " + e.peer);
+
+ /* don't bother if we already have a proxy going */
+ if (p_p != null && p_p.connected) {
+ return;
+ }
+
+ /* if we're in proxy mode, we should have already set
+ up a proxy pair */
+ if (!proxy_mode) {
+ proxy_pair_factory = rtmfp_proxy_pair_factory;
+ start_proxy_pair();
+ s_c.send_hello(e.peer);
+ } else if (!debug_mode && badge != null) {
+ badge.total_proxy_pairs++;
+ badge.num_proxy_pairs++;
+ }
+
+ p_p.client = {peer: e.peer, stream: e.stream};
+ });
+
+ s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
}
- private function fac_connected(e:Event):void
+ private function establish_facilitator_connection():void
{
- puts("Facilitator: connected.");
-
- s_f.addEventListener(ProgressEvent.SOCKET_DATA, fac_data);
-
- s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
+ s_f = new FacilitatorSocket(fac_addr.host, fac_addr.port);
+ s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
+ puts("Facilitator: connect failed.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+
+ if (proxy_mode) {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void {
+ var client_addr:Object = parse_addr_spec(e.client);
+ if (client_addr == null) {
+ puts("Facilitator: got registration " + e.client);
+ proxy_pair_factory = rtmfp_proxy_pair_factory;
+ if (s_c == null || !s_c.connected) {
+ client_id = e.client;
+ establish_cirrus_connection();
+ } else {
+ start_proxy_pair();
+ s_c.send_hello(e.client);
+ }
+ } else {
+ proxy_pair_factory = tcp_proxy_pair_factory;
+ start_proxy_pair();
+ p_p.client = client_addr;
+ }
+ });
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATIONS_EMPTY, function (e:Event):void {
+ puts("Facilitator: no registrations available.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+ puts("Facilitator: getting registration.");
+ s_f.get_registration();
+ } else {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
+ puts("Facilitator: registration failed.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+ puts("Facilitator: posting registration.");
+ s_f.post_registration(s_c.id);
+ }
}
-
- private function fac_data(e:ProgressEvent):void
+
+ private function start_proxy_pair():void
{
- var client_spec:String;
- var client_addr:Object;
- var proxy_pair: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;
- }
-
- num_proxy_pairs++;
- total_proxy_pairs++;
- /* Update the client count on the badge. */
- update_client_count();
-
- proxy_pair = new ProxyPair(this, client_addr, relay_addr);
- proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
- proxy_pair.log("Complete.");
-
- num_proxy_pairs--;
- /* Update the client count on the badge. */
- update_client_count();
+ p_p = proxy_pair_factory();
+ p_p.addEventListener(Event.CONNECT, function (e:Event):void {
+ puts("ProxyPair: connected!");
});
- proxy_pair.connect();
-
+ p_p.addEventListener(Event.CLOSE, function (e:Event):void {
+ puts("ProxyPair: connection closed.");
+ p_p = null;
+ if (proxy_mode && !debug_mode && badge != null) {
+ badge.num_proxy_pairs--;
+ }
+ establish_facilitator_connection();
+ });
+ p_p.relay = relay_addr;
+ }
+
+ private function rtmfp_proxy_pair_factory():ProxyPair
+ {
+ return new RTMFPProxyPair(this, s_c, s_c.local_stream_name);
+ }
+
+ private function tcp_proxy_pair_factory():ProxyPair
+ {
+ return new TCPProxyPair(this);
}
/* Parse an address in the form "host:port". Returns an Object with
keys "host" (String) and "port" (int). Returns null on error. */
- private static function parse_addr_spec(spec:String):Object
+ private function parse_addr_spec(spec:String):Object
{
var parts:Array;
var addr:Object;
@@ -266,267 +283,105 @@ package
}
}
-import flash.display.Sprite;
-import flash.events.Event;
-import flash.events.EventDispatcher;
-import flash.events.IOErrorEvent;
-import flash.events.ProgressEvent;
-import flash.events.SecurityErrorEvent;
-import flash.net.Socket;
-import flash.utils.ByteArray;
-import flash.utils.clearTimeout;
-import flash.utils.getTimer;
-import flash.utils.setTimeout;
-
-class RateLimit
-{
- public function RateLimit()
- {
- }
-
- public function update(n:Number):Boolean
- {
- return true;
- }
+import flash.text.TextField;
+import flash.text.TextFormat;
- public function when():Number
- {
- return 0.0;
- }
-
- public function is_limited():Boolean
- {
- return false;
- }
-}
-
-class RateUnlimit extends RateLimit
-{
- public function RateUnlimit()
- {
- }
-
- public override function update(n:Number):Boolean
- {
- return true;
- }
-
- public override function when():Number
- {
- return 0.0;
- }
-
- public override function is_limited():Boolean
- {
- return false;
- }
-}
-
-class BucketRateLimit extends RateLimit
-{
- private var amount:Number;
- private var capacity:Number;
- private var time:Number;
- private var last_update:uint;
-
- public function BucketRateLimit(capacity:Number, time:Number)
- {
- this.amount = 0.0;
- /* capacity / time is the rate we are aiming for. */
- this.capacity = capacity;
- this.time = time;
- this.last_update = getTimer();
- }
-
- private function age():void
- {
- var now:uint;
- var delta:Number;
-
- now = getTimer();
- delta = (now - last_update) / 1000.0;
- last_update = now;
-
- amount -= delta * capacity / time;
- if (amount < 0.0)
- amount = 0.0;
- }
-
- public override function update(n:Number):Boolean
- {
- age();
- amount += n;
-
- return amount <= capacity;
- }
-
- public override function when():Number
- {
- age();
- return (amount - capacity) / (capacity / time);
- }
-
- public override function is_limited():Boolean
- {
- age();
- return amount > capacity;
- }
-}
-
-/* An instance of a client-relay connection. */
-class ProxyPair extends EventDispatcher
-{
- // Address ({host, port}) of client.
- private var addr_c:Object;
- // Address ({host, port}) of relay.
- private var addr_r:Object;
-
- // Socket to client.
- private var s_c:Socket;
- // Socket to relay.
- private var s_r:Socket;
-
- // Parent swfcat, for UI updates and rate meter.
+class InternetFreedomBadge {
+
private var ui:swfcat;
-
- // Pending byte read counts for relay and client sockets.
- private var r2c_schedule:Array;
- private var c2r_schedule:Array;
- // Callback id.
- private var flush_id:uint;
-
- public function log(msg:String):void
- {
- ui.puts(id() + ": " + msg)
- }
-
- // String describing this pair for output.
- public function id():String
- {
- return "<" + this.addr_c.host + ":" + this.addr_c.port +
- "," + this.addr_r.host + ":" + this.addr_r.port + ">";
- }
-
- public function ProxyPair(ui:swfcat, addr_c:Object, addr_r:Object)
+
+ private var _num_proxy_pairs:uint;
+ private var _total_proxy_pairs:uint;
+
+ [Embed(source="badge.png")]
+ private var BadgeImage:Class;
+ private var tot_client_count_tf:TextField;
+ private var tot_client_count_fmt:TextFormat;
+ private var cur_client_count_tf:TextField;
+ private var cur_client_count_fmt:TextFormat;
+
+ public function InternetFreedomBadge(ui:swfcat)
{
this.ui = ui;
- this.addr_c = addr_c;
- this.addr_r = addr_r;
-
- this.c2r_schedule = [];
- this.r2c_schedule = [];
- }
-
- public function connect():void
- {
- s_r = new Socket();
-
- s_r.addEventListener(Event.CONNECT, relay_connected);
- s_r.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Relay: closed.");
- if (s_c.connected)
- s_c.close();
- dispatchEvent(new Event(Event.COMPLETE));
- });
- s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Relay: I/O error: " + e.text + ".");
- if (s_c.connected)
- s_c.close();
- dispatchEvent(new Event(Event.COMPLETE));
- });
- s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Relay: security error: " + e.text + ".");
- if (s_c.connected)
- s_c.close();
- dispatchEvent(new Event(Event.COMPLETE));
- });
- s_r.addEventListener(ProgressEvent.SOCKET_DATA, relay_to_client);
-
- log("Relay: connecting to " + addr_r.host + ":" + addr_r.port + ".");
- s_r.connect(addr_r.host, addr_r.port);
+ _num_proxy_pairs = 0;
+ _total_proxy_pairs = 0;
+
+ /* Setup client counter for badge. */
+ tot_client_count_fmt = new TextFormat();
+ tot_client_count_fmt.color = 0xFFFFFF;
+ tot_client_count_fmt.align = "center";
+ tot_client_count_fmt.font = "courier-new";
+ tot_client_count_fmt.bold = true;
+ tot_client_count_fmt.size = 10;
+ tot_client_count_tf = new TextField();
+ tot_client_count_tf.width = 20;
+ tot_client_count_tf.height = 17;
+ tot_client_count_tf.background = false;
+ tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
+ tot_client_count_tf.x=47;
+ tot_client_count_tf.y=0;
+
+ cur_client_count_fmt = new TextFormat();
+ cur_client_count_fmt.color = 0xFFFFFF;
+ cur_client_count_fmt.align = "center";
+ cur_client_count_fmt.font = "courier-new";
+ cur_client_count_fmt.bold = true;
+ cur_client_count_fmt.size = 10;
+ cur_client_count_tf = new TextField();
+ cur_client_count_tf.width = 20;
+ cur_client_count_tf.height = 17;
+ cur_client_count_tf.background = false;
+ cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
+ cur_client_count_tf.x=47;
+ cur_client_count_tf.y=6;
+
+ /* Update the client counter on badge. */
+ update_client_count();
}
-
- private function relay_connected(e:Event):void
+
+ public function display():void
{
- log("Relay: connected.");
-
- s_c = new Socket();
-
- s_c.addEventListener(Event.CONNECT, client_connected);
- s_c.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Client: closed.");
- if (s_r.connected)
- s_r.close();
- dispatchEvent(new Event(Event.COMPLETE));
- });
- s_c.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Client: I/O error: " + e.text + ".");
- if (s_r.connected)
- s_r.close();
- dispatchEvent(new Event(Event.COMPLETE));
- });
- s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Client: security error: " + e.text + ".");
- if (s_r.connected)
- s_r.close();
- dispatchEvent(new Event(Event.COMPLETE));
- });
- s_c.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
-
- log("Client: connecting to " + addr_c.host + ":" + addr_c.port + ".");
- s_c.connect(addr_c.host, addr_c.port);
+ ui.addChild(new BadgeImage());
+ /* Tried unsuccessfully to add counter to badge. */
+ /* For now, need two addChilds :( */
+ ui.addChild(tot_client_count_tf);
+ ui.addChild(cur_client_count_tf);
}
-
- private function relay_to_client(e:ProgressEvent):void
+
+ public function get num_proxy_pairs():uint
{
- r2c_schedule.push(e.bytesLoaded);
- flush();
+ return _num_proxy_pairs;
}
-
- private function client_to_relay(e:ProgressEvent):void
+
+ public function set num_proxy_pairs(amount:uint):void
{
- c2r_schedule.push(e.bytesLoaded);
- flush();
+ _num_proxy_pairs = amount;
+ update_client_count();
}
-
- private function client_connected(e:Event):void
+
+ public function get total_proxy_pairs():uint
{
- log("Client: connected.");
+ return _total_proxy_pairs;
}
-
- private function transfer_chunk(s_from:Socket, s_to:Socket, n:uint,
- label:String):void
+
+ public function set total_proxy_pairs(amount:uint):void
{
- var bytes:ByteArray;
-
- bytes = new ByteArray();
- s_from.readBytes(bytes, 0, n);
- s_to.writeBytes(bytes);
- ui.rate_limit.update(n);
- log(label + ": read " + bytes.length + ".");
+ _total_proxy_pairs = amount;
+ /* note: doesn't update, so be sure to update this
+ before you update num_proxy_pairs! */
}
-
- /* Send as much data as the rate limit currently allows. */
- private function flush():void
+
+ private function update_client_count():void
{
- if (flush_id)
- clearTimeout(flush_id);
- flush_id = undefined;
-
- if (!(s_r.connected && s_c.connected))
- /* Can't do anything until both sockets are connected. */
- return;
-
- while (!ui.rate_limit.is_limited() &&
- (r2c_schedule.length > 0 || c2r_schedule.length > 0)) {
- if (r2c_schedule.length > 0)
- transfer_chunk(s_r, s_c, r2c_schedule.shift(), "Relay");
- if (c2r_schedule.length > 0)
- transfer_chunk(s_c, s_r, c2r_schedule.shift(), "Client");
- }
-
- /* Call again when safe, if necessary. */
- if (r2c_schedule.length > 0 || c2r_schedule.length > 0)
- flush_id = setTimeout(flush, ui.rate_limit.when() * 1000);
+ /* Update total client count. */
+ if (String(total_proxy_pairs).length == 1)
+ tot_client_count_tf.text = "0" + String(total_proxy_pairs);
+ else
+ tot_client_count_tf.text = String(total_proxy_pairs);
+
+ /* Update current client count. */
+ cur_client_count_tf.text = "";
+ for(var i:Number = 0; i < num_proxy_pairs; i++)
+ cur_client_count_tf.appendText(".");
}
}
1
0

[flashproxy/master] Pulling Facilitator stuff out of rtmfp package, adding some commentary and boilerplate for an SQSProxyPair (currently is just a TCPProxyPair)
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 6307de6a85132ea3859ab0dca7e95db9b04d0af0
Author: Nate Hardison <nate(a)rescomp-09-154551.stanford.edu>
Date: Thu Jun 9 01:12:37 2011 -0700
Pulling Facilitator stuff out of rtmfp package, adding some commentary and boilerplate for an SQSProxyPair (currently is just a TCPProxyPair)
---
FacilitatorSocket.as | 103 +++++++++++++++++++++++++++++++
SQSProxyPair.as | 86 ++++++++++++++++++++++++++
events/FacilitatorSocketEvent.as | 22 +++++++
rtmfp/FacilitatorSocket.as | 104 --------------------------------
rtmfp/events/FacilitatorSocketEvent.as | 22 -------
swfcat.as | 25 +++++++-
6 files changed, 233 insertions(+), 129 deletions(-)
diff --git a/FacilitatorSocket.as b/FacilitatorSocket.as
new file mode 100644
index 0000000..3930fea
--- /dev/null
+++ b/FacilitatorSocket.as
@@ -0,0 +1,103 @@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.HTTPStatusEvent;
+ import flash.events.IOErrorEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.URLLoader;
+ import flash.net.URLLoaderDataFormat;
+ import flash.net.URLRequest;
+ import flash.net.URLRequestMethod;
+ import flash.net.URLVariables;
+
+ import events.FacilitatorSocketEvent;
+
+ [Event(name=FacilitatorSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATION_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATION_RECEIVED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATIONS_EMPTY, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ public class FacilitatorSocket extends EventDispatcher
+ {
+ private var host:String;
+ private var port:uint;
+
+ public function FacilitatorSocket(host:String, port:uint)
+ {
+ this.host = host;
+ this.port = port;
+ }
+
+ public function get_registration():void
+ {
+ make_request(URLRequestMethod.GET);
+ }
+
+ public function post_registration(registration_data:String):void
+ {
+ var data:URLVariables = new URLVariables();
+ data.client = registration_data;
+ make_request(URLRequestMethod.POST, data);
+ }
+
+ private function fail():void
+ {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_FAILED));
+ }
+
+ private function make_request(method:String, data:URLVariables = null):void
+ {
+ var request:URLRequest = new URLRequest(url)
+ request.data = data;
+ request.method = method;
+
+ var url_loader:URLLoader = new URLLoader();
+ url_loader = new URLLoader();
+ url_loader.dataFormat = URLLoaderDataFormat.VARIABLES;
+
+ url_loader.addEventListener(Event.COMPLETE, on_complete_event);
+ url_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, on_http_status_event);
+ url_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
+ url_loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
+
+ url_loader.load(request);
+ }
+
+ private function on_complete_event(event:Event):void
+ {
+ try {
+ var client_id:String = event.target.data.client;
+ if (client_id == "Registration list empty") {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY));
+ } else {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id));
+ }
+ } catch (e:Error) {
+ /* error is thrown for POST when we don't care about
+ the response anyways */
+ }
+
+ event.target.close()
+ }
+
+ private function on_http_status_event(event:HTTPStatusEvent):void
+ {
+ /* empty for now */
+ }
+
+ private function on_io_error_event(event:IOErrorEvent):void
+ {
+ fail();
+ }
+
+ private function on_security_error_event(event:SecurityErrorEvent):void
+ {
+ fail();
+ }
+
+ private function get url():String
+ {
+ return "http://" + host + ":" + port;
+ }
+ }
+}
\ No newline at end of file
diff --git a/SQSProxyPair.as b/SQSProxyPair.as
new file mode 100644
index 0000000..54f763d
--- /dev/null
+++ b/SQSProxyPair.as
@@ -0,0 +1,86 @@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+
+ public class SQSProxyPair extends ProxyPair
+ {
+ private var client_socket:Socket;
+
+ public function SQSProxyPair(ui:swfcat)
+ {
+ super(this, ui);
+
+ log("Starting SQS proxy pair");
+ setup_client_socket();
+ }
+
+ override public function set client(client_addr:Object):void
+ {
+ this.client_addr = client_addr;
+ log("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
+ client_socket.connect(client_addr.host, client_addr.port);
+ }
+
+ override public function close():void
+ {
+ super.close();
+ if (client_socket != null && client_socket.connected) {
+ client_socket.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ override public function get connected():Boolean
+ {
+ return (super.connected && client_socket != null && client_socket.connected);
+ }
+
+ override protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ var bytes:ByteArray = new ByteArray();
+
+ if (src == null) {
+ src = client_socket;
+ }
+
+ if (dst == null) {
+ dst = client_socket;
+ }
+
+ Socket(src).readBytes(bytes, 0, num_bytes);
+ log("SQSProxyPair: transferring " + num_bytes + " bytes.");
+ Socket(dst).writeBytes(bytes);
+ }
+
+ private function setup_client_socket():void
+ {
+ client_socket = new Socket();
+
+ client_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Client: connected to " + client_addr.host + ":" + client_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
+ client_socket.addEventListener(Event.CLOSE, function (e:Event):void {
+ log("Client: closed.");
+ close();
+ });
+ client_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
+ log("Client: I/O error: " + e.text + ".");
+ close();
+ });
+ client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ log("Client: security error: " + e.text + ".");
+ close();
+ });
+ client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+ }
+ }
+}
\ No newline at end of file
diff --git a/events/FacilitatorSocketEvent.as b/events/FacilitatorSocketEvent.as
new file mode 100644
index 0000000..9fc478b
--- /dev/null
+++ b/events/FacilitatorSocketEvent.as
@@ -0,0 +1,22 @@
+package events
+{
+ import flash.events.Event;
+
+ public class FacilitatorSocketEvent extends Event
+ {
+ public static const CONNECT_CLOSED:String = "connectClosed";
+ public static const CONNECT_FAILED:String = "connectFailed";
+ public static const CONNECT_SUCCESS:String = "connectSuccess";
+ public static const REGISTRATION_RECEIVED:String = "registrationReceived";
+ public static const REGISTRATION_FAILED:String = "registrationFailed";
+ public static const REGISTRATIONS_EMPTY:String = "registrationsEmpty";
+
+ public var client:String;
+
+ public function FacilitatorSocketEvent(type:String, client:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
+ {
+ super(type, bubbles, cancelable);
+ this.client = client;
+ }
+ }
+}
diff --git a/rtmfp/FacilitatorSocket.as b/rtmfp/FacilitatorSocket.as
deleted file mode 100644
index 32c8a7d..0000000
--- a/rtmfp/FacilitatorSocket.as
+++ /dev/null
@@ -1,104 +0,0 @@
-package rtmfp
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.HTTPStatusEvent;
- import flash.events.IOErrorEvent;
- import flash.events.SecurityErrorEvent;
- import flash.net.URLLoader;
- import flash.net.URLLoaderDataFormat;
- import flash.net.URLRequest;
- import flash.net.URLRequestMethod;
- import flash.net.URLVariables;
- import flash.system.Security;
-
- import rtmfp.events.FacilitatorSocketEvent;
-
- [Event(name=FacilitatorSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
- [Event(name=FacilitatorSocketEvent.REGISTRATION_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
- [Event(name=FacilitatorSocketEvent.REGISTRATION_RECEIVED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
- [Event(name=FacilitatorSocketEvent.REGISTRATIONS_EMPTY, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
- public class FacilitatorSocket extends EventDispatcher
- {
- private var host:String;
- private var port:uint;
-
- public function FacilitatorSocket(host:String, port:uint)
- {
- this.host = host;
- this.port = port;
- }
-
- public function get_registration():void
- {
- make_request(URLRequestMethod.GET);
- }
-
- public function post_registration(registration_data:String):void
- {
- var data:URLVariables = new URLVariables();
- data.client = registration_data;
- make_request(URLRequestMethod.POST, data);
- }
-
- private function fail():void
- {
- dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_FAILED));
- }
-
- private function make_request(method:String, data:URLVariables = null):void
- {
- var request:URLRequest = new URLRequest(url)
- request.data = data;
- request.method = method;
-
- var url_loader:URLLoader = new URLLoader();
- url_loader = new URLLoader();
- url_loader.dataFormat = URLLoaderDataFormat.VARIABLES;
-
- url_loader.addEventListener(Event.COMPLETE, on_complete_event);
- url_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, on_http_status_event);
- url_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
- url_loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
-
- url_loader.load(request);
- }
-
- private function on_complete_event(event:Event):void
- {
- try {
- var client_id:String = event.target.data.client;
- if (client_id == "Registration list empty") {
- dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY));
- } else {
- dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id));
- }
- } catch (e:Error) {
- /* error is thrown for POST when we don't care about
- the response anyways */
- }
-
- event.target.close()
- }
-
- private function on_http_status_event(event:HTTPStatusEvent):void
- {
- /* empty for now */
- }
-
- private function on_io_error_event(event:IOErrorEvent):void
- {
- fail();
- }
-
- private function on_security_error_event(event:SecurityErrorEvent):void
- {
- fail();
- }
-
- private function get url():String
- {
- return "http://" + host + ":" + port;
- }
- }
-}
\ No newline at end of file
diff --git a/rtmfp/events/FacilitatorSocketEvent.as b/rtmfp/events/FacilitatorSocketEvent.as
deleted file mode 100644
index a0599aa..0000000
--- a/rtmfp/events/FacilitatorSocketEvent.as
+++ /dev/null
@@ -1,22 +0,0 @@
-package rtmfp.events
-{
- import flash.events.Event;
-
- public class FacilitatorSocketEvent extends Event
- {
- public static const CONNECT_CLOSED:String = "connectClosed";
- public static const CONNECT_FAILED:String = "connectFailed";
- public static const CONNECT_SUCCESS:String = "connectSuccess";
- public static const REGISTRATION_RECEIVED:String = "registrationReceived";
- public static const REGISTRATION_FAILED:String = "registrationFailed";
- public static const REGISTRATIONS_EMPTY:String = "registrationsEmpty";
-
- public var client:String;
-
- public function FacilitatorSocketEvent(type:String, client:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- this.client = client;
- }
- }
-}
diff --git a/swfcat.as b/swfcat.as
index 7729d2c..627a3cd 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -8,14 +8,22 @@ package
import flash.events.Event;
import flash.utils.setTimeout;
+ import FacilitatorSocket;
+ import events.FacilitatorSocketEvent;
+
+ import ProxyPair;
+ import RTMFPProxyPair;
+ import SQSProxyPair;
+ import TCPProxyPair;
+
import rtmfp.CirrusSocket;
- import rtmfp.FacilitatorSocket;
import rtmfp.events.CirrusSocketEvent;
- import rtmfp.events.FacilitatorSocketEvent;
public class swfcat extends Sprite
{
- /* Adobe's Cirrus server and Nate's key */
+ /* Adobe's Cirrus server for RTMFP connections.
+ The Cirrus key is defined at compile time by
+ reading from the CIRRUS_KEY environment var. */
private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
@@ -25,6 +33,7 @@ package
port: 9002
};
+ /* Default Tor client to use in case of RTMFP connection */
private const DEFAULT_TOR_CLIENT_ADDR:Object = {
host: "127.0.0.1",
port: 9002
@@ -122,6 +131,8 @@ package
fac_addr = DEFAULT_FACILITATOR_ADDR;
}
+ /* TODO: modify this for the client so that it can specify
+ a relay for the proxy to use */
relay_spec = this.loaderInfo.parameters["relay"];
if (relay_spec) {
puts("Relay spec: \"" + relay_spec + "\"");
@@ -259,6 +270,14 @@ package
return new RTMFPProxyPair(this, s_c, s_c.local_stream_name);
}
+ // currently is the same as TCPProxyPair
+ // could be interesting to see how this works
+ // can't imagine it will work terribly well...
+ private function sqs_proxy_pair_factory():ProxyPair
+ {
+ return new SQSProxyPair(this);
+ }
+
private function tcp_proxy_pair_factory():ProxyPair
{
return new TCPProxyPair(this);
1
0
commit 8ae82797738a29167cf1c6b1326b20b1794f2997
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 13:45:18 2011 -0700
Use a separate Badge class for UI.
Ported from rtmfp branch.
---
swfcat.as | 162 ++++++++++++++++++++++++++++++++++--------------------------
1 files changed, 92 insertions(+), 70 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index 4aa430b..8d893b2 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -36,23 +36,16 @@ package
/* TextField for debug output. */
private var output_text:TextField;
- private var fac_addr:Object;
+ /* UI shown when debug is off. */
+ private var badge:Badge;
/* Number of proxy pairs currently connected (up to
MAX_NUM_PROXY_PAIRS). */
private var num_proxy_pairs:int = 0;
- /* Number of proxy pairs ever connected. */
- private var total_proxy_pairs:int = 0;
- public var rate_limit:RateLimit;
+ private var fac_addr:Object;
- /* Badge with a client counter */
- [Embed(source="badge.png")]
- private var BadgeImage:Class;
- private var tot_client_count_tf:TextField;
- private var tot_client_count_fmt:TextFormat;
- private var cur_client_count_tf:TextField;
- private var cur_client_count_fmt:TextFormat;
+ public var rate_limit:RateLimit;
public function puts(s:String):void
{
@@ -60,20 +53,6 @@ package
output_text.scrollV = output_text.maxScrollV;
}
- public function update_client_count():void
- {
- /* Update total client count. */
- if (String(total_proxy_pairs).length == 1)
- tot_client_count_tf.text = "0" + String(total_proxy_pairs);
- else
- tot_client_count_tf.text = String(total_proxy_pairs);
-
- /* Update current client count. */
- cur_client_count_tf.text = "";
- for(var i:Number=0; i<num_proxy_pairs; i++)
- cur_client_count_tf.appendText(".");;
- }
-
public function swfcat()
{
// Absolute positioning.
@@ -87,38 +66,7 @@ package
output_text.backgroundColor = 0x001f0f;
output_text.textColor = 0x44cc44;
- /* Setup client counter for badge. */
- tot_client_count_fmt = new TextFormat();
- tot_client_count_fmt.color = 0xFFFFFF;
- tot_client_count_fmt.align = "center";
- tot_client_count_fmt.font = "courier-new";
- tot_client_count_fmt.bold = true;
- tot_client_count_fmt.size = 10;
- tot_client_count_tf = new TextField();
- tot_client_count_tf.width = 20;
- tot_client_count_tf.height = 17;
- tot_client_count_tf.background = false;
- tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
- tot_client_count_tf.x=47;
- tot_client_count_tf.y=0;
-
- cur_client_count_fmt = new TextFormat();
- cur_client_count_fmt.color = 0xFFFFFF;
- cur_client_count_fmt.align = "center";
- cur_client_count_fmt.font = "courier-new";
- cur_client_count_fmt.bold = true;
- cur_client_count_fmt.size = 10;
- cur_client_count_tf = new TextField();
- cur_client_count_tf.width = 20;
- cur_client_count_tf.height = 17;
- cur_client_count_tf.background = false;
- cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
- cur_client_count_tf.x=47;
- cur_client_count_tf.y=6;
-
-
- /* Update the client counter on badge. */
- update_client_count();
+ badge = new Badge();
if (RATE_LIMIT)
rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
@@ -138,13 +86,8 @@ package
if (this.loaderInfo.parameters["debug"])
addChild(output_text);
- else {
- addChild(new BadgeImage());
- /* Tried unsuccessfully to add counter to badge. */
- /* For now, need two addChilds :( */
- addChild(tot_client_count_tf);
- addChild(cur_client_count_tf);
- }
+ else
+ addChild(badge);
fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
if (!fac_addr) {
@@ -236,17 +179,13 @@ package
}
num_proxy_pairs++;
- total_proxy_pairs++;
- /* Update the client count on the badge. */
- update_client_count();
+ badge.proxy_begin();
proxy_pair = new ProxyPair(this, client_addr, relay_addr);
proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
proxy_pair.log("Complete.");
-
num_proxy_pairs--;
- /* Update the client count on the badge. */
- update_client_count();
+ badge.proxy_end();
});
proxy_pair.connect();
@@ -272,6 +211,8 @@ package
}
import flash.display.Sprite;
+import flash.text.TextFormat;
+import flash.text.TextField;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
@@ -284,6 +225,87 @@ import flash.utils.clearTimeout;
import flash.utils.getTimer;
import flash.utils.setTimeout;
+class Badge extends flash.display.Sprite
+{
+ /* Number of proxy pairs currently connected. */
+ private var num_proxy_pairs:int = 0;
+ /* Number of proxy pairs ever connected. */
+ private var total_proxy_pairs:int = 0;
+
+ [Embed(source="badge.png")]
+ private var BadgeImage:Class;
+ private var tot_client_count_tf:TextField;
+ private var tot_client_count_fmt:TextFormat;
+ private var cur_client_count_tf:TextField;
+ private var cur_client_count_fmt:TextFormat;
+
+ public function Badge()
+ {
+ /* Setup client counter for badge. */
+ tot_client_count_fmt = new TextFormat();
+ tot_client_count_fmt.color = 0xFFFFFF;
+ tot_client_count_fmt.align = "center";
+ tot_client_count_fmt.font = "courier-new";
+ tot_client_count_fmt.bold = true;
+ tot_client_count_fmt.size = 10;
+ tot_client_count_tf = new TextField();
+ tot_client_count_tf.width = 20;
+ tot_client_count_tf.height = 17;
+ tot_client_count_tf.background = false;
+ tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
+ tot_client_count_tf.x=47;
+ tot_client_count_tf.y=0;
+
+ cur_client_count_fmt = new TextFormat();
+ cur_client_count_fmt.color = 0xFFFFFF;
+ cur_client_count_fmt.align = "center";
+ cur_client_count_fmt.font = "courier-new";
+ cur_client_count_fmt.bold = true;
+ cur_client_count_fmt.size = 10;
+ cur_client_count_tf = new TextField();
+ cur_client_count_tf.width = 20;
+ cur_client_count_tf.height = 17;
+ cur_client_count_tf.background = false;
+ cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
+ cur_client_count_tf.x=47;
+ cur_client_count_tf.y=6;
+
+ addChild(new BadgeImage());
+ addChild(tot_client_count_tf);
+ addChild(cur_client_count_tf);
+
+ /* Update the client counter on badge. */
+ update_client_count();
+ }
+
+ public function proxy_begin():void
+ {
+ num_proxy_pairs++;
+ total_proxy_pairs++;
+ update_client_count();
+ }
+
+ public function proxy_end():void
+ {
+ num_proxy_pairs--;
+ update_client_count();
+ }
+
+ private function update_client_count():void
+ {
+ /* Update total client count. */
+ if (String(total_proxy_pairs).length == 1)
+ tot_client_count_tf.text = "0" + String(total_proxy_pairs);
+ else
+ tot_client_count_tf.text = String(total_proxy_pairs);
+
+ /* Update current client count. */
+ cur_client_count_tf.text = "";
+ for(var i:Number = 0; i < num_proxy_pairs; i++)
+ cur_client_count_tf.appendText(".");
+ }
+}
+
class RateLimit
{
public function RateLimit()
1
0