tor_manager: expose errors when --tor-control-port= is provided
If you pass --tor-control-port= and we can't use it, throw an error that will kill the whole process, instead of falling back to the default SOCKS port. If you omit --tor-control-port=, then if all default control port connections fail, we'll fall back to the default SOCKS port. Also, test each combination separately, and improve the status messages.
This commit is contained in:
parent
ed420e0001
commit
0aeae9ce10
|
@ -50,7 +50,48 @@ class Tor(unittest.TestCase):
|
|||
def test_connect(self):
|
||||
reactor = object()
|
||||
my_tor = X() # object() didn't like providedBy()
|
||||
tcp = "port"
|
||||
connect_d = defer.Deferred()
|
||||
stderr = io.StringIO()
|
||||
with mock.patch("wormhole.tor_manager.txtorcon.connect",
|
||||
side_effect=connect_d) as connect:
|
||||
with mock.patch("wormhole.tor_manager.clientFromString",
|
||||
side_effect=["foo"]) as sfs:
|
||||
d = get_tor(reactor, stderr=stderr)
|
||||
self.assertEqual(sfs.mock_calls, [])
|
||||
self.assertNoResult(d)
|
||||
self.assertEqual(connect.mock_calls, [mock.call(reactor)])
|
||||
connect_d.callback(my_tor)
|
||||
tor = self.successResultOf(d)
|
||||
self.assertIs(tor, my_tor)
|
||||
self.assert_(ITorManager.providedBy(tor))
|
||||
self.assertEqual(stderr.getvalue(),
|
||||
" using Tor via default control port\n")
|
||||
|
||||
def test_connect_fails(self):
|
||||
reactor = object()
|
||||
connect_d = defer.Deferred()
|
||||
stderr = io.StringIO()
|
||||
with mock.patch("wormhole.tor_manager.txtorcon.connect",
|
||||
side_effect=connect_d) as connect:
|
||||
with mock.patch("wormhole.tor_manager.clientFromString",
|
||||
side_effect=["foo"]) as sfs:
|
||||
d = get_tor(reactor, stderr=stderr)
|
||||
self.assertEqual(sfs.mock_calls, [])
|
||||
self.assertNoResult(d)
|
||||
self.assertEqual(connect.mock_calls, [mock.call(reactor)])
|
||||
|
||||
connect_d.errback(ConnectError())
|
||||
tor = self.successResultOf(d)
|
||||
self.assertIsInstance(tor, SocksOnlyTor)
|
||||
self.assert_(ITorManager.providedBy(tor))
|
||||
self.assertEqual(tor._reactor, reactor)
|
||||
self.assertEqual(stderr.getvalue(),
|
||||
" unable to find default Tor control port, using SOCKS\n")
|
||||
|
||||
def test_connect_custom_control_port(self):
|
||||
reactor = object()
|
||||
my_tor = X() # object() didn't like providedBy()
|
||||
tcp = "PORT"
|
||||
ep = object()
|
||||
connect_d = defer.Deferred()
|
||||
stderr = io.StringIO()
|
||||
|
@ -66,9 +107,10 @@ class Tor(unittest.TestCase):
|
|||
tor = self.successResultOf(d)
|
||||
self.assertIs(tor, my_tor)
|
||||
self.assert_(ITorManager.providedBy(tor))
|
||||
self.assertEqual(stderr.getvalue(), " using Tor via control port\n")
|
||||
self.assertEqual(stderr.getvalue(),
|
||||
" using Tor via control port at PORT\n")
|
||||
|
||||
def test_connect_fails(self):
|
||||
def test_connect_custom_control_port_fails(self):
|
||||
reactor = object()
|
||||
tcp = "port"
|
||||
ep = object()
|
||||
|
@ -84,12 +126,8 @@ class Tor(unittest.TestCase):
|
|||
self.assertEqual(connect.mock_calls, [mock.call(reactor, ep)])
|
||||
|
||||
connect_d.errback(ConnectError())
|
||||
tor = self.successResultOf(d)
|
||||
self.assertIsInstance(tor, SocksOnlyTor)
|
||||
self.assert_(ITorManager.providedBy(tor))
|
||||
self.assertEqual(tor._reactor, reactor)
|
||||
self.assertEqual(stderr.getvalue(),
|
||||
" unable to find Tor control port, using SOCKS\n")
|
||||
self.failureResultOf(d, ConnectError)
|
||||
self.assertEqual(stderr.getvalue(), "")
|
||||
|
||||
class SocksOnly(unittest.TestCase):
|
||||
def test_tor(self):
|
||||
|
|
|
@ -81,22 +81,24 @@ def get_tor(reactor, launch_tor=False, tor_control_port=None,
|
|||
#data_directory=,
|
||||
#tor_binary=,
|
||||
)
|
||||
elif tor_control_port:
|
||||
with timing.add("find tor"):
|
||||
control_ep = clientFromString(reactor, tor_control_port)
|
||||
tor = yield txtorcon.connect(reactor, control_ep) # might raise
|
||||
print(" using Tor via control port at %s" % tor_control_port,
|
||||
file=stderr)
|
||||
else:
|
||||
# Let txtorcon look through a list of usual places. If that fails,
|
||||
# we'll arrange to attempt the default SOCKS port
|
||||
with timing.add("find tor"):
|
||||
try:
|
||||
# If tor_control_port is None (the default), txtorcon
|
||||
# will look through a list of usual places. If it is set,
|
||||
# it will look only in the place we tell it to.
|
||||
if tor_control_port is not None:
|
||||
tor_control_port = clientFromString(reactor,
|
||||
tor_control_port)
|
||||
tor = yield txtorcon.connect(reactor, tor_control_port)
|
||||
print(" using Tor via control port", file=stderr)
|
||||
tor = yield txtorcon.connect(reactor)
|
||||
print(" using Tor via default control port", file=stderr)
|
||||
except Exception:
|
||||
# TODO: make this more specific. I think connect() is
|
||||
# likely to throw a reactor.connectTCP -type error, like
|
||||
# ConnectionFailed or ConnectionRefused or something
|
||||
print(" unable to find Tor control port, using SOCKS",
|
||||
print(" unable to find default Tor control port, using SOCKS",
|
||||
file=stderr)
|
||||
tor = SocksOnlyTor(reactor)
|
||||
directlyProvides(tor, _interfaces.ITorManager)
|
||||
|
|
Loading…
Reference in New Issue
Block a user