2006-11-30 22:14:47 +00:00
|
|
|
|
2006-11-30 23:23:39 +00:00
|
|
|
import os.path
|
2006-11-30 22:29:52 +00:00
|
|
|
from foolscap import Tub, Referenceable
|
2006-11-30 22:14:47 +00:00
|
|
|
from twisted.application import service
|
2006-11-30 22:27:06 +00:00
|
|
|
from twisted.python import log
|
2006-11-30 23:23:39 +00:00
|
|
|
from allmydata.util.iputil import get_local_ip_for
|
|
|
|
|
|
|
|
from twisted.internet import reactor
|
|
|
|
from twisted.internet.base import BlockingResolver
|
|
|
|
reactor.installResolver(BlockingResolver())
|
2006-11-30 22:14:47 +00:00
|
|
|
|
2006-12-01 03:14:23 +00:00
|
|
|
from allmydata.storageserver import StorageServer
|
2006-11-30 22:29:52 +00:00
|
|
|
|
2006-12-01 00:43:15 +00:00
|
|
|
class Client(service.MultiService, Referenceable):
|
2006-11-30 22:27:06 +00:00
|
|
|
CERTFILE = "client.pem"
|
2006-12-01 03:14:23 +00:00
|
|
|
STOREDIR = 'storage'
|
2006-11-30 22:27:06 +00:00
|
|
|
|
2006-12-01 00:13:40 +00:00
|
|
|
def __init__(self, queen_pburl):
|
2006-11-30 22:14:47 +00:00
|
|
|
service.MultiService.__init__(self)
|
|
|
|
self.queen_pburl = queen_pburl
|
2006-11-30 22:27:06 +00:00
|
|
|
if os.path.exists(self.CERTFILE):
|
|
|
|
self.tub = Tub(certData=open(self.CERTFILE, "rb").read())
|
|
|
|
else:
|
|
|
|
self.tub = Tub()
|
|
|
|
f = open(self.CERTFILE, "wb")
|
|
|
|
f.write(self.tub.getCertData())
|
|
|
|
f.close()
|
2006-12-01 02:20:17 +00:00
|
|
|
self.nodeid = self.tub.tubID
|
2006-11-30 23:23:39 +00:00
|
|
|
self.tub.setServiceParent(self)
|
2006-11-30 22:27:06 +00:00
|
|
|
self.queen = None # self.queen is either None or a RemoteReference
|
2006-12-01 01:09:57 +00:00
|
|
|
self.all_peers = set()
|
|
|
|
self.connections = {}
|
2006-12-01 03:14:23 +00:00
|
|
|
s = StorageServer(self.STOREDIR)
|
2006-12-01 01:09:57 +00:00
|
|
|
s.setServiceParent(self)
|
|
|
|
|
2006-12-01 02:34:25 +00:00
|
|
|
AUTHKEYSFILEBASE = "authorized_keys."
|
|
|
|
for f in os.listdir("."):
|
|
|
|
if f.startswith(AUTHKEYSFILEBASE):
|
|
|
|
portnum = int(f[len(AUTHKEYSFILEBASE):])
|
|
|
|
from allmydata import manhole
|
|
|
|
m = manhole.AuthorizedKeysManhole(portnum, f)
|
|
|
|
m.setServiceParent(self)
|
|
|
|
log.msg("AuthorizedKeysManhole listening on %d" % portnum)
|
2006-11-30 23:23:39 +00:00
|
|
|
|
2006-12-01 01:09:57 +00:00
|
|
|
def _setup_tub(self, local_ip):
|
2006-11-30 23:23:39 +00:00
|
|
|
portnum = 0
|
|
|
|
l = self.tub.listenOn("tcp:%d" % portnum)
|
|
|
|
self.tub.setLocation("%s:%d" % (local_ip, l.getPortnum()))
|
2006-12-01 01:09:57 +00:00
|
|
|
self.my_pburl = self.tub.registerReference(self)
|
2006-11-30 22:27:06 +00:00
|
|
|
|
|
|
|
def startService(self):
|
2006-11-30 23:23:39 +00:00
|
|
|
# note: this class can only be started and stopped once.
|
2006-11-30 22:27:06 +00:00
|
|
|
service.MultiService.startService(self)
|
2006-12-01 00:13:40 +00:00
|
|
|
d = get_local_ip_for()
|
2006-12-01 01:09:57 +00:00
|
|
|
d.addCallback(self._setup_tub)
|
2006-11-30 22:27:06 +00:00
|
|
|
if self.queen_pburl:
|
2006-12-01 01:09:57 +00:00
|
|
|
# TODO: maybe this should wait for tub.setLocation ?
|
2006-11-30 22:27:06 +00:00
|
|
|
self.connector = self.tub.connectTo(self.queen_pburl,
|
|
|
|
self._got_queen)
|
|
|
|
else:
|
|
|
|
log.msg("no queen_pburl, cannot connect")
|
|
|
|
|
|
|
|
def stopService(self):
|
2006-11-30 22:55:26 +00:00
|
|
|
if self.queen_pburl:
|
|
|
|
self.connector.stopConnecting()
|
2006-11-30 23:23:39 +00:00
|
|
|
service.MultiService.stopService(self)
|
2006-11-30 22:27:06 +00:00
|
|
|
|
|
|
|
def _got_queen(self, queen):
|
|
|
|
log.msg("connected to queen")
|
|
|
|
self.queen = queen
|
|
|
|
queen.notifyOnDisconnect(self._lost_queen)
|
2006-12-01 01:09:57 +00:00
|
|
|
queen.callRemote("hello",
|
2006-12-01 02:20:17 +00:00
|
|
|
nodeid=self.nodeid, node=self, pburl=self.my_pburl)
|
2006-11-30 22:27:06 +00:00
|
|
|
|
|
|
|
def _lost_queen(self):
|
|
|
|
log.msg("lost connection to queen")
|
|
|
|
self.queen = None
|
2006-12-01 01:09:57 +00:00
|
|
|
|
|
|
|
def remote_get_service(self, name):
|
|
|
|
return self.getServiceNamed(name)
|
|
|
|
|
|
|
|
def remote_add_peers(self, new_peers):
|
|
|
|
for nodeid, pburl in new_peers:
|
2006-12-01 02:20:17 +00:00
|
|
|
if nodeid == self.nodeid:
|
2006-12-01 01:09:57 +00:00
|
|
|
continue
|
|
|
|
log.msg("adding peer %s" % nodeid)
|
|
|
|
if nodeid in self.all_peers:
|
|
|
|
log.msg("weird, I already had an entry for them")
|
|
|
|
self.all_peers.add(nodeid)
|
|
|
|
if nodeid not in self.connections:
|
|
|
|
d = self.tub.getReference(pburl)
|
|
|
|
def _got_reference(ref):
|
2006-12-01 01:13:46 +00:00
|
|
|
log.msg("connected to %s" % nodeid)
|
2006-12-01 01:09:57 +00:00
|
|
|
if nodeid in self.all_peers:
|
|
|
|
self.connections[nodeid] = ref
|
|
|
|
d.addCallback(_got_reference)
|
|
|
|
|
|
|
|
def remote_lost_peers(self, lost_peers):
|
|
|
|
for nodeid in lost_peers:
|
|
|
|
log.msg("lost peer %s" % nodeid)
|
|
|
|
if nodeid in self.all_peers:
|
2006-12-01 01:13:46 +00:00
|
|
|
self.all_peers.remove(nodeid)
|
2006-12-01 01:09:57 +00:00
|
|
|
else:
|
|
|
|
log.msg("weird, I didn't have an entry for them")
|
|
|
|
if nodeid in self.connections:
|
|
|
|
del self.connections[nodeid]
|
2006-12-01 01:17:36 +00:00
|
|
|
|
|
|
|
def get_remote_service(self, nodeid, servicename):
|
|
|
|
if nodeid not in self.connections:
|
|
|
|
raise IndexError("no connection to that peer")
|
|
|
|
d = self.connections[nodeid].callRemote("get_service", name=servicename)
|
|
|
|
return d
|