tor-commits
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- 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
- 1 participants
- 216095 discussions
[flashproxy/master] Remove spurious differences from master branch.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 04b11aa394ec3484844ed146d832ffa8d90fb16a
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 14:52:18 2011 -0700
Remove spurious differences from master branch.
---
swfcat.as | 98 +++++++++++++++++++++++++++++++++---------------------------
1 files changed, 54 insertions(+), 44 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index 8e54f72..ac52ec8 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -37,6 +37,8 @@ package
port: 9002
};
+ private const MAX_NUM_PROXY_PAIRS:uint = 1;
+
// Milliseconds.
private const FACILITATOR_POLL_INTERVAL:int = 10000;
@@ -54,84 +56,90 @@ package
private var client_id:String;
private var proxy_pair_factory:Function;
+ private var relay_addr:Object;
- private var debug_mode:Boolean;
private var proxy_mode:Boolean;
/* TextField for debug output. */
private var output_text:TextField;
-
- /* Badge for display */
+
+ /* 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;
+
private var fac_addr:Object;
- private var relay_addr:Object;
public var rate_limit:RateLimit;
+ public function puts(s:String):void
+ {
+ output_text.appendText(s + "\n");
+ output_text.scrollV = output_text.maxScrollV;
+ }
+
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;
+
+ badge = new Badge();
+
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;
- 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 Badge();
- addChild(badge);
- } 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;
+ puts("Parameters loaded.");
+
+ if (this.loaderInfo.parameters["debug"])
addChild(output_text);
- }
-
- puts("Starting: parameters loaded.");
-
- 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;
+ else
+ addChild(badge);
+
+ proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
+
+ fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
+ if (!fac_addr) {
+ puts("Error: Facilitator spec must be in the form \"host:port\".");
+ return;
}
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
{
@@ -175,7 +183,8 @@ package
proxy_pair_factory = rtmfp_proxy_pair_factory;
start_proxy_pair();
s_c.send_hello(e.peer);
- } else if (!debug_mode && badge != null) {
+ } else {
+ num_proxy_pairs++;
badge.proxy_begin();
}
@@ -238,7 +247,8 @@ package
p_p.addEventListener(Event.CLOSE, function (e:Event):void {
puts("ProxyPair: connection closed.");
p_p = null;
- if (proxy_mode && !debug_mode && badge != null) {
+ if (proxy_mode) {
+ num_proxy_pairs--;
badge.proxy_end();
}
establish_facilitator_connection();
1
0
[flashproxy/master] Update documentation for combined TCP/RTMFP proxy.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit f6e2fb73a707c34760326fa760406a38f7144c35
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 01:40:11 2011 -0700
Update documentation for combined TCP/RTMFP proxy.
---
README | 73 +++++++++++++++++++++++++++++++++++++-----------------------
design.txt | 19 +++++++++++----
2 files changed, 59 insertions(+), 33 deletions(-)
diff --git a/README b/README
index ff12174..4b6a2dc 100644
--- a/README
+++ b/README
@@ -16,6 +16,10 @@ There are five main parts. Our terminology for each part is in quotes.
5. A Tor "relay," which is just a normal Tor relay except that its host
must also serve a Flash crossdomain policy.
+A proxy is capable of connecting to a client in two ways: Using a normal
+TCP connection, or over Adobe RTMFP, which involves a third party but is
+capable of traversing NAT.
+
== Demonstration page
https://crypto.stanford.edu/flashproxy/
@@ -28,42 +32,56 @@ Download the (free software) Flex SDK.
http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK
Put its bin directory in your PATH. The important executable is mxmlc.
-You need a Cirrus developer key from Adobe. Put it in the environment
-variable CIRRUS_KEY so it can be found by Makefile.
+For RTMFP support, you need a Cirrus developer key from Adobe. Put it in
+the environment variable CIRRUS_KEY so it can be found by Makefile.
$ export CIRRUS_KEY=XXXXXXXXXXXXXXXXXXXXXXXX-YYYYYYYYYYYY
To build, run
$ make
Copy the resulting swfcat.swf file to a web server.
-On the computer that will be the facilitator, run
+=== Connecting
+
+On the Tor relay, run
sudo ./crossdomaind.py
- ./facilitator.py
-crossdomaind.py needs to be run on any server that will accept
-connections from a Flash proxy. It serves a chunk of data on port 843.
+In general, any computer that a proxy connects to needs to serve a
+crossdomain policy, but the connector and facilitator have it built in.
+
+On the facilitator, run
+ ./facilitator.py -r <relay-ip>
The facilitator runs on port 9002 by default.
+In a browser somewhere, open swfcat.swf and pass it a parameters telling it
+which facilitator to use, for example
+ http://www.example.com/swfcat.swf?facilitator=<facilitator-ip>:9002&debug=1
+
+There are two ways in which the client can receive connections: over TCP
+or RTMFP. TCP doesn't send traffic to anyone other than the facilitator
+and the proxy, but it only works if you have a public IP address. RTMFP
+coordinates connections using a server controlled by Adobe, but works
+when the client is behind a NAT.
+
+To connect with TCP, run
+ ./connector.py -f <facilitator-ip>
+(If you are running the facilitator locally, be sure to use an external
+IP address, not 127.0.0.1.) The connector informs the facilitator that
+it wants a connection, then listens on 0.0.0.0:9000 and 127.0.0.1:9001.
+The proxy will connect on port 9000 and the local Tor will connect on
+9001.
+
+To connect with RTMFP, run
+ ./connector.py 127.0.0.1:9001 127.0.0.1:9002
+and open in a browser
+ http://www.example.com/swfcat.swf?client=1&facilitator=<facilitator-ip>:9002
+In this case, it is swfcat running in client mode that registers with
+the facilitator. The connector acts to join the local swfcat and the
+local Tor client.
+
The client needs to be running a version of Tor that supports the
Socks4Proxy configuration. This means version 0.2.2.1-alpha or
later--not the current stable release.
-On the client, run
- ./connector.py 127.0.0.1:9001 127.0.0.1:9002
-Also on the client, open up the browser to swfcat.swf. Passing no
-arguments should give you good defaults (expects the facilitator running
-on Nate's server). swfcat will connect to the Cirrus server to
-obtain a client ID which it then registers with the facilitator.
-
-In a browser somewhere, open swfcat.swf and pass parameters telling it
-which facilitator to use and to operate in proxy mode.
- http://www.example.com/swfcat.swf?proxy=true&facilitator=<FACILITATOR_IP>:9002&debug=1
-This swfcat will also connect to the Cirrus server to obtain a client ID,
-and then it will ping the facilitator to check if there are any registered
-client IDs. If there is one, it will open a RTMFP connection (coordinated
-by the Cirrus server) to the client and an additional connection to a
-Tor relay.
-
-Back on the client, start Tor with the following configuration:
+Start Tor with the following configuration:
UseBridges 1
Bridge 127.0.0.1:9001
Socks4Proxy 127.0.0.1:9001
@@ -73,8 +91,8 @@ If you see messages like
[notice] no known bridge descriptors running yet; stalling
try deleting the files in ~/.tor or /var/lib/tor.
-You will be able to see byte counts flowing in both browsers displaying
-swfcat.swf (client and proxy), and eventually be able to build a circuit.
+You will be able to see byte counts flowing in the browser window, and
+eventually be able to build a circuit.
== Rationale
@@ -92,16 +110,15 @@ policy.
Clients register with the facilitator by sending an HTTP message:
POST / HTTP/1.0\r\n
\r\n
- client=<CIRRUS-CLIENT-ID>
+ client=<ip-addr/rtmfp-id>
The Flash proxy also gets a client address over HTTP:
GET / HTTP/1.0\r\n
\r\n
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=<CIRRUS-CLIENT-ID>&relay=9.9.9.9:9001
+ client=<ip-addr/rtmfp-id>&relay=<relay-ip>
== ActionScript programming
diff --git a/design.txt b/design.txt
index 27be8ab..2d5ad2b 100644
--- a/design.txt
+++ b/design.txt
@@ -101,13 +101,19 @@ Design of Flash proxies
On startup, the connector sends a registration message to the
facilitator, informing the facilitator that it is waiting for a
connection. The facilitator will later hand this registration to a
- Flash proxy. The registration message is an HTTP POST request of this
+ Flash proxy. The registration message is an HTTP POST request of the
form:
POST / HTTP/1.0
client=[<address>]:<port>
+ or the form:
+
+ POST / HTTP/1.0
+
+ client=[<rtmfp-id>]:<port>
+
The facilitator sends a 200 reply if the registration was successful
and an error status otherwise. If the connector omits the [<address>]
part, the facilitator will automatically fill it in based on the HTTP
@@ -141,11 +147,14 @@ Design of Flash proxies
client=[<address>:<port>]&relay=<address>:<port>
- If <address>:<port> is missing, it means that there are no client
- registrations for this proxy.
+ or this:
+
+ client=[<rtmfp-id>]&relay=<address>:<port>
+
+ If the value for the client parameter is empty, it means that there are no
+ client registrations for this proxy.
- The Flash proxy may serve more than one relay–client pair at once. It
- limits its own bandwidth to 10 KB/s (combined upload/download).
+ The Flash proxy may serve more than one relay–client pair at once.
8. Behavior of the facilitator
1
0
commit 3cfcc0dcab1f8235bc847b12b03e265006575382
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 13:47:53 2011 -0700
Make parse_addr_spec static.
Uniformity with master.
---
swfcat.as | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index d24c833..e75ffac 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -260,7 +260,7 @@ package
/* 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
+ private static function parse_addr_spec(spec:String):Object
{
var parts:Array;
var addr:Object;
1
0
commit c9df47139a3e9ad3a2412dcb4bc85b5b3c322bce
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 14:15:55 2011 -0700
Move ProxyPair into its own file.
---
Makefile | 2 +-
ProxyPair.as | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
swfcat.as | 154 ---------------------------------------------------------
3 files changed, 157 insertions(+), 155 deletions(-)
diff --git a/Makefile b/Makefile
index 7f81cf9..ed799c6 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ TARGETS = swfcat.swf
all: $(TARGETS)
-swfcat.swf: badge.png
+swfcat.swf: *.as badge.png
%.swf: %.as
$(MXMLC) -output $@ -static-link-runtime-shared-libraries $<
diff --git a/ProxyPair.as b/ProxyPair.as
new file mode 100644
index 0000000..ead6e00
--- /dev/null
+++ b/ProxyPair.as
@@ -0,0 +1,156 @@
+package
+{
+ 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;
+
+ /* An instance of a client-relay connection. */
+ public 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.
+ 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)
+ {
+ this.ui = ui;
+ this.addr_c = addr_c;
+ this.addr_r = addr_r;
+
+ this.c2r_schedule = [];
+ this.r2c_schedule = [];
+ }
+
+ /* Return a function that shows an error message and closes the other half
+ of a communication pair. */
+ private function socket_error(message:String, other:Socket):Function
+ {
+ return function(e:Event):void {
+ if (e is TextEvent)
+ log(message + ": " + (e as TextEvent).text + ".");
+ else
+ log(message + ".");
+ if (other && other.connected)
+ other.close();
+ dispatchEvent(new Event(Event.COMPLETE));
+ };
+ }
+
+ public function connect():void
+ {
+ s_r = new Socket();
+
+ s_r.addEventListener(Event.CONNECT, relay_connected);
+ s_r.addEventListener(Event.CLOSE, socket_error("Relay: closed", s_c));
+ s_r.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Relay: I/O error", s_c));
+ s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Relay: security error", s_c));
+ 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);
+ }
+
+ private function relay_connected(e:Event):void
+ {
+ log("Relay: connected.");
+
+ s_c = new Socket();
+
+ s_c.addEventListener(Event.CONNECT, client_connected);
+ s_c.addEventListener(Event.CLOSE, socket_error("Client: closed", s_r));
+ s_c.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Client: I/O error", s_r));
+ s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Client: security error", s_r));
+ 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);
+ }
+
+ private function relay_to_client(e:ProgressEvent):void
+ {
+ r2c_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ private function client_to_relay(e:ProgressEvent):void
+ {
+ c2r_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ private function client_connected(e:Event):void
+ {
+ log("Client: connected.");
+ }
+
+ private function transfer_chunk(s_from:Socket, s_to:Socket, n:uint,
+ label:String):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 + ".");
+ }
+
+ /* 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_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);
+ }
+ }
+}
diff --git a/swfcat.as b/swfcat.as
index 8d893b2..b8e198a 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -210,20 +210,9 @@ 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;
-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.getTimer;
-import flash.utils.setTimeout;
class Badge extends flash.display.Sprite
{
@@ -400,146 +389,3 @@ class BucketRateLimit extends RateLimit
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.
- 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)
- {
- this.ui = ui;
- this.addr_c = addr_c;
- this.addr_r = addr_r;
-
- this.c2r_schedule = [];
- this.r2c_schedule = [];
- }
-
- /* Return a function that shows an error message and closes the other half
- of a communication pair. */
- private function socket_error(message:String, other:Socket):Function
- {
- return function(e:Event):void {
- if (e is TextEvent)
- log(message + ": " + (e as TextEvent).text + ".");
- else
- log(message + ".");
- if (other && other.connected)
- other.close();
- dispatchEvent(new Event(Event.COMPLETE));
- };
- }
-
- public function connect():void
- {
- s_r = new Socket();
-
- s_r.addEventListener(Event.CONNECT, relay_connected);
- s_r.addEventListener(Event.CLOSE, socket_error("Relay: closed", s_c));
- s_r.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Relay: I/O error", s_c));
- s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Relay: security error", s_c));
- 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);
- }
-
- private function relay_connected(e:Event):void
- {
- log("Relay: connected.");
-
- s_c = new Socket();
-
- s_c.addEventListener(Event.CONNECT, client_connected);
- s_c.addEventListener(Event.CLOSE, socket_error("Client: closed", s_r));
- s_c.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Client: I/O error", s_r));
- s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Client: security error", s_r));
- 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);
- }
-
- private function relay_to_client(e:ProgressEvent):void
- {
- r2c_schedule.push(e.bytesLoaded);
- flush();
- }
-
- private function client_to_relay(e:ProgressEvent):void
- {
- c2r_schedule.push(e.bytesLoaded);
- flush();
- }
-
- private function client_connected(e:Event):void
- {
- log("Client: connected.");
- }
-
- private function transfer_chunk(s_from:Socket, s_to:Socket, n:uint,
- label:String):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 + ".");
- }
-
- /* 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_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);
- }
-}
1
0
[flashproxy/master] Move the rate limit back into swfcat from ProxyPair.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 832f6bcf7fda65054a553aeeaf569d493030bf85
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 14:03:08 2011 -0700
Move the rate limit back into swfcat from ProxyPair.
It should be global, not per-ProxyPair. Also uniformity with master.
---
ProxyPair.as | 117 ++--------------------------------------------------------
swfcat.as | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 113 deletions(-)
diff --git a/ProxyPair.as b/ProxyPair.as
index 6ca60ef..fa51933 100644
--- a/ProxyPair.as
+++ b/ProxyPair.as
@@ -30,13 +30,6 @@ package
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;
@@ -51,11 +44,6 @@ package
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 */
@@ -147,25 +135,25 @@ package
/* Can't do anything until connected. */
return;
- while (!rate_limit.is_limited() && (c2r_schedule.length > 0 || r2c_schedule.length > 0)) {
+ while (!ui.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);
+ ui.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);
+ ui.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);
+ flush_id = setTimeout(flush, ui.rate_limit.when() * 1000);
}
/* Helper function to write output to the
@@ -177,100 +165,3 @@ package
}
}
}
-
-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 --git a/swfcat.as b/swfcat.as
index e75ffac..42bcfea 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -41,6 +41,11 @@ package
// 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;
+
// Socket to Cirrus server
private var s_c:CirrusSocket;
// Socket to facilitator.
@@ -65,6 +70,8 @@ package
private var fac_addr:Object;
private var relay_addr:Object;
+ public var rate_limit:RateLimit;
+
public function swfcat()
{
proxy_mode = false;
@@ -73,6 +80,11 @@ package
// Absolute positioning.
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
+
+ if (RATE_LIMIT)
+ rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
+ else
+ rate_limit = new RateUnlimit();
// Wait until the query string parameters are loaded.
this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
@@ -279,6 +291,7 @@ package
import flash.text.TextFormat;
import flash.text.TextField;
+import flash.utils.getTimer;
class Badge extends flash.display.Sprite
{
@@ -360,3 +373,98 @@ class Badge extends flash.display.Sprite
cur_client_count_tf.appendText(".");
}
}
+
+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;
+ }
+}
1
0
12 Jun '11
commit 024e47f75fa52f3fa65659e05f0e8e6358b59285
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 13:34:30 2011 -0700
Refactor InternetFreedomBadge (now Badge).
Make it its own Sprite, don't cause it to change the UI of the main
display. Use proxy_begin and proxy_end methods instead of modifying
current/total counts directly.
---
swfcat.as | 76 ++++++++++++++++++++++--------------------------------------
1 files changed, 28 insertions(+), 48 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index d0aad9a..d24c833 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -60,7 +60,7 @@ package
private var output_text:TextField;
/* Badge for display */
- private var badge:InternetFreedomBadge;
+ private var badge:Badge;
private var fac_addr:Object;
private var relay_addr:Object;
@@ -94,8 +94,8 @@ package
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();
+ badge = new Badge();
+ addChild(badge);
} else {
output_text = new TextField();
output_text.width = stage.stageWidth;
@@ -170,8 +170,7 @@ package
start_proxy_pair();
s_c.send_hello(e.peer);
} else if (!debug_mode && badge != null) {
- badge.total_proxy_pairs++;
- badge.num_proxy_pairs++;
+ badge.proxy_begin();
}
p_p.client = {peer: e.peer, stream: e.stream};
@@ -234,7 +233,7 @@ package
puts("ProxyPair: connection closed.");
p_p = null;
if (proxy_mode && !debug_mode && badge != null) {
- badge.num_proxy_pairs--;
+ badge.proxy_end();
}
establish_facilitator_connection();
});
@@ -278,29 +277,25 @@ package
}
}
-import flash.text.TextField;
import flash.text.TextFormat;
+import flash.text.TextField;
+
+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;
-class InternetFreedomBadge {
-
- private var ui:swfcat;
-
- 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)
+
+ public function Badge()
{
- 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;
@@ -330,42 +325,27 @@ class InternetFreedomBadge {
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 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
+
+ public function proxy_begin():void
{
- _num_proxy_pairs = amount;
+ num_proxy_pairs++;
+ total_proxy_pairs++;
update_client_count();
}
-
- public function get total_proxy_pairs():uint
- {
- return _total_proxy_pairs;
- }
-
- public function set total_proxy_pairs(amount:uint):void
+
+ public function proxy_end():void
{
- _total_proxy_pairs = amount;
- /* note: doesn't update, so be sure to update this
- before you update num_proxy_pairs! */
+ num_proxy_pairs--;
+ update_client_count();
}
-
+
private function update_client_count():void
{
/* Update total client count. */
1
0
[flashproxy/master] Do RTMFP client and proxy using the new RTMFPSocket and ProxyPair.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit b631fc0bc82957e07ad2a18ca1747eced2d6ca6e
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 00:25:39 2011 -0700
Do RTMFP client and proxy using the new RTMFPSocket and ProxyPair.
---
swfcat.as | 294 ++++++++++++++++++++++++++++++++++---------------------------
1 files changed, 163 insertions(+), 131 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index ac52ec8..6125187 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -5,26 +5,24 @@ package
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.net.URLRequestMethod;
+ import flash.net.URLVariables;
import flash.events.Event;
+ import flash.events.IOErrorEvent;
+ import flash.events.SecurityErrorEvent;
import flash.utils.setTimeout;
- import FacilitatorSocket;
- import events.FacilitatorSocketEvent;
-
- import ProxyPair;
- import RTMFPProxyPair;
- 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;
+ private const CIRRUS_URL:String = "rtmfp://p2p.rtmfp.net";
+ private const CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
private const DEFAULT_FACILITATOR_ADDR:Object = {
host: "tor-facilitator.bamsoftware.com",
@@ -47,17 +45,6 @@ package
// Seconds.
private const RATE_LIMIT_HISTORY:Number = 5.0;
- // 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 relay_addr:Object;
-
private var proxy_mode:Boolean;
/* TextField for debug output. */
@@ -124,7 +111,10 @@ package
return;
}
- main();
+ if (proxy_mode)
+ proxy_main();
+ else
+ client_main();
}
/* Get an address structure from the given movie parameter, or the given
@@ -141,129 +131,171 @@ package
}
/* The main logic begins here, after start-up issues are taken care of. */
- private function main():void
+ private function proxy_main():void
{
- if (proxy_mode) {
- establish_facilitator_connection();
- } else {
- establish_cirrus_connection();
+ var fac_url:String;
+ var loader:URLLoader;
+
+ if (num_proxy_pairs >= MAX_NUM_PROXY_PAIRS) {
+ setTimeout(proxy_main, FACILITATOR_POLL_INTERVAL);
+ return;
}
- }
- 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_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.");
+ 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 + ".");
});
- 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 {
- num_proxy_pairs++;
- badge.proxy_begin();
- }
-
- p_p.client = {peer: e.peer, stream: e.stream};
+ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ puts("Facilitator: security error: " + e.text + ".");
});
-
- s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
+
+ fac_url = "http://" + encodeURIComponent(fac_addr.host)
+ + ":" + encodeURIComponent(fac_addr.port) + "/";
+ puts("Facilitator: connecting to " + fac_url + ".");
+ loader.load(new URLRequest(fac_url));
}
- private function establish_facilitator_connection():void
+ private function fac_complete(e:Event):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, FACILITATOR_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, FACILITATOR_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, FACILITATOR_POLL_INTERVAL);
- });
- puts("Facilitator: posting registration.");
- s_f.post_registration(s_c.id);
+ var loader:URLLoader;
+ var client_spec:String;
+ var relay_spec:String;
+ var proxy_pair:Object;
+
+ setTimeout(proxy_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 + "\".");
+
+ try {
+ proxy_pair = make_proxy_pair(client_spec, relay_spec);
+ } catch (e:ArgumentError) {
+ puts("Error: " + e);
+ return;
+ }
+ proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
+ proxy_pair.log("Complete.");
+ num_proxy_pairs--;
+ badge.proxy_end();
+ });
+ proxy_pair.connect();
+
+ num_proxy_pairs++;
+ badge.proxy_begin();
}
-
- private function start_proxy_pair():void
+
+ private function client_main():void
{
- p_p = proxy_pair_factory();
- p_p.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("ProxyPair: connected!");
+ var rs:RTMFPSocket;
+
+ rs = new RTMFPSocket(CIRRUS_URL, CIRRUS_KEY);
+ rs.addEventListener(Event.COMPLETE, function (e:Event):void {
+ puts("Got RTMFP id " + rs.id);
+ register(rs);
});
- p_p.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("ProxyPair: connection closed.");
- p_p = null;
- if (proxy_mode) {
- num_proxy_pairs--;
- badge.proxy_end();
- }
- establish_facilitator_connection();
+ rs.addEventListener(RTMFPSocket.ACCEPT_EVENT, client_accept);
+
+ rs.listen();
+ }
+
+ private function client_accept(e:Event):void {
+ var rs:RTMFPSocket;
+ var s_t:Socket;
+ var proxy_pair:ProxyPair;
+
+ rs = e.target as RTMFPSocket;
+ s_t = new Socket();
+
+ puts("Got RTMFP connection from " + rs.peer_id);
+
+ proxy_pair = new ProxyPair(this, rs, function ():void {
+ /* Do nothing; already connected. */
+ }, s_t, function ():void {
+ s_t.connect(DEFAULT_TOR_CLIENT_ADDR.host, DEFAULT_TOR_CLIENT_ADDR.port);
});
- p_p.relay = relay_addr;
+ proxy_pair.connect();
}
-
- private function rtmfp_proxy_pair_factory():ProxyPair
- {
- return new RTMFPProxyPair(this, s_c, s_c.local_stream_name);
+
+ private function register(rs:RTMFPSocket):void {
+ var fac_url:String;
+ var loader:URLLoader;
+ var request:URLRequest;
+ var variables:URLVariables;
+
+ loader = new URLLoader();
+ loader.addEventListener(Event.COMPLETE, function (e:Event):void {
+ puts("Facilitator: registered.");
+ });
+ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ puts("Facilitator: security error: " + e.text + ".");
+ rs.close();
+ });
+ loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
+ puts("Facilitator: I/O error: " + e.text + ".");
+ rs.close();
+ });
+
+ fac_url = "http://" + encodeURIComponent(fac_addr.host)
+ + ":" + encodeURIComponent(fac_addr.port) + "/";
+ request = new URLRequest(fac_url);
+ request.method = URLRequestMethod.POST;
+ request.data = new URLVariables;
+ request.data["client"] = rs.id;
+
+ puts("Facilitator: connecting to " + fac_url + ".");
+ loader.load(request);
}
-
- private function tcp_proxy_pair_factory():ProxyPair
+
+ private function make_proxy_pair(client_spec:String, relay_spec:String):ProxyPair
{
- return new TCPProxyPair(this);
+ var addr_c:Object;
+ var addr_r:Object;
+ var s_c:*;
+ var s_r:Socket;
+
+ addr_r = swfcat.parse_addr_spec(relay_spec);
+ if (!addr_r)
+ throw new ArgumentError("Relay spec must be in the form \"host:port\".");
+
+ addr_c = swfcat.parse_addr_spec(client_spec);
+ if (addr_c) {
+ s_c = new Socket();
+ s_r = new Socket();
+ return new ProxyPair(this, s_c, function ():void {
+ s_c.connect(addr_c.host, addr_c.port);
+ }, s_r, function ():void {
+ s_r.connect(addr_r.host, addr_r.port);
+ });
+ }
+
+ if (client_spec.match(/^[0-9A-Fa-f]{64}$/)) {
+ s_c = new RTMFPSocket(CIRRUS_URL, CIRRUS_KEY);
+ s_r = new Socket();
+ return new ProxyPair(this, s_c, function ():void {
+ s_c.connect(client_spec);
+ }, s_r, function ():void {
+ s_r.connect(addr_r.host, addr_r.port);
+ });
+ }
+
+ throw new ArgumentError("Can't parse client spec \"" + client_spec + "\".");
}
/* Parse an address in the form "host:port". Returns an Object with
1
0
commit 53aecf9837f1dd95d005aaea8a116907488927ea
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 22:19:30 2011 -0700
Remove unused code.
---
FacilitatorSocket.as | 100 ------------------
RTMFPProxyPair.as | 101 ------------------
TCPProxyPair.as | 77 --------------
events/FacilitatorSocketEvent.as | 24 -----
rtmfp/CirrusSocket.as | 142 --------------------------
rtmfp/RTMFPSocket.as | 202 -------------------------------------
rtmfp/RTMFPSocketClient.as | 46 ---------
rtmfp/events/CirrusSocketEvent.as | 22 ----
rtmfp/events/RTMFPSocketEvent.as | 25 -----
9 files changed, 0 insertions(+), 739 deletions(-)
diff --git a/FacilitatorSocket.as b/FacilitatorSocket.as
deleted file mode 100644
index 70325c1..0000000
--- a/FacilitatorSocket.as
+++ /dev/null
@@ -1,100 +0,0 @@
-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;
- 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;
- loader.load(request);
- }
-
- private function on_complete_event(event:Event):void
- {
- try {
- var client_id:String = event.target.data.client;
- 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, 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_io_error_event(event:IOErrorEvent):void
- {
- fail();
- }
-
- private function on_security_error_event(event:SecurityErrorEvent):void
- {
- fail();
- }
-
- private function get url():String
- {
- return "http://" + encodeURIComponent(host)
- + ":" + encodeURIComponent(port.toString()) + "/";
- }
- }
-}
diff --git a/RTMFPProxyPair.as b/RTMFPProxyPair.as
deleted file mode 100644
index 346d63c..0000000
--- a/RTMFPProxyPair.as
+++ /dev/null
@@ -1,101 +0,0 @@
-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
deleted file mode 100644
index de18dd6..0000000
--- a/TCPProxyPair.as
+++ /dev/null
@@ -1,77 +0,0 @@
-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, 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 --git a/events/FacilitatorSocketEvent.as b/events/FacilitatorSocketEvent.as
deleted file mode 100644
index 5787309..0000000
--- a/events/FacilitatorSocketEvent.as
+++ /dev/null
@@ -1,24 +0,0 @@
-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, relay:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- this.client = client;
- this.relay = relay;
- }
- }
-}
diff --git a/rtmfp/CirrusSocket.as b/rtmfp/CirrusSocket.as
deleted file mode 100644
index 071ac0d..0000000
--- a/rtmfp/CirrusSocket.as
+++ /dev/null
@@ -1,142 +0,0 @@
-/* CirrusSocket abstraction
- * ------------------------
- * Manages the NetConnection portion of RTMFP and also handles
- * the handshake between two Flash players to decide what their
- * data stream names will be.
- *
- * TODO: consider using farNonce/nearNonce instead of sending bytes?
- */
-
-package rtmfp
-{
- 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.net.NetConnection;
- import flash.utils.clearInterval;
- import flash.utils.setInterval;
-
- import rtmfp.RTMFPSocket;
- import rtmfp.events.CirrusSocketEvent;
- import rtmfp.events.RTMFPSocketEvent;
-
- [Event(name=CirrusSocketEvent.CONNECT_CLOSED, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- [Event(name=CirrusSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- [Event(name=CirrusSocketEvent.CONNECT_SUCCESS, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- [Event(name=CirrusSocketEvent.HELLO_RECEIVED, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- public class CirrusSocket extends EventDispatcher
- {
- private static const CONNECT_TIMEOUT:uint = 4000; // in milliseconds
-
- /* We'll append a unique number to the DATA_STREAM_PREFIX for each
- new stream we create so that we have unique streams per player. */
- private static const DATA_STREAM_PREFIX:String = "DATA";
- private var data_stream_suffix:uint = 0;
-
- /* Connection to the Cirrus rendezvous service */
- public var connection:NetConnection;
-
- /* Timeouts */
- private var connect_timeout:int;
- private var hello_timeout:int;
-
- public function CirrusSocket()
- {
- connection = new NetConnection();
- connection.addEventListener(NetStatusEvent.NET_STATUS, on_net_status_event);
- connection.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
- connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
-
- /* Set up a client object to handle the hello callback */
- var client:Object = new Object();
- client.onRelay = on_hello;
- connection.client = client;
- }
-
- public function connect(addr:String, key:String):void
- {
- if (!this.connected) {
- connect_timeout = setInterval(fail, CONNECT_TIMEOUT);
- connection.connect(addr, key);
- } else {
- throw new Error("Cannot connect Cirrus socket: already connected.");
- }
- }
-
- public function close():void
- {
- if (this.connected) {
- connection.close();
- } else {
- throw new Error("Cannot close Cirrus socket: not connected.");
- }
- }
-
- public function get connected():Boolean
- {
- return (connection != null && connection.connected);
- }
-
- public function get id():String
- {
- if (this.connected) {
- return connection.nearID;
- }
-
- return null;
- }
-
- public function get local_stream_name():String
- {
- return DATA_STREAM_PREFIX + data_stream_suffix;
- }
-
- /* Sends a hello message to the Flash player with Cirrus ID "id"
- We use this new call protocol outlined here:
- http://forums.adobe.com/thread/780788?tstart=0 */
- public function send_hello(id:String):void
- {
- if (this.connected) {
- connection.call("relay", null, id, local_stream_name);
- } else {
- throw new Error("Cannot send hello: Cirrus socket not connected.");
- }
- }
-
-/*************************** PRIVATE HELPER FUNCTIONS *************************/
-
- private function fail():void
- {
- clearInterval(connect_timeout);
- dispatchEvent(new CirrusSocketEvent(CirrusSocketEvent.CONNECT_FAILED));
- }
-
- private function on_hello(peer:String, ...args):void
- {
- var stream:String = args[0];
- dispatchEvent(new CirrusSocketEvent(CirrusSocketEvent.HELLO_RECEIVED, peer, stream));
- data_stream_suffix++;
- }
-
- private function on_io_error_event(event:IOErrorEvent):void
- {
- fail();
- }
-
- private function on_net_status_event(event:NetStatusEvent):void
- {
- if (event.info.code == "NetConnection.Connect.Success") {
- clearInterval(connect_timeout);
- dispatchEvent(new CirrusSocketEvent(CirrusSocketEvent.CONNECT_SUCCESS));
- }
- }
-
- private function on_security_error_event(event:SecurityErrorEvent):void
- {
- fail();
- }
- }
-}
diff --git a/rtmfp/RTMFPSocket.as b/rtmfp/RTMFPSocket.as
deleted file mode 100644
index 4efe702..0000000
--- a/rtmfp/RTMFPSocket.as
+++ /dev/null
@@ -1,202 +0,0 @@
-package rtmfp
-{
- 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.net.NetConnection;
- import flash.net.NetStream;
- import flash.utils.ByteArray;
- import flash.utils.clearTimeout;
- import flash.utils.setTimeout;
-
- import rtmfp.CirrusSocket;
- import rtmfp.RTMFPSocketClient;
- import rtmfp.events.CirrusSocketEvent;
- import rtmfp.events.RTMFPSocketEvent;
-
- [Event(name=RTMFPSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.CONNECT_CLOSED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.CONNECT_SUCCESS, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PEER_CONNECTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PEER_DISCONNECTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PLAY_STARTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PUBLISH_STARTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PUBLISH_FAILED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- public class RTMFPSocket extends EventDispatcher
- {
- private const CONNECT_TIMEOUT:uint = 10000;
-
- private var s_c:CirrusSocket;
-
- private var recv_stream:NetStream;
- private var send_stream:NetStream;
-
- private var peer_stream:NetStream;
-
- private var connect_timeout:int;
-
- public function RTMFPSocket(s_c:CirrusSocket)
- {
- this.s_c = s_c;
- recv_stream = null;
- send_stream = null;
- connect_timeout = 0;
- }
-
- /* Tears down this RTMFPSocket, closing both its streams.
- To be used when destroying this object. */
- public function close():void
- {
- if (send_stream != null) {
- s_c.connection.removeEventListener(NetStatusEvent.NET_STATUS, on_stream_disconnection_event);
- send_stream.close();
- }
-
- if (recv_stream != null) {
- recv_stream.close();
- }
- }
-
- /* In RTMFP, you connect to a remote socket by requesting to
- "play" the data being published on a named stream by the
- host identified by id. The connection request goes through
- the Cirrus server which handles the mapping from id/stream
- to IP/port and any necessary NAT traversal. */
- public function connect(id:String, stream:String):void
- {
- recv_stream = new NetStream(s_c.connection, id);
- var client:RTMFPSocketClient = new RTMFPSocketClient();
- client.addEventListener(ProgressEvent.SOCKET_DATA, on_data_available, false, 0, true);
- client.addEventListener(RTMFPSocketClient.CONNECT_ACKNOWLEDGED, on_connect_acknowledged, false, 0, true);
- recv_stream.client = client;
- recv_stream.addEventListener(NetStatusEvent.NET_STATUS, on_recv_stream_event);
- recv_stream.play(stream);
- connect_timeout = setTimeout(on_connect_timeout, CONNECT_TIMEOUT, recv_stream);
- }
-
- public function get connected():Boolean
- {
- return (recv_stream != null && recv_stream.client != null &&
- RTMFPSocketClient(recv_stream.client).connect_acknowledged);
- }
-
- /* In RTMFP, you open a listening socket by publishing a named
- stream that others can connect to instead of listening on a port.
- You register this stream with the Cirrus server via the Cirrus
- socket so that it can redirect connection requests for an id/stream
- tuple to this socket. */
- public function listen(stream:String):void
- {
- // apparently streams don't get disconnection events, only the NetConnection
- // object does...bleh.
- s_c.connection.addEventListener(NetStatusEvent.NET_STATUS, on_stream_disconnection_event);
-
- send_stream = new NetStream(s_c.connection, NetStream.DIRECT_CONNECTIONS);
- send_stream.addEventListener(NetStatusEvent.NET_STATUS, on_send_stream_event);
- var client:Object = new Object();
- client.onPeerConnect = on_peer_connect;
- send_stream.client = client;
- send_stream.publish(stream);
- }
-
- public function get peer():String
- {
- if (!connected) return null;
- return recv_stream.farID;
- }
-
- public function get peer_connected():Boolean
- {
- return send_stream.peerStreams.length > 0;
- }
-
- public function readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void
- {
- if (recv_stream != null && recv_stream.client != null) {
- recv_stream.client.bytes.readBytes(bytes, offset, length);
- }
- }
-
- public function writeBytes(bytes:ByteArray):void
- {
- if (send_stream != null && peer_connected) {
- send_stream.send(RTMFPSocketClient.DATA_AVAILABLE, bytes);
- }
- }
-
- /* Listens for acknowledgement of a connection attempt to a
- remote peer. */
- private function on_connect_acknowledged(event:Event):void
- {
- clearTimeout(connect_timeout);
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_SUCCESS, recv_stream));
- }
-
- /* If we don't get a connection acknowledgement by the time this
- timeout function is called, we punt. */
- private function on_connect_timeout(peer:NetStream):void
- {
- if (!this.connected) {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_FAILED, recv_stream));
- }
- }
-
- private function on_data_available(event:ProgressEvent):void
- {
- dispatchEvent(event);
- }
-
- private function on_recv_stream_event(event:NetStatusEvent):void
- {
- /* empty, here for symmetry */
- }
-
- /* This function gets called whenever someone tries to connect
- to this socket's send_stream tuple. We don't want multiple
- peers connecting at once, so we disallow that. The socket
- acknowledges the connection back to the peer with the
- SET_CONNECTION_ACKNOWLEDGED message. */
- private function on_peer_connect(peer:NetStream):Boolean
- {
- if (peer_connected) {
- return false;
- }
-
- peer_stream = peer;
- peer.send(RTMFPSocketClient.SET_CONNECT_ACKNOWLEDGED);
-
- // need to do this in a timeout so that this function can
- // return true to finalize the connection before firing the event
- setTimeout(function (stream:NetStream):void {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_CONNECTED, stream));
- }, 0, peer);
-
- return true;
- }
-
- private function on_send_stream_event(event:NetStatusEvent):void
- {
- switch (event.info.code) {
- case "NetStream.Publish.Start":
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PUBLISH_STARTED));
- break;
- case "NetStream.Publish.BadName":
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PUBLISH_FAILED));
- break;
- default:
- break;
- }
- }
-
- private function on_stream_disconnection_event(event:NetStatusEvent):void
- {
- if (event.info.code == "NetStream.Connect.Closed" && event.info.stream === peer_stream) {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_DISCONNECTED));
- }
- }
- }
-}
-
diff --git a/rtmfp/RTMFPSocketClient.as b/rtmfp/RTMFPSocketClient.as
deleted file mode 100644
index b917bcb..0000000
--- a/rtmfp/RTMFPSocketClient.as
+++ /dev/null
@@ -1,46 +0,0 @@
-package rtmfp
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.ProgressEvent;
- import flash.utils.ByteArray;
-
- [Event(name=RTMFPSocketClient.CONNECT_ACKNOWLEDGED, type="flash.events.Event")]
- public dynamic class RTMFPSocketClient extends EventDispatcher {
- public static const DATA_AVAILABLE:String = "data_available";
- public static const CONNECT_ACKNOWLEDGED:String = "connectAcknowledged";
- public static const SET_CONNECT_ACKNOWLEDGED:String = "set_connect_acknowledged";
-
- private var _bytes:ByteArray;
- private var _connect_acknowledged:Boolean;
-
- public function RTMFPSocketClient()
- {
- super();
- _bytes = new ByteArray();
- _connect_acknowledged = false;
- }
-
- public function get bytes():ByteArray
- {
- return _bytes;
- }
-
- public function data_available(bytes:ByteArray):void
- {
- bytes.readBytes(_bytes, _bytes.length, 0);
- dispatchEvent(new ProgressEvent(ProgressEvent.SOCKET_DATA, false, false, _bytes.bytesAvailable, _bytes.bytesAvailable));
- }
-
- public function get connect_acknowledged():Boolean
- {
- return _connect_acknowledged;
- }
-
- public function set_connect_acknowledged():void
- {
- _connect_acknowledged = true;
- dispatchEvent(new Event(CONNECT_ACKNOWLEDGED));
- }
- }
-}
diff --git a/rtmfp/events/CirrusSocketEvent.as b/rtmfp/events/CirrusSocketEvent.as
deleted file mode 100644
index 831ad73..0000000
--- a/rtmfp/events/CirrusSocketEvent.as
+++ /dev/null
@@ -1,22 +0,0 @@
-package rtmfp.events
-{
- import flash.events.Event;
-
- public class CirrusSocketEvent 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 HELLO_RECEIVED:String = "helloReceived";
-
- public var peer:String;
- public var stream:String;
-
- public function CirrusSocketEvent(type:String, peer:String = null, stream:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- this.peer = peer;
- this.stream = stream;
- }
- }
-}
diff --git a/rtmfp/events/RTMFPSocketEvent.as b/rtmfp/events/RTMFPSocketEvent.as
deleted file mode 100644
index 87a7e09..0000000
--- a/rtmfp/events/RTMFPSocketEvent.as
+++ /dev/null
@@ -1,25 +0,0 @@
-package rtmfp.events
-{
- import flash.events.Event;
- import flash.net.NetStream;
-
- public class RTMFPSocketEvent extends Event
- {
- public static const CONNECT_FAILED:String = "connectFailed";
- public static const CONNECT_SUCCESS:String = "connectSuccess";
- public static const CONNECT_CLOSED:String = "connectClosed"
- public static const PEER_CONNECTED:String = "peerConnected";
- public static const PEER_DISCONNECTED:String = "peerDisconnected";
- public static const PLAY_STARTED:String = "playStarted";
- public static const PUBLISH_STARTED:String = "publishStarted";
- public static const PUBLISH_FAILED:String = "publishFailed";
-
- public var stream:NetStream;
-
- public function RTMFPSocketEvent(type:String, stream:NetStream = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- this.stream = stream;
- }
- }
-}
1
0
[flashproxy/master] Show the debug window output always in client mode.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 67ac951f4b75983d1329edab7ab781f0caafd28c
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 01:24:53 2011 -0700
Show the debug window output always in client mode.
---
swfcat.as | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index 27752e9..9739419 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -96,7 +96,7 @@ package
puts("Parameters loaded.");
- if (this.loaderInfo.parameters["debug"])
+ if (this.loaderInfo.parameters["debug"] || this.loaderInfo.parameters["client"])
addChild(output_text);
else
addChild(badge);
1
0
commit 9a85e5b90a37c8c989cda04f69862b82f25ca924
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 21:26:55 2011 -0700
Add an RTMFPSocket class.
---
RTMFPSocket.as | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 209 insertions(+), 0 deletions(-)
diff --git a/RTMFPSocket.as b/RTMFPSocket.as
new file mode 100644
index 0000000..e23c4fd
--- /dev/null
+++ b/RTMFPSocket.as
@@ -0,0 +1,209 @@
+/*
+The RTMFPSocket class provides a socket-like interface around RTMFP
+NetConnection and NetStream. Each RTMFPSocket contains one NetConnection and two
+NetStreams, one for reading and one for writing.
+
+To create a listening socket:
+ var rs:RTMFPSocket = new RTMFPSocket(url, key);
+ rs.addEventListener(Event.COMPLETE, function (e:Event):void {
+ // rs.id is set and can be sent out of band to the client.
+ });
+ rs.addEventListener(RTMFPSocket.ACCEPT_EVENT, function (e:Event):void {
+ // rs.peer_id is the ID of the connected client.
+ });
+ rs.listen();
+To connect to a listening socket:
+ // Receive peer_id out of band.
+ var rs:RTMFPSocket = new RTMFPSocket(url, key);
+ rs.addEventListener(Event.CONNECT, function (e:Event):void {
+ // rs.id and rs.peer_id are now set.
+ });
+*/
+
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.NetStatusEvent;
+ import flash.events.ProgressEvent;
+ import flash.net.NetConnection;
+ import flash.net.NetStream;
+ import flash.utils.ByteArray;
+
+ public class RTMFPSocket extends EventDispatcher
+ {
+ public static const ACCEPT_EVENT:String = "accept";
+
+ public var connected:Boolean;
+
+ private var nc:NetConnection;
+ private var incoming:NetStream;
+ private var outgoing:NetStream;
+
+ /* Cache to hold the peer ID between when connect is called and the
+ NetConnection exists. */
+ private var connect_peer_id:String;
+
+ private var buffer:ByteArray;
+
+ private var cirrus_url:String;
+ private var cirrus_key:String;
+
+ public function RTMFPSocket(cirrus_url:String, cirrus_key:String)
+ {
+ connected = false;
+
+ buffer = new ByteArray();
+
+ this.cirrus_url = cirrus_url;
+ this.cirrus_key = cirrus_key;
+
+ nc = new NetConnection();
+ }
+
+ public function get id():String
+ {
+ return nc.nearID;
+ }
+
+ public function get peer_id():String
+ {
+ return incoming.farID;
+ }
+
+ /* NetStatusEvents that aren't handled more specifically in
+ listen_netstatus_event or connect_netstatus_event. */
+ private function generic_netstatus_event(e:NetStatusEvent):void
+ {
+ switch (e.info.code) {
+ case "NetConnection.Connect.Closed":
+ dispatchEvent(new Event(Event.CLOSE));
+ break;
+ case "NetStream.Connect.Closed":
+ connected = false;
+ close();
+ break;
+ default:
+ var event:IOErrorEvent = new IOErrorEvent(IOErrorEvent.IO_ERROR);
+ event.text = e.info.code;
+ dispatchEvent(event);
+ break;
+ }
+ }
+
+ private function listen_netstatus_event(e:NetStatusEvent):void
+ {
+ switch (e.info.code) {
+ case "NetConnection.Connect.Success":
+ outgoing = new NetStream(nc, NetStream.DIRECT_CONNECTIONS);
+ outgoing.client = {
+ onPeerConnect: listen_onpeerconnect
+ };
+ outgoing.publish("server");
+
+ /* listen is complete, ready to accept. */
+ dispatchEvent(new Event(Event.COMPLETE));
+ break;
+ case "NetStream.Connect.Success":
+ break;
+ default:
+ return generic_netstatus_event(e);
+ break;
+ }
+ }
+
+ private function listen_onpeerconnect(peer:NetStream):Boolean {
+ incoming = new NetStream(nc, peer.farID);
+ incoming.client = {
+ r: receive_data
+ };
+ incoming.play("client");
+
+ connected = true;
+ dispatchEvent(new Event(ACCEPT_EVENT));
+
+ return true;
+ }
+
+ private function connect_netstatus_event(e:NetStatusEvent):void
+ {
+ switch (e.info.code) {
+ case "NetConnection.Connect.Success":
+ outgoing = new NetStream(nc, NetStream.DIRECT_CONNECTIONS);
+ outgoing.publish("client");
+
+ incoming = new NetStream(nc, connect_peer_id);
+ incoming.client = {
+ r: receive_data
+ };
+ incoming.play("server");
+ break;
+ case "NetStream.Connect.Success":
+ connected = true;
+ dispatchEvent(new Event(Event.CONNECT));
+ break;
+ default:
+ return generic_netstatus_event(e);
+ break;
+ }
+ }
+
+ /* Function called back when the other side does a send. */
+ private function receive_data(bytes:ByteArray):void {
+ var event:ProgressEvent;
+
+ event = new ProgressEvent(ProgressEvent.SOCKET_DATA);
+ event.bytesLoaded = bytes.bytesAvailable;
+
+ bytes.readBytes(buffer, buffer.length, bytes.bytesAvailable);
+ if (bytes.bytesAvailable == 0) {
+ /* Reclaim memory space. */
+ bytes.position = 0;
+ bytes.length = 0;
+ }
+
+ dispatchEvent(event);
+ }
+
+ public function listen():void
+ {
+ nc.addEventListener(NetStatusEvent.NET_STATUS, listen_netstatus_event);
+ nc.connect(cirrus_url, cirrus_key);
+ }
+
+ public function connect(peer_id:String):void
+ {
+ /* Store for later reading by connect_netstatus_event. */
+ this.connect_peer_id = peer_id;
+
+ nc.addEventListener(NetStatusEvent.NET_STATUS, connect_netstatus_event);
+ nc.connect(cirrus_url, cirrus_key);
+ }
+
+ public function close():void
+ {
+ outgoing.close();
+ incoming.close();
+ nc.close();
+ }
+
+ public function readBytes(output:ByteArray, offset:uint = 0, length:uint = 0):void
+ {
+ buffer.readBytes(output, offset, length);
+ }
+
+ public function writeBytes(input:ByteArray, offset:uint = 0, length:uint = 0):void
+ {
+ var sendbuf:ByteArray;
+
+ /* Read into a new buffer, in case offset and length do not
+ completely span input. */
+ sendbuf = new ByteArray();
+ sendbuf.writeBytes(input, offset, length);
+
+ /* Use a short method name because it's sent over the wire. */
+ outgoing.send("r", sendbuf);
+ }
+ }
+}
1
0