import os
import time
-import foolscap
-from foolscap.eventual import eventually
+from foolscap.api import Referenceable, Tub
from zope.interface import implements
from twisted.internet import reactor
from twisted.application import service
-from twisted.python import log
+from allmydata.util import log, fileutil
from pycryptopp.publickey import rsa
from allmydata.interfaces import RIKeyGenerator
-class KeyGenerator(foolscap.Referenceable):
+class KeyGenerator(service.MultiService, Referenceable):
implements(RIKeyGenerator)
- DEFAULT_KEY_SIZE = 2048
pool_size = 16 # no. keys to keep on hand in the pool
pool_refresh_delay = 6 # no. sec to wait after a fetch before generating new keys
verbose = False
- def __init__(self):
+ def __init__(self, default_key_size=2048):
+ service.MultiService.__init__(self)
self.keypool = []
self.last_fetch = 0
- eventually(self.maybe_refill_pool)
+ self.default_key_size = default_key_size
+
+ def startService(self):
+ self.timer = reactor.callLater(0, self.maybe_refill_pool)
+ return service.MultiService.startService(self)
+
+ def stopService(self):
+ if self.timer.active():
+ self.timer.cancel()
+ return service.MultiService.stopService(self)
def __repr__(self):
return '<KeyGenerator[%s]>' % (len(self.keypool),)
def reset_timer(self):
self.last_fetch = time.time()
- reactor.callLater(self.pool_refresh_delay, self.maybe_refill_pool)
+ if self.timer.active():
+ self.timer.reset(self.pool_refresh_delay)
+ else:
+ self.timer = reactor.callLater(self.pool_refresh_delay, self.maybe_refill_pool)
def maybe_refill_pool(self):
now = time.time()
if self.last_fetch + self.pool_refresh_delay < now:
self.vlog('%s refilling pool' % (self,))
while len(self.keypool) < self.pool_size:
- self.keypool.append(self.gen_key(self.DEFAULT_KEY_SIZE))
+ self.keypool.append(self.gen_key(self.default_key_size))
else:
self.vlog('%s not refilling pool' % (self,))
+ reactor.callLater(1, self.maybe_refill_pool)
def gen_key(self, key_size):
self.vlog('%s generating key size %s' % (self, key_size, ))
def remote_get_rsa_key_pair(self, key_size):
self.vlog('%s remote_get_key' % (self,))
- if key_size != self.DEFAULT_KEY_SIZE or not self.keypool:
- return self.gen_key(key_size)
+ if key_size != self.default_key_size or not self.keypool:
+ key = self.gen_key(key_size)
+ self.reset_timer()
+ return key
else:
self.reset_timer()
return self.keypool.pop()
class KeyGeneratorService(service.MultiService):
furl_file = 'key_generator.furl'
- def __init__(self):
+ def __init__(self, basedir='.', display_furl=True, default_key_size=2048):
service.MultiService.__init__(self)
- self.tub = foolscap.Tub(certFile='key_generator.pem')
+ self.basedir = basedir
+ fileutil.make_dirs(self.basedir)
+ self.tub = Tub(certFile=os.path.join(self.basedir, 'key_generator.pem'))
+ self.tub.setOption("expose-remote-exception-types", False)
self.tub.setServiceParent(self)
- self.key_generator = KeyGenerator()
+ self.key_generator = KeyGenerator(default_key_size=default_key_size)
+ self.key_generator.setServiceParent(self)
portnum = self.get_portnum()
self.listener = self.tub.listenOn(portnum or 'tcp:0')
d = self.tub.setLocationAutomatically()
if portnum is None:
d.addCallback(self.save_portnum)
- d.addCallback(self.tub_ready)
+ d.addCallback(self.tub_ready, display_furl)
d.addErrback(log.err)
def get_portnum(self):
- if os.path.exists('portnum'):
- return file('portnum', 'rb').read().strip()
+ portnumfile = os.path.join(self.basedir, 'portnum')
+ if os.path.exists(portnumfile):
+ return file(portnumfile, 'rb').read().strip()
def save_portnum(self, junk):
portnum = self.listener.getPortnum()
- file('portnum', 'wb').write('%d\n' % (portnum,))
-
- def tub_ready(self, junk):
- self.keygen_furl = self.tub.registerReference(self.key_generator, furlFile=self.furl_file)
- print 'key generator at:', self.keygen_furl
+ portnumfile = os.path.join(self.basedir, 'portnum')
+ file(portnumfile, 'wb').write('%d\n' % (portnum,))
+
+ def tub_ready(self, junk, display_furl):
+ kgf = os.path.join(self.basedir, self.furl_file)
+ self.keygen_furl = self.tub.registerReference(self.key_generator, furlFile=kgf)
+ if display_furl:
+ print 'key generator at:', self.keygen_furl