[tor-commits] [bridgedb/develop] Add a filter for unblocked pluggable transports.

isis at torproject.org isis at torproject.org
Thu Jun 25 07:10:55 UTC 2015


commit 5088163284bd512082f113fe84f27f7af86973b8
Author: Isis Lovecruft <isis at torproject.org>
Date:   Tue Apr 21 03:08:03 2015 +0000

    Add a filter for unblocked pluggable transports.
    
     * ADD Filters.filterBridgesByUnblockedTransport().
     * CHANGE bridgerequest.BridgeRequestBase.generateFilters() to handle
       requests for unblocked bridges with pluggable transports.
---
 lib/bridgedb/Filters.py       |   61 +++++++++++++++++++++++++++++++++++++++++
 lib/bridgedb/bridgerequest.py |   25 +++++++++++------
 2 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/lib/bridgedb/Filters.py b/lib/bridgedb/Filters.py
index eb7db4e..d0d65e8 100644
--- a/lib/bridgedb/Filters.py
+++ b/lib/bridgedb/Filters.py
@@ -90,6 +90,67 @@ def filterBridgesByTransport(methodname, addressClass=None):
         funcs[ruleset] = _filterByTransport
         return _filterByTransport
 
+def filterBridgesByUnblockedTransport(methodname, countryCode=None, addressClass=None):
+    """Return a filter function for :class:`~bridgedb.bridges.Bridge`s.
+
+    The returned filter function should be called on a
+    :class:`~bridgedb.bridges.Bridge`.  It returns ``True`` if the ``Bridge``
+    has a :class:`~bridgedb.bridges.PluggableTransport` such that:
+
+      1. The :data:`~bridge.bridges.PluggableTransport.methodname` matches
+         **methodname**,
+
+      2. The :data:`~bridgedb.bridges.PluggableTransport.address`` is an
+         instance of **addressClass**, and isn't known to be blocked in
+         **countryCode**.
+
+    :param str methodname: A Pluggable Transport
+        :data:`~bridge.bridges.PluggableTransport.methodname`.
+    :type countryCode: str or ``None``
+    :param countryCode: A two-letter country code which the filtered
+        :class:`PluggableTransport`s should not be blocked in.
+    :type addressClass: ``ipaddr.IPAddress``
+    :param addressClass: The IP version that the ``Bridge``'s
+        ``PluggableTransport``
+        :data:`~bridgedb.bridges.PluggableTransport.address`` should have.
+    :rtype: callable
+    :returns: A filter function for :class:`~bridgedb.bridges.Bridge`s.
+    """
+    if not countryCode:
+        return filterBridgesByTransport(methodname, addressClass)
+
+    if not ((addressClass is IPv4Address) or (addressClass is IPv6Address)):
+        addressClass = IPv4Address
+
+    # Ignore case
+    methodname = methodname.lower()
+    countryCode = countryCode.lower()
+
+    ruleset = frozenset([methodname, countryCode, addressClass.__name__])
+    try:
+        return funcs[ruleset]
+    except KeyError:
+        def _filterByUnblockedTransport(bridge):
+            # Since bridge.transportIsBlockedIn() will return True if the
+            # bridge has that type of transport AND that transport is blocked,
+            # we can "fail fast" here by doing this faster check before
+            # iterating over all the transports testing for the other
+            # conditions.
+            if bridge.transportIsBlockedIn(countryCode, methodname):
+                return False
+            else:
+                for transport in bridge.transports:
+                    if (transport.methodname == methodname and
+                        isinstance(transport.address, addressClass)):
+                        return True
+            return False
+        _filterByUnblockedTransport.__name__ = ("filterBridgesByUnblockedTransport(%s,%s,%s)"
+                                                % (methodname, countryCode, addressClass))
+        setattr(_filterByUnblockedTransport, "description",
+                "transport=%s unblocked=%s" % (methodname, countryCode))
+        funcs[ruleset] = _filterByUnblockedTransport
+        return _filterByUnblockedTransport
+
 def filterBridgesByNotBlockedIn(countryCode):
     """Return ``True`` if at least one of a bridge's (transport) bridgelines isn't
     known to be blocked in **countryCode**.
diff --git a/lib/bridgedb/bridgerequest.py b/lib/bridgedb/bridgerequest.py
index 532558d..b699896 100644
--- a/lib/bridgedb/bridgerequest.py
+++ b/lib/bridgedb/bridgerequest.py
@@ -171,15 +171,22 @@ class BridgeRequestBase(object):
         return ptType
 
     def generateFilters(self):
-        if self.addressClass is ipaddr.IPv6Address:
-            self.addFilter(Filters.filterBridgesByIP6)
-        else:
-            self.addFilter(Filters.filterBridgesByIP4)
+        self.clearFilters()
 
         transport = self.justOnePTType()
+
         if transport:
-            self.clearFilters()
-            self.addFilter(Filters.filterBridgesByTransport(transport,
-                                                            self.addressClass))
-        for country in self.notBlockedIn:
-            self.addFilter(Filters.filterBridgesByNotBlockedIn(country.lower()))
+            if self.notBlockedIn:
+                for country in self.notBlockedIn:
+                    self.addFilter(Filters.filterBridgesByUnblockedTransport(
+                        transport, country, self.addressClass))
+            else:
+                self.addFilter(Filters.filterBridgesByTransport(
+                    transport, self.addressClass))
+        else:
+            if self.addressClass is ipaddr.IPv6Address:
+                self.addFilter(Filters.filterBridgesByIP6)
+            else:
+                self.addFilter(Filters.filterBridgesByIP4)
+            for country in self.notBlockedIn:
+                self.addFilter(Filters.filterBridgesByNotBlockedIn(country.lower()))





More information about the tor-commits mailing list