[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