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] New version of rtmfpcat that works with reconnection
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 7c4ca7bf575684c35773605e522ee118c1f8f0bf
Author: Nate Hardison <nate(a)rescomp-09-154551.stanford.edu>
Date: Thu Jun 2 03:45:18 2011 -0700
New version of rtmfpcat that works with reconnection
---
Makefile | 2 +-
rtmfp/CirrusSocket.as | 140 +++++++++++++
rtmfp/FacilitatorSocket.as | 115 +++++++++++
rtmfp/ProxyPair.as | 125 ++++++++++++
rtmfp/RTMFPSocket.as | 340 +++++++++++++++-----------------
rtmfp/RTMFPSocketClient.as | 34 ++--
rtmfp/events/CirrusSocketEvent.as | 22 ++
rtmfp/events/FacilitatorSocketEvent.as | 22 ++
rtmfp/events/RTMFPSocketEvent.as | 13 +-
rtmfpcat.as | 240 ++++++++++++-----------
10 files changed, 729 insertions(+), 324 deletions(-)
diff --git a/Makefile b/Makefile
index bc1f8bf..3595385 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
MXMLC ?= mxmlc
-TARGETS = rtmfpcat.swf return_of_the_rtmfpcat.swf
+TARGETS = rtmfpcat.swf
all: $(TARGETS)
diff --git a/rtmfp/CirrusSocket.as b/rtmfp/CirrusSocket.as
new file mode 100644
index 0000000..d9996f2
--- /dev/null
+++ b/rtmfp/CirrusSocket.as
@@ -0,0 +1,140 @@
+/* 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);
+ 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/FacilitatorSocket.as b/rtmfp/FacilitatorSocket.as
new file mode 100644
index 0000000..e175290
--- /dev/null
+++ b/rtmfp/FacilitatorSocket.as
@@ -0,0 +1,115 @@
+package rtmfp
+{
+ 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.clearInterval;
+ import flash.utils.setInterval;
+
+ import rtmfp.events.FacilitatorSocketEvent;
+
+ [Event(name=FacilitatorSocketEvent.CONNECT_CLOSED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.CONNECT_SUCCESS, 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 socket:Socket;
+ private var connected:Boolean;
+ private var connection_timeout:uint;
+
+ public function FacilitatorSocket()
+ {
+ socket = null;
+ connected = false;
+ }
+
+ public function close():void
+ {
+ connected = false;
+ if (socket != null) {
+ socket.removeEventListener(Event.CONNECT, on_connect_event);
+ socket.removeEventListener(Event.CLOSE, on_close_event);
+ socket.removeEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
+ socket.removeEventListener(ProgressEvent.SOCKET_DATA, on_progress_event);
+ socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
+ if (connected) {
+ socket.close();
+ }
+ }
+ }
+
+ public function connect(host:String, port:uint):void
+ {
+ if (socket != null || connected) {
+ return;
+ }
+
+ socket = new Socket();
+ socket.addEventListener(Event.CONNECT, on_connect_event);
+ socket.addEventListener(Event.CLOSE, on_close_event);
+ socket.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
+ socket.addEventListener(ProgressEvent.SOCKET_DATA, on_progress_event);
+ socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
+ socket.connect(host, port);
+ }
+
+ public function get_registration():void
+ {
+ if (!connected) return;
+ socket.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
+ }
+
+ public function post_registration(registration_data:String):void
+ {
+ if (!connected) return;
+ socket.writeUTFBytes("POST / HTTP/1.0\r\n\r\nclient=" + registration_data + "\r\n");
+ }
+
+ private function fail():void
+ {
+ clearInterval(connection_timeout);
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_FAILED));
+ }
+
+ private function on_close_event(event:Event):void
+ {
+ close();
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_CLOSED));
+ }
+
+ private function on_connect_event(event:Event):void
+ {
+ connected = true;
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_SUCCESS));
+ }
+
+ private function on_io_error_event(event:IOErrorEvent):void
+ {
+ fail();
+ }
+
+ private function on_progress_event(event:ProgressEvent):void
+ {
+ var client_id:String = socket.readUTFBytes(event.bytesLoaded);
+ if (client_id == "Registration list empty") {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY));
+ } else {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id));
+ }
+ }
+
+ private function on_security_error_event(event:SecurityErrorEvent):void
+ {
+ fail();
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/rtmfp/ProxyPair.as b/rtmfp/ProxyPair.as
new file mode 100644
index 0000000..42d4b81
--- /dev/null
+++ b/rtmfp/ProxyPair.as
@@ -0,0 +1,125 @@
+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 rtmfp.CirrusSocket;
+ import rtmfp.RTMFPSocket;
+ import rtmfp.events.RTMFPSocketEvent;
+
+ public class ProxyPair extends EventDispatcher
+ {
+ private var parent:rtmfpcat;
+
+ private var s_r:RTMFPSocket;
+ private var s_t:Socket;
+
+ private var tor_host:String;
+ private var tor_port:uint;
+
+ public function ProxyPair(parent:rtmfpcat, s_c:CirrusSocket, tor_host:String, tor_port:uint)
+ {
+ this.parent = parent;
+ this.tor_host = tor_host;
+ this.tor_port = tor_port;
+
+ setup_rtmfp_socket(s_c);
+ setup_tor_socket();
+ }
+
+ public function close():void
+ {
+ if (s_r.connected) {
+ s_r.close();
+ }
+ if (s_t.connected) {
+ s_t.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ public function connect(peer:String, stream:String):void
+ {
+ s_r.connect(peer, stream);
+ }
+
+ public function get connected():Boolean
+ {
+ return (s_r.connected && s_t.connected);
+ }
+
+ public function listen(stream:String):void
+ {
+ s_r.listen(stream);
+ }
+
+ private function setup_rtmfp_socket(s_c:CirrusSocket):void
+ {
+ s_r = new RTMFPSocket(s_c);
+ s_r.addEventListener(RTMFPSocketEvent.PLAY_STARTED, function (e:RTMFPSocketEvent):void {
+ puts("Play started.");
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PUBLISH_STARTED, function (e:RTMFPSocketEvent):void {
+ puts("Publishing started.");
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PEER_CONNECTED, function (e:RTMFPSocketEvent):void {
+ puts("Peer connected.");
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PEER_DISCONNECTED, function (e:RTMFPSocketEvent):void {
+ puts("Peer disconnected.");
+ close();
+ });
+ s_r.addEventListener(RTMFPSocketEvent.CONNECT_SUCCESS, function (e:RTMFPSocketEvent):void {
+ puts("Peering success.");
+ s_t.connect(tor_host, tor_port);
+ });
+ s_r.addEventListener(RTMFPSocketEvent.CONNECT_FAILED, function (e:RTMFPSocketEvent):void {
+ puts("Peering failed.");
+ });
+ }
+
+ private function setup_tor_socket():void
+ {
+ s_t = new Socket();
+ s_t.addEventListener(Event.CONNECT, function (e:Event):void {
+ puts("Tor: connected to " + tor_host + ":" + tor_port + ".");
+ s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
+ var bytes:ByteArray = new ByteArray();
+ s_t.readBytes(bytes, 0, e.bytesLoaded);
+ puts("RTMFPSocket: Tor: read " + bytes.length + " bytes.");
+ s_r.writeBytes(bytes);
+ });
+ s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
+ var bytes:ByteArray = new ByteArray();
+ s_r.readBytes(bytes, 0, e.bytesLoaded);
+ puts("RTMFPSocket: RTMFP: read " + bytes.length + " bytes.");
+ s_t.writeBytes(bytes);
+ });
+ dispatchEvent(new Event(Event.CONNECT));
+ });
+ s_t.addEventListener(Event.CLOSE, function (e:Event):void {
+ puts("Tor: closed connection.");
+ close();
+ });
+ s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
+ puts("Tor: I/O error: " + e.text + ".");
+ close();
+ });
+ s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ puts("Tor: security error: " + e.text + ".");
+ close();
+ });
+ }
+
+ private function puts(s:String):void
+ {
+ parent.puts(s);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/rtmfp/RTMFPSocket.as b/rtmfp/RTMFPSocket.as
index d524699..783a0e0 100644
--- a/rtmfp/RTMFPSocket.as
+++ b/rtmfp/RTMFPSocket.as
@@ -1,13 +1,3 @@
-/* RTMFPSocket abstraction
- * Author: Nate Hardison, May 2011
- *
- * This code is heavily based off of BelugaFile, an open-source
- * Air file-transfer application written by Nicholas Bliyk.
- * Website: http://www.belugafile.com/
- * Source: http://code.google.com/p/belugafile/
- *
- */
-
package rtmfp
{
import flash.events.Event;
@@ -19,213 +9,205 @@ package rtmfp
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.utils.ByteArray;
- import flash.utils.clearInterval;
- import flash.utils.setInterval;
+ import flash.utils.clearTimeout;
import flash.utils.setTimeout;
-
+
+ import rtmfp.CirrusSocket;
import rtmfp.RTMFPSocketClient;
+ import rtmfp.events.CirrusSocketEvent;
import rtmfp.events.RTMFPSocketEvent;
-
- [Event(name="connectSuccess", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="connectFail", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="publishStart", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peerConnected", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peeringSuccess", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peeringFail", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peerDisconnected", type="com.jscat.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
- {
- /* The name of the "media" to pass between peers */
- private static const DATA:String = "data";
- private static const DEFAULT_CIRRUS_ADDRESS:String = "rtmfp://p2p.rtmfp.net";
- private static const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
- private static const DEFAULT_CONNECT_TIMEOUT:uint = 4000;
-
- /* Connection to the Cirrus rendezvous service */
- private var connection:NetConnection;
-
- /* ID of the peer to connect to */
- private var peerID:String;
-
- /* Data streams to be established with peer */
- private var sendStream:NetStream;
- private var recvStream:NetStream;
-
- /* Timeouts */
- private var connectionTimeout:int;
- private var peerConnectTimeout:uint;
-
- public function RTMFPSocket(){}
-
- public function connect(addr:String = DEFAULT_CIRRUS_ADDRESS, key:String = DEFAULT_CIRRUS_KEY):void
- {
- connection = new NetConnection();
- connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
- connection.addEventListener(IOErrorEvent.IO_ERROR, onIOErrorEvent);
- connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityErrorEvent);
- connection.connect(addr + "/" + key);
- connectionTimeout = setInterval(fail, DEFAULT_CONNECT_TIMEOUT);
- }
-
- public function close():void
- {
- connection.close();
- }
-
- public function get id():String
- {
- if (connection != null && connection.connected) {
- return connection.nearID;
+ {
+ private const CONNECT_TIMEOUT:uint = 10000;
+
+ private var s_c:CirrusSocket;
+
+ private var recv_stream:NetStream;
+ private var send_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. If you just want
+ to disconnect from a client, call disconnect() below */
+ 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();
}
-
- return null;
- }
-
- public function get connected():Boolean
- {
- return (connection != null && connection.connected);
}
- public function readBytes(bytes:ByteArray):void
+ /* 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
{
- recvStream.client.bytes.readBytes(bytes);
- }
-
- public function writeBytes(bytes:ByteArray):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
{
- sendStream.send("dataAvailable", bytes);
- }
-
+ return (recv_stream != null && recv_stream.client != null &&
+ RTMFPSocketClient(recv_stream.client).connect_acknowledged);
+ }
+
+ public function disconnect():void
+ {
+ if (recv_stream != null) {
+ if (recv_stream.client != null) {
+ recv_stream.client.removeEventListener(ProgressEvent.SOCKET_DATA, on_data_available);
+ recv_stream.client.removeEventListener(RTMFPSocketClient.CONNECT_ACKNOWLEDGED, on_connect_acknowledged);
+ }
+ recv_stream.removeEventListener(NetStatusEvent.NET_STATUS, on_recv_stream_event);
+ recv_stream.close();
+ recv_stream = null;
+ }
+ }
+
+ /* 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
{
- return this.peerID;
+ if (!connected) return null;
+ return recv_stream.farID;
}
-
- public function set peer(peerID:String):void
- {
- if (peerID == null || peerID.length == 0) {
- throw new Error("Peer ID is null/empty.")
- } else if (peerID == connection.nearID) {
- throw new Error("Peer ID cannot be the same as our ID.");
- } else if (this.peerID == peerID) {
- throw new Error("Already connected to peer " + peerID + ".");
- } else if (this.recvStream != null) {
- throw new Error("Cannot connect to a second peer.");
- }
-
- this.peerID = peerID;
-
- recvStream = new NetStream(connection, peerID);
- var client:RTMFPSocketClient = new RTMFPSocketClient();
- client.addEventListener(ProgressEvent.SOCKET_DATA, onDataAvailable, false, 0, true);
- client.addEventListener(RTMFPSocketClient.PEER_CONNECT_ACKNOWLEDGED, onPeerConnectAcknowledged, false, 0, true);
- recvStream.client = client;
- recvStream.addEventListener(NetStatusEvent.NET_STATUS, onRecvStreamEvent);
- recvStream.play(DATA);
- setTimeout(onPeerConnectTimeout, peerConnectTimeout, recvStream);
- }
-
- private function startPublishStream():void
+
+ public function get peer_connected():Boolean
{
- sendStream = new NetStream(connection, NetStream.DIRECT_CONNECTIONS);
- sendStream.addEventListener(NetStatusEvent.NET_STATUS, onSendStreamEvent);
- var o:Object = new Object();
- o.onPeerConnect = onPeerConnect;
- sendStream.client = o;
- sendStream.publish(DATA);
+ return send_stream.peerStreams.length > 0;
}
-
- private function fail():void
+
+ public function readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void
{
- clearInterval(connectionTimeout);
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_FAIL));
+ if (recv_stream != null && recv_stream.client != null) {
+ recv_stream.client.bytes.readBytes(bytes, offset, length);
+ }
}
- private function onDataAvailable(event:ProgressEvent):void
- {
- dispatchEvent(event);
- }
- private function onIOErrorEvent(event:IOErrorEvent):void
+ public function writeBytes(bytes:ByteArray):void
{
- fail();
+ if (send_stream != null && peer_connected) {
+ send_stream.send(RTMFPSocketClient.DATA_AVAILABLE, bytes);
+ }
}
-
- private function onNetStatusEvent(event:NetStatusEvent):void
+
+ /* Listens for acknowledgement of a connection attempt to a
+ remote peer. */
+ private function on_connect_acknowledged(event:Event):void
{
- switch (event.info.code) {
- case "NetConnection.Connect.Success" :
- clearInterval(connectionTimeout);
- startPublishStream();
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_SUCCESS));
- break;
- case "NetStream.Connect.Success" :
- break;
- case "NetStream.Publish.BadName" :
- fail();
- break;
- case "NetStream.Connect.Closed" :
- // we've disconnected from the peer
- // can reset to accept another
- // clear the publish stream and re-publish another
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_DISCONNECTED, recvStream));
- break;
- }
+ clearTimeout(connect_timeout);
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_SUCCESS, recv_stream));
}
- private function onPeerConnect(peer:NetStream):Boolean
+ /* 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
{
- // establish a bidirectional stream with the peer
- if (peerID == null) {
- this.peer = peer.farID;
+ if (!this.connected) {
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_FAILED, recv_stream));
}
-
- // disallow additional peers connecting to us
- if (peer.farID != peerID)
- return false;
-
- peer.send("setPeerConnectAcknowledged");
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_CONNECTED, peer));
-
- return true;
}
-
- private function onPeerConnectAcknowledged(event:Event):void
+
+ private function on_data_available(event:ProgressEvent):void
{
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEERING_SUCCESS, recvStream));
+ dispatchEvent(event);
}
-
- private function onPeerConnectTimeout(peer:NetStream):void
+
+ private function on_recv_stream_event(event:NetStatusEvent):void
{
- if (!recvStream.client) return;
- if (!RTMFPSocketClient(recvStream.client).peerConnectAcknowledged) {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEERING_FAIL, recvStream));
- }
+ /* empty, here for symmetry */
}
- private function onSecurityErrorEvent(event:SecurityErrorEvent):void
+ /* 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
{
- fail();
+ if (peer_connected) {
+ return false;
+ }
+
+ 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 onSendStreamEvent(event:NetStatusEvent):void
+
+ private function on_send_stream_event(event:NetStatusEvent):void
{
switch (event.info.code) {
- case ("NetStream.Publish.Start") :
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PUBLISH_START));
- break;
- case ("NetStream.Play.Reset") :
- case ("NetStream.Play.Start") :
- break;
+ 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 onRecvStreamEvent(event:NetStatusEvent):void
+
+ private function on_stream_disconnection_event(event:NetStatusEvent):void
{
- switch (event.info.code) {
- case ("NetStream.Publish.Start") :
- case ("NetStream.Play.Reset") :
- case ("NetStream.Play.Start") :
- break;
+ if (event.info.code == "NetStream.Connect.Closed") {
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_DISCONNECTED));
+ //disconnect();
}
}
}
diff --git a/rtmfp/RTMFPSocketClient.as b/rtmfp/RTMFPSocketClient.as
index e2f93ef..7469a53 100644
--- a/rtmfp/RTMFPSocketClient.as
+++ b/rtmfp/RTMFPSocketClient.as
@@ -5,20 +5,20 @@ package rtmfp
import flash.events.ProgressEvent;
import flash.utils.ByteArray;
- [Event(name="peerConnectAcknowledged", type="flash.events.Event")]
+ [Event(name=RTMFPSocketClient.CONNECT_ACKNOWLEDGED, type="flash.events.Event")]
public dynamic class RTMFPSocketClient extends EventDispatcher {
- public static const PEER_CONNECT_ACKNOWLEDGED:String = "peerConnectAcknowledged";
+ 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 _peerID:String;
- private var _peerConnectAcknowledged:Boolean;
+ private var _connect_acknowledged:Boolean;
public function RTMFPSocketClient()
{
super();
_bytes = new ByteArray();
- _peerID = null;
- _peerConnectAcknowledged = false;
+ _connect_acknowledged = false;
}
public function get bytes():ByteArray
@@ -26,32 +26,22 @@ package rtmfp
return _bytes;
}
- public function dataAvailable(bytes:ByteArray):void
+ public function data_available(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
+ public function get connect_acknowledged():Boolean
{
- return _peerConnectAcknowledged;
+ return _connect_acknowledged;
}
- public function setPeerConnectAcknowledged():void
+ public function set_connect_acknowledged():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;
+ _connect_acknowledged = true;
+ dispatchEvent(new Event(CONNECT_ACKNOWLEDGED));
}
}
}
diff --git a/rtmfp/events/CirrusSocketEvent.as b/rtmfp/events/CirrusSocketEvent.as
new file mode 100644
index 0000000..831ad73
--- /dev/null
+++ b/rtmfp/events/CirrusSocketEvent.as
@@ -0,0 +1,22 @@
+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/FacilitatorSocketEvent.as b/rtmfp/events/FacilitatorSocketEvent.as
new file mode 100644
index 0000000..a0599aa
--- /dev/null
+++ b/rtmfp/events/FacilitatorSocketEvent.as
@@ -0,0 +1,22 @@
+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/rtmfp/events/RTMFPSocketEvent.as b/rtmfp/events/RTMFPSocketEvent.as
index 5bc08e5..87a7e09 100644
--- a/rtmfp/events/RTMFPSocketEvent.as
+++ b/rtmfp/events/RTMFPSocketEvent.as
@@ -5,20 +5,21 @@ package rtmfp.events
public class RTMFPSocketEvent extends Event
{
+ public static const CONNECT_FAILED:String = "connectFailed";
public static const CONNECT_SUCCESS:String = "connectSuccess";
- public static const CONNECT_FAIL:String = "connectFail";
- public static const PUBLISH_START:String = "publishStart";
+ public static const CONNECT_CLOSED:String = "connectClosed"
public static const PEER_CONNECTED:String = "peerConnected";
public static const PEER_DISCONNECTED:String = "peerDisconnected";
- public static const PEERING_SUCCESS:String = "peeringSuccess";
- public static const PEERING_FAIL:String = "peeringFail";
+ 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, streamVal:NetStream = null, bubbles:Boolean = false, cancelable:Boolean = false)
+ public function RTMFPSocketEvent(type:String, stream:NetStream = null, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
- stream = streamVal;
+ this.stream = stream;
}
}
}
diff --git a/rtmfpcat.as b/rtmfpcat.as
index d01bb37..866175e 100644
--- a/rtmfpcat.as
+++ b/rtmfpcat.as
@@ -5,46 +5,54 @@ package
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.setTimeout;
+ import flash.utils.clearInterval;
+ import flash.utils.setInterval;
- import rtmfp.RTMFPSocket;
- import rtmfp.events.RTMFPSocketEvent;
+ import rtmfp.CirrusSocket;
+ import rtmfp.FacilitatorSocket;
+ import rtmfp.ProxyPair;
+ import rtmfp.events.CirrusSocketEvent;
+ import rtmfp.events.FacilitatorSocketEvent;
public class 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
- };
- /* Nate's facilitator -- also serving a crossdomain policy */
+ /* 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_PROXY_ADDR:Object = {
+ host: "173.255.221.44",
+ port: 9001
+ };
+
+ /* Poll facilitator every 3 sec if in proxy mode and haven't found
+ anyone to proxy */
+ private const DEFAULT_FAC_POLL_INTERVAL:uint = 3000;
- // Milliseconds.
- private const FACILITATOR_POLL_INTERVAL:int = 10000;
-
+ // Socket to Cirrus server
+ private var s_c:CirrusSocket;
// Socket to facilitator.
- private var s_f:Socket;
- // Socket to RTMFP peer (flash proxy).
- private var s_r:RTMFPSocket;
- // Socket to local Tor client.
- private var s_t:Socket;
+ private var s_f:FacilitatorSocket;
+ // Handle local-remote traffic
+ private var p_p:ProxyPair;
+
+ private var proxy_mode:Boolean;
+
+ private var fac_poll_interval:uint;
/* TextField for debug output. */
private var output_text:TextField;
@@ -52,14 +60,6 @@ package
private var fac_addr:Object;
private var tor_addr:Object;
- private var proxy_mode:Boolean;
-
- public function puts(s:String):void
- {
- output_text.appendText(s + "\n");
- output_text.scrollV = output_text.maxScrollV;
- }
-
public function rtmfpcat()
{
// Absolute positioning.
@@ -72,7 +72,8 @@ package
output_text.background = true;
output_text.backgroundColor = 0x001f0f;
output_text.textColor = 0x44cc44;
-
+ addChild(output_text);
+
puts("Starting.");
// Wait until the query string parameters are loaded.
this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
@@ -82,11 +83,10 @@ package
{
var fac_spec:String;
var tor_spec:String;
-
+
puts("Parameters loaded.");
proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
- addChild(output_text);
fac_spec = this.loaderInfo.parameters["facilitator"];
if (fac_spec) {
@@ -109,10 +109,11 @@ package
return;
}
} else {
- if (proxy_mode)
+ if (proxy_mode) {
tor_addr = DEFAULT_TOR_PROXY_ADDR;
- else
+ } else {
tor_addr = DEFAULT_TOR_CLIENT_ADDR;
+ }
}
main();
@@ -121,105 +122,106 @@ package
/* The main logic begins here, after start-up issues are taken care of. */
private function main():void
{
- establishRTMFPConnection();
+ establish_cirrus_connection();
}
- private function establishRTMFPConnection():void
+ private function establish_cirrus_connection():void
{
- s_r = new RTMFPSocket();
- s_r.addEventListener(RTMFPSocketEvent.CONNECT_SUCCESS, function (e:Event):void {
- puts("Cirrus: connected with id " + s_r.id + ".");
- establishFacilitatorConnection();
+ 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) {
+ fac_poll_interval = setInterval(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ } else {
+ establish_facilitator_connection();
+ }
});
- s_r.addEventListener(RTMFPSocketEvent.CONNECT_FAIL, function (e:Event):void {
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
puts("Error: failed to connect to Cirrus.");
});
- s_r.addEventListener(RTMFPSocketEvent.PUBLISH_START, function(e:RTMFPSocketEvent):void {
- puts("Publishing started.");
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: closed connection.");
});
- s_r.addEventListener(RTMFPSocketEvent.PEER_CONNECTED, function(e:RTMFPSocketEvent):void {
- puts("Peer connected.");
- });
- s_r.addEventListener(RTMFPSocketEvent.PEER_DISCONNECTED, function(e:RTMFPSocketEvent):void {
- puts("Peer disconnected.");
- });
- s_r.addEventListener(RTMFPSocketEvent.PEERING_SUCCESS, function(e:RTMFPSocketEvent):void {
- puts("Peering success.");
- establishTorConnection();
- });
- s_r.addEventListener(RTMFPSocketEvent.PEERING_FAIL, function(e:RTMFPSocketEvent):void {
- puts("Peering fail.");
- });
- s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- var bytes:ByteArray = new ByteArray();
- s_r.readBytes(bytes);
- puts("RTMFP: read " + bytes.length + " bytes.");
- s_t.writeBytes(bytes);
+
+ 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);
+ }
+ p_p.connect(e.peer, e.stream);
});
-
- s_r.connect();
+
+ s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
}
- private function establishTorConnection():void
+ private function establish_facilitator_connection():void
{
- s_t = new Socket();
- s_t.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("Tor: connected to " + tor_addr.host + ":" + tor_addr.port + ".");
- });
- s_t.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("Tor: closed connection.");
- });
- s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- puts("Tor: I/O error: " + e.text + ".");
- });
- s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- var bytes:ByteArray = new ByteArray();
- s_t.readBytes(bytes, 0, e.bytesLoaded);
- puts("Tor: read " + bytes.length + " bytes.");
- s_r.writeBytes(bytes);
- });
- s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- puts("Tor: security error: " + e.text + ".");
+ s_f = new FacilitatorSocket();
+ s_f.addEventListener(FacilitatorSocketEvent.CONNECT_SUCCESS, function (e:Event):void {
+ if (proxy_mode) {
+ puts("Facilitator: getting registration.");
+ s_f.get_registration();
+ } else {
+ puts("Facilitator: posting registration.");
+ s_f.post_registration(s_c.id);
+ }
});
-
- s_t.connect(tor_addr.host, tor_addr.port);
+ s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
+ puts("Facilitator: connect failed.");
+ });
+ s_f.addEventListener(FacilitatorSocketEvent.CONNECT_CLOSED, function (e:Event):void {
+ puts("Facilitator: connect closed.");
+ });
+
+ if (proxy_mode) {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void {
+ puts("Facilitator: got registration " + e.client);
+ clearInterval(fac_poll_interval);
+ start_proxy_pair();
+ s_c.send_hello(e.client);
+ });
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATIONS_EMPTY, function (e:Event):void {
+ puts("Facilitator: no registrations available.");
+ });
+ } else {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
+ puts("Facilitator: registration failed.");
+ });
+ }
+ s_f.connect(fac_addr.host, fac_addr.port);
}
-
- private function establishFacilitatorConnection():void
+
+ private function start_proxy_pair():void
{
- s_f = new Socket();
- s_f.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("Facilitator: connected to " + fac_addr.host + ":" + fac_addr.port + ".");
- if (proxy_mode) s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
- else s_f.writeUTFBytes("POST / HTTP/1.0\r\n\r\nclient=" + s_r.id + "\r\n");
- });
- s_f.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("Facilitator: connection closed.");
+ puts("Starting proxy pair on stream " + s_c.local_stream_name);
+ p_p = new ProxyPair(this, s_c, tor_addr.host, tor_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) {
- setTimeout(establishFacilitatorConnection, FACILITATOR_POLL_INTERVAL);
+ fac_poll_interval = setInterval(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ } else {
+ establish_facilitator_connection();
}
});
- 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 clientID:String = s_f.readMultiByte(e.bytesLoaded, "utf-8");
- puts("Facilitator: got \"" + clientID + "\"");
- if (clientID != "Registration list empty") {
- puts("Connecting to " + clientID + ".");
- s_r.peer = clientID;
- }
- });
- 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);
+ 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 static function parse_addr_spec(spec:String):Object
+ private function parse_addr_spec(spec:String):Object
{
var parts:Array;
var addr:Object;
@@ -233,5 +235,11 @@ package
return addr;
}
+
+ public function puts(s:String):void
+ {
+ output_text.appendText(s + "\n");
+ output_text.scrollV = output_text.maxScrollV;
+ }
}
}
1
0
[flashproxy/master] Merge branch 'rtmfp' of ssh://upload.bamsoftware.com/~dcf/flashproxy into rtmfp
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 07752417d9a42099bc0c869b0ebac1862f72baa4
Merge: 7c4ca7b a7cdef5
Author: Nate Hardison <nate(a)rescomp-09-154551.stanford.edu>
Date: Thu Jun 2 03:46:27 2011 -0700
Merge branch 'rtmfp' of ssh://upload.bamsoftware.com/~dcf/flashproxy into rtmfp
badge_con_counter.png | Bin 0 -> 270 bytes
return_of_the_rtmfpcat.as | 234 +++++++++++++++++++++++++++++++++++++--------
2 files changed, 192 insertions(+), 42 deletions(-)
1
0
[flashproxy/master] Appended unique data stream name to registration to prevent connection aliasing
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit f77bd570a94428678cedbcf0899d11b569b599c4
Author: ellitron <jdellit(a)stanford.edu>
Date: Fri May 27 09:54:55 2011 -0700
Appended unique data stream name to registration to prevent connection aliasing
---
return_of_the_rtmfpcat.as | 87 ++++++++++++++++++++++++++++++--------------
1 files changed, 59 insertions(+), 28 deletions(-)
diff --git a/return_of_the_rtmfpcat.as b/return_of_the_rtmfpcat.as
index f1842e4..a1d14cc 100644
--- a/return_of_the_rtmfpcat.as
+++ b/return_of_the_rtmfpcat.as
@@ -55,11 +55,13 @@ package
private static const DEFAULT_CIRCON_TIMEOUT:uint = 4000;
/* Maximum connections. */
- private const MAXIMUM_RCP_PAIRS:uint = 1;
+ private const DEFAULT_MAXIMUM_RCP_PAIRS:uint = 1;
/* Milliseconds. */
private const FACILITATOR_POLL_INTERVAL:int = 10000;
+ private var max_rcp_pairs;
+
/* TextField for debug output. */
private var output_text:TextField;
@@ -89,6 +91,8 @@ package
/* Number of connected RTMFPConnectionPairs. */
private var rcp_pairs:uint;
+ private var rtmfp_data_counter:uint;
+
/* Keep track of facilitator polling timer. */
private var fac_poll_timeo_id:uint;
@@ -115,6 +119,9 @@ package
/* 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.
@@ -168,6 +175,11 @@ package
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;
+
main();
}
@@ -202,11 +214,12 @@ package
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();
+ rcp.listen(String(rtmfp_data_counter));
- puts("Registering with facilitator");
- /* Register ID with facilitator. */
- register_id(circon.nearID, fac_addr);
+ 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;
@@ -229,19 +242,25 @@ package
puts("Facilitator: I/O error: " + e.text + ".");
});
s_f.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- var clientID:String = s_f.readMultiByte(e.bytesLoaded, "utf-8");
- puts("Facilitator: got \"" + clientID + "\"");
- if (clientID != "Registration list empty") {
- puts("Connecting to " + clientID + ".");
+ 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.CLOSE, rcp_close_event);
- rcp.connect(clientID);
+ rcp.connect(client_id, client_data);
} else {
/* Need to clear any outstanding timers to ensure
* that only one timer ever runs. */
clearTimeout(fac_poll_timeo_id);
- if(rcp_pairs < MAXIMUM_RCP_PAIRS)
+ if(rcp_pairs < max_rcp_pairs)
fac_poll_timeo_id = setTimeout(poll_for_id, FACILITATOR_POLL_INTERVAL);
}
});
@@ -260,17 +279,21 @@ package
rcp_pairs++;
if(proxy_mode) {
- if(rcp_pairs < MAXIMUM_RCP_PAIRS) {
+ if(rcp_pairs < max_rcp_pairs) {
poll_for_id();
}
} else {
/* Setup listening RTMFPConnectionPair. */
- if(rcp_pairs < MAXIMUM_RCP_PAIRS) {
+ 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();
+ 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++;
}
}
}
@@ -284,16 +307,20 @@ package
/* 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 < MAXIMUM_RCP_PAIRS) {
+ if(rcp_pairs < max_rcp_pairs) {
poll_for_id();
}
} else {
- if(rcp_pairs < MAXIMUM_RCP_PAIRS) {
+ 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();
+ 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++;
}
}
}
@@ -362,7 +389,7 @@ import flash.text.TextField;
class RTMFPSocket extends EventDispatcher
{
/* The name of the "media" to pass between peers. */
- private static const DATA:String = "data";
+ private var data:String;
/* Connection to the Cirrus rendezvous service.
* RTMFPSocket is established using this service. */
@@ -399,19 +426,23 @@ class RTMFPSocket extends EventDispatcher
});
}
- public function listen():void
+ 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);
+ send_stream.publish(data);
}
- public function connect(clientID:String):void
+ public function connect(clientID:String, data:String):void
{
puts("RTMFPSocket: connecting to peer...");
+ this.data = data;
+
send_stream = new NetStream(circon, NetStream.DIRECT_CONNECTIONS);
var client:Object = new Object();
client.onPeerConnect = function (peer:NetStream):Boolean {
@@ -422,7 +453,7 @@ class RTMFPSocket extends EventDispatcher
return true;
};
send_stream.client = client;
- send_stream.publish(DATA);
+ send_stream.publish(data);
recv_stream = new NetStream(circon, clientID);
var client_rtmfp:RTMFPSocketClient = new RTMFPSocketClient();
@@ -434,7 +465,7 @@ class RTMFPSocket extends EventDispatcher
}, false, 0, true);
recv_stream.client = client_rtmfp;
- recv_stream.play(DATA);
+ recv_stream.play(data);
}
private function send_stream_peer_connect(peer:NetStream):Boolean
@@ -451,7 +482,7 @@ class RTMFPSocket extends EventDispatcher
dispatchEvent(new Event(Event.CONNECT));
}, false, 0, true);
recv_stream.client = client;
- recv_stream.play(DATA);
+ recv_stream.play(data);
peer.send("setPeerConnectAcknowledged");
@@ -574,20 +605,20 @@ class RTMFPConnectionPair extends EventDispatcher
this.output_text = output_text;
}
- public function connect(clientID:String):void
+ public function connect(clientID:String, rtmfp_data:String):void
{
s_r = new RTMFPSocket(circon, output_text);
s_r.addEventListener(Event.CONNECT, rtmfp_connect_event);
s_r.addEventListener(Event.CLOSE, rtmfp_close_event);
- s_r.connect(clientID);
+ s_r.connect(clientID, rtmfp_data);
}
- public function listen():void
+ 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(Event.CLOSE, rtmfp_close_event);
- s_r.listen();
+ s_r.listen(rtmfp_data);
}
private function rtmfp_connect_event(e:Event):void
1
0
commit 07fb8b258a2f87358af0328469dc2d12e0bcfa70
Author: David Fifield <david(a)bamsoftware.com>
Date: Wed May 25 18:03:06 2011 -0700
Use parse_addr_spec to parse regs.
---
facilitator.py | 56 ++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/facilitator.py b/facilitator.py
index fde81b7..0333aee 100755
--- a/facilitator.py
+++ b/facilitator.py
@@ -47,6 +47,41 @@ def log(msg):
finally:
log_lock.release()
+def parse_addr_spec(spec, defhost = None, defport = None):
+ host = None
+ port = None
+ m = None
+ # IPv6 syntax.
+ if not m:
+ m = re.match(ur'^\[(.+)\]:(\d+)$', spec)
+ if m:
+ host, port = m.groups()
+ af = socket.AF_INET6
+ if not m:
+ m = re.match(ur'^\[(.+)\]:?$', spec)
+ if m:
+ host, = m.groups()
+ af = socket.AF_INET6
+ # IPv4 syntax.
+ if not m:
+ m = re.match(ur'^(.+):(\d+)$', spec)
+ if m:
+ host, port = m.groups()
+ af = socket.AF_INET
+ if not m:
+ m = re.match(ur'^:?(\d+)$', spec)
+ if m:
+ port, = m.groups()
+ af = 0
+ if not m:
+ host = spec
+ af = 0
+ host = host or defhost
+ port = port or defport
+ if not (host and port):
+ raise ValueError("Bad address specification \"%s\"" % spec)
+ return af, host, int(port)
+
def format_addr(addr):
host, port = addr
if not host:
@@ -77,26 +112,7 @@ class Reg(object):
@staticmethod
def parse(spec, defhost = None, defport = None):
- host = None
- port = None
- m = re.match(r'^\[(.+)\]:(\d*)$', spec)
- if m:
- host, port = m.groups()
- af = socket.AF_INET6
- else:
- m = re.match(r'^(.*):(\d*)$', spec)
- if m:
- host, port = m.groups()
- if host:
- af = socket.AF_INET
- else:
- # Has to be guessed from format of defhost.
- af = 0
- host = host or defhost
- port = port or defport
- if not (host and port):
- raise ValueError("Bad address specification \"%s\"" % spec)
-
+ af, host, port = parse_addr_spec(spec, defhost, defport)
try:
addrs = socket.getaddrinfo(host, port, af, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST)
except socket.gaierror, e:
1
0
commit b875382c6e5d2c4a0feaeb3a9e91632fdab9b741
Author: David Fifield <david(a)bamsoftware.com>
Date: Wed May 25 00:43:28 2011 -0700
Messed up the last commit.
---
rtmfpcat.as | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/rtmfpcat.as b/rtmfpcat.as
index 49fcdeb..d01bb37 100644
--- a/rtmfpcat.as
+++ b/rtmfpcat.as
@@ -109,7 +109,10 @@ package
return;
}
} else {
- tor_addr = DEFAULT_TOR_CLIENT_ADDR;
+ if (proxy_mode)
+ tor_addr = DEFAULT_TOR_PROXY_ADDR;
+ else
+ tor_addr = DEFAULT_TOR_CLIENT_ADDR;
}
main();
1
0
commit 4ba49ccb6c04da8565f06923a30734aa765414cd
Merge: d5c1258 9b584d0
Author: David Fifield <david(a)bamsoftware.com>
Date: Tue May 24 22:56:05 2011 -0700
Merge branch 'master' into rtmfp
badge.png | Bin 264 -> 682 bytes
badge_con_counter.png | Bin 270 -> 0 bytes
nat-birthday.py | 132 -----------------------------------
notes.txt | 2 -
swfcat.as | 184 +++++++++++++++++++++++++++++++++++++++++++++----
5 files changed, 170 insertions(+), 148 deletions(-)
diff --cc swfcat.as
index 76de948,6f4be0c..108f6eb
--- a/swfcat.as
+++ b/swfcat.as
@@@ -45,13 -50,13 +50,15 @@@ packag
/* 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_con_counter.png")]
+ [Embed(source="badge.png")]
private var BadgeImage:Class;
- private var client_count_tf:TextField;
- private var client_count_fmt:TextFormat;
+ 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
{
1
0
commit 6c616f701d878246f82b59df0cf4415a861f6ff8
Merge: fd7c1d3 b875382
Author: ellitron <jdellit(a)stanford.edu>
Date: Wed May 25 11:06:13 2011 -0700
merged move of com into main branch
Makefile | 2 +-
README | 88 ++++---
badge.png | Bin 264 -> 682 bytes
badge_con_counter.png | Bin 270 -> 0 bytes
com/rtmfpcat/Makefile | 11 -
com/rtmfpcat/README | 118 ---------
com/rtmfpcat/Utils.as | 25 --
com/rtmfpcat/connector.py | 326 -------------------------
com/rtmfpcat/facilitator.py | 146 -----------
com/rtmfpcat/rtmfp/RTMFPSocket.as | 232 ------------------
com/rtmfpcat/rtmfp/RTMFPSocketClient.as | 57 -----
com/rtmfpcat/rtmfp/events/RTMFPSocketEvent.as | 25 --
com/rtmfpcat/rtmfpcat.as | 208 ----------------
connector.py | 4 +-
facilitator.py | 11 +-
nat-birthday.py | 132 ----------
notes.txt | 2 -
rtmfp/RTMFPSocket.as | 232 ++++++++++++++++++
rtmfp/RTMFPSocketClient.as | 57 +++++
rtmfp/events/RTMFPSocketEvent.as | 24 ++
rtmfpcat.as | 237 ++++++++++++++++++
swfcat.as | 230 +++++++++++++-----
22 files changed, 778 insertions(+), 1389 deletions(-)
1
0
[flashproxy/master] Completed return_of_the_rtmfpcat client side code, works
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 59ccbab495b24f513c45976b81a318948510d207
Author: ellitron <jdellit(a)stanford.edu>
Date: Wed May 25 18:05:13 2011 -0700
Completed return_of_the_rtmfpcat client side code, works
---
return_of_the_rtmfpcat.as | 157 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 157 insertions(+), 0 deletions(-)
diff --git a/return_of_the_rtmfpcat.as b/return_of_the_rtmfpcat.as
index e8b786d..9ecc61f 100644
--- a/return_of_the_rtmfpcat.as
+++ b/return_of_the_rtmfpcat.as
@@ -76,6 +76,9 @@ package
/* Cirrus connection timeout ID. */
private var circon_timeo_id:int;
+ /* Array of connection pairs */
+ private var con_pairs:Array;
+
/* Put a string to the screen. */
public function puts(s:String):void
{
@@ -175,6 +178,19 @@ package
puts("circon_netstatus_event: NetConnection.Connect.Success");
puts("Got id " + circon.nearID + ".");
clearInterval(circon_timeo_id);
+
+ if(proxy_mode) {
+
+ } else {
+ /* Listen for incoming RTMFP connections. */
+ var s_r:RTMFPSocket = new RTMFPSocket(circon);
+ s_r.addEventListener(Event.CONNECT, rtmfp_connect_event);
+ s_r.listen();
+
+ /* Register ID with facilitator. */
+ register_id(circon.nearID, fac_addr);
+ }
+
break;
case "NetStream.Connect.Success" :
puts("circon_netstatus_event: NetStream.Connect.Success");
@@ -191,6 +207,32 @@ package
}
}
+ private function rtmfp_connect_event(e:Event):void
+ {
+ puts("VICTORY!");
+ }
+
+ 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("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!");
@@ -215,3 +257,118 @@ 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;
+import flash.net.NetConnection;
+import flash.net.NetStream;
+
+class RTMFPSocket extends EventDispatcher
+{
+ /* The name of the "media" to pass between peers. */
+ private static const DATA:String = "data";
+
+ /* 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;
+
+ public function RTMFPSocket(circon:NetConnection)
+ {
+ this.circon = circon;
+ }
+
+ public function listen():void
+ {
+ 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 send_stream_peer_connect(peer:NetStream):Boolean
+ {
+ 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 {
+ dispatchEvent(new Event(Event.CONNECT));
+ }, false, 0, true);
+ recv_stream.client = client;
+ recv_stream.play(DATA);
+
+ return true;
+ }
+
+
+}
+
+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 ConnectionPair extends EventDispatcher
+{
+
+}
1
0
12 Jun '11
commit 486fba47f3bf851eb8549c03ff506fece4dc4818
Merge: e178468 0423ede
Author: ellitron <jdellit(a)stanford.edu>
Date: Thu May 26 13:56:26 2011 -0700
Merge remote branch 'origin/rtmfp' into rtmfp
facilitator.py | 106 ++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 76 insertions(+), 30 deletions(-)
1
0
commit 389c5f56f79bed8c5d220fa8a6bf05666951292e
Author: David Fifield <david(a)bamsoftware.com>
Date: Tue May 24 23:16:51 2011 -0700
Whitespace.
---
rtmfp/RTMFPSocket.as | 283 +++++++++++++++--------------
rtmfp/RTMFPSocketClient.as | 110 ++++++------
rtmfp/events/RTMFPSocketEvent.as | 43 ++---
rtmfpcat.as | 372 +++++++++++++++++++-------------------
4 files changed, 404 insertions(+), 404 deletions(-)
diff --git a/rtmfp/RTMFPSocket.as b/rtmfp/RTMFPSocket.as
index bb00994..d524699 100644
--- a/rtmfp/RTMFPSocket.as
+++ b/rtmfp/RTMFPSocket.as
@@ -1,10 +1,10 @@
/* RTMFPSocket abstraction
* Author: Nate Hardison, May 2011
- *
+ *
* This code is heavily based off of BelugaFile, an open-source
* Air file-transfer application written by Nicholas Bliyk.
* Website: http://www.belugafile.com/
- * Source: http://code.google.com/p/belugafile/
+ * Source: http://code.google.com/p/belugafile/
*
*/
@@ -22,210 +22,211 @@ package rtmfp
import flash.utils.clearInterval;
import flash.utils.setInterval;
import flash.utils.setTimeout;
-
+
import rtmfp.RTMFPSocketClient;
import rtmfp.events.RTMFPSocketEvent;
[Event(name="connectSuccess", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="connectFail", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="publishStart", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peerConnected", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peeringSuccess", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peeringFail", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
- [Event(name="peerDisconnected", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
+ [Event(name="connectFail", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
+ [Event(name="publishStart", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
+ [Event(name="peerConnected", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
+ [Event(name="peeringSuccess", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
+ [Event(name="peeringFail", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
+ [Event(name="peerDisconnected", type="com.jscat.rtmfp.events.RTMFPSocketEvent")]
public class RTMFPSocket extends EventDispatcher
{
/* The name of the "media" to pass between peers */
private static const DATA:String = "data";
- private static const DEFAULT_CIRRUS_ADDRESS:String = "rtmfp://p2p.rtmfp.net";
- private static const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
- private static const DEFAULT_CONNECT_TIMEOUT:uint = 4000;
-
+ private static const DEFAULT_CIRRUS_ADDRESS:String = "rtmfp://p2p.rtmfp.net";
+ private static const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
+ private static const DEFAULT_CONNECT_TIMEOUT:uint = 4000;
+
/* Connection to the Cirrus rendezvous service */
private var connection:NetConnection;
-
- /* ID of the peer to connect to */
- private var peerID:String;
-
- /* Data streams to be established with peer */
- private var sendStream:NetStream;
- private var recvStream:NetStream;
-
- /* Timeouts */
- private var connectionTimeout:int;
- private var peerConnectTimeout:uint;
+
+ /* ID of the peer to connect to */
+ private var peerID:String;
+
+ /* Data streams to be established with peer */
+ private var sendStream:NetStream;
+ private var recvStream:NetStream;
+
+ /* Timeouts */
+ private var connectionTimeout:int;
+ private var peerConnectTimeout:uint;
public function RTMFPSocket(){}
-
+
public function connect(addr:String = DEFAULT_CIRRUS_ADDRESS, key:String = DEFAULT_CIRRUS_KEY):void
{
- connection = new NetConnection();
- connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
- connection.addEventListener(IOErrorEvent.IO_ERROR, onIOErrorEvent);
- connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityErrorEvent);
- connection.connect(addr + "/" + key);
- connectionTimeout = setInterval(fail, DEFAULT_CONNECT_TIMEOUT);
+ connection = new NetConnection();
+ connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
+ connection.addEventListener(IOErrorEvent.IO_ERROR, onIOErrorEvent);
+ connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityErrorEvent);
+ connection.connect(addr + "/" + key);
+ connectionTimeout = setInterval(fail, DEFAULT_CONNECT_TIMEOUT);
}
public function close():void
{
- connection.close();
+ connection.close();
}
public function get id():String
{
- if (connection != null && connection.connected) {
- return connection.nearID;
- }
-
- return null;
+ if (connection != null && connection.connected) {
+ return connection.nearID;
+ }
+
+ return null;
}
-
+
public function get connected():Boolean
{
- return (connection != null && connection.connected);
+ return (connection != null && connection.connected);
}
-
+
public function readBytes(bytes:ByteArray):void
{
- recvStream.client.bytes.readBytes(bytes);
+ recvStream.client.bytes.readBytes(bytes);
}
public function writeBytes(bytes:ByteArray):void
{
- sendStream.send("dataAvailable", bytes);
+ sendStream.send("dataAvailable", bytes);
}
-
+
public function get peer():String
{
- return this.peerID;
+ return this.peerID;
}
public function set peer(peerID:String):void
{
- if (peerID == null || peerID.length == 0) {
- throw new Error("Peer ID is null/empty.")
- } else if (peerID == connection.nearID) {
- throw new Error("Peer ID cannot be the same as our ID.");
- } else if (this.peerID == peerID) {
- throw new Error("Already connected to peer " + peerID + ".");
- } else if (this.recvStream != null) {
- throw new Error("Cannot connect to a second peer.");
- }
-
- this.peerID = peerID;
-
- recvStream = new NetStream(connection, peerID);
- var client:RTMFPSocketClient = new RTMFPSocketClient();
- client.addEventListener(ProgressEvent.SOCKET_DATA, onDataAvailable, false, 0, true);
- client.addEventListener(RTMFPSocketClient.PEER_CONNECT_ACKNOWLEDGED, onPeerConnectAcknowledged, false, 0, true);
- recvStream.client = client;
- recvStream.addEventListener(NetStatusEvent.NET_STATUS, onRecvStreamEvent);
- recvStream.play(DATA);
- setTimeout(onPeerConnectTimeout, peerConnectTimeout, recvStream);
- }
-
+ if (peerID == null || peerID.length == 0) {
+ throw new Error("Peer ID is null/empty.")
+ } else if (peerID == connection.nearID) {
+ throw new Error("Peer ID cannot be the same as our ID.");
+ } else if (this.peerID == peerID) {
+ throw new Error("Already connected to peer " + peerID + ".");
+ } else if (this.recvStream != null) {
+ throw new Error("Cannot connect to a second peer.");
+ }
+
+ this.peerID = peerID;
+
+ recvStream = new NetStream(connection, peerID);
+ var client:RTMFPSocketClient = new RTMFPSocketClient();
+ client.addEventListener(ProgressEvent.SOCKET_DATA, onDataAvailable, false, 0, true);
+ client.addEventListener(RTMFPSocketClient.PEER_CONNECT_ACKNOWLEDGED, onPeerConnectAcknowledged, false, 0, true);
+ recvStream.client = client;
+ recvStream.addEventListener(NetStatusEvent.NET_STATUS, onRecvStreamEvent);
+ recvStream.play(DATA);
+ setTimeout(onPeerConnectTimeout, peerConnectTimeout, recvStream);
+ }
+
private function startPublishStream():void
{
- sendStream = new NetStream(connection, NetStream.DIRECT_CONNECTIONS);
- sendStream.addEventListener(NetStatusEvent.NET_STATUS, onSendStreamEvent);
- var o:Object = new Object();
- o.onPeerConnect = onPeerConnect;
- sendStream.client = o;
- sendStream.publish(DATA);
+ sendStream = new NetStream(connection, NetStream.DIRECT_CONNECTIONS);
+ sendStream.addEventListener(NetStatusEvent.NET_STATUS, onSendStreamEvent);
+ var o:Object = new Object();
+ o.onPeerConnect = onPeerConnect;
+ sendStream.client = o;
+ sendStream.publish(DATA);
}
-
+
private function fail():void
{
- clearInterval(connectionTimeout);
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_FAIL));
+ clearInterval(connectionTimeout);
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_FAIL));
}
-
+
private function onDataAvailable(event:ProgressEvent):void
{
- dispatchEvent(event);
+ dispatchEvent(event);
}
-
+
private function onIOErrorEvent(event:IOErrorEvent):void
{
- fail();
+ fail();
}
-
+
private function onNetStatusEvent(event:NetStatusEvent):void
{
- switch (event.info.code) {
- case "NetConnection.Connect.Success" :
- clearInterval(connectionTimeout);
- startPublishStream();
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_SUCCESS));
- break;
- case "NetStream.Connect.Success" :
- break;
- case "NetStream.Publish.BadName" :
- fail();
- break;
- case "NetStream.Connect.Closed" :
- // we've disconnected from the peer
- // can reset to accept another
- // clear the publish stream and re-publish another
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_DISCONNECTED, recvStream));
- break;
- }
- }
-
+ switch (event.info.code) {
+ case "NetConnection.Connect.Success" :
+ clearInterval(connectionTimeout);
+ startPublishStream();
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_SUCCESS));
+ break;
+ case "NetStream.Connect.Success" :
+ break;
+ case "NetStream.Publish.BadName" :
+ fail();
+ break;
+ case "NetStream.Connect.Closed" :
+ // we've disconnected from the peer
+ // can reset to accept another
+ // clear the publish stream and re-publish another
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_DISCONNECTED, recvStream));
+ break;
+ }
+ }
+
private function onPeerConnect(peer:NetStream):Boolean
{
- // establish a bidirectional stream with the peer
- if (peerID == null) {
- this.peer = peer.farID;
- }
-
- // disallow additional peers connecting to us
- if (peer.farID != peerID) return false;
-
- peer.send("setPeerConnectAcknowledged");
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_CONNECTED, peer));
-
- return true;
- }
-
+ // establish a bidirectional stream with the peer
+ if (peerID == null) {
+ this.peer = peer.farID;
+ }
+
+ // disallow additional peers connecting to us
+ if (peer.farID != peerID)
+ return false;
+
+ peer.send("setPeerConnectAcknowledged");
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_CONNECTED, peer));
+
+ return true;
+ }
+
private function onPeerConnectAcknowledged(event:Event):void
{
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEERING_SUCCESS, recvStream));
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEERING_SUCCESS, recvStream));
}
-
+
private function onPeerConnectTimeout(peer:NetStream):void
{
- if (!recvStream.client) return;
- if (!RTMFPSocketClient(recvStream.client).peerConnectAcknowledged) {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEERING_FAIL, recvStream));
- }
+ if (!recvStream.client) return;
+ if (!RTMFPSocketClient(recvStream.client).peerConnectAcknowledged) {
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEERING_FAIL, recvStream));
+ }
}
-
+
private function onSecurityErrorEvent(event:SecurityErrorEvent):void
{
- fail();
+ fail();
}
-
+
private function onSendStreamEvent(event:NetStatusEvent):void
{
- switch (event.info.code) {
- case ("NetStream.Publish.Start") :
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PUBLISH_START));
- break;
- case ("NetStream.Play.Reset") :
- case ("NetStream.Play.Start") :
- break;
- }
- }
- private function onRecvStreamEvent(event:NetStatusEvent):void
- {
- switch (event.info.code) {
- case ("NetStream.Publish.Start") :
- case ("NetStream.Play.Reset") :
- case ("NetStream.Play.Start") :
- break;
- }
- }
+ switch (event.info.code) {
+ case ("NetStream.Publish.Start") :
+ dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PUBLISH_START));
+ break;
+ case ("NetStream.Play.Reset") :
+ case ("NetStream.Play.Start") :
+ break;
+ }
+ }
+ private function onRecvStreamEvent(event:NetStatusEvent):void
+ {
+ switch (event.info.code) {
+ case ("NetStream.Publish.Start") :
+ case ("NetStream.Play.Reset") :
+ case ("NetStream.Play.Start") :
+ break;
+ }
+ }
}
}
diff --git a/rtmfp/RTMFPSocketClient.as b/rtmfp/RTMFPSocketClient.as
index d9fcffa..e2f93ef 100644
--- a/rtmfp/RTMFPSocketClient.as
+++ b/rtmfp/RTMFPSocketClient.as
@@ -1,57 +1,57 @@
package rtmfp
{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.ProgressEvent;
- import flash.utils.ByteArray;
-
- [Event(name="peerConnectAcknowledged", type="flash.events.Event")]
- public 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;
- }
- }
-}
\ No newline at end of file
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.ProgressEvent;
+ import flash.utils.ByteArray;
+
+ [Event(name="peerConnectAcknowledged", type="flash.events.Event")]
+ public 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;
+ }
+ }
+}
diff --git a/rtmfp/events/RTMFPSocketEvent.as b/rtmfp/events/RTMFPSocketEvent.as
index c5b4af1..5bc08e5 100644
--- a/rtmfp/events/RTMFPSocketEvent.as
+++ b/rtmfp/events/RTMFPSocketEvent.as
@@ -1,25 +1,24 @@
package rtmfp.events
{
- import flash.events.Event;
- import flash.net.NetStream;
+ import flash.events.Event;
+ import flash.net.NetStream;
- public class RTMFPSocketEvent extends Event
- {
- public static const CONNECT_SUCCESS:String = "connectSuccess";
- public static const CONNECT_FAIL:String = "connectFail";
- public static const PUBLISH_START:String = "publishStart";
- public static const PEER_CONNECTED:String = "peerConnected";
- public static const PEER_DISCONNECTED:String = "peerDisconnected";
- public static const PEERING_SUCCESS:String = "peeringSuccess";
- public static const PEERING_FAIL:String = "peeringFail";
-
- public var stream:NetStream;
-
- public function RTMFPSocketEvent(type:String, streamVal:NetStream = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- stream = streamVal;
- }
-
- }
-}
\ No newline at end of file
+ public class RTMFPSocketEvent extends Event
+ {
+ public static const CONNECT_SUCCESS:String = "connectSuccess";
+ public static const CONNECT_FAIL:String = "connectFail";
+ public static const PUBLISH_START:String = "publishStart";
+ public static const PEER_CONNECTED:String = "peerConnected";
+ public static const PEER_DISCONNECTED:String = "peerDisconnected";
+ public static const PEERING_SUCCESS:String = "peeringSuccess";
+ public static const PEERING_FAIL:String = "peeringFail";
+
+ public var stream:NetStream;
+
+ public function RTMFPSocketEvent(type:String, streamVal:NetStream = null, bubbles:Boolean = false, cancelable:Boolean = false)
+ {
+ super(type, bubbles, cancelable);
+ stream = streamVal;
+ }
+ }
+}
diff --git a/rtmfpcat.as b/rtmfpcat.as
index 328274a..d4766c4 100644
--- a/rtmfpcat.as
+++ b/rtmfpcat.as
@@ -11,198 +11,198 @@ package
import flash.events.SecurityErrorEvent;
import flash.utils.ByteArray;
import flash.utils.setTimeout;
-
+
import rtmfp.RTMFPSocket;
import rtmfp.events.RTMFPSocketEvent;
import Utils;
-
- public class rtmfpcat extends Sprite {
-
- /* Nate's facilitator -- also serving a crossdomain policy */
- private const DEFAULT_FAC_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_PROXY_ADDR:Object = {
- host: "173.255.221.44",
- port: 9001
- };
-
- // Milliseconds.
- private const FACILITATOR_POLL_INTERVAL:int = 10000;
-
- private var output_text:TextField;
-
- private var s_f:Socket;
- private var s_r:RTMFPSocket;
- private var s_t:Socket;
-
- private var fac_addr:Object;
- private var tor_addr:Object;
-
- private var proxy_mode:Boolean;
-
- public function rtmfpcat()
- {
- output_text = new TextField();
- output_text.width = 400;
- output_text.height = 300;
- output_text.background = true;
- output_text.backgroundColor = 0x001f0f;
- output_text.textColor = 0x44CC44;
- addChild(output_text);
-
- puts("Starting.");
-
- this.loaderInfo.addEventListener(Event.COMPLETE, onLoaderInfoComplete);
- }
-
- private function puts(s:String):void
- {
- output_text.appendText(s + "\n");
- output_text.scrollV = output_text.maxScrollV;
- }
-
- private function onLoaderInfoComplete(e:Event):void
- {
- var fac_spec:String;
- var tor_spec:String;
-
- puts("Parameters loaded.");
-
- proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
-
- fac_spec = this.loaderInfo.parameters["facilitator"];
- if (!fac_spec) {
- puts("No \"facilitator\" specification provided...using default.");
- fac_addr = DEFAULT_FAC_ADDR;
- } else {
- puts("Facilitator spec: \"" + fac_spec + "\"");
- fac_addr = Utils.parseAddrSpec(fac_spec);
+
+ public class rtmfpcat extends Sprite
+ {
+ /* Nate's facilitator -- also serving a crossdomain policy */
+ private const DEFAULT_FAC_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_PROXY_ADDR:Object = {
+ host: "173.255.221.44",
+ port: 9001
+ };
+
+ // Milliseconds.
+ private const FACILITATOR_POLL_INTERVAL:int = 10000;
+
+ private var output_text:TextField;
+
+ private var s_f:Socket;
+ private var s_r:RTMFPSocket;
+ private var s_t:Socket;
+
+ private var fac_addr:Object;
+ private var tor_addr:Object;
+
+ private var proxy_mode:Boolean;
+
+ public function rtmfpcat()
+ {
+ output_text = new TextField();
+ output_text.width = 400;
+ output_text.height = 300;
+ output_text.background = true;
+ output_text.backgroundColor = 0x001f0f;
+ output_text.textColor = 0x44CC44;
+ addChild(output_text);
+
+ puts("Starting.");
+
+ this.loaderInfo.addEventListener(Event.COMPLETE, onLoaderInfoComplete);
}
-
- if (!fac_addr) {
- puts("Error: Facilitator spec must be in the form \"host:port\".");
- return;
+
+ private function puts(s:String):void
+ {
+ output_text.appendText(s + "\n");
+ output_text.scrollV = output_text.maxScrollV;
}
-
- tor_spec = this.loaderInfo.parameters["tor"];
- if (!tor_spec) {
- puts("No Tor specification provided...using default.");
- if (proxy_mode) tor_addr = DEFAULT_TOR_PROXY_ADDR;
- else tor_addr = DEFAULT_TOR_CLIENT_ADDR;
- } else {
- puts("Tor spec: \"" + tor_spec + "\"")
- tor_addr = Utils.parseAddrSpec(tor_spec);
+
+ private function onLoaderInfoComplete(e:Event):void
+ {
+ var fac_spec:String;
+ var tor_spec:String;
+
+ puts("Parameters loaded.");
+
+ proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
+
+ fac_spec = this.loaderInfo.parameters["facilitator"];
+ if (!fac_spec) {
+ puts("No \"facilitator\" specification provided...using default.");
+ fac_addr = DEFAULT_FAC_ADDR;
+ } else {
+ puts("Facilitator spec: \"" + fac_spec + "\"");
+ fac_addr = Utils.parseAddrSpec(fac_spec);
+ }
+
+ if (!fac_addr) {
+ puts("Error: Facilitator spec must be in the form \"host:port\".");
+ return;
+ }
+
+ tor_spec = this.loaderInfo.parameters["tor"];
+ if (!tor_spec) {
+ puts("No Tor specification provided...using default.");
+ if (proxy_mode) tor_addr = DEFAULT_TOR_PROXY_ADDR;
+ else tor_addr = DEFAULT_TOR_CLIENT_ADDR;
+ } else {
+ puts("Tor spec: \"" + tor_spec + "\"")
+ tor_addr = Utils.parseAddrSpec(tor_spec);
+ }
+
+ if (!tor_addr) {
+ puts("Error: Tor spec must be in the form \"host:port\".");
+ return;
+ }
+
+ establishRTMFPConnection();
}
- if (!tor_addr) {
- puts("Error: Tor spec must be in the form \"host:port\".");
- return;
+ private function establishRTMFPConnection():void
+ {
+ s_r = new RTMFPSocket();
+ s_r.addEventListener(RTMFPSocketEvent.CONNECT_SUCCESS, function (e:Event):void {
+ puts("Cirrus: connected with id " + s_r.id + ".");
+ establishFacilitatorConnection();
+ });
+ s_r.addEventListener(RTMFPSocketEvent.CONNECT_FAIL, function (e:Event):void {
+ puts("Error: failed to connect to Cirrus.");
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PUBLISH_START, function(e:RTMFPSocketEvent):void {
+ puts("Publishing started.");
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PEER_CONNECTED, function(e:RTMFPSocketEvent):void {
+ puts("Peer connected.");
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PEER_DISCONNECTED, function(e:RTMFPSocketEvent):void {
+ puts("Peer disconnected.");
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PEERING_SUCCESS, function(e:RTMFPSocketEvent):void {
+ puts("Peering success.");
+ establishTorConnection();
+ });
+ s_r.addEventListener(RTMFPSocketEvent.PEERING_FAIL, function(e:RTMFPSocketEvent):void {
+ puts("Peering fail.");
+ });
+ s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
+ var bytes:ByteArray = new ByteArray();
+ s_r.readBytes(bytes);
+ puts("RTMFP: read " + bytes.length + " bytes.");
+ s_t.writeBytes(bytes);
+ });
+
+ s_r.connect();
+ }
+
+ private function establishTorConnection():void
+ {
+ s_t = new Socket();
+ s_t.addEventListener(Event.CONNECT, function (e:Event):void {
+ puts("Tor: connected to " + tor_addr.host + ":" + tor_addr.port + ".");
+ });
+ s_t.addEventListener(Event.CLOSE, function (e:Event):void {
+ puts("Tor: closed connection.");
+ });
+ s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
+ puts("Tor: I/O error: " + e.text + ".");
+ });
+ s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
+ var bytes:ByteArray = new ByteArray();
+ s_t.readBytes(bytes, 0, e.bytesLoaded);
+ puts("Tor: read " + bytes.length + " bytes.");
+ s_r.writeBytes(bytes);
+ });
+ s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ puts("Tor: security error: " + e.text + ".");
+ });
+
+ s_t.connect(tor_addr.host, tor_addr.port);
}
- establishRTMFPConnection();
- }
-
- private function establishRTMFPConnection():void
- {
- s_r = new RTMFPSocket();
- s_r.addEventListener(RTMFPSocketEvent.CONNECT_SUCCESS, function (e:Event):void {
- puts("Cirrus: connected with id " + s_r.id + ".");
- establishFacilitatorConnection();
- });
- s_r.addEventListener(RTMFPSocketEvent.CONNECT_FAIL, function (e:Event):void {
- puts("Error: failed to connect to Cirrus.");
- });
- s_r.addEventListener(RTMFPSocketEvent.PUBLISH_START, function(e:RTMFPSocketEvent):void {
- puts("Publishing started.");
- });
- s_r.addEventListener(RTMFPSocketEvent.PEER_CONNECTED, function(e:RTMFPSocketEvent):void {
- puts("Peer connected.");
- });
- s_r.addEventListener(RTMFPSocketEvent.PEER_DISCONNECTED, function(e:RTMFPSocketEvent):void {
- puts("Peer disconnected.");
- });
- s_r.addEventListener(RTMFPSocketEvent.PEERING_SUCCESS, function(e:RTMFPSocketEvent):void {
- puts("Peering success.");
- establishTorConnection();
- });
- s_r.addEventListener(RTMFPSocketEvent.PEERING_FAIL, function(e:RTMFPSocketEvent):void {
- puts("Peering fail.");
- });
- s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- var bytes:ByteArray = new ByteArray();
- s_r.readBytes(bytes);
- puts("RTMFP: read " + bytes.length + " bytes.");
- s_t.writeBytes(bytes);
- });
-
- s_r.connect();
- }
-
- private function establishTorConnection():void
- {
- s_t = new Socket();
- s_t.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("Tor: connected to " + tor_addr.host + ":" + tor_addr.port + ".");
- });
- s_t.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("Tor: closed connection.");
- });
- s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- puts("Tor: I/O error: " + e.text + ".");
- });
- s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
- var bytes:ByteArray = new ByteArray();
- s_t.readBytes(bytes, 0, e.bytesLoaded);
- puts("Tor: read " + bytes.length + " bytes.");
- s_r.writeBytes(bytes);
- });
- s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- puts("Tor: security error: " + e.text + ".");
- });
-
- s_t.connect(tor_addr.host, tor_addr.port);
- }
-
- private function establishFacilitatorConnection():void
- {
- s_f = new Socket();
- s_f.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("Facilitator: connected to " + fac_addr.host + ":" + fac_addr.port + ".");
- if (proxy_mode) s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
- else s_f.writeUTFBytes("POST / HTTP/1.0\r\n\r\nclient=" + s_r.id + "\r\n");
- });
- s_f.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("Facilitator: connection closed.");
- if (proxy_mode) {
- setTimeout(establishFacilitatorConnection, FACILITATOR_POLL_INTERVAL);
- }
- });
- 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 clientID:String = s_f.readMultiByte(e.bytesLoaded, "utf-8");
- puts("Facilitator: got \"" + clientID + "\"");
- if (clientID != "Registration list empty") {
- puts("Connecting to " + clientID + ".");
- s_r.peer = clientID;
- }
- });
- 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);
- }
- }
-}
\ No newline at end of file
+ private function establishFacilitatorConnection():void
+ {
+ s_f = new Socket();
+ s_f.addEventListener(Event.CONNECT, function (e:Event):void {
+ puts("Facilitator: connected to " + fac_addr.host + ":" + fac_addr.port + ".");
+ if (proxy_mode) s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
+ else s_f.writeUTFBytes("POST / HTTP/1.0\r\n\r\nclient=" + s_r.id + "\r\n");
+ });
+ s_f.addEventListener(Event.CLOSE, function (e:Event):void {
+ puts("Facilitator: connection closed.");
+ if (proxy_mode) {
+ setTimeout(establishFacilitatorConnection, FACILITATOR_POLL_INTERVAL);
+ }
+ });
+ 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 clientID:String = s_f.readMultiByte(e.bytesLoaded, "utf-8");
+ puts("Facilitator: got \"" + clientID + "\"");
+ if (clientID != "Registration list empty") {
+ puts("Connecting to " + clientID + ".");
+ s_r.peer = clientID;
+ }
+ });
+ 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);
+ }
+ }
+}
1
0