[Pkg-privacy-commits] [txtorcon] 20/96: Wait for descriptor upload on HiddenSerivce .listen()

Jérémy Bobbio lunar at moszumanska.debian.org
Sun Sep 6 18:33:34 UTC 2015


This is an automated email from the git hooks/post-receive script.

lunar pushed a commit to branch master
in repository txtorcon.

commit 4e106e21ae93bdeadad1d9a6142712b7e25a5008
Author: meejah <meejah at meejah.ca>
Date:   Sat Jan 17 00:30:04 2015 -0700

    Wait for descriptor upload on HiddenSerivce .listen()
    
    We wait for the right text to appear in an INFO message from Tor -- fragile,
    but the only way to determine if your hidden service descriptor has been
    uploaded to an HSDir
    
    Also refactor a test so it gets the 650 INFO events we have to send now.
---
 test/test_endpoints.py | 29 +++++++++++++----------------
 test/test_torconfig.py | 19 ++++++++++++++++++-
 test/test_torinfo.py   |  1 +
 txtorcon/endpoints.py  | 31 ++++++++++++++++++++++++++++---
 4 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/test/test_endpoints.py b/test/test_endpoints.py
index 19ea38c..c4ceed9 100644
--- a/test/test_endpoints.py
+++ b/test/test_endpoints.py
@@ -45,6 +45,11 @@ class EndpointTests(unittest.TestCase):
         endpoints._global_tor_lock = defer.DeferredLock()
         self.reactor = FakeReactorTcp(self)
         self.protocol = FakeControlProtocol([])
+        self.protocol.event_happened(
+            'INFO',
+            'connection_dir_client_reached_eof(): Uploaded rendezvous '\
+            'descriptor (status 200 ("Service descriptor (v2) stored"))'
+        )
         self.config = TorConfig(self.protocol)
         self.protocol.answers.append('config/names=\nHiddenServiceOptions Virtual')
         self.protocol.answers.append('HiddenServiceOptions')
@@ -185,32 +190,24 @@ class EndpointTests(unittest.TestCase):
 
     def test_already_bootstrapped(self):
         self.config.bootstrap()
-
         ep = TCPHiddenServiceEndpoint(self.reactor, self.config, 123)
         d = ep.listen(NoOpProtocolFactory())
         return d
 
     @defer.inlineCallbacks
     def test_explicit_data_dir(self):
-        config = TorConfig()
-        td = tempfile.mkdtemp()
-        ep = TCPHiddenServiceEndpoint(self.reactor, config, 123, td)
-
-        # fake out some things so we don't actually have to launch + bootstrap
-        class FakeTorProcessProtocol(object):
-            tor_protocol = self.reactor.protocol
-        process = FakeTorProcessProtocol()
-        ep._launch_tor = Mock(return_value=process)
-        config._update_proto(Mock())
-        config.bootstrap()
-        yield config.post_bootstrap
+        config = TorConfig(self.protocol)
+        ep = TCPHiddenServiceEndpoint(self.reactor, config, 123, '/dev/null')
 
         # make sure listen() correctly configures our hidden-serivce
         # with the explicit directory we passed in above
-        port = yield ep.listen(NoOpProtocolFactory())
+        d = ep.listen(NoOpProtocolFactory())
+        def foo(fail):
+            print "ERROR", fail
+        d.addErrback(foo)
+        port = yield d
         self.assertEqual(1, len(config.HiddenServices))
-        self.assertEqual(config.HiddenServices[0].dir, td)
-        shutil.rmtree(td)
+        self.assertEqual(config.HiddenServices[0].dir, '/dev/null')
 
     def test_failure(self):
         self.reactor.failures = 1
diff --git a/test/test_torconfig.py b/test/test_torconfig.py
index cdbbeda..94a3d37 100644
--- a/test/test_torconfig.py
+++ b/test/test_torconfig.py
@@ -44,7 +44,18 @@ class FakeControlProtocol:
         self.post_bootstrap = defer.succeed(self)
         self.on_disconnect = defer.Deferred()
         self.sets = []
-        self.events = {}
+        self.events = {} # event type -> callback
+        self.pending_events = {} # event type -> list
+
+    def event_happened(self, event_type, *args):
+        '''
+        Use this in your tests to send 650 events when an event-listener is added.
+        XXX Also if we've *already* added one? Do that if there's a use-case for it
+        '''
+        if event_type in self.pending_events:
+            self.pending_events[event_type].append(args)
+        else:
+            self.pending_events[event_type] = [args]
 
     def answer_pending(self, answer):
         d = self.pending[0]
@@ -80,6 +91,12 @@ class FakeControlProtocol:
 
     def add_event_listener(self, nm, cb):
         self.events[nm] = cb
+        if nm in self.pending_events:
+            for event in self.pending_events[nm]:
+                cb(*event)
+
+    def remove_event_listener(self, nm, cb):
+        del self.events[nm]
 
 
 class CheckAnswer:
diff --git a/test/test_torinfo.py b/test/test_torinfo.py
index 5cd7958..8610b7c 100644
--- a/test/test_torinfo.py
+++ b/test/test_torinfo.py
@@ -14,6 +14,7 @@ class FakeControlProtocol:
 
     def __init__(self, answers):
         self.answers = answers
+        self.pending = []
         self.post_bootstrap = defer.succeed(self)
 
     def get_info_raw(self, info):
diff --git a/txtorcon/endpoints.py b/txtorcon/endpoints.py
index 4aff66b..6d78394 100644
--- a/txtorcon/endpoints.py
+++ b/txtorcon/endpoints.py
@@ -357,6 +357,11 @@ class TCPHiddenServiceEndpoint(object):
         FIXME TODO: also listen for an INFO-level Tor message (does
         exist, #tor-dev says) that indicates the hidden service's
         descriptor is published.
+
+        It is "connection_dir_client_reached_eof(): Uploaded
+        rendezvous descriptor (status 200 ("Service descriptor (v2)
+        stored"))" at INFO level.
+
         """
 
         self.protocolfactory = protocolfactory
@@ -378,15 +383,35 @@ class TCPHiddenServiceEndpoint(object):
 
         # NOTE at some point, we can support unix sockets here
         # once Tor does. See bug #XXX
+
+        # specifically NOT creating the hidden-service dir; letting
+        # Tor do it will more-likely result in a usable situation...
         if not os.path.exists(self.hidden_service_dir):
-                log.msg('Creating "%s".' % self.hidden_service_dir)
-                os.makedirs(self.hidden_service_dir)
+            log.msg('Noting that "%s" does not exist; letting Tor create it.' % self.hidden_service_dir)
+
+        # listen for the descriptor upload event
+        info_callback = defer.Deferred()
+        def info_event(msg):
+            # XXX giant hack here; Right Thing would be to implement a
+            # "real" event in Tor and listen for that.
+            if 'Service descriptor (v2) stored' in msg:
+                info_callback.callback(None)
+        self.config.protocol.add_event_listener('INFO', info_event)
+
         self.hiddenservice = HiddenService(
             self.config, self.hidden_service_dir,
-            ['%d 127.0.0.1:%d' % (self.public_port, self.local_port)])
+            ['%d 127.0.0.1:%d' % (self.public_port, self.local_port)],
+            group_readable=1)
         self.config.HiddenServices.append(self.hiddenservice)
         yield self.config.save()
 
+        self._tor_progress_update(100.0, 'wait_descriptor',
+                                  'Waiting for descriptor upload...')
+        yield info_callback  # awaits an INFO log-line from Tor .. sketchy
+        yield self.config.protocol.remove_event_listener('INFO', info_event)
+        self._tor_progress_update(100.0, 'wait_descriptor',
+                                  'At least one descriptor uploaded.')
+
         log.msg(
             'Started hidden service "%s" on port %d' %
             (self.onion_uri, self.public_port))

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/txtorcon.git



More information about the Pkg-privacy-commits mailing list