Merge PR327 from david415:2813.socks_endpoint_desc.0

This should fix compatibility with the current versions of foolscap and
txtorcon.
This commit is contained in:
Brian Warner 2016-09-01 20:28:40 -07:00
commit 78ccae35b1
4 changed files with 29 additions and 33 deletions

View File

@ -261,7 +261,7 @@ setup(name="tahoe-lafs", # also set in __init__.py
"coverage", "coverage",
"mock", "mock",
"tox", "tox",
"foolscap[tor]", "foolscap[tor] >= 0.12.3",
"txtorcon", # in case pip's resolver doesn't work "txtorcon", # in case pip's resolver doesn't work
"foolscap[i2p]", "foolscap[i2p]",
"txi2p", # in case pip's resolver doesn't work "txi2p", # in case pip's resolver doesn't work
@ -269,7 +269,7 @@ setup(name="tahoe-lafs", # also set in __init__.py
"pytest-twisted", "pytest-twisted",
], ],
"tor": [ "tor": [
"foolscap[tor]", "foolscap[tor] >= 0.12.3",
"txtorcon", # in case pip's resolver doesn't work "txtorcon", # in case pip's resolver doesn't work
], ],
"i2p": [ "i2p": [

View File

@ -39,8 +39,8 @@ install_requires = [
# * foolscap 0.8.0 generates 2048-bit RSA-with-SHA-256 signatures, # * foolscap 0.8.0 generates 2048-bit RSA-with-SHA-256 signatures,
# rather than 1024-bit RSA-with-MD5. This also allows us to work # rather than 1024-bit RSA-with-MD5. This also allows us to work
# with a FIPS build of OpenSSL. # with a FIPS build of OpenSSL.
# * foolscap >= 0.12.2 provides tcp/tor/i2p connection handlers we need # * foolscap >= 0.12.3 provides tcp/tor/i2p connection handlers we need
"foolscap >= 0.12.2", "foolscap >= 0.12.3",
# Needed for SFTP. # Needed for SFTP.
# pycrypto 2.2 doesn't work due to <https://bugs.launchpad.net/pycrypto/+bug/620253> # pycrypto 2.2 doesn't work due to <https://bugs.launchpad.net/pycrypto/+bug/620253>

View File

@ -207,24 +207,10 @@ class Node(service.MultiService):
datadir = os.path.join(self.basedir, "private", "tor-statedir") datadir = os.path.join(self.basedir, "private", "tor-statedir")
return tor.launch(data_directory=datadir, tor_binary=executable) return tor.launch(data_directory=datadir, tor_binary=executable)
socksport = self.get_config("tor", "socks.port", None) socks_endpoint_desc = self.get_config("tor", "socks.port", None)
if socksport: if socks_endpoint_desc:
# this is nominally and endpoint string, but txtorcon requires socks_ep = endpoints.clientFromString(reactor, socks_endpoint_desc)
# TCP host and port. So parse it now, and reject non-TCP return tor.socks_endpoint(socks_ep)
# endpoints.
pieces = socksport.split(":")
if pieces[0] != "tcp" or len(pieces) != 3:
raise ValueError("'tahoe.cfg [tor] socks.port' = "
"is currently limited to 'tcp:HOST:PORT', "
"not '%s'" % (socksport,))
host = pieces[1]
try:
port = int(pieces[2])
except ValueError:
raise ValueError("'tahoe.cfg [tor] socks.port' used "
"non-numeric PORT value '%s'" % (pieces[2],))
return tor.socks_port(host, port)
controlport = self.get_config("tor", "control.port", None) controlport = self.get_config("tor", "control.port", None)
if controlport: if controlport:

View File

@ -3,6 +3,7 @@ import mock
from io import BytesIO from io import BytesIO
from twisted.trial import unittest from twisted.trial import unittest
from twisted.internet import reactor, endpoints from twisted.internet import reactor, endpoints
from twisted.internet.interfaces import IStreamClientEndpoint
from ConfigParser import SafeConfigParser from ConfigParser import SafeConfigParser
from foolscap.connections import tcp from foolscap.connections import tcp
from ..node import Node, PrivacyError from ..node import Node, PrivacyError
@ -71,33 +72,42 @@ class Tor(unittest.TestCase):
self.assertEqual(f.mock_calls, [exp]) self.assertEqual(f.mock_calls, [exp])
self.assertIdentical(h, h1) self.assertIdentical(h, h1)
def test_socksport(self): def test_socksport_unix_endpoint(self):
n = FakeNode(BASECONFIG+"[tor]\nsocks.port = tcp:127.0.0.1:1234\n") n = FakeNode(BASECONFIG+"[tor]\nsocks.port = unix:/var/lib/fw-daemon/tor_socks.socket\n")
h1 = mock.Mock() h1 = mock.Mock()
with mock.patch("foolscap.connections.tor.socks_port", with mock.patch("foolscap.connections.tor.socks_endpoint",
return_value=h1) as f: return_value=h1) as f:
h = n._make_tor_handler() h = n._make_tor_handler()
self.assertEqual(f.mock_calls, [mock.call("127.0.0.1", 1234)]) self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0]))
self.assertIdentical(h, h1) self.assertIdentical(h, h1)
def test_socksport_otherhost(self): def test_socksport_endpoint(self):
n = FakeNode(BASECONFIG+"[tor]\nsocks.port = tcp:otherhost:1234\n") n = FakeNode(BASECONFIG+"[tor]\nsocks.port = tcp:127.0.0.1:1234\n")
h1 = mock.Mock() h1 = mock.Mock()
with mock.patch("foolscap.connections.tor.socks_port", with mock.patch("foolscap.connections.tor.socks_endpoint",
return_value=h1) as f: return_value=h1) as f:
h = n._make_tor_handler() h = n._make_tor_handler()
self.assertEqual(f.mock_calls, [mock.call("otherhost", 1234)]) self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0]))
self.assertIdentical(h, h1)
def test_socksport_endpoint_otherhost(self):
n = FakeNode(BASECONFIG+"[tor]\nsocks.port = tcp:otherhost:1234\n")
h1 = mock.Mock()
with mock.patch("foolscap.connections.tor.socks_endpoint",
return_value=h1) as f:
h = n._make_tor_handler()
self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0]))
self.assertIdentical(h, h1) self.assertIdentical(h, h1)
def test_socksport_bad_endpoint(self): def test_socksport_bad_endpoint(self):
n = FakeNode(BASECONFIG+"[tor]\nsocks.port = unix:unsupported\n") n = FakeNode(BASECONFIG+"[tor]\nsocks.port = meow:unsupported\n")
e = self.assertRaises(ValueError, n._make_tor_handler) e = self.assertRaises(ValueError, n._make_tor_handler)
self.assertIn("is currently limited to 'tcp:HOST:PORT'", str(e)) self.assertIn("Unknown endpoint type: 'meow'", str(e))
def test_socksport_not_integer(self): def test_socksport_not_integer(self):
n = FakeNode(BASECONFIG+"[tor]\nsocks.port = tcp:localhost:kumquat\n") n = FakeNode(BASECONFIG+"[tor]\nsocks.port = tcp:localhost:kumquat\n")
e = self.assertRaises(ValueError, n._make_tor_handler) e = self.assertRaises(ValueError, n._make_tor_handler)
self.assertIn("used non-numeric PORT value", str(e)) self.assertIn("invalid literal for int() with base 10: 'kumquat'", str(e))
def test_controlport(self): def test_controlport(self):
n = FakeNode(BASECONFIG+"[tor]\ncontrol.port = tcp:localhost:1234\n") n = FakeNode(BASECONFIG+"[tor]\ncontrol.port = tcp:localhost:1234\n")