2016-08-28 09:28:39 +00:00
|
|
|
import os
|
|
|
|
import mock
|
|
|
|
from twisted.trial import unittest
|
2016-10-09 05:02:11 +00:00
|
|
|
from twisted.internet import reactor, endpoints, defer
|
2016-09-02 03:17:45 +00:00
|
|
|
from twisted.internet.interfaces import IStreamClientEndpoint
|
2016-08-28 09:28:39 +00:00
|
|
|
from foolscap.connections import tcp
|
2018-01-28 04:40:43 +00:00
|
|
|
from ..node import Node, PrivacyError, config_from_string
|
2018-01-28 05:00:57 +00:00
|
|
|
from ..node import create_connection_handlers
|
|
|
|
from ..node import create_i2p_provider, create_tor_provider
|
2018-01-28 04:45:59 +00:00
|
|
|
from ..node import create_main_tub, _tub_portlocation
|
2018-01-28 04:40:43 +00:00
|
|
|
from ..client import create_client_from_config
|
2016-12-09 19:46:26 +00:00
|
|
|
from ..util import connection_status
|
2016-08-28 09:28:39 +00:00
|
|
|
|
2018-01-28 04:40:43 +00:00
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
class FakeNode(Node):
|
|
|
|
def __init__(self, config_str):
|
2018-01-31 18:30:46 +00:00
|
|
|
self.config = config_from_string(config_str, "fake.port", "no-basedir")
|
2017-09-06 01:08:35 +00:00
|
|
|
self._reveal_ip = True
|
2016-10-09 05:02:11 +00:00
|
|
|
self.services = []
|
2016-08-28 09:28:39 +00:00
|
|
|
|
|
|
|
BASECONFIG = ("[client]\n"
|
|
|
|
"introducer.furl = \n"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class TCP(unittest.TestCase):
|
2018-01-28 04:45:59 +00:00
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
def test_default(self):
|
2018-01-28 04:45:59 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG,
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:45:59 +00:00
|
|
|
)
|
2018-01-29 00:46:08 +00:00
|
|
|
_, foolscap_handlers = create_connection_handlers(None, 'basedir', config, mock.Mock(), mock.Mock())
|
2018-01-28 04:45:59 +00:00
|
|
|
self.assertIsInstance(
|
|
|
|
foolscap_handlers['tcp'],
|
|
|
|
tcp.DefaultTCP,
|
|
|
|
)
|
2016-08-28 09:28:39 +00:00
|
|
|
|
2018-01-28 05:00:57 +00:00
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
class Tor(unittest.TestCase):
|
2018-01-28 05:00:57 +00:00
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
def test_disabled(self):
|
2018-01-28 05:00:57 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[tor]\nenabled = false\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 05:00:57 +00:00
|
|
|
)
|
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
2016-08-28 09:28:39 +00:00
|
|
|
self.assertEqual(h, None)
|
|
|
|
|
2016-08-31 08:50:13 +00:00
|
|
|
def test_unimportable(self):
|
2016-10-09 05:02:11 +00:00
|
|
|
with mock.patch("allmydata.util.tor_provider._import_tor",
|
|
|
|
return_value=None):
|
2018-01-29 02:32:19 +00:00
|
|
|
config = config_from_string(BASECONFIG, "fake.port", "no-basedir")
|
2018-01-28 05:00:57 +00:00
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
2016-08-31 08:50:13 +00:00
|
|
|
self.assertEqual(h, None)
|
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
def test_default(self):
|
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.tor.default_socks",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 05:00:57 +00:00
|
|
|
|
2018-01-29 02:32:19 +00:00
|
|
|
config = config_from_string(BASECONFIG, "fake.port", "no-basedir")
|
2018-01-28 05:00:57 +00:00
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
|
|
|
self.assertEqual(f.mock_calls, [mock.call()])
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 09:28:39 +00:00
|
|
|
|
2016-10-09 05:02:11 +00:00
|
|
|
def _do_test_launch(self, executable):
|
|
|
|
# the handler is created right away
|
|
|
|
config = BASECONFIG+"[tor]\nlaunch = true\n"
|
|
|
|
if executable:
|
|
|
|
config += "tor.executable = %s\n" % executable
|
2016-08-28 09:28:39 +00:00
|
|
|
h1 = mock.Mock()
|
2016-10-09 05:02:11 +00:00
|
|
|
with mock.patch("foolscap.connections.tor.control_endpoint_maker",
|
2016-08-28 09:28:39 +00:00
|
|
|
return_value=h1) as f:
|
2018-01-28 05:00:57 +00:00
|
|
|
|
2018-01-29 02:32:19 +00:00
|
|
|
config = config_from_string(config, "fake.port", "no-basedir")
|
2018-01-28 05:00:57 +00:00
|
|
|
tp = create_tor_provider("reactor", 'BASEDIR', config)
|
|
|
|
h = tp.get_tor_handler()
|
|
|
|
|
|
|
|
private_dir = config.get_config_path("private")
|
|
|
|
exp = mock.call(tp._make_control_endpoint,
|
2016-12-08 23:11:45 +00:00
|
|
|
takes_status=True)
|
2016-08-28 09:28:39 +00:00
|
|
|
self.assertEqual(f.mock_calls, [exp])
|
|
|
|
self.assertIdentical(h, h1)
|
|
|
|
|
2016-10-09 05:02:11 +00:00
|
|
|
# later, when Foolscap first connects, Tor should be launched
|
|
|
|
reactor = "reactor"
|
|
|
|
tcp = object()
|
|
|
|
tcep = object()
|
|
|
|
launch_tor = mock.Mock(return_value=defer.succeed(("ep_desc", tcp)))
|
|
|
|
cfs = mock.Mock(return_value=tcep)
|
|
|
|
with mock.patch("allmydata.util.tor_provider._launch_tor", launch_tor):
|
|
|
|
with mock.patch("allmydata.util.tor_provider.clientFromString", cfs):
|
2016-12-08 23:11:45 +00:00
|
|
|
d = tp._make_control_endpoint(reactor,
|
|
|
|
update_status=lambda status: None)
|
|
|
|
cep = self.successResultOf(d)
|
2018-01-31 18:30:46 +00:00
|
|
|
launch_tor.assert_called_with(reactor, executable,
|
|
|
|
os.path.abspath(private_dir),
|
2016-10-09 05:02:11 +00:00
|
|
|
tp._txtorcon)
|
|
|
|
cfs.assert_called_with(reactor, "ep_desc")
|
|
|
|
self.assertIs(cep, tcep)
|
|
|
|
|
|
|
|
def test_launch(self):
|
|
|
|
self._do_test_launch(None)
|
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
def test_launch_executable(self):
|
2016-10-09 05:02:11 +00:00
|
|
|
self._do_test_launch("/special/tor")
|
2016-08-28 09:28:39 +00:00
|
|
|
|
2016-09-02 03:17:45 +00:00
|
|
|
def test_socksport_unix_endpoint(self):
|
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.tor.socks_endpoint",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 05:00:57 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[tor]\nsocks.port = unix:/var/lib/fw-daemon/tor_socks.socket\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 05:00:57 +00:00
|
|
|
)
|
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
|
|
|
self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0]))
|
|
|
|
self.assertIdentical(h, h1)
|
2016-09-02 03:17:45 +00:00
|
|
|
|
|
|
|
def test_socksport_endpoint(self):
|
2016-08-28 09:28:39 +00:00
|
|
|
h1 = mock.Mock()
|
2016-09-02 03:17:45 +00:00
|
|
|
with mock.patch("foolscap.connections.tor.socks_endpoint",
|
2016-08-28 09:28:39 +00:00
|
|
|
return_value=h1) as f:
|
2018-01-28 05:00:57 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[tor]\nsocks.port = tcp:127.0.0.1:1234\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 05:00:57 +00:00
|
|
|
)
|
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
|
|
|
self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0]))
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 09:28:39 +00:00
|
|
|
|
2016-09-02 03:17:45 +00:00
|
|
|
def test_socksport_endpoint_otherhost(self):
|
2016-08-28 09:28:39 +00:00
|
|
|
h1 = mock.Mock()
|
2016-09-02 03:17:45 +00:00
|
|
|
with mock.patch("foolscap.connections.tor.socks_endpoint",
|
2016-08-28 09:28:39 +00:00
|
|
|
return_value=h1) as f:
|
2018-01-28 05:00:57 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[tor]\nsocks.port = tcp:otherhost:1234\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 05:00:57 +00:00
|
|
|
)
|
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
|
|
|
self.assertTrue(IStreamClientEndpoint.providedBy(f.mock_calls[0]))
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 09:28:39 +00:00
|
|
|
|
2016-08-28 23:28:01 +00:00
|
|
|
def test_socksport_bad_endpoint(self):
|
2018-01-28 05:00:57 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[tor]\nsocks.port = meow:unsupported\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 05:00:57 +00:00
|
|
|
)
|
|
|
|
with self.assertRaises(ValueError) as ctx:
|
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
|
|
|
self.assertIn(
|
|
|
|
"Unknown endpoint type: 'meow'",
|
|
|
|
str(ctx.exception)
|
|
|
|
)
|
2016-08-28 09:28:39 +00:00
|
|
|
|
|
|
|
def test_socksport_not_integer(self):
|
2018-01-28 05:00:57 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[tor]\nsocks.port = tcp:localhost:kumquat\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 05:00:57 +00:00
|
|
|
)
|
|
|
|
with self.assertRaises(ValueError) as ctx:
|
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
|
|
|
self.assertIn(
|
|
|
|
"invalid literal for int() with base 10: 'kumquat'",
|
|
|
|
str(ctx.exception)
|
|
|
|
)
|
2016-08-28 09:28:39 +00:00
|
|
|
|
|
|
|
def test_controlport(self):
|
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.tor.control_endpoint",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 05:00:57 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[tor]\ncontrol.port = tcp:localhost:1234\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 05:00:57 +00:00
|
|
|
)
|
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = tor_provider.get_tor_handler()
|
2016-08-28 09:28:39 +00:00
|
|
|
self.assertEqual(len(f.mock_calls), 1)
|
|
|
|
ep = f.mock_calls[0][1][0]
|
|
|
|
self.assertIsInstance(ep, endpoints.TCP4ClientEndpoint)
|
|
|
|
self.assertIdentical(h, h1)
|
|
|
|
|
2016-08-28 10:15:35 +00:00
|
|
|
class I2P(unittest.TestCase):
|
2018-01-28 04:40:43 +00:00
|
|
|
|
2016-08-28 10:15:35 +00:00
|
|
|
def test_disabled(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\nenabled = false\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
|
|
|
i2p_provider = create_i2p_provider(None, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
2016-08-28 10:15:35 +00:00
|
|
|
self.assertEqual(h, None)
|
|
|
|
|
2016-08-31 08:50:13 +00:00
|
|
|
def test_unimportable(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG,
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-10-22 19:26:36 +00:00
|
|
|
with mock.patch("allmydata.util.i2p_provider._import_i2p",
|
|
|
|
return_value=None):
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
2016-08-31 08:50:13 +00:00
|
|
|
self.assertEqual(h, None)
|
|
|
|
|
2016-08-28 10:15:35 +00:00
|
|
|
def test_default(self):
|
2018-01-29 02:32:19 +00:00
|
|
|
config = config_from_string(BASECONFIG, "fake.port", "no-basedir")
|
2016-08-28 10:15:35 +00:00
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.i2p.default",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
|
|
|
self.assertEqual(f.mock_calls, [mock.call(reactor, keyfile=None)])
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
|
|
|
def test_samport(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\nsam.port = tcp:localhost:1234\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-08-28 10:15:35 +00:00
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.i2p.sam_endpoint",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
|
|
|
|
|
|
|
self.assertEqual(len(f.mock_calls), 1)
|
|
|
|
ep = f.mock_calls[0][1][0]
|
|
|
|
self.assertIsInstance(ep, endpoints.TCP4ClientEndpoint)
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
|
|
|
def test_samport_and_launch(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\n" +
|
|
|
|
"sam.port = tcp:localhost:1234\n" + "launch = true\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
|
|
|
with self.assertRaises(ValueError) as ctx:
|
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
|
|
|
self.assertIn(
|
|
|
|
"must not set both sam.port and launch",
|
|
|
|
str(ctx.exception)
|
|
|
|
)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
|
|
|
def test_launch(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\nlaunch = true\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-08-28 10:15:35 +00:00
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.i2p.launch",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
2016-08-28 10:15:35 +00:00
|
|
|
exp = mock.call(i2p_configdir=None, i2p_binary=None)
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(f.mock_calls, [exp])
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
|
|
|
def test_launch_executable(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\nlaunch = true\n" + "i2p.executable = i2p\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-08-28 10:15:35 +00:00
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.i2p.launch",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
2016-08-28 10:15:35 +00:00
|
|
|
exp = mock.call(i2p_configdir=None, i2p_binary="i2p")
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(f.mock_calls, [exp])
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
|
|
|
def test_launch_configdir(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\nlaunch = true\n" + "i2p.configdir = cfg\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-08-28 10:15:35 +00:00
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.i2p.launch",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
2016-08-28 10:15:35 +00:00
|
|
|
exp = mock.call(i2p_configdir="cfg", i2p_binary=None)
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(f.mock_calls, [exp])
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
|
|
|
def test_launch_configdir_and_executable(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\nlaunch = true\n" +
|
|
|
|
"i2p.executable = i2p\n" + "i2p.configdir = cfg\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-08-28 10:15:35 +00:00
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.i2p.launch",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(reactor, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
2016-08-28 10:15:35 +00:00
|
|
|
exp = mock.call(i2p_configdir="cfg", i2p_binary="i2p")
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(f.mock_calls, [exp])
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
|
|
|
def test_configdir(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[i2p]\ni2p.configdir = cfg\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-08-28 10:15:35 +00:00
|
|
|
h1 = mock.Mock()
|
|
|
|
with mock.patch("foolscap.connections.i2p.local_i2p",
|
|
|
|
return_value=h1) as f:
|
2018-01-28 04:40:43 +00:00
|
|
|
i2p_provider = create_i2p_provider(None, 'BASEDIR', config)
|
|
|
|
h = i2p_provider.get_i2p_handler()
|
|
|
|
|
|
|
|
self.assertEqual(f.mock_calls, [mock.call("cfg")])
|
|
|
|
self.assertIdentical(h, h1)
|
2016-08-28 10:15:35 +00:00
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
class Connections(unittest.TestCase):
|
2018-01-28 04:40:43 +00:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.basedir = 'BASEDIR'
|
2018-01-29 02:32:19 +00:00
|
|
|
self.config = config_from_string(BASECONFIG, "fake.port", self.basedir)
|
2018-01-28 04:40:43 +00:00
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
def test_default(self):
|
2018-01-29 00:46:08 +00:00
|
|
|
default_connection_handlers, _ = create_connection_handlers(None, self.basedir, self.config, mock.Mock(), mock.Mock())
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(default_connection_handlers["tcp"], "tcp")
|
|
|
|
self.assertEqual(default_connection_handlers["tor"], "tor")
|
|
|
|
self.assertEqual(default_connection_handlers["i2p"], "i2p")
|
2016-08-28 09:28:39 +00:00
|
|
|
|
|
|
|
def test_tor(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[connections]\ntcp = tor\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2018-01-29 00:46:08 +00:00
|
|
|
default_connection_handlers, _ = create_connection_handlers(None, self.basedir, config, mock.Mock(), mock.Mock())
|
2018-01-28 04:40:43 +00:00
|
|
|
|
|
|
|
self.assertEqual(default_connection_handlers["tcp"], "tor")
|
|
|
|
self.assertEqual(default_connection_handlers["tor"], "tor")
|
|
|
|
self.assertEqual(default_connection_handlers["i2p"], "i2p")
|
2016-08-28 09:28:39 +00:00
|
|
|
|
2016-08-31 08:50:13 +00:00
|
|
|
def test_tor_unimportable(self):
|
2016-10-09 05:02:11 +00:00
|
|
|
with mock.patch("allmydata.util.tor_provider._import_tor",
|
|
|
|
return_value=None):
|
2018-01-28 04:40:43 +00:00
|
|
|
self.config = config_from_string(
|
|
|
|
BASECONFIG + "[connections]\ntcp = tor\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
|
|
|
with self.assertRaises(ValueError) as ctx:
|
2018-01-29 00:46:08 +00:00
|
|
|
tor_provider = create_tor_provider(reactor, 'BASEDIR', self.config)
|
|
|
|
default_connection_handlers, _ = create_connection_handlers(None, self.basedir, self.config, mock.Mock(), tor_provider)
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(
|
|
|
|
str(ctx.exception),
|
|
|
|
"'tahoe.cfg [connections] tcp='"
|
|
|
|
" uses unavailable/unimportable handler type 'tor'."
|
|
|
|
" Please pip install tahoe-lafs[tor] to fix.",
|
|
|
|
)
|
2016-08-31 08:50:13 +00:00
|
|
|
|
2016-08-28 09:28:39 +00:00
|
|
|
def test_unknown(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[connections]\ntcp = unknown\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
|
|
|
with self.assertRaises(ValueError) as ctx:
|
2018-01-29 00:46:08 +00:00
|
|
|
create_connection_handlers(None, self.basedir, config, mock.Mock(), mock.Mock())
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertIn("'tahoe.cfg [connections] tcp='", str(ctx.exception))
|
|
|
|
self.assertIn("uses unknown handler type 'unknown'", str(ctx.exception))
|
2016-08-31 09:44:27 +00:00
|
|
|
|
2016-09-14 23:21:55 +00:00
|
|
|
def test_tcp_disabled(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[connections]\ntcp = disabled\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2018-01-29 00:46:08 +00:00
|
|
|
default_connection_handlers, _ = create_connection_handlers(None, self.basedir, config, mock.Mock(), mock.Mock())
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(default_connection_handlers["tcp"], None)
|
|
|
|
self.assertEqual(default_connection_handlers["tor"], "tor")
|
|
|
|
self.assertEqual(default_connection_handlers["i2p"], "i2p")
|
2016-09-14 23:21:55 +00:00
|
|
|
|
2016-08-31 09:44:27 +00:00
|
|
|
class Privacy(unittest.TestCase):
|
|
|
|
|
2018-01-28 04:40:43 +00:00
|
|
|
def test_connections(self):
|
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[node]\nreveal-IP-address = false\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2016-08-31 09:44:27 +00:00
|
|
|
|
2018-01-28 04:40:43 +00:00
|
|
|
with self.assertRaises(PrivacyError) as ctx:
|
2018-01-29 00:46:08 +00:00
|
|
|
create_connection_handlers(None, 'BASEDIR', config, mock.Mock(), mock.Mock())
|
2016-08-31 09:44:27 +00:00
|
|
|
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(
|
|
|
|
str(ctx.exception),
|
|
|
|
"tcp = tcp, must be set to 'tor' or 'disabled'",
|
|
|
|
)
|
2016-08-31 09:44:27 +00:00
|
|
|
|
2016-09-14 23:21:55 +00:00
|
|
|
def test_connections_tcp_disabled(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[connections]\ntcp = disabled\n" +
|
|
|
|
"[node]\nreveal-IP-address = false\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
2018-01-29 00:46:08 +00:00
|
|
|
default_connection_handlers, _ = create_connection_handlers(None, 'BASEDIR', config, mock.Mock(), mock.Mock())
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(default_connection_handlers["tcp"], None)
|
2016-09-14 23:21:55 +00:00
|
|
|
|
2016-08-31 09:44:27 +00:00
|
|
|
def test_tub_location_auto(self):
|
2018-01-28 04:40:43 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[node]\nreveal-IP-address = false\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:40:43 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
with self.assertRaises(PrivacyError) as ctx:
|
2018-01-29 00:46:08 +00:00
|
|
|
create_main_tub('basedir', config, {}, {}, {}, mock.Mock(), mock.Mock())
|
2018-01-28 04:40:43 +00:00
|
|
|
self.assertEqual(
|
|
|
|
str(ctx.exception),
|
|
|
|
"tub.location uses AUTO",
|
|
|
|
)
|
|
|
|
return
|
2016-09-01 00:16:23 +00:00
|
|
|
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n")
|
2016-08-31 09:44:27 +00:00
|
|
|
n._portnumfile = "missing"
|
|
|
|
n.check_privacy()
|
2016-09-01 00:16:23 +00:00
|
|
|
e = self.assertRaises(PrivacyError, n.get_tub_portlocation,
|
|
|
|
None, "AUTO")
|
2016-08-31 09:44:27 +00:00
|
|
|
self.assertEqual(str(e), "tub.location uses AUTO")
|
|
|
|
|
2016-09-01 00:16:23 +00:00
|
|
|
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n")
|
2016-08-31 09:44:27 +00:00
|
|
|
n._portnumfile = "missing"
|
|
|
|
n.check_privacy()
|
2016-09-01 00:16:23 +00:00
|
|
|
e = self.assertRaises(PrivacyError, n.get_tub_portlocation,
|
|
|
|
None, "AUTO,tcp:hostname:1234")
|
2016-08-31 09:44:27 +00:00
|
|
|
self.assertEqual(str(e), "tub.location uses AUTO")
|
|
|
|
|
|
|
|
def test_tub_location_tcp(self):
|
2018-01-28 04:45:59 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[node]\nreveal-IP-address = false\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:45:59 +00:00
|
|
|
)
|
|
|
|
with self.assertRaises(PrivacyError) as ctx:
|
|
|
|
_tub_portlocation(config, None, "tcp:hostname:1234")
|
|
|
|
self.assertEqual(
|
|
|
|
str(ctx.exception),
|
|
|
|
"tub.location includes tcp: hint",
|
|
|
|
)
|
2016-08-31 09:44:27 +00:00
|
|
|
|
2016-09-02 16:25:26 +00:00
|
|
|
def test_tub_location_legacy_tcp(self):
|
2018-01-28 04:45:59 +00:00
|
|
|
config = config_from_string(
|
|
|
|
BASECONFIG + "[node]\nreveal-IP-address = false\n",
|
|
|
|
"fake.port",
|
2018-01-29 02:32:19 +00:00
|
|
|
"no-basedir",
|
2018-01-28 04:45:59 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
with self.assertRaises(PrivacyError) as ctx:
|
|
|
|
_tub_portlocation(config, None, "hostname:1234")
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
str(ctx.exception),
|
|
|
|
"tub.location includes tcp: hint",
|
|
|
|
)
|
2016-09-02 16:25:26 +00:00
|
|
|
|
2016-12-09 19:46:26 +00:00
|
|
|
class Status(unittest.TestCase):
|
2016-12-10 00:35:46 +00:00
|
|
|
def test_hint_statuses(self):
|
|
|
|
ncs = connection_status._hint_statuses(["h2","h1"],
|
|
|
|
{"h1": "hand1", "h4": "hand4"},
|
|
|
|
{"h1": "st1", "h2": "st2",
|
|
|
|
"h3": "st3"})
|
|
|
|
self.assertEqual(ncs, {"h1 via hand1": "st1",
|
|
|
|
"h2": "st2"})
|
2016-12-09 19:46:26 +00:00
|
|
|
|
|
|
|
def test_reconnector_connected(self):
|
|
|
|
ci = mock.Mock()
|
|
|
|
ci.connectorStatuses = {"h1": "st1"}
|
|
|
|
ci.connectionHandlers = {"h1": "hand1"}
|
|
|
|
ci.winningHint = "h1"
|
|
|
|
ci.establishedAt = 120
|
|
|
|
ri = mock.Mock()
|
|
|
|
ri.state = "connected"
|
|
|
|
ri.connectionInfo = ci
|
|
|
|
rc = mock.Mock
|
|
|
|
rc.getReconnectionInfo = mock.Mock(return_value=ri)
|
|
|
|
cs = connection_status.from_foolscap_reconnector(rc, 123)
|
|
|
|
self.assertEqual(cs.connected, True)
|
2016-12-10 00:35:46 +00:00
|
|
|
self.assertEqual(cs.summary, "Connected to h1 via hand1")
|
|
|
|
self.assertEqual(cs.non_connected_statuses, {})
|
2016-12-09 19:46:26 +00:00
|
|
|
self.assertEqual(cs.last_connection_time, 120)
|
|
|
|
self.assertEqual(cs.last_received_time, 123)
|
|
|
|
|
|
|
|
def test_reconnector_connected_others(self):
|
|
|
|
ci = mock.Mock()
|
|
|
|
ci.connectorStatuses = {"h1": "st1", "h2": "st2"}
|
|
|
|
ci.connectionHandlers = {"h1": "hand1"}
|
|
|
|
ci.winningHint = "h1"
|
|
|
|
ci.establishedAt = 120
|
|
|
|
ri = mock.Mock()
|
|
|
|
ri.state = "connected"
|
|
|
|
ri.connectionInfo = ci
|
|
|
|
rc = mock.Mock
|
|
|
|
rc.getReconnectionInfo = mock.Mock(return_value=ri)
|
|
|
|
cs = connection_status.from_foolscap_reconnector(rc, 123)
|
|
|
|
self.assertEqual(cs.connected, True)
|
2016-12-10 00:35:46 +00:00
|
|
|
self.assertEqual(cs.summary, "Connected to h1 via hand1")
|
|
|
|
self.assertEqual(cs.non_connected_statuses, {"h2": "st2"})
|
2016-12-09 19:46:26 +00:00
|
|
|
self.assertEqual(cs.last_connection_time, 120)
|
|
|
|
self.assertEqual(cs.last_received_time, 123)
|
|
|
|
|
|
|
|
def test_reconnector_connected_listener(self):
|
|
|
|
ci = mock.Mock()
|
|
|
|
ci.connectorStatuses = {"h1": "st1", "h2": "st2"}
|
|
|
|
ci.connectionHandlers = {"h1": "hand1"}
|
|
|
|
ci.listenerStatus = ("listener1", "successful")
|
|
|
|
ci.winningHint = None
|
|
|
|
ci.establishedAt = 120
|
|
|
|
ri = mock.Mock()
|
|
|
|
ri.state = "connected"
|
|
|
|
ri.connectionInfo = ci
|
|
|
|
rc = mock.Mock
|
|
|
|
rc.getReconnectionInfo = mock.Mock(return_value=ri)
|
|
|
|
cs = connection_status.from_foolscap_reconnector(rc, 123)
|
|
|
|
self.assertEqual(cs.connected, True)
|
2016-12-10 00:35:46 +00:00
|
|
|
self.assertEqual(cs.summary, "Connected via listener (listener1)")
|
|
|
|
self.assertEqual(cs.non_connected_statuses,
|
|
|
|
{"h1 via hand1": "st1", "h2": "st2"})
|
2016-12-09 19:46:26 +00:00
|
|
|
self.assertEqual(cs.last_connection_time, 120)
|
|
|
|
self.assertEqual(cs.last_received_time, 123)
|
|
|
|
|
|
|
|
def test_reconnector_connecting(self):
|
|
|
|
ci = mock.Mock()
|
|
|
|
ci.connectorStatuses = {"h1": "st1", "h2": "st2"}
|
|
|
|
ci.connectionHandlers = {"h1": "hand1"}
|
|
|
|
ri = mock.Mock()
|
|
|
|
ri.state = "connecting"
|
|
|
|
ri.connectionInfo = ci
|
|
|
|
rc = mock.Mock
|
|
|
|
rc.getReconnectionInfo = mock.Mock(return_value=ri)
|
|
|
|
cs = connection_status.from_foolscap_reconnector(rc, 123)
|
|
|
|
self.assertEqual(cs.connected, False)
|
2016-12-10 00:35:46 +00:00
|
|
|
self.assertEqual(cs.summary, "Trying to connect")
|
|
|
|
self.assertEqual(cs.non_connected_statuses,
|
|
|
|
{"h1 via hand1": "st1", "h2": "st2"})
|
2016-12-09 19:46:26 +00:00
|
|
|
self.assertEqual(cs.last_connection_time, None)
|
|
|
|
self.assertEqual(cs.last_received_time, 123)
|
|
|
|
|
|
|
|
def test_reconnector_waiting(self):
|
|
|
|
ci = mock.Mock()
|
|
|
|
ci.connectorStatuses = {"h1": "st1", "h2": "st2"}
|
|
|
|
ci.connectionHandlers = {"h1": "hand1"}
|
|
|
|
ri = mock.Mock()
|
|
|
|
ri.state = "waiting"
|
|
|
|
ri.lastAttempt = 10
|
|
|
|
ri.nextAttempt = 20
|
|
|
|
ri.connectionInfo = ci
|
|
|
|
rc = mock.Mock
|
|
|
|
rc.getReconnectionInfo = mock.Mock(return_value=ri)
|
|
|
|
with mock.patch("time.time", return_value=12):
|
|
|
|
cs = connection_status.from_foolscap_reconnector(rc, 5)
|
|
|
|
self.assertEqual(cs.connected, False)
|
2016-12-10 00:35:46 +00:00
|
|
|
self.assertEqual(cs.summary,
|
|
|
|
"Reconnecting in 8 seconds (last attempt 2s ago)")
|
|
|
|
self.assertEqual(cs.non_connected_statuses,
|
|
|
|
{"h1 via hand1": "st1", "h2": "st2"})
|
2016-12-09 19:46:26 +00:00
|
|
|
self.assertEqual(cs.last_connection_time, None)
|
|
|
|
self.assertEqual(cs.last_received_time, 5)
|
2016-08-31 09:44:27 +00:00
|
|
|
|