[tor-commits] [flashproxy/master] Add an RTMFPSocket class.
dcf at torproject.org
dcf at torproject.org
Sun Jun 12 08:56:31 UTC 2011
commit 9a85e5b90a37c8c989cda04f69862b82f25ca924
Author: David Fifield <david at 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);
+ }
+ }
+}
More information about the tor-commits
mailing list