From c599adb68f5e7afefb25375b063e5e7fe02f949c Mon Sep 17 00:00:00 2001 From: Cameron Dale Date: Sat, 15 Dec 2007 19:27:41 -0800 Subject: [PATCH] Added the application control files. --- HTTPServer.py | 2 +- apt-dht.py | 67 ++++++++++++++++++++++++++++++ apt_dht.py | 24 +++++++++++ apt_dht_conf.py | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 apt-dht.py create mode 100644 apt_dht.py create mode 100644 apt_dht_conf.py diff --git a/HTTPServer.py b/HTTPServer.py index 5d98d23..688b296 100644 --- a/HTTPServer.py +++ b/HTTPServer.py @@ -14,7 +14,7 @@ class FileDownloader(static.File): if self.manager: if resp != responsecode.NOT_FOUND: - return self.manager.check_freshness(req.uri, resp.headers.getHeader('Last-Modified')) + return self.manager.check_freshness(req.uri, resp.headers.getHeader('Last-Modified'), resp) return self.manager.get_resp(req.uri) diff --git a/apt-dht.py b/apt-dht.py new file mode 100644 index 0000000..30b6a93 --- /dev/null +++ b/apt-dht.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +# Load apt-dht application +# +# There are two ways apt-dht can be started: +# 1. twistd -y apt-dht +# - twistd will load this file and execute the app +# in 'application' variable +# 2. from command line +# - __name__ will be '__main__' + +import pwd,sys + +from twisted.application import service, internet, app, strports +from twisted.internet import reactor +from twisted.python import usage, log +from twisted.web2 import channel + +from apt_dht import AptDHT +from apt_dht_conf import config + +config_file = [] + +if __name__ == '__main__': + # Parse command line parameters when started on command line + class AptDHTOptions(usage.Options): + optFlags = [ + ['help', 'h'], + ] + optParameters = [ + ['config-file', 'c', None, "Configuration file"], + ] + longdesc="apt-dht is a peer-to-peer downloader for apt users" + def opt_version(self): + print "apt-dht 1.9.x" + sys.exit(0) + + opts = AptDHTOptions() + try: + opts.parseOptions() + except usage.UsageError, ue: + print '%s: %s' % (sys.argv[0], ue) + sys.exit(1) + + config_file = opts.opts['config-file'] + +config.read(config_file) +if config.defaults()['username']: + uid,gid = pwd.getpwnam(config.defaults()['username'])[2:4] +else: + uid,gid = None,None + +application = service.Application("apt-dht", uid, gid) +print service.IProcess(application).processName +service.IProcess(application).processName = 'apt-dht' + +myapp = AptDHT() +site = myapp.getSite() +s = strports.service('tcp:'+config.defaults()['port'], channel.HTTPFactory(site)) +s.setServiceParent(application) + +if __name__ == '__main__': + # Run on command line + log.startLogging(sys.stdout, setStdout=0) + service.IServiceCollection(application).privilegedStartService() + service.IServiceCollection(application).startService() + reactor.run() diff --git a/apt_dht.py b/apt_dht.py new file mode 100644 index 0000000..d30f0b8 --- /dev/null +++ b/apt_dht.py @@ -0,0 +1,24 @@ + +from twisted.web2 import server, http, http_headers + +from apt_dht_conf import config +from HTTPServer import TopLevel + +class AptDHT: + def __init__(self): + self.http_server = TopLevel(config.defaults()['cache_dir'], self) + self.http_site = server.Site(self.http_server) + + def getSite(self): + return self.http_site + + def check_freshness(self, path, modtime, resp): + return resp + + def get_resp(self, path): + return http.Response( + 200, + {'content-type': http_headers.MimeType('text', 'html')}, + """ +

Statistics

+

TODO: eventually this will cause a P2P lookup.""") diff --git a/apt_dht_conf.py b/apt_dht_conf.py new file mode 100644 index 0000000..32ffa06 --- /dev/null +++ b/apt_dht_conf.py @@ -0,0 +1,105 @@ + +import os, sys +from ConfigParser import SafeConfigParser + +from twisted.python import log, versions + +class ConfigError(Exception): + def __init__(self, message): + self.message = message + def __str__(self): + return repr(self.message) + +version = versions.Version('apt-dht', 0, 0, 0) +home = os.path.expandvars('${HOME}') +if home == '${HOME}' or not os.path.isdir(home): + home = os.path.expanduser('~') + if not os.path.isdir(home): + home = os.path.abspath(os.path.dirname(sys.argv[0])) + +DEFAULTS = { + + # Port to listen on for all requests (TCP and UDP) + 'port': '9977', + + # Directory to store the downloaded files in + 'cache_dir': home + '/.apt-dht/cache', + + # User name to try and run as + 'username': '', + + # Which DHT implementation to use + 'DHT': 'Khashmir', +} + +DHT_DEFAULTS = { + # magic id to use before we know a peer's id + 'NULL_ID': 20 * '\0', + + # Kademlia "K" constant, this should be an even number + 'K': '8', + + # SHA1 is 160 bits long + 'HASH_LENGTH': '160', + + # checkpoint every this many seconds + 'CHECKPOINT_INTERVAL': '15m', # fifteen minutes + + ### SEARCHING/STORING + # concurrent xmlrpc calls per find node/value request! + 'CONCURRENT_REQS': '4', + + # how many hosts to post to + 'STORE_REDUNDANCY': '3', + + ### ROUTING TABLE STUFF + # how many times in a row a node can fail to respond before it's booted from the routing table + 'MAX_FAILURES': '3', + + # never ping a node more often than this + 'MIN_PING_INTERVAL': '15m', # fifteen minutes + + # refresh buckets that haven't been touched in this long + 'BUCKET_STALENESS': '1h', # one hour + + ### KEY EXPIRER + # time before expirer starts running + 'KEINITIAL_DELAY': '15s', # 15 seconds - to clean out old stuff in persistent db + + # time between expirer runs + 'KE_DELAY': '20m', # 20 minutes + + # expire entries older than this + 'KE_AGE': '1h', # 60 minutes +} + +class AptDHTConfigParser(SafeConfigParser): + """ + Adds 'gettime' to ConfigParser to interpret the suffixes. + """ + time_multipliers={ + 's': 1, #seconds + 'm': 60, #minutes + 'h': 3600, #hours + 'd': 86400,#days + } + + def gettime(self, section, option): + mult = 1 + value = self.get(section, option) + if len(value) == 0: + raise ConfigError("Configuration parse error: [%s] %s" % (section, option)) + suffix = value[-1].lower() + if suffix in self.time_multipliers.keys(): + mult = self.time_multipliers[suffix] + value = value[:-1] + return int(value)*mult + def getstring(self, section, option): + return self.get(section,option) + def getstringlist(self, section, option): + return self.get(section,option).split() + +config = AptDHTConfigParser(DEFAULTS) +config.add_section(config.get('DEFAULT', 'DHT')) +for k in DHT_DEFAULTS: + config.set(config.get('DEFAULT', 'DHT'), k, DHT_DEFAULTS[k]) -- 2.39.5