[tor-commits] [ooni-probe/master] * Still working on the @defer.inlineCallbacks structure; I think I should

isis at torproject.org isis at torproject.org
Thu Oct 4 14:41:15 UTC 2012


commit c4978ff0e750d044b3efd9c211dc3cfa80cc2ec4
Author: Isis Lovecruft <isis at torproject.org>
Date:   Thu Sep 20 14:18:38 2012 +0000

    * Still working on the @defer.inlineCallbacks structure; I think I should
      use DeferredLists for each of the sets of Deferreds, and then pile all
      the DeferredLists onto TorState().
---
 ooni/plugins/bridget.py |  124 ++++++++++++++++++++++++++++++++++++----------
 ooni/utils/circuit.py   |   35 ++++++++------
 2 files changed, 117 insertions(+), 42 deletions(-)

diff --git a/ooni/plugins/bridget.py b/ooni/plugins/bridget.py
index 07d7269..d82f2e7 100644
--- a/ooni/plugins/bridget.py
+++ b/ooni/plugins/bridget.py
@@ -360,16 +360,25 @@ class BridgetTest(OONITest):
                     raise PTNotFoundException
 
                 controller_response = reset_tor.callback
-                if not controller_response:
-                    defer.returnValue((state.callback, None))
+
+                #if not controller_response:
+                #    defer.returnValue((state.callback, None))
+                #else:
+                #    defer.returnValue((state.callback, controller_response)) 
+                if controller_response == 'OK':
+                    defer.returnValue(state.callback)
                 else:
-                    defer.returnValue((state.callback, controller_response)) 
+                    log.msg("TorControlProtocol responded with error:\n%s\n"
+                            % controller_response)
+                    defer.returnValue(state.callback)
+                
             except Exception, e:
-                log.msg("Reconfiguring torrc Bridge line failed with %s" % bridge)
+                log.msg("Reconfiguring torrc with Bridge line %s failed:\n%s\n" 
+                        % (bridge, e))
 
-        def reconfigure_fail(*param):
-            log.msg("Reconfiguring TorConfig with parameters %s failed" % param)
-            reactor.stop()
+        def reconfigure_fail(state, bridge, bad):
+            log.msg("Reconfiguring TorConfig with parameters %s failed" % state)
+            bad.append(bridge)
 
         @defer.inlineCallbacks
         def remove_public_relays(state, bridges):
@@ -399,6 +408,44 @@ class BridgetTest(OONITest):
                             % both)
                     log.err(e)
 
+        def request_circuit_build(state, deferred, path=None):
+            if path is None:
+                if relays_remaining() > 0:
+                    first, middle,last = (state.relays.pop()
+                                          for i in range(3))
+                else:
+                    first = random.choice(state.entry_guards.values())
+                    middle, last = (random.choice(state.routers.values())
+                                    for i in range(2))
+                path = [first, middle, last]
+            else:
+                assert type(path) is list, "Circuit path must be a list of routers!"
+                assert len(path) >= 3, "Circuits must be at least three hops!"
+
+            log.msg("Requesting a circuit: %s"
+                    % '->'.join(map(lambda node: node, path)))
+
+            class AppendWaiting:
+                def __init__(self, attacher, deferred):
+                    self.attacher = attacher
+                    self.d        = deferred
+                def __call__(self, circ):
+                    """
+                    Return from build_circuit is a Circuit, however,
+                    we want to wait until it is built before we can
+                    issue an attach on it and callback to the Deferred
+                    we issue here.
+                    """
+                    log.msg("Circuit %s is in progress ..." % circ.id)
+                    self.attacher.waiting_circuits.append((circ.id, self.d))
+
+            return self.state.build_circuit(path).addCallback(
+                AppendWaiting(self, deferred)).addErrback(
+                log.err)
+
+        def attacher_extend_circuit(attacher, deferred, router):
+            
+
         def setup_fail(proto, bridge_list, relay_list):
             log.err("Setup Failed: %s" % proto)
             log.err("We were given bridge list:\n%s\nAnd our relay list:\n%s\n"
@@ -508,27 +555,17 @@ class BridgetTest(OONITest):
 
         log.msg("Bridget: initiating test ... ")
 
-        #while self.bridges_remaining() > 0:
-        while args['bridge']:
+        while self.bridges_remaining() > 0:
+
+            self.current_bridge = self.bridges.pop()
+            #self.current_bridge = args['bridge']
 
-            #self.current_bridge = self.bridges.pop()
-            self.current_bridge = args['bridge']
             try:
                 self.bridges.remove(self.current_bridge)
             except ValueError, ve:
                 log.err(ve)
                 
-            if self.config.config.has_key('Bridge'):
-                log.msg("We now have %d untested bridges..." 
-                        % self.bridges_remaining())
-                reconf = defer.Deferred()
-                reconf.addCallback(reconfigure_bridge, state,
-                                   self.current_bridge, self.use_pt,
-                                   self.pt_type)
-                reconf.addErrback(reconfigure_fail)
-                state.chainDeferred(reconf)
-
-            else:
+            if not self.config.config.has_key('Bridge'):
                 self.config.Bridge = self.current_bridge
                 (torrc, self.data_directory, to_delete) = write_torrc(
                     self.config, self.data_directory)
@@ -538,14 +575,48 @@ class BridgetTest(OONITest):
                         % self.config.create_torrc())
                 report = {'tor_config': self.config.create_torrc()}
 
-                state = start_tor(reactor, updates, torrc, to_delete,
-                                  self.control_port, self.tor_binary, 
-                                  self.data_directory)
+                state = start_tor(reactor, updates, torrc, to_delete, 
+                                  self.control_port, 
+                                  self.tor_binary, 
+                                  self.data_directory, 
+                                  bridge_list=self.bridges)
                 state.addCallback(setup_done)
                 state.addErrback(setup_fail)
-                state.addBoth(remove_relays, self.bridges)
+                state.addCallback(remove_public_relays, self.bridges)
+
+            else:
+                log.msg("We now have %d untested bridges..." 
+                        % self.bridges_remaining())
+                reconf = defer.Deferred()
+                reconf.addCallback(reconfigure_bridge, state,
+                                   self.current_bridge, self.use_pt,
+                                   self.pt_type)
+                reconf.addErrback(reconfigure_fail, state,
+                                  self.current_bridge, self.bridges_down)
+                state.chainDeferred(reconf)
+                #all = []
+                #reconf = reconfigure_bridge(state, self.current_bridge,
+                #                            self.use_pt, self.pt_type)
+                #reconf.addCallback(reconfigure_done)
+                #reconf.addErrback(reconfigure_fail)
+                #state.DeferredList(all)
+
+            while self.relays_remaining() >= 3:
+                #path = list(self.relays.pop() for i in range(3))
+                #log.msg("Trying path %s" % '->'.join(map(lambda node: node, path)))
+                self.current_relay = self.relays.pop()
+                for circ in state.circuits.values():
+                    for node in circ.path:
+                        if node == self.current_relay:
+                            self.relays_up.append(self.current_relay)
+                    try:
+                        ext = attacher_extend_circuit(state.attacher, circ, 
+                                                      self.current_relay)
+                        
 
             return state
+        ## still need to attach attacher to state
+        ## then build circuits
 
             ## XXX see txtorcon.TorControlProtocol.add_event_listener we
             ##     may not need full CustomCircuit class
@@ -569,7 +640,6 @@ class BridgetTest(OONITest):
             #        self.bridges_up.append(self.current_bridge)
 
         reactor.run()
-        ## now build circuits
 
 
 ## So that getPlugins() can register the Test:
diff --git a/ooni/utils/circuit.py b/ooni/utils/circuit.py
index 6ee0720..d725879 100644
--- a/ooni/utils/circuit.py
+++ b/ooni/utils/circuit.py
@@ -9,7 +9,7 @@
 # circuits without actually attaching streams.
 #
 # :author: Meejah, Isis Lovecruft
-# :license: see included license file
+# :license: see included LICENSE file
 # :version: 0.1.0-alpha
 #
 
@@ -24,9 +24,10 @@ from zope.interface    import implements
 class CustomCircuit(CircuitListenerMixin):
     implements(IStreamAttacher)
 
-    def __init__(self, state):
+    def __init__(self, state, relays=None):
         self.state = state
         self.waiting_circuits = []
+        self.relays = relays
 
     def waiting_on(self, circuit):
         for (circid, d) in self.waiting_circuits:
@@ -54,12 +55,12 @@ class CustomCircuit(CircuitListenerMixin):
 
     def circuit_failed(self, circuit, reason):
         if self.waiting_on(circuit):
-            log.msg("A circuit we requested %s failed for reason %s" 
+            log.msg("Circuit %s failed for reason %s" 
                     % (circuit.id, reason))
             circid, d = None, None
-            for x in self.waiting_circuits:
-                if x[0] == circuit.id:
-                    circid, d = x
+            for c in self.waiting_circuits:
+                if c[0] == circuit.id:
+                    circid, d = c
             if d is None:
                 raise Exception("Expected to find circuit.")
 
@@ -72,15 +73,19 @@ class CustomCircuit(CircuitListenerMixin):
             #router.update() ## XXX can i use without args? no.
             TorInfo.dump(self)
 
-    def request_circuit_build(self, deferred):
-        if self.state.relays_remaining() > 0:
-            first, middle,last = (self.state.relays.pop()
-                                  for i in range(3))
+    def request_circuit_build(self, deferred, path=None):
+        if path is None:
+            if self.state.relays_remaining() > 0:
+                first, middle,last = (self.state.relays.pop()
+                                      for i in range(3))
+            else:
+                first = random.choice(self.state.entry_guards.values())
+                middle, last = (random.choice(self.state.routers.values())
+                                for i in range(2))
+            path = [first, middle, last]
         else:
-            first = random.choice(self.state.entry_guards.values())
-            middle, last = (random.choice(self.state.routers.values())
-                            for i in range(2))
-        path = [first, middle, last]
+            assert type(path) is list, "Circuit path must be a list of routers!"
+            assert len(path) >= 3, "Circuits must be at least three hops!"
 
         log.msg("Requesting a circuit: %s" 
                 % '->'.join(map(lambda node: node, path)))
@@ -100,5 +105,5 @@ class CustomCircuit(CircuitListenerMixin):
                 self.attacher.waiting_circuits.append((circ.id, self.d))
 
         return self.state.build_circuit(path).addCallback(
-            AppendWaiting(self, deferred_to_callback)).addErrback(
+            AppendWaiting(self, deferred)).addErrback(
             log.err)





More information about the tor-commits mailing list