Pull "config" handling out of Node and hide node-derivitives

This includes:

 - refactor to create_client and _Client
 - refactor to _IntroducerNode and create_introducer
This commit is contained in:
meejah 2017-09-05 19:08:35 -06:00
parent 7e5a87e800
commit 1b6f477549
18 changed files with 297 additions and 199 deletions

View File

@ -17,7 +17,7 @@ from allmydata.immutable.offloaded import Helper
from allmydata.control import ControlServer
from allmydata.introducer.client import IntroducerClient
from allmydata.util import (hashutil, base32, pollmixin, log, keyutil, idlib,
yamlutil, configutil)
yamlutil)
from allmydata.util.encodingutil import (get_filesystem_encoding,
from_utf8_or_none)
from allmydata.util.fileutil import abspath_expanduser_unicode
@ -153,10 +153,22 @@ class Terminator(service.Service):
return service.Service.stopService(self)
@implementer(IStatsProducer)
class Client(node.Node, pollmixin.PollMixin):
#@defer.inlineCallbacks
def create_client(basedir=u"."):
from allmydata.node import read_config
config = read_config(basedir, u"client.port")
config.validate(_valid_config_sections())
#defer.returnValue(
return _Client(
config,
basedir=basedir
)
#)
@implementer(IStatsProducer)
class _Client(node.Node, pollmixin.PollMixin):
PORTNUMFILE = "client.port"
STOREDIR = 'storage'
NODETYPE = "client"
EXIT_TRIGGER_FILE = "exit_trigger"
@ -176,12 +188,10 @@ class Client(node.Node, pollmixin.PollMixin):
"max_segment_size": 128*KiB,
}
def __init__(self, basedir="."):
node.Node.__init__(self, basedir)
def __init__(self, config, basedir=u"."):
node.Node.__init__(self, config, basedir=basedir)
# All tub.registerReference must happen *after* we upcall, since
# that's what does tub.setLocation()
configutil.validate_config(self.config_fname, self.config,
_valid_config_sections())
self._magic_folder = None
self.started_timestamp = time.time()
self.logSource="Client"

View File

@ -2,7 +2,7 @@
# This is for compatibilty with old .tac files, which reference
# allmydata.introducer.IntroducerNode
from allmydata.introducer.server import IntroducerNode
from allmydata.introducer.server import _IntroducerNode as IntroducerNode
# hush pyflakes
_unused = [IntroducerNode]

View File

@ -5,7 +5,7 @@ from twisted.application import service
from foolscap.api import Referenceable
import allmydata
from allmydata import node
from allmydata.util import log, rrefutil, configutil
from allmydata.util import log, rrefutil
from allmydata.util.fileutil import abspath_expanduser_unicode
from allmydata.introducer.interfaces import \
RIIntroducerPublisherAndSubscriberService_v2
@ -19,14 +19,24 @@ def _valid_config_sections():
class FurlFileConflictError(Exception):
pass
class IntroducerNode(node.Node):
PORTNUMFILE = "introducer.port"
NODETYPE = "introducer"
GENERATED_FILES = ['introducer.furl']
#@defer.inlineCallbacks
def create_introducer(basedir=u"."):
from allmydata.node import read_config
config = read_config(basedir, u"client.port", generated_files=["introducer.furl"])
config.validate(_valid_config_sections())
#defer.returnValue(
return _IntroducerNode(
config,
basedir=basedir
)
#)
def __init__(self, basedir=u"."):
node.Node.__init__(self, basedir)
configutil.validate_config(self.config_fname, self.config, _valid_config_sections())
class _IntroducerNode(node.Node):
NODETYPE = "introducer"
def __init__(self, config, basedir=u"."):
node.Node.__init__(self, config, basedir=basedir)
self.init_introducer()
webport = self.get_config("node", "web.port", None)
if webport:

View File

@ -1,4 +1,5 @@
import datetime, os.path, re, types, ConfigParser, tempfile
from io import BytesIO
from base64 import b32decode, b32encode
from twisted.internet import reactor
@ -106,28 +107,144 @@ class PrivacyError(Exception):
"""reveal-IP-address = false, but the node is configured in such a way
that the IP address could be revealed"""
def read_config(basedir, portnumfile, generated_files=[], _valid_config_sections=None):
basedir = abspath_expanduser_unicode(unicode(basedir))
if _valid_config_sections is None:
_valid_config_sections = _common_config_sections
# complain if there's bad stuff in the config dir
_error_about_old_config_files(basedir, generated_files)
# canonicalize the portnum file
portnumfile = os.path.join(basedir, portnumfile)
# (try to) read the main config file
config_fname = os.path.join(basedir, "tahoe.cfg")
parser = ConfigParser.SafeConfigParser()
try:
parser = configutil.get_config(config_fname)
except EnvironmentError:
if os.path.exists(config_fname):
raise
configutil.validate_config(config_fname, parser, _valid_config_sections())
return _Config(parser, portnumfile, config_fname)
def config_from_string(config_str, portnumfile):
parser = ConfigParser.SafeConfigParser()
parser.readfp(BytesIO(config_str))
return _Config(parser, portnumfile, '<in-memory>')
def _error_about_old_config_files(basedir, generated_files):
"""
If any old configuration files are detected, raise
OldConfigError.
"""
oldfnames = set()
old_names = [
'nickname', 'webport', 'keepalive_timeout', 'log_gatherer.furl',
'disconnect_timeout', 'advertised_ip_addresses', 'introducer.furl',
'helper.furl', 'key_generator.furl', 'stats_gatherer.furl',
'no_storage', 'readonly_storage', 'sizelimit',
'debug_discard_storage', 'run_helper'
]
for fn in generated_files:
old_names.remove(fn)
for name in old_names:
fullfname = os.path.join(basedir, name)
if os.path.exists(fullfname):
oldfnames.add(fullfname)
if oldfnames:
e = OldConfigError(oldfnames)
twlog.msg(e)
raise e
class _Config(object):
"""
FIXME better name
pulling out all the 'config' stuff from Node, so we can pass it in
as a helper instead.
"""
def __init__(self, configparser, portnum_fname, config_fname):
# XXX I think this portnumfile thing is just legacy?
self.portnum_fname = portnum_fname
self._config_fname = config_fname
self.config = configparser
nickname_utf8 = self.get_config("node", "nickname", "<unspecified>")
self.nickname = nickname_utf8.decode("utf-8")
assert type(self.nickname) is unicode
def validate(self, valid_config_sections):
configutil.validate_config(self._config_fname, self.config, valid_config_sections)
def read_config(self):
try:
self.config = configutil.get_config(self.config_fname)
except EnvironmentError:
if os.path.exists(self.config_fname):
raise
def get_config(self, section, option, default=_None, boolean=False):
try:
if boolean:
return self.config.getboolean(section, option)
item = self.config.get(section, option)
if option.endswith(".furl") and self._contains_unescaped_hash(item):
raise UnescapedHashError(section, option, item)
return item
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
if default is _None:
raise MissingConfigEntry(
"{} is missing the [{}]{} entry".format(
quote_output(self._config_fname),
section,
option,
)
)
return default
@staticmethod
def _contains_unescaped_hash(item):
characters = iter(item)
for c in characters:
if c == '\\':
characters.next()
elif c == '#':
return True
return False
class Node(service.MultiService):
# this implements common functionality of both Client nodes and Introducer
# nodes.
NODETYPE = "unknown NODETYPE"
PORTNUMFILE = None
CERTFILE = "node.pem"
GENERATED_FILES = []
def __init__(self, basedir=u"."):
def __init__(self, config, basedir=u"."):
service.MultiService.__init__(self)
# ideally, this would only be in _Config (or otherwise abstracted)
self.basedir = abspath_expanduser_unicode(unicode(basedir))
self.config_fname = os.path.join(self.basedir, "tahoe.cfg")
self._portnumfile = os.path.join(self.basedir, self.PORTNUMFILE)
# XXX don't write files in ctor!
fileutil.make_dirs(os.path.join(self.basedir, "private"), 0700)
with open(os.path.join(self.basedir, "private", "README"), "w") as f:
f.write(PRIV_README)
# creates self.config
self.read_config()
nickname_utf8 = self.get_config("node", "nickname", "<unspecified>")
self.nickname = nickname_utf8.decode("utf-8")
assert type(self.nickname) is unicode
self.config = config
self.get_config = config.get_config # XXX stopgap
self.nickname = config.nickname # XXX stopgap
self.init_tempdir()
self.check_privacy()
@ -147,7 +264,7 @@ class Node(service.MultiService):
iputil.increase_rlimits()
def init_tempdir(self):
tempdir_config = self.get_config("node", "tempdir", "tmp").decode('utf-8')
tempdir_config = self.config.get_config("node", "tempdir", "tmp").decode('utf-8')
tempdir = abspath_expanduser_unicode(tempdir_config, base=self.basedir)
if not os.path.exists(tempdir):
fileutil.make_dirs(tempdir)
@ -159,73 +276,16 @@ class Node(service.MultiService):
test_name = tempfile.mktemp()
_assert(os.path.dirname(test_name) == tempdir, test_name, tempdir)
@staticmethod
def _contains_unescaped_hash(item):
characters = iter(item)
for c in characters:
if c == '\\':
characters.next()
elif c == '#':
return True
return False
def get_config(self, section, option, default=_None, boolean=False):
try:
if boolean:
return self.config.getboolean(section, option)
item = self.config.get(section, option)
if option.endswith(".furl") and self._contains_unescaped_hash(item):
raise UnescapedHashError(section, option, item)
return item
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
if default is _None:
fn = os.path.join(self.basedir, u"tahoe.cfg")
raise MissingConfigEntry("%s is missing the [%s]%s entry"
% (quote_output(fn), section, option))
return default
def read_config(self):
self.error_about_old_config_files()
self.config = ConfigParser.SafeConfigParser()
try:
self.config = configutil.get_config(self.config_fname)
except EnvironmentError:
if os.path.exists(self.config_fname):
raise
def error_about_old_config_files(self):
""" If any old configuration files are detected, raise OldConfigError. """
oldfnames = set()
for name in [
'nickname', 'webport', 'keepalive_timeout', 'log_gatherer.furl',
'disconnect_timeout', 'advertised_ip_addresses', 'introducer.furl',
'helper.furl', 'key_generator.furl', 'stats_gatherer.furl',
'no_storage', 'readonly_storage', 'sizelimit',
'debug_discard_storage', 'run_helper']:
if name not in self.GENERATED_FILES:
fullfname = os.path.join(self.basedir, name)
if os.path.exists(fullfname):
oldfnames.add(fullfname)
if oldfnames:
e = OldConfigError(oldfnames)
twlog.msg(e)
raise e
def check_privacy(self):
self._reveal_ip = self.get_config("node", "reveal-IP-address", True,
self._reveal_ip = self.config.get_config("node", "reveal-IP-address", True,
boolean=True)
def create_i2p_provider(self):
self._i2p_provider = i2p_provider.Provider(self.basedir, self, reactor)
self._i2p_provider = i2p_provider.Provider(self.basedir, self.config, reactor)
self._i2p_provider.check_dest_config()
self._i2p_provider.setServiceParent(self)
def create_tor_provider(self):
self._tor_provider = tor_provider.Provider(self.basedir, self, reactor)
self._tor_provider = tor_provider.Provider(self.basedir, self.config, reactor)
self._tor_provider.check_onion_config()
self._tor_provider.setServiceParent(self)
@ -254,7 +314,7 @@ class Node(service.MultiService):
# then we remember the default mappings from tahoe.cfg
self._default_connection_handlers = {"tor": "tor", "i2p": "i2p"}
tcp_handler_name = self.get_config("connections", "tcp", "tcp").lower()
tcp_handler_name = self.config.get_config("connections", "tcp", "tcp").lower()
if tcp_handler_name == "disabled":
self._default_connection_handlers["tcp"] = None
else:
@ -282,10 +342,10 @@ class Node(service.MultiService):
}
# see #521 for a discussion of how to pick these timeout values.
keepalive_timeout_s = self.get_config("node", "timeout.keepalive", "")
keepalive_timeout_s = self.config.get_config("node", "timeout.keepalive", "")
if keepalive_timeout_s:
self.tub_options["keepaliveTimeout"] = int(keepalive_timeout_s)
disconnect_timeout_s = self.get_config("node", "timeout.disconnect", "")
disconnect_timeout_s = self.config.get_config("node", "timeout.disconnect", "")
if disconnect_timeout_s:
# N.B.: this is in seconds, so use "1800" to get 30min
self.tub_options["disconnectTimeout"] = int(disconnect_timeout_s)
@ -340,12 +400,12 @@ class Node(service.MultiService):
# For 'tub.port', tahoe.cfg overrides the individual file on
# disk. So only read self._portnumfile if tahoe.cfg doesn't
# provide a value.
if os.path.exists(self._portnumfile):
file_tubport = fileutil.read(self._portnumfile).strip()
if os.path.exists(self.config.portnum_fname):
file_tubport = fileutil.read(self.config.portnum_fname).strip()
tubport = self._convert_tub_port(file_tubport)
else:
tubport = "tcp:%d" % iputil.allocate_tcp_port()
fileutil.write_atomically(self._portnumfile, tubport + "\n",
fileutil.write_atomically(self.config.portnum_fname, tubport + "\n",
mode="")
else:
tubport = self._convert_tub_port(cfg_tubport)
@ -392,8 +452,8 @@ class Node(service.MultiService):
self.nodeid = b32decode(self.tub.tubID.upper()) # binary format
self.write_config("my_nodeid", b32encode(self.nodeid).lower() + "\n")
self.short_nodeid = b32encode(self.nodeid).lower()[:8] # for printing
cfg_tubport = self.get_config("node", "tub.port", None)
cfg_location = self.get_config("node", "tub.location", None)
cfg_tubport = self.config.get_config("node", "tub.port", None)
cfg_location = self.config.get_config("node", "tub.location", None)
portlocation = self.get_tub_portlocation(cfg_tubport, cfg_location)
if portlocation:
tubport, location = portlocation
@ -573,7 +633,7 @@ class Node(service.MultiService):
if os.path.exists(lgfurl_file):
os.remove(lgfurl_file)
self.log_tub.setOption("logport-furlfile", lgfurl_file)
lgfurl = self.get_config("node", "log_gatherer.furl", "")
lgfurl = self.config.get_config("node", "log_gatherer.furl", "")
if lgfurl:
# this is in addition to the contents of log-gatherer-furlfile
self.log_tub.setOption("log-gatherer-furl", lgfurl)

View File

@ -6,6 +6,7 @@ from twisted.python import usage
from twisted.python.reflect import namedAny
from allmydata.scripts.default_nodedir import _default_nodedir
from allmydata.util import fileutil
from allmydata.node import read_config
from allmydata.util.encodingutil import listdir_unicode, quote_local_unicode_path
from twisted.application.service import Service
@ -113,9 +114,9 @@ class DaemonizeTheRealService(Service):
def start():
node_to_instance = {
u"client": lambda: namedAny("allmydata.client.Client")(self.basedir),
u"introducer": lambda: namedAny("allmydata.introducer.server.IntroducerNode")(self.basedir),
u"stats-gatherer": lambda: namedAny("allmydata.stats.StatsGathererService")(self.basedir, verbose=True),
u"client": lambda: namedAny("allmydata.client.create_client")(self.basedir),
u"introducer": lambda: namedAny("allmydata.introducer.server.create_introducer")(self.basedir),
u"stats-gatherer": lambda: namedAny("allmydata.stats.StatsGathererService")(read_config(self.basedir, None), self.basedir, verbose=True),
u"key-generator": key_generator_removed,
}

View File

@ -26,7 +26,7 @@ import treq
from allmydata.util.assertutil import _assert
from allmydata import uri as tahoe_uri
from allmydata.client import Client
from allmydata.client import _Client
from allmydata.storage.server import StorageServer, storage_index_to_dir
from allmydata.util import fileutil, idlib, hashutil
from allmydata.util.hashutil import permute_server_hash
@ -183,7 +183,16 @@ class NoNetworkStorageBroker(object):
def get_known_servers(self):
return [] # FIXME?
class NoNetworkClient(Client):
def NoNetworkClient(basedir):
# XXX FIXME this is just to avoid massive search-replace for now;
# should be create_nonetwork_client() or something...
from allmydata.node import read_config
config = read_config(basedir, u'client.port')
return _NoNetworkClient(config, basedir=basedir)
class _NoNetworkClient(_Client):
def init_connections(self):
pass

View File

@ -7,7 +7,7 @@ import allmydata
import allmydata.frontends.magic_folder
import allmydata.util.log
from allmydata.node import Node, OldConfigError, OldConfigOptionError, MissingConfigEntry, UnescapedHashError
from allmydata.node import OldConfigError, OldConfigOptionError, MissingConfigEntry, UnescapedHashError, _Config, read_config
from allmydata.frontends.auth import NeedRootcapLookupScheme
from allmydata import client
from allmydata.storage_client import StorageFarmBroker
@ -32,7 +32,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), \
BASECONFIG)
client.Client(basedir)
client.create_client(basedir)
def test_comment(self):
should_fail = [r"test#test", r"#testtest", r"test\\#test"]
@ -47,15 +47,15 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
fileutil.write(os.path.join(basedir, "tahoe.cfg"), config)
for s in should_fail:
self.failUnless(Node._contains_unescaped_hash(s))
self.failUnless(_Config._contains_unescaped_hash(s))
write_config(s)
e = self.assertRaises(UnescapedHashError, client.Client, basedir)
e = self.assertRaises(UnescapedHashError, client.create_client, basedir)
self.assertIn("[client]introducer.furl", str(e))
for s in should_not_fail:
self.failIf(Node._contains_unescaped_hash(s))
self.failIf(_Config._contains_unescaped_hash(s))
write_config(s)
client.Client(basedir)
client.create_client(basedir)
def test_unreadable_config(self):
if sys.platform == "win32":
@ -70,7 +70,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
old_mode = os.stat(fn).st_mode
os.chmod(fn, 0)
try:
e = self.assertRaises(EnvironmentError, client.Client, basedir)
e = self.assertRaises(EnvironmentError, read_config, basedir, "client.port")
self.assertIn("Permission denied", str(e))
finally:
# don't leave undeleteable junk lying around
@ -92,7 +92,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
logged_messages = []
self.patch(twisted.python.log, 'msg', logged_messages.append)
e = self.failUnlessRaises(OldConfigError, client.Client, basedir)
e = self.failUnlessRaises(OldConfigError, read_config, basedir, "client.port")
abs_basedir = fileutil.abspath_expanduser_unicode(unicode(basedir)).encode(sys.getfilesystemencoding())
self.failUnlessIn(os.path.join(abs_basedir, "introducer.furl"), e.args[0])
self.failUnlessIn(os.path.join(abs_basedir, "no_storage"), e.args[0])
@ -119,7 +119,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), \
BASECONFIG)
c = client.Client(basedir)
c = client.create_client(basedir)
secret_fname = os.path.join(basedir, "private", "secret")
self.failUnless(os.path.exists(secret_fname), secret_fname)
renew_secret = c.get_renewal_secret()
@ -132,7 +132,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"),
BASECONFIG)
c = client.Client(basedir)
c = client.create_client(basedir)
self.failUnless(c.get_long_nodeid().startswith("v0-"))
def test_nodekey_no_storage(self):
@ -140,7 +140,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"),
BASECONFIG + "[storage]\n" + "enabled = false\n")
c = client.Client(basedir)
c = client.create_client(basedir)
self.failUnless(c.get_long_nodeid().startswith("v0-"))
def test_reserved_1(self):
@ -151,7 +151,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \
"enabled = true\n" + \
"reserved_space = 1000\n")
c = client.Client(basedir)
c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 1000)
def test_reserved_2(self):
@ -162,7 +162,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \
"enabled = true\n" + \
"reserved_space = 10K\n")
c = client.Client(basedir)
c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 10*1000)
def test_reserved_3(self):
@ -173,7 +173,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \
"enabled = true\n" + \
"reserved_space = 5mB\n")
c = client.Client(basedir)
c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
5*1000*1000)
@ -185,7 +185,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \
"enabled = true\n" + \
"reserved_space = 78Gb\n")
c = client.Client(basedir)
c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
78*1000*1000*1000)
@ -197,7 +197,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \
"enabled = true\n" + \
"reserved_space = bogus\n")
self.failUnlessRaises(ValueError, client.Client, basedir)
self.failUnlessRaises(ValueError, client.create_client, basedir)
def test_web_staticdir(self):
basedir = u"client.Basic.test_web_staticdir"
@ -207,7 +207,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[node]\n" +
"web.port = tcp:0:interface=127.0.0.1\n" +
"web.static = relative\n")
c = client.Client(basedir)
c = client.create_client(basedir)
w = c.getServiceNamed("webish")
abs_basedir = fileutil.abspath_expanduser_unicode(basedir)
expected = fileutil.abspath_expanduser_unicode(u"relative", abs_basedir)
@ -226,7 +226,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"accounts.file = private/accounts\n"))
os.mkdir(os.path.join(basedir, "private"))
fileutil.write(os.path.join(basedir, "private", "accounts"), "\n")
c = client.Client(basedir) # just make sure it can be instantiated
c = client.create_client(basedir) # just make sure it can be instantiated
del c
def test_ftp_auth_url(self):
@ -238,7 +238,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"enabled = true\n"
"port = tcp:0:interface=127.0.0.1\n"
"accounts.url = http://0.0.0.0/\n"))
c = client.Client(basedir) # just make sure it can be instantiated
c = client.create_client(basedir) # just make sure it can be instantiated
del c
def test_ftp_auth_no_accountfile_or_url(self):
@ -249,7 +249,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[ftpd]\n"
"enabled = true\n"
"port = tcp:0:interface=127.0.0.1\n"))
self.failUnlessRaises(NeedRootcapLookupScheme, client.Client, basedir)
self.failUnlessRaises(NeedRootcapLookupScheme, client.create_client, basedir)
def _permute(self, sb, key):
return [ s.get_longname() for s in sb.get_servers_for_psi(key) ]
@ -285,7 +285,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
BASECONFIG + \
"[storage]\n" + \
"enabled = true\n")
c = client.Client(basedir)
c = client.create_client(basedir)
ss = c.getServiceNamed("storage")
verdict = ss.remote_get_version()
self.failUnlessReallyEqual(verdict["application-version"],
@ -307,7 +307,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
def _check(config, expected_furl):
fileutil.write(os.path.join(basedir, "tahoe.cfg"),
BASECONFIG + config)
c = client.Client(basedir)
c = client.create_client(basedir)
uploader = c.getServiceNamed("uploader")
furl, connected = uploader.get_helper_info()
self.failUnlessEqual(furl, expected_furl)
@ -352,20 +352,20 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
config + "local.directory = " + local_dir_utf8 + "\n")
self.failUnlessRaises(MissingConfigEntry, client.Client, basedir1)
self.failUnlessRaises(MissingConfigEntry, client.create_client, basedir1)
fileutil.write(os.path.join(basedir1, "tahoe.cfg"), config)
fileutil.write(os.path.join(basedir1, "private", "magic_folder_dircap"), "URI:DIR2:blah")
fileutil.write(os.path.join(basedir1, "private", "collective_dircap"), "URI:DIR2:meow")
self.failUnlessRaises(MissingConfigEntry, client.Client, basedir1)
self.failUnlessRaises(MissingConfigEntry, client.create_client, basedir1)
fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
config.replace("[magic_folder]\n", "[drop_upload]\n"))
self.failUnlessRaises(OldConfigOptionError, client.Client, basedir1)
self.failUnlessRaises(OldConfigOptionError, client.create_client, basedir1)
fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
config + "local.directory = " + local_dir_utf8 + "\n")
c1 = client.Client(basedir1)
c1 = client.create_client(basedir1)
magicfolder = c1.getServiceNamed('magic-folder')
self.failUnless(isinstance(magicfolder, MockMagicFolder), magicfolder)
self.failUnlessReallyEqual(magicfolder.client, c1)
@ -391,7 +391,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"local.directory = " + local_dir_utf8 + "\n")
fileutil.write(os.path.join(basedir2, "private", "magic_folder_dircap"), "URI:DIR2:blah")
fileutil.write(os.path.join(basedir2, "private", "collective_dircap"), "URI:DIR2:meow")
self.failUnlessRaises(Boom, client.Client, basedir2)
self.failUnlessRaises(Boom, client.create_client, basedir2)
def flush_but_dont_ignore(res):
@ -416,15 +416,15 @@ class Run(unittest.TestCase, testutil.StallMixin):
os.mkdir(basedir)
dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG_I % dummy)
fileutil.write(os.path.join(basedir, client.Client.EXIT_TRIGGER_FILE), "")
client.Client(basedir)
fileutil.write(os.path.join(basedir, client._Client.EXIT_TRIGGER_FILE), "")
client.create_client(basedir)
def test_reloadable(self):
basedir = "test_client.Run.test_reloadable"
os.mkdir(basedir)
dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG_I % dummy)
c1 = client.Client(basedir)
c1 = client.create_client(basedir)
c1.setServiceParent(self.sparent)
# delay to let the service start up completely. I'm not entirely sure
@ -446,7 +446,7 @@ class Run(unittest.TestCase, testutil.StallMixin):
# also change _check_exit_trigger to use it instead of a raw
# reactor.stop, also instrument the shutdown event in an
# attribute that we can check.)
c2 = client.Client(basedir)
c2 = client.create_client(basedir)
c2.setServiceParent(self.sparent)
return c2.disownServiceParent()
d.addCallback(_restart)
@ -457,7 +457,7 @@ class NodeMaker(testutil.ReallyEqualMixin, unittest.TestCase):
basedir = "client/NodeMaker/maker"
fileutil.make_dirs(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG)
c = client.Client(basedir)
c = client.create_client(basedir)
n = c.create_node_from_uri("URI:CHK:6nmrpsubgbe57udnexlkiwzmlu:bjt7j6hshrlmadjyr7otq3dc24end5meo5xcr5xe5r663po6itmq:3:10:7277")
self.failUnless(IFilesystemNode.providedBy(n))

View File

@ -1,20 +1,18 @@
import os
import mock
from io import BytesIO
from twisted.trial import unittest
from twisted.internet import reactor, endpoints, defer
from twisted.internet.interfaces import IStreamClientEndpoint
from ConfigParser import SafeConfigParser
from foolscap.connections import tcp
from ..node import Node, PrivacyError
from ..util import connection_status
class FakeNode(Node):
def __init__(self, config_str):
self.config = SafeConfigParser()
self.config.readfp(BytesIO(config_str))
self._reveal_ip = True
from allmydata.node import config_from_string
self.config = config_from_string(config_str, "fake.port")
self.basedir = "BASEDIR"
self._reveal_ip = True
self.services = []
self.create_i2p_provider()
self.create_tor_provider()

View File

@ -7,7 +7,7 @@ from twisted.trial import unittest
from twisted.internet import defer
from twisted.internet.interfaces import IConsumer
from allmydata import uri, dirnode
from allmydata.client import Client
from allmydata.client import _Client
from allmydata.immutable import upload
from allmydata.interfaces import IImmutableFileNode, IMutableFileNode, \
ExistingChildError, NoSuchChildError, MustNotBeUnknownRWError, \
@ -1553,7 +1553,7 @@ class FakeNodeMaker(NodeMaker):
def create_mutable_file(self, contents="", keysize=None, version=None):
return defer.succeed(FakeMutableFile(contents))
class FakeClient2(Client):
class FakeClient2(_Client):
def __init__(self):
self.nodemaker = FakeNodeMaker(None, None, None,
None, None,

View File

@ -16,10 +16,10 @@ from allmydata.introducer.server import IntroducerService, FurlFileConflictError
from allmydata.introducer.common import get_tubid_string_from_ann, \
get_tubid_string, sign_to_foolscap, unsign_from_foolscap, \
UnknownKeyError
# test compatibility with old introducer .tac files
from allmydata.introducer import IntroducerNode
# the "new way" to create introducer node instance
from allmydata.introducer.server import create_introducer
from allmydata.web import introweb
from allmydata.client import Client as TahoeClient
from allmydata.client import create_client
from allmydata.util import pollmixin, keyutil, idlib, fileutil, iputil, yamlutil
import allmydata.test.common_util as testutil
@ -28,13 +28,19 @@ class LoggingMultiService(service.MultiService):
log.msg(msg, **kw)
class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
def test_backwards_compat_import(self):
# for old introducer .tac files
from allmydata.introducer import IntroducerNode
IntroducerNode # pyflakes
def test_furl(self):
basedir = "introducer.IntroducerNode.test_furl"
os.mkdir(basedir)
public_fn = os.path.join(basedir, "introducer.furl")
private_fn = os.path.join(basedir, "private", "introducer.furl")
q1 = IntroducerNode(basedir)
q1 = create_introducer(basedir)
del q1
# new nodes create unguessable furls in private/introducer.furl
ifurl = fileutil.read(private_fn)
@ -48,13 +54,13 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
# if we see both files, throw an error
self.failUnlessRaises(FurlFileConflictError,
IntroducerNode, basedir)
create_introducer, basedir)
# when we see only the public one, move it to private/ and use
# the existing furl instead of creating a new one
os.unlink(private_fn)
q2 = IntroducerNode(basedir)
q2 = create_introducer(basedir)
del q2
self.failIf(os.path.exists(public_fn))
ifurl2 = fileutil.read(private_fn)
@ -68,7 +74,7 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
"[node]\n" +
"web.port = tcp:0:interface=127.0.0.1\n" +
"web.static = relative\n")
c = IntroducerNode(basedir)
c = create_introducer(basedir)
w = c.getServiceNamed("webish")
abs_basedir = fileutil.abspath_expanduser_unicode(basedir)
expected = fileutil.abspath_expanduser_unicode(u"relative", abs_basedir)
@ -740,7 +746,7 @@ class Announcements(unittest.TestCase):
f.write("enabled = false\n")
f.close()
c = TahoeClient(basedir)
c = create_client(basedir)
ic = c.introducer_clients[0]
sk_s, vk_s = keyutil.make_keypair()
sk, _ignored = keyutil.parse_privkey(sk_s)
@ -808,7 +814,7 @@ class Announcements(unittest.TestCase):
self.failUnlessEqual(announcements[pub2]["anonymous-storage-FURL"],
furl3)
c2 = TahoeClient(basedir)
c2 = create_client(basedir)
c2.introducer_clients[0]._load_announcements()
yield flushEventualQueue()
self.assertEqual(c2.storage_broker.get_all_serverids(),
@ -829,7 +835,7 @@ class ClientSeqnums(unittest.TestCase):
f.write("enabled = false\n")
f.close()
c = TahoeClient(basedir)
c = create_client(basedir)
ic = c.introducer_clients[0]
outbound = ic._outbound_announcements
published = ic._published_announcements

View File

@ -4,7 +4,7 @@ import os
from twisted.python.filepath import FilePath
from twisted.trial import unittest
from allmydata.util import yamlutil
from allmydata.client import Client
from allmydata.client import create_client
from allmydata.scripts.create_node import write_node_config
INTRODUCERS_CFG_FURLS=['furl1', 'furl2']
@ -44,7 +44,7 @@ class MultiIntroTests(unittest.TestCase):
}
self.yaml_path.setContent(yamlutil.safe_dump(connections))
# get a client and count of introducer_clients
myclient = Client(self.basedir)
myclient = create_client(self.basedir)
ic_count = len(myclient.introducer_clients)
# assertions
@ -56,7 +56,7 @@ class MultiIntroTests(unittest.TestCase):
commented."""
self.yaml_path.setContent(INTRODUCERS_CFG_FURLS_COMMENTED)
# get a client and count of introducer_clients
myclient = Client(self.basedir)
myclient = create_client(self.basedir)
ic_count = len(myclient.introducer_clients)
# assertions
@ -78,7 +78,7 @@ class MultiIntroTests(unittest.TestCase):
c.close()
# get a client and first introducer_furl
myclient = Client(self.basedir)
myclient = create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0]
# assertions
@ -89,7 +89,7 @@ class MultiIntroTests(unittest.TestCase):
u'default': { 'furl': 'furl1' },
}}
self.yaml_path.setContent(yamlutil.safe_dump(connections))
e = self.assertRaises(ValueError, Client, self.basedir)
e = self.assertRaises(ValueError, create_client, self.basedir)
self.assertEquals(str(e), "'default' introducer furl cannot be specified in introducers.yaml; please fix impossible configuration.")
SIMPLE_YAML = """
@ -129,25 +129,25 @@ class NoDefault(unittest.TestCase):
u'one': { 'furl': 'furl1' },
}}
self.yaml_path.setContent(yamlutil.safe_dump(connections))
myclient = Client(self.basedir)
myclient = create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0]
self.assertEquals(tahoe_cfg_furl, 'furl1')
def test_real_yaml(self):
self.yaml_path.setContent(SIMPLE_YAML)
myclient = Client(self.basedir)
myclient = create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0]
self.assertEquals(tahoe_cfg_furl, 'furl1')
def test_invalid_equals_yaml(self):
self.yaml_path.setContent(EQUALS_YAML)
e = self.assertRaises(TypeError, Client, self.basedir)
e = self.assertRaises(TypeError, create_client, self.basedir)
self.assertEquals(str(e), "string indices must be integers")
def test_introducerless(self):
connections = {'introducers': {} }
self.yaml_path.setContent(yamlutil.safe_dump(connections))
myclient = Client(self.basedir)
myclient = create_client(self.basedir)
self.assertEquals(len(myclient.introducer_furls), 0)
if __name__ == "__main__":

View File

@ -9,9 +9,9 @@ from foolscap.api import flushEventualQueue
import foolscap.logging.log
from twisted.application import service
from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry
from allmydata.introducer.server import IntroducerNode
from allmydata.client import Client
from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry, read_config, config_from_string
from allmydata.introducer.server import create_introducer
from allmydata.client import create_client
from allmydata.util import fileutil, iputil
from allmydata.util.namespace import Namespace
import allmydata.test.common_util as testutil
@ -23,7 +23,11 @@ class LoggingMultiService(service.MultiService):
class TestNode(Node):
CERTFILE='DEFAULT_CERTFILE_BLANK'
PORTNUMFILE='DEFAULT_PORTNUMFILE_BLANK'
def __init__(self, basedir):
config = read_config(basedir, 'DEFAULT_PORTNUMFILE_BLANK')
Node.__init__(self, config, basedir)
class TestCase(testutil.SignalMixin, unittest.TestCase):
@ -198,7 +202,8 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
class EmptyNode(Node):
def __init__(self):
pass
config = config_from_string("", "no portfile")
Node.__init__(self, config, 'no basedir')
EXPECTED = {
# top-level key is tub.port category
@ -252,7 +257,7 @@ class PortLocation(unittest.TestCase):
n = EmptyNode()
basedir = os.path.join("test_node/portlocation/%s/%s" % (tp, tl))
fileutil.make_dirs(basedir)
n._portnumfile = os.path.join(basedir, "node.port")
config = n.config = read_config(basedir, "node.port")
n._reveal_ip = True
if exp in ("ERR1", "ERR2", "ERR3", "ERR4"):
@ -281,7 +286,7 @@ class PortLocation(unittest.TestCase):
port, location = n.get_tub_portlocation(cfg_tubport,
cfg_location)
try:
with open(n._portnumfile, "r") as f:
with open(config.portnum_fname, "r") as f:
saved_port = f.read().strip()
except EnvironmentError:
saved_port = None
@ -367,7 +372,7 @@ class Listeners(unittest.TestCase):
f.write("tub.location = %s\n" % location)
# we're doing a lot of calling-into-setup-methods here, it might be
# better to just create a real Node instance, I'm not sure.
n.read_config()
n.config = read_config(n.basedir, "client.port")
n.check_privacy()
n.services = []
n.create_i2p_provider()
@ -393,7 +398,7 @@ class Listeners(unittest.TestCase):
f.write("tub.location = tcp:example.org:1234\n")
# we're doing a lot of calling-into-setup-methods here, it might be
# better to just create a real Node instance, I'm not sure.
n.read_config()
n.config = read_config(n.basedir, "client.port")
n.check_privacy()
n.services = []
i2p_ep = object()
@ -420,7 +425,7 @@ class ClientNotListening(unittest.TestCase):
f.write(NOLISTEN)
f.write(DISABLE_STORAGE)
f.close()
n = Client(basedir)
n = create_client(basedir)
self.assertEqual(n.tub.getListeners(), [])
def test_disabled_but_storage(self):
@ -431,7 +436,7 @@ class ClientNotListening(unittest.TestCase):
f.write(NOLISTEN)
f.write(ENABLE_STORAGE)
f.close()
e = self.assertRaises(ValueError, Client, basedir)
e = self.assertRaises(ValueError, create_client, basedir)
self.assertIn("storage is enabled, but tub is not listening", str(e))
def test_disabled_but_helper(self):
@ -443,7 +448,7 @@ class ClientNotListening(unittest.TestCase):
f.write(DISABLE_STORAGE)
f.write(ENABLE_HELPER)
f.close()
e = self.assertRaises(ValueError, Client, basedir)
e = self.assertRaises(ValueError, create_client, basedir)
self.assertIn("helper is enabled, but tub is not listening", str(e))
class IntroducerNotListening(unittest.TestCase):
@ -455,5 +460,5 @@ class IntroducerNotListening(unittest.TestCase):
f.write("tub.port = disabled\n")
f.write("tub.location = disabled\n")
f.close()
e = self.assertRaises(ValueError, IntroducerNode, basedir)
e = self.assertRaises(ValueError, create_introducer, basedir)
self.assertIn("we are Introducer, but tub is not listening", str(e))

View File

@ -9,7 +9,7 @@ from twisted.internet.defer import inlineCallbacks, returnValue
from allmydata.util import fileutil, pollmixin
from allmydata.util.encodingutil import unicode_to_argv, unicode_to_output, \
get_filesystem_encoding
from allmydata.client import Client
from allmydata.client import _Client
from allmydata.test import common_util
import allmydata
from allmydata import __appname__
@ -337,7 +337,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
basedir = self.workdir("test_introducer")
c1 = os.path.join(basedir, "c1")
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
exit_trigger_file = os.path.join(c1, _Client.EXIT_TRIGGER_FILE)
twistd_pid_file = os.path.join(c1, "twistd.pid")
introducer_furl_file = os.path.join(c1, "private", "introducer.furl")
node_url_file = os.path.join(c1, "node.url")
@ -457,7 +457,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
basedir = self.workdir("test_client_no_noise")
c1 = os.path.join(basedir, "c1")
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
exit_trigger_file = os.path.join(c1, _Client.EXIT_TRIGGER_FILE)
twistd_pid_file = os.path.join(c1, "twistd.pid")
node_url_file = os.path.join(c1, "node.url")
@ -521,7 +521,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
basedir = self.workdir("test_client")
c1 = os.path.join(basedir, "c1")
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
exit_trigger_file = os.path.join(c1, _Client.EXIT_TRIGGER_FILE)
twistd_pid_file = os.path.join(c1, "twistd.pid")
node_url_file = os.path.join(c1, "node.url")
storage_furl_file = os.path.join(c1, "private", "storage.furl")

View File

@ -7,7 +7,7 @@ from twisted.application import service
import allmydata
from allmydata import client, uri
from allmydata.introducer.server import IntroducerNode
from allmydata.introducer.server import create_introducer
from allmydata.storage.mutable import MutableShareFile
from allmydata.storage.server import si_a2b
from allmydata.immutable import offloaded, upload
@ -423,7 +423,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
f = open(os.path.join(iv_dir, "private", "node.pem"), "w")
f.write(SYSTEM_TEST_CERTS[0])
f.close()
iv = IntroducerNode(basedir=iv_dir)
iv = create_introducer(basedir=iv_dir)
self.introducer = self.add_service(iv)
self._get_introducer_web()
d = defer.succeed(None)
@ -520,7 +520,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
# start clients[0], wait for it's tub to be ready (at which point it
# will have registered the helper furl).
c = self.add_service(client.Client(basedir=basedirs[0]))
c = self.add_service(client.create_client(basedirs[0]))
self.clients.append(c)
c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
@ -537,7 +537,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
# this starts the rest of the clients
for i in range(1, self.numclients):
c = self.add_service(client.Client(basedir=basedirs[i]))
c = self.add_service(client.create_client(basedirs[i]))
self.clients.append(c)
c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
log.msg("STARTING")
@ -569,7 +569,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
# better than blindly waiting for a second.
d.addCallback(self.stall, 1.0)
def _stopped(res):
new_c = client.Client(basedir=self.getdir("client%d" % num))
new_c = client.create_client(self.getdir("client%d" % num))
self.clients[num] = new_c
new_c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
self.add_service(new_c)
@ -596,7 +596,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
config += "helper.furl = %s\n" % helper_furl
fileutil.write(os.path.join(basedir, 'tahoe.cfg'), config)
c = client.Client(basedir=basedir)
c = client.create_client(basedir)
self.clients.append(c)
c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
self.numclients += 1

View File

@ -20,7 +20,7 @@ from allmydata.util.happinessutil import servers_of_happiness, \
shares_by_server, merge_servers
from allmydata.storage_client import StorageFarmBroker
from allmydata.storage.server import storage_index_to_dir
from allmydata.client import Client
from allmydata.client import _Client
MiB = 1024*1024
@ -754,7 +754,7 @@ class ServerSelection(unittest.TestCase):
class StorageIndex(unittest.TestCase):
def test_params_must_matter(self):
DATA = "I am some data"
PARAMS = Client.DEFAULT_ENCODING_PARAMETERS
PARAMS = _Client.DEFAULT_ENCODING_PARAMETERS
u = upload.Data(DATA, convergence="")
u.set_default_encoding_parameters(PARAMS)

View File

@ -1,7 +1,5 @@
import os.path
from twisted.trial import unittest
from foolscap.api import fireEventually, flushEventualQueue
from allmydata.util import fileutil
from twisted.internet import defer
from allmydata.introducer import IntroducerNode
from .common import FAVICON_MARKUP
@ -20,14 +18,15 @@ class IntroducerWeb(unittest.TestCase):
@defer.inlineCallbacks
def test_welcome(self):
basedir = "web.IntroducerWeb.test_welcome"
os.mkdir(basedir)
cfg = "\n".join(["[node]",
"tub.location = 127.0.0.1:1",
"web.port = tcp:0",
]) + "\n"
fileutil.write(os.path.join(basedir, "tahoe.cfg"), cfg)
self.node = IntroducerNode(basedir)
config = (
"[node]\n"
"tub.location = 127.0.0.1:1\n"
"web.port = tcp:0\n"
)
from allmydata.node import config_from_string
self.node = IntroducerNode(
config_from_string(config, portnumfile="introducer.port"),
)
self.ws = self.node.getServiceNamed("webish")
yield fireEventually(None)

View File

@ -46,7 +46,7 @@ from ..common_web import (
do_http,
Error,
)
from allmydata.client import Client, SecretHolder
from allmydata.client import _Client, SecretHolder
from .common import unknown_rwcap, unknown_rocap, unknown_immcap, FAVICON_MARKUP
# create a fake uploader/downloader, and a couple of fake dirnodes, then
# create a webserver that works against them
@ -238,7 +238,7 @@ class FakeStorageServer(service.MultiService):
def on_status_changed(self, cb):
cb(self)
class FakeClient(Client):
class FakeClient(_Client):
def __init__(self):
# don't upcall to Client.__init__, since we only want to initialize a
# minimal subset

View File

@ -124,16 +124,16 @@ def create_config(reactor, cli_config):
# a nice error, and startService will throw an ugly error.
class Provider(service.MultiService):
def __init__(self, basedir, node_for_config, reactor):
def __init__(self, basedir, config, reactor):
service.MultiService.__init__(self)
self._basedir = basedir
self._node_for_config = node_for_config
self._config = config
self._i2p = _import_i2p()
self._txi2p = _import_txi2p()
self._reactor = reactor
def _get_i2p_config(self, *args, **kwargs):
return self._node_for_config.get_config("i2p", *args, **kwargs)
return self._config.get_config("i2p", *args, **kwargs)
def get_listener(self):
# this is relative to BASEDIR, and our cwd should be BASEDIR