[tor-commits] [flashproxy/master] Using URLLoader in the FacilitatorSocket, Facilitator now speaks true HTTP

dcf at torproject.org dcf at torproject.org
Sun Jun 12 08:56:29 UTC 2011


commit fbffb6fce47047c877d8dc4d2a83bcb4ee2926ea
Author: Nate Hardison <nate at rescomp-09-154551.stanford.edu>
Date:   Thu Jun 2 19:49:49 2011 -0700

    Using URLLoader in the FacilitatorSocket, Facilitator now speaks true HTTP
---
 facilitator.py             |   55 +++++++++++++++++---
 rtmfp/FacilitatorSocket.as |  121 ++++++++++++++++++++------------------------
 rtmfpcat.as                |   19 ++-----
 3 files changed, 106 insertions(+), 89 deletions(-)

diff --git a/facilitator.py b/facilitator.py
index c9859db..0ea86a1 100755
--- a/facilitator.py
+++ b/facilitator.py
@@ -10,6 +10,7 @@ import socket
 import sys
 import threading
 import time
+import urllib
 
 DEFAULT_ADDRESS = "0.0.0.0"
 DEFAULT_PORT = 9002
@@ -190,31 +191,47 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
     def do_GET(self):
         log(u"proxy %s connects" % format_addr(self.client_address))
 
+        if self.path == "/crossdomain.xml":
+            self.send_crossdomain()
+            return
+        
+        client = ""
         reg = REGS.fetch()
         if reg:
             log(u"proxy %s gets %s (now %d)" % (format_addr(self.client_address), unicode(reg), len(REGS)))
-            self.request.send(str(reg))
+            client = str(reg)
         else:
             log(u"proxy %s gets none" % format_addr(self.client_address))
+            client = "Registration list empty"
+        
+        response = "client=%s" % urllib.quote(client)
+        self.send_response(200)
+        self.send_header('Content-Type', 'text/html')    
+        self.send_header('Content-Length', str(len(response)))
+        self.end_headers()
+        self.wfile.write(response)
 
     def do_POST(self):
-        data = self.rfile.readline(1024).strip()
-        try:
-            vals = cgi.parse_qs(data, False, True)
-        except ValueError, e:
-            log(u"client %s POST syntax error: %s" % (format_addr(self.client_address), repr(str(e))))
+        data = cgi.FieldStorage(fp = self.rfile, headers = self.headers, 
+                                environ = {'REQUEST_METHOD' : 'POST',
+                                           'CONTENT_TYPE' : self.headers['Content-Type']})
+
+        if self.path == "/crossdomain.xml":
+            self.send_crossdomain()
             return
 
-        client_specs = vals.get("client")
-        if client_specs is None or len(client_specs) != 1:
+        client_specs = data["client"]
+        if client_specs is None or client_specs.value is None:
             log(u"client %s missing \"client\" param" % format_addr(self.client_address))
+            self.send_error(404)
             return
-        val = client_specs[0]
+        val = client_specs.value
 
         try:
             reg = Reg.parse(val, self.client_address[0])
         except ValueError, e:
             log(u"client %s syntax error in %s: %s" % (format_addr(self.client_address), repr(val), repr(str(e))))
+            self.send_error(404)
             return
 
         log(u"client %s regs %s -> %s" % (format_addr(self.client_address), val, unicode(reg)))
@@ -222,10 +239,30 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
             log(u"client %s %s (now %d)" % (format_addr(self.client_address), unicode(reg), len(REGS)))
         else:
             log(u"client %s %s (already present, now %d)" % (format_addr(self.client_address), unicode(reg), len(REGS)))
+        
+        response = ""
+
+        self.send_response(200)
+        self.send_header('Content-Type', 'text/html')
+        self.send_header('Content-Length', str(len(response)))
+        self.send_header('Connection', 'close')
+        self.end_headers()
+        self.wfile.write(response)
 
     def log_message(self, format, *args):
         msg = format % args
         log(u"message from HTTP handler for %s: %s" % (format_addr(self.client_address), repr(msg)))
+        
+    def send_crossdomain(self):
+        crossdomain = """\
+<cross-domain-policy>
+    <allow-access-from domain="*" to-ports="%s"/>
+</cross-domain-policy>\r\n""" % (address[1])
+        self.send_response(200)
+        self.send_header('Content-Type', 'application/xml')
+        self.send_header('Content-Length', str(len(crossdomain)))
+        self.end_headers()
+        self.wfile.write(crossdomain)  
 
 REGS = RegSet()
 
diff --git a/rtmfp/FacilitatorSocket.as b/rtmfp/FacilitatorSocket.as
index e175290..32c8a7d 100644
--- a/rtmfp/FacilitatorSocket.as
+++ b/rtmfp/FacilitatorSocket.as
@@ -1,108 +1,94 @@
 package rtmfp
 {
-    import flash.net.Socket;
     import flash.events.Event;
     import flash.events.EventDispatcher;
+    import flash.events.HTTPStatusEvent;
     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 flash.net.URLLoader;
+    import flash.net.URLLoaderDataFormat;
+    import flash.net.URLRequest;
+    import flash.net.URLRequestMethod;
+    import flash.net.URLVariables;
+    import flash.system.Security;
     
     import rtmfp.events.FacilitatorSocketEvent;
     
-    [Event(name=FacilitatorSocketEvent.CONNECT_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;
+        private var host:String;
+        private var port: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 FacilitatorSocket(host:String, port:uint)
+        {   
+            this.host = host;
+            this.port = port; 
         }
         
         public function get_registration():void
         {
-            if (!connected) return;
-            socket.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
+            make_request(URLRequestMethod.GET);
         }
         
         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");
+        {    
+            var data:URLVariables = new URLVariables();
+            data.client = registration_data;
+            make_request(URLRequestMethod.POST, data);
         }
         
         private function fail():void
         {
-            clearInterval(connection_timeout);
             dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_FAILED));
         }
         
-        private function on_close_event(event:Event):void
+        private function make_request(method:String, data:URLVariables = null):void
         {
-            close();
-            dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_CLOSED));
+            var request:URLRequest = new URLRequest(url)
+            request.data = data;
+            request.method = method;
+
+            var url_loader:URLLoader = new URLLoader();
+            url_loader = new URLLoader();
+            url_loader.dataFormat = URLLoaderDataFormat.VARIABLES;
+            
+            url_loader.addEventListener(Event.COMPLETE, on_complete_event);
+            url_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, on_http_status_event);
+            url_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
+            url_loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
+            
+            url_loader.load(request);
         }
         
-        private function on_connect_event(event:Event):void
+        private function on_complete_event(event:Event):void
         {
-            connected = true;
-            dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_SUCCESS));
+            try {
+                var client_id:String = event.target.data.client;
+                if (client_id == "Registration list empty") {
+                    dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY));
+                } else {
+                    dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id));
+                }
+            } catch (e:Error) {
+                /* error is thrown for POST when we don't care about
+                   the response anyways */
+            }
+            
+            event.target.close()
         }
         
-        private function on_io_error_event(event:IOErrorEvent):void
+        private function on_http_status_event(event:HTTPStatusEvent):void
         {
-            fail();
+            /* empty for now */
         }
         
-        private function on_progress_event(event:ProgressEvent):void
+        private function on_io_error_event(event:IOErrorEvent):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));
-            }   
+            fail();
         }
 
         private function on_security_error_event(event:SecurityErrorEvent):void
@@ -110,6 +96,9 @@ package rtmfp
             fail();
         }
         
-        
+        private function get url():String
+        {
+            return "http://" + host + ":" + port;
+        }
     }
 }
\ No newline at end of file
diff --git a/rtmfpcat.as b/rtmfpcat.as
index 713fc45..224fe56 100644
--- a/rtmfpcat.as
+++ b/rtmfpcat.as
@@ -166,23 +166,11 @@ package
 
         private function establish_facilitator_connection():void
         {
-            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_f = new FacilitatorSocket(fac_addr.host, fac_addr.port);
             s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
                 puts("Facilitator: connect failed.");
                 setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
             });
-            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 {
@@ -194,13 +182,16 @@ package
                     puts("Facilitator: no registrations available.");
                     setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
                 });
+                puts("Facilitator: getting registration.");
+                s_f.get_registration();
             } else {
                 s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
                     puts("Facilitator: registration failed.");
                     setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
                 });
+                puts("Facilitator: posting registration.");
+                s_f.post_registration(s_c.id);
             }
-            s_f.connect(fac_addr.host, fac_addr.port);
         }
         
         private function start_proxy_pair():void





More information about the tor-commits mailing list