[tor-commits] [flashproxy/master] Revert facilitator blocking until a reg is available.

dcf at torproject.org dcf at torproject.org
Mon Sep 5 04:49:17 UTC 2011


commit 55841fece74c90019457092bf67ed4309b0d7312
Author: David Fifield <david at bamsoftware.com>
Date:   Sun Sep 4 20:17:15 2011 -0700

    Revert facilitator blocking until a reg is available.
    
    This reverts
    91cceeef62061d66732be7039d559f5fff49e8ef Document the facilitator's waiting until a reg is available.
    c3ea89cb2a2c1e5f8496ec526b9d1c7451e2d06d Log the socket error when we fail to send a reg.
    90510d7bf565f0cc9876665aa6e85b55c8e5a3c1 Make facilitator requests block until a reg is available.
    
    This would be a nice model, but the URLLoader in ActionScript doesn't
    work exactly the way I expect it to (at least with Flash Player in
    Firefox), and it means that this "long polling" technique doesn't work
    robustly.
    
    The first time swfcat is loaded, everything is fine: it makes the
    /crossdomain.xml request, then starts a URLLoader for /. If there is no
    client to be served immediately, then the URLLoader just hangs until
    there is one (this part works well).
    
    What goes wrong is when you refresh the page (or navigate away and then
    back again). I expected that the URLLoader would break its connection
    when this happens, which would be noticed by the facilitator. Instead,
    what seems to happen is the URLLoader's HTTP connection goes into limbo,
    still alive and waiting for a response, but not hooked up to anything on
    the client side. (I suppose this is an artifact of Flash Player using
    the browser to make the request, so it might differ on other browsers.)
    
    The new instance of swfcat asks for /crossdomain.xml, and claims to be
    opening a URLLoader for /, but instead what appears to happen is the new
    request gets queued behind the pending one that is in limbo; tcpdump
    doesn't see any second request until the first is completed. Now, if a
    client registers, its reg goes out over the in-limbo connection and
    effectively disappears. The queued URLLoader request from the proxy gets
    sent, but at this point there is no more client reg because it was
    presumed to be handled by the first proxy request.
    
    This queueing behavior is evident if you refresh the page, say, five
    times, and then kill the facilitator: you see one HTTP request, then a
    RST from the server, then four other immediate SYN-RST pairs.
    
    So instead, we go back to the facilitator always returning immediately
    (possibly without a client), and the proxy polling on a regular basis
    for clients.
---
 design.txt     |    4 ++--
 facilitator.py |   38 ++++++++++++++------------------------
 2 files changed, 16 insertions(+), 26 deletions(-)

diff --git a/design.txt b/design.txt
index f33468c..55427b6 100644
--- a/design.txt
+++ b/design.txt
@@ -151,8 +151,8 @@ Design of flash proxies
 
     client=[<rtmfp-id>]&relay=<address>:<port>
 
-  The facilitator keeps the HTTP session alive and does not send a
-  registration until one is available.
+  If the value for the client parameter is empty, it means that there are no
+  client registrations for this proxy.
 
   The flash proxy may serve more than one relay–client pair at once.
 
diff --git a/facilitator.py b/facilitator.py
index bea3957..495cd3b 100755
--- a/facilitator.py
+++ b/facilitator.py
@@ -183,23 +183,11 @@ class RegSet(object):
         finally:
             self.cv.release()
 
-    def add_front(self, reg):
-        self.cv.acquire()
-        try:
-            if reg not in list(self.set):
-                self.set.append(reg)
-                self.cv.notify()
-                return True
-            else:
-                return False
-        finally:
-            self.cv.release()
-
     def fetch(self):
         self.cv.acquire()
         try:
-            while not self.set:
-                self.cv.wait()
+            if not self.set:
+                return None
             return self.set.pop(0)
         finally:
             self.cv.release()
@@ -224,16 +212,13 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
             return
 
         reg = REGS.fetch()
-
-        try:
-            self.send_client(reg)
+        if reg:
             log(u"proxy %s gets %s, relay %s (now %d)" %
                 (proxy_addr_s, unicode(reg), options.relay_spec, len(REGS)))
-        except socket.error, e:
-            # Something went wrong; likely the proxy disconnected without
-            # receiving a reg. Restore the reg to the front of the queue.
-            REGS.add_front(reg)
-            log(u"proxy %s gets none (%s)" % (proxy_addr_s, str(e)))
+            self.send_client(reg)
+        else:
+            log(u"proxy %s gets none" % proxy_addr_s)
+            self.send_client(None)
 
     def do_POST(self):
         client_addr_s = format_addr(self.client_address)
@@ -301,8 +286,13 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
             % (format_addr(self.client_address), repr(msg)))
 
     def send_client(self, reg):
-        client_str = str(reg)
-
+        if reg:
+            client_str = str(reg)
+        else:
+            # Send an empty string rather than a 404 or similar because Flash
+            # Player's URLLoader can't always distinguish a 404 from, say,
+            # "server not found."
+            client_str = ""
         self.send_response(200)
         self.send_header("Content-Type", "x-www-form-urlencoded")
         self.send_header("Cache-Control", "no-cache")





More information about the tor-commits mailing list