3 from ConfigParser import SafeConfigParser
5 from twisted.python import log, versions
7 class ConfigError(Exception):
8 def __init__(self, message):
11 return repr(self.message)
13 version = versions.Version('apt-dht', 0, 0, 0)
14 home = os.path.expandvars('${HOME}')
15 if home == '${HOME}' or not os.path.isdir(home):
16 home = os.path.expanduser('~')
17 if not os.path.isdir(home):
18 home = os.path.abspath(os.path.dirname(sys.argv[0]))
19 DEFAULT_CONFIG_FILES=['/etc/apt-dht/apt-dht.conf',
20 home + '/.apt-dht/apt-dht.conf']
24 # Port to listen on for all requests (TCP and UDP)
27 # Directory to store the downloaded files in
28 'CACHE_DIR': home + '/.apt-dht/cache',
30 # Other directories containing packages to share with others
31 # WARNING: all files in these directories will be hashed and available
32 # for everybody to download
35 # User name to try and run as
38 # Whether it's OK to use an IP addres from a known local/private range
41 # Unload the packages cache after an interval of inactivity this long.
42 # The packages cache uses a lot of memory, and only takes a few seconds
43 # to reload when a new request arrives.
44 'UNLOAD_PACKAGES_CACHE': '5m',
46 # Refresh the DHT keys after this much time has passed.
47 # This should be a time slightly less than the DHT's KEY_EXPIRE value.
50 # Which DHT implementation to use.
51 # It must be possile to do "from <DHT>.DHT import DHT" to get a class that
52 # implements the IDHT interface.
53 'DHT': 'apt_dht_Khashmir',
55 # Whether to only run the DHT (for providing only a bootstrap node)
60 # bootstrap nodes to contact to join the DHT
61 'BOOTSTRAP': """www.camrdale.org:9977
62 steveholt.hopto.org:9976""",
64 # whether this node is a bootstrap node
65 'BOOTSTRAP_NODE': "no",
67 # Kademlia "K" constant, this should be an even number
70 # SHA1 is 160 bits long
73 # checkpoint every this many seconds
74 'CHECKPOINT_INTERVAL': '5m', # five minutes
77 # concurrent xmlrpc calls per find node/value request!
78 'CONCURRENT_REQS': '4',
80 # how many hosts to post to
81 'STORE_REDUNDANCY': '3',
83 # How many values to attempt to retrieve from the DHT.
84 # Setting this to 0 will try and get all values (which could take a while if
85 # a lot of nodes have values). Setting it negative will try to get that
86 # number of results from only the closest STORE_REDUNDANCY nodes to the hash.
87 # The default is a large negative number so all values from the closest
88 # STORE_REDUNDANCY nodes will be retrieved.
89 'RETRIEVE_VALUES': '-10000',
91 ### ROUTING TABLE STUFF
92 # how many times in a row a node can fail to respond before it's booted from the routing table
95 # never ping a node more often than this
96 'MIN_PING_INTERVAL': '15m', # fifteen minutes
98 # refresh buckets that haven't been touched in this long
99 'BUCKET_STALENESS': '1h', # one hour
101 # expire entries older than this
102 'KEY_EXPIRE': '1h', # 60 minutes
104 # whether to spew info about the requests/responses in the protocol
108 class AptDHTConfigParser(SafeConfigParser):
110 Adds 'gettime' to ConfigParser to interpret the suffixes.
119 def gettime(self, section, option):
121 value = self.get(section, option)
123 raise ConfigError("Configuration parse error: [%s] %s" % (section, option))
124 suffix = value[-1].lower()
125 if suffix in self.time_multipliers.keys():
126 mult = self.time_multipliers[suffix]
128 return int(value)*mult
129 def getstring(self, section, option):
130 return self.get(section,option)
131 def getstringlist(self, section, option):
132 return self.get(section,option).split()
133 def optionxform(self, option):
134 return option.upper()
136 config = AptDHTConfigParser(DEFAULTS)
137 config.add_section(config.get('DEFAULT', 'DHT'))
138 for k in DHT_DEFAULTS:
139 config.set(config.get('DEFAULT', 'DHT'), k, DHT_DEFAULTS[k])