[tor-commits] [ooni-probe/master] Add support for adding tor version to the bridge_reachability report.

art at torproject.org art at torproject.org
Wed Apr 30 17:30:23 UTC 2014


commit eccaec864777ea75dfea5f48db63468cc378a6c4
Author: Arturo Filastò <art at fuffa.org>
Date:   Mon Mar 24 15:21:13 2014 +0100

    Add support for adding tor version to the bridge_reachability report.
    
    Fail with a good error code if the version is unsupported for the given bridge.
---
 ooni/director.py                              |    4 ++-
 ooni/managers.py                              |    7 ++--
 ooni/nettests/blocking/bridge_reachability.py |   33 +++++++++----------
 ooni/tests/test_onion.py                      |    8 +++++
 ooni/utils/__init__.py                        |    3 --
 ooni/utils/onion.py                           |   43 +++++++++++++++++++++++++
 6 files changed, 74 insertions(+), 24 deletions(-)

diff --git a/ooni/director.py b/ooni/director.py
index ada1b82..b95639a 100644
--- a/ooni/director.py
+++ b/ooni/director.py
@@ -208,7 +208,6 @@ class Director(object):
         self.activeNetTests.remove(net_test)
         if len(self.activeNetTests) == 0:
             self.allTestsDone.callback(None)
-            self.allTestsDone = defer.Deferred()
 
     @defer.inlineCallbacks
     def startNetTest(self, net_test_loader, reporters):
@@ -219,6 +218,9 @@ class Director(object):
             net_test_loader:
                 an instance of :class:ooni.nettest.NetTestLoader
         """
+        if self.allTestsDone.called:
+            self.allTestsDone = defer.Deferred()
+
         if config.privacy.includepcap:
             if not config.reports.pcap:
                 config.reports.pcap = config.generate_pcap_filename(net_test_loader.testDetails)
diff --git a/ooni/managers.py b/ooni/managers.py
index f6af282..cd05d42 100644
--- a/ooni/managers.py
+++ b/ooni/managers.py
@@ -30,6 +30,8 @@ class TaskManager(object):
         to be re-run once all the currently scheduled tasks have run.
         """
         log.err("Task %s has failed %s times" % (task, task.failures))
+        if config.advanced.debug:
+            log.exception(failure)
 
         self._active_tasks.remove(task)
         self.failures = self.failures + 1
@@ -81,10 +83,11 @@ class TaskManager(object):
         """
         self._active_tasks.remove(task)
 
-        self._fillSlots()
-
         # Fires the done deferred when the task has completed
         task.done.callback(result)
+
+        self._fillSlots()
+
         self.succeeded(result, task)
 
     @property
diff --git a/ooni/nettests/blocking/bridge_reachability.py b/ooni/nettests/blocking/bridge_reachability.py
index 892ed02..9e6bb9e 100644
--- a/ooni/nettests/blocking/bridge_reachability.py
+++ b/ooni/nettests/blocking/bridge_reachability.py
@@ -9,7 +9,7 @@ from twisted.internet import defer, reactor, error
 
 import txtorcon
 
-from ooni.utils import log
+from ooni.utils import log, onion
 from ooni import nettest
 
 class UsageOptions(usage.Options):
@@ -35,8 +35,11 @@ class BridgeReachability(nettest.NetTestCase):
         self.tor_progress = 0
         self.timeout = int(self.localOptions['timeout'])
 
+        self.report['error'] = None
+        self.report['success'] = None
         self.report['timeout'] = self.timeout
         self.report['transport_name'] = 'vanilla'
+        self.report['tor_version'] = str(onion.tor_details['version'])
         self.report['tor_progress'] = 0
         self.report['tor_progress_tag'] = None
         self.report['tor_progress_summary'] = None
@@ -90,36 +93,30 @@ class BridgeReachability(nettest.NetTestCase):
         print "Failing bridges: %s" % failing_bridges
 
     def test_full_tor_connection(self):
-        def getTransport(address):
-            """
-            If the address of the bridge starts with a valid c identifier then
-            we consider it to be a bridge.
-            Returns:
-                The transport_name if it's a transport.
-                None if it's not a obfsproxy bridge.
-            """
-            transport_name = address.split(' ')[0]
-            transport_name_chars = string.ascii_letters + string.digits
-            if all(c in transport_name_chars for c in transport_name):
-                return transport_name
-            else:
-                return None
-
         config = txtorcon.TorConfig()
         config.ControlPort = random.randint(2**14, 2**16)
         config.SocksPort = random.randint(2**14, 2**16)
         
-        transport_name = getTransport(self.bridge)
+        transport_name = onion.transport_name(self.bridge)
         if transport_name and self.pyobfsproxy_bin:
             config.ClientTransportPlugin = "%s exec %s managed" % (transport_name, self.pyobfsproxy_bin)
             self.report['transport_name'] = transport_name
             self.report['bridge_address'] = self.bridge.split(' ')[1]
         elif transport_name and not self.pyobfsproxy_bin:
             log.err("Unable to test bridge because pyobfsproxy is not installed")
-            self.report['success'] = None
+            self.report['error'] = 'missing-pyobfsproxy'
             return
         else:
             self.report['bridge_address'] = self.bridge.split(' ')[0]
+        
+        if transport_name and transport_name == 'scramblesuit' and \
+                onion.TorVersion('0.2.5') > onion.tor_details['version']:
+            self.report['error'] = 'unsupported-tor-version'
+            return
+        elif transport_name and \
+                onion.TorVersion('0.2.4.1') > onion.tor_details['version']:
+            self.report['error'] = 'unsupported-tor-version'
+            return
 
         config.Bridge = self.bridge
         config.UseBridges = 1
diff --git a/ooni/tests/test_onion.py b/ooni/tests/test_onion.py
new file mode 100644
index 0000000..9830235
--- /dev/null
+++ b/ooni/tests/test_onion.py
@@ -0,0 +1,8 @@
+from twisted.trial import unittest 
+from ooni.utils import onion
+
+class TestOnion(unittest.TestCase):
+    def test_tor_details(self):
+        assert isinstance(onion.tor_details, dict)
+        assert onion.tor_details['version']
+        assert onion.tor_details['binary']
diff --git a/ooni/utils/__init__.py b/ooni/utils/__init__.py
index 1b6a8e9..3f47bd1 100644
--- a/ooni/utils/__init__.py
+++ b/ooni/utils/__init__.py
@@ -82,7 +82,6 @@ def randomStr(length, num=True):
         chars += string.digits
     return ''.join(random.choice(chars) for x in range(length))
 
-
 def pushFilenameStack(filename):
     """
     Takes as input a target filename and checks to see if a file by such name
@@ -103,5 +102,3 @@ def pushFilenameStack(filename):
         new_filename = "%s.%s" % (c_filename, new_idx)
         os.rename(f, new_filename)
     os.rename(filename, filename+".1")
-
-
diff --git a/ooni/utils/onion.py b/ooni/utils/onion.py
new file mode 100644
index 0000000..91d8a2d
--- /dev/null
+++ b/ooni/utils/onion.py
@@ -0,0 +1,43 @@
+import string
+import subprocess
+from distutils.version import LooseVersion
+
+from txtorcon.util import find_tor_binary
+
+class TorVersion(LooseVersion):
+    pass
+
+def tor_version():
+    tor_binary = find_tor_binary()
+    if not tor_binary:
+        return None
+    try:
+        proc = subprocess.Popen((tor_binary, '--version'),
+                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    except OSError:
+        pass
+    else:
+        stdout, _ = proc.communicate()
+        if proc.poll() == 0 and stdout != '':
+            return TorVersion(stdout.strip().split(' ')[2])
+    return None
+
+def transport_name(address):
+    """
+    If the address of the bridge starts with a valid c identifier then
+    we consider it to be a bridge.
+    Returns:
+        The transport_name if it's a transport.
+        None if it's not a obfsproxy bridge.
+    """
+    transport_name = address.split(' ')[0]
+    transport_name_chars = string.ascii_letters + string.digits
+    if all(c in transport_name_chars for c in transport_name):
+        return transport_name
+    else:
+        return None
+
+tor_details = {
+    'binary': find_tor_binary(),
+    'version': tor_version()
+}





More information about the tor-commits mailing list