2006-11-30 15:14:47 -07:00
|
|
|
|
2007-07-03 17:27:07 -07:00
|
|
|
import os, sha, stat, time, re
|
2007-06-07 15:32:21 -07:00
|
|
|
from foolscap import Referenceable, SturdyRef
|
2006-12-01 19:17:50 -07:00
|
|
|
from zope.interface import implements
|
2007-06-27 17:11:06 -07:00
|
|
|
from allmydata.interfaces import RIClient
|
|
|
|
from allmydata import node
|
2006-11-30 16:23:39 -07:00
|
|
|
|
2007-06-28 18:01:00 -07:00
|
|
|
from twisted.internet import reactor
|
2007-05-24 17:34:42 -07:00
|
|
|
from twisted.application.internet import TimerService
|
2007-07-03 17:27:07 -07:00
|
|
|
from twisted.python import log
|
2006-11-30 15:14:47 -07:00
|
|
|
|
2007-04-26 12:01:25 -07:00
|
|
|
import allmydata
|
2007-03-29 20:19:52 -07:00
|
|
|
from allmydata.Crypto.Util.number import bytes_to_long
|
2007-07-13 17:25:45 -07:00
|
|
|
from allmydata.storage import StorageServer
|
2006-12-02 18:27:18 -07:00
|
|
|
from allmydata.upload import Uploader
|
2006-12-03 03:01:43 -07:00
|
|
|
from allmydata.download import Downloader
|
2006-12-04 04:06:09 -07:00
|
|
|
from allmydata.webish import WebishServer
|
2007-03-07 19:16:06 -07:00
|
|
|
from allmydata.control import ControlServer
|
2007-03-27 16:12:11 -07:00
|
|
|
from allmydata.introducer import IntroducerClient
|
2007-06-27 17:11:06 -07:00
|
|
|
from allmydata.vdrive import VirtualDrive
|
2006-11-30 15:29:52 -07:00
|
|
|
|
2006-12-02 18:27:18 -07:00
|
|
|
class Client(node.Node, Referenceable):
|
2006-12-01 19:17:50 -07:00
|
|
|
implements(RIClient)
|
2006-12-02 18:27:18 -07:00
|
|
|
PORTNUMFILE = "client.port"
|
2006-11-30 20:14:23 -07:00
|
|
|
STOREDIR = 'storage'
|
2006-12-02 18:27:18 -07:00
|
|
|
NODETYPE = "client"
|
2006-12-04 04:06:09 -07:00
|
|
|
WEBPORTFILE = "webport"
|
2007-08-10 18:21:22 -07:00
|
|
|
WEB_ALLOW_LOCAL_ACCESS_FILE = "webport_allow_localfile"
|
2007-03-27 16:12:11 -07:00
|
|
|
INTRODUCER_FURL_FILE = "introducer.furl"
|
2007-06-07 15:32:21 -07:00
|
|
|
MY_FURL_FILE = "myself.furl"
|
2007-05-24 17:34:42 -07:00
|
|
|
SUICIDE_PREVENTION_HOTLINE_FILE = "suicide_prevention_hotline"
|
2007-07-03 17:27:07 -07:00
|
|
|
SIZELIMIT_FILE = "sizelimit"
|
2007-08-09 18:30:24 -07:00
|
|
|
PUSH_TO_OURSELVES_FILE = "push_to_ourselves"
|
2006-11-30 15:27:06 -07:00
|
|
|
|
2007-04-26 12:01:25 -07:00
|
|
|
# we're pretty narrow-minded right now
|
|
|
|
OLDEST_SUPPORTED_VERSION = allmydata.__version__
|
|
|
|
|
2006-12-02 18:27:18 -07:00
|
|
|
def __init__(self, basedir="."):
|
|
|
|
node.Node.__init__(self, basedir)
|
2007-05-22 14:08:30 -07:00
|
|
|
self.my_furl = None
|
2007-03-23 16:20:26 -07:00
|
|
|
self.introducer_client = None
|
2007-07-03 17:27:07 -07:00
|
|
|
self.init_storage()
|
2007-08-09 18:30:24 -07:00
|
|
|
self.init_options()
|
2006-12-02 18:27:18 -07:00
|
|
|
self.add_service(Uploader())
|
2006-12-03 03:01:43 -07:00
|
|
|
self.add_service(Downloader())
|
2007-06-27 17:11:06 -07:00
|
|
|
self.add_service(VirtualDrive())
|
2006-12-04 04:06:09 -07:00
|
|
|
WEBPORTFILE = os.path.join(self.basedir, self.WEBPORTFILE)
|
|
|
|
if os.path.exists(WEBPORTFILE):
|
|
|
|
f = open(WEBPORTFILE, "r")
|
2007-06-07 15:32:21 -07:00
|
|
|
webport = f.read().strip() # strports string
|
2006-12-04 04:06:09 -07:00
|
|
|
f.close()
|
2007-08-10 18:21:22 -07:00
|
|
|
ws = WebishServer(webport)
|
|
|
|
local_access_file = os.path.join(self.basedir,
|
|
|
|
self.WEB_ALLOW_LOCAL_ACCESS_FILE)
|
|
|
|
if os.path.exists(local_access_file):
|
|
|
|
ws.allow_local_access(True)
|
|
|
|
self.add_service(ws)
|
2007-03-27 16:12:11 -07:00
|
|
|
|
|
|
|
INTRODUCER_FURL_FILE = os.path.join(self.basedir,
|
|
|
|
self.INTRODUCER_FURL_FILE)
|
|
|
|
f = open(INTRODUCER_FURL_FILE, "r")
|
|
|
|
self.introducer_furl = f.read().strip()
|
|
|
|
f.close()
|
|
|
|
|
2007-05-24 17:34:42 -07:00
|
|
|
hotline_file = os.path.join(self.basedir,
|
|
|
|
self.SUICIDE_PREVENTION_HOTLINE_FILE)
|
|
|
|
if os.path.exists(hotline_file):
|
2007-08-14 02:12:30 -07:00
|
|
|
self.log("hotline file noticed, starting timer")
|
2007-05-29 17:39:39 -07:00
|
|
|
hotline = TimerService(1.0, self._check_hotline, hotline_file)
|
2007-05-24 17:34:42 -07:00
|
|
|
hotline.setServiceParent(self)
|
|
|
|
|
2007-07-03 17:27:07 -07:00
|
|
|
def init_storage(self):
|
|
|
|
storedir = os.path.join(self.basedir, self.STOREDIR)
|
|
|
|
sizelimit = None
|
|
|
|
SIZELIMIT_FILE = os.path.join(self.basedir,
|
|
|
|
self.SIZELIMIT_FILE)
|
|
|
|
if os.path.exists(SIZELIMIT_FILE):
|
|
|
|
f = open(SIZELIMIT_FILE, "r")
|
|
|
|
data = f.read().strip()
|
|
|
|
f.close()
|
|
|
|
m = re.match(r"^(\d+)([kKmMgG]?[bB]?)$", data)
|
|
|
|
if not m:
|
|
|
|
log.msg("SIZELIMIT_FILE contains unparseable value %s" % data)
|
|
|
|
else:
|
|
|
|
number, suffix = m.groups()
|
|
|
|
suffix = suffix.upper()
|
|
|
|
if suffix.endswith("B"):
|
|
|
|
suffix = suffix[:-1]
|
|
|
|
multiplier = {"": 1,
|
|
|
|
"K": 1000,
|
|
|
|
"M": 1000 * 1000,
|
|
|
|
"G": 1000 * 1000 * 1000,
|
|
|
|
}[suffix]
|
|
|
|
sizelimit = int(number) * multiplier
|
2007-07-16 18:07:03 -07:00
|
|
|
NOSTORAGE_FILE = os.path.join(self.basedir, "debug_no_storage")
|
|
|
|
no_storage = os.path.exists(NOSTORAGE_FILE)
|
|
|
|
self.add_service(StorageServer(storedir, sizelimit, no_storage))
|
2007-07-03 17:27:07 -07:00
|
|
|
|
2007-08-09 18:30:24 -07:00
|
|
|
def init_options(self):
|
|
|
|
self.push_to_ourselves = None
|
|
|
|
filename = os.path.join(self.basedir, self.PUSH_TO_OURSELVES_FILE)
|
|
|
|
if os.path.exists(filename):
|
|
|
|
self.push_to_ourselves = True
|
|
|
|
|
2007-05-24 17:34:42 -07:00
|
|
|
def _check_hotline(self, hotline_file):
|
|
|
|
if os.path.exists(hotline_file):
|
|
|
|
mtime = os.stat(hotline_file)[stat.ST_MTIME]
|
|
|
|
if mtime > time.time() - 10.0:
|
|
|
|
return
|
|
|
|
self.log("hotline missing or too old, shutting down")
|
|
|
|
reactor.stop()
|
|
|
|
|
2006-12-02 19:37:31 -07:00
|
|
|
def tub_ready(self):
|
2007-03-27 16:12:11 -07:00
|
|
|
self.log("tub_ready")
|
2007-06-07 15:32:21 -07:00
|
|
|
|
|
|
|
my_old_name = None
|
|
|
|
MYSELF_FURL_PATH = os.path.join(self.basedir, self.MY_FURL_FILE)
|
|
|
|
if os.path.exists(MYSELF_FURL_PATH):
|
|
|
|
my_old_furl = open(MYSELF_FURL_PATH, "r").read().strip()
|
|
|
|
sturdy = SturdyRef(my_old_furl)
|
|
|
|
my_old_name = sturdy.name
|
|
|
|
|
|
|
|
self.my_furl = self.tub.registerReference(self, my_old_name)
|
|
|
|
f = open(MYSELF_FURL_PATH, "w")
|
|
|
|
f.write(self.my_furl)
|
|
|
|
f.close()
|
2007-03-27 16:12:11 -07:00
|
|
|
|
2007-05-22 14:08:30 -07:00
|
|
|
ic = IntroducerClient(self.tub, self.introducer_furl, self.my_furl)
|
2007-03-27 16:12:11 -07:00
|
|
|
self.introducer_client = ic
|
|
|
|
ic.setServiceParent(self)
|
|
|
|
|
2007-03-23 16:20:26 -07:00
|
|
|
self.register_control()
|
2007-03-27 16:12:11 -07:00
|
|
|
|
2007-03-23 16:20:26 -07:00
|
|
|
def register_control(self):
|
|
|
|
c = ControlServer()
|
|
|
|
c.setServiceParent(self)
|
|
|
|
control_url = self.tub.registerReference(c)
|
2007-07-16 18:06:27 -07:00
|
|
|
control_furl_file = os.path.join(self.basedir, "control.furl")
|
|
|
|
f = open(control_furl_file, "w")
|
2007-03-23 16:20:26 -07:00
|
|
|
f.write(control_url + "\n")
|
|
|
|
f.close()
|
2007-07-16 18:06:27 -07:00
|
|
|
os.chmod(control_furl_file, 0600)
|
2007-03-23 16:20:26 -07:00
|
|
|
|
2007-06-15 01:33:24 -07:00
|
|
|
|
2007-04-26 12:01:25 -07:00
|
|
|
def remote_get_versions(self):
|
|
|
|
return str(allmydata.__version__), str(self.OLDEST_SUPPORTED_VERSION)
|
|
|
|
|
2006-11-30 18:09:57 -07:00
|
|
|
def remote_get_service(self, name):
|
2007-06-14 20:14:34 -07:00
|
|
|
if name in ("storageserver",):
|
|
|
|
return self.getServiceNamed(name)
|
|
|
|
raise RuntimeError("I am unwilling to give you service %s" % name)
|
2006-11-30 18:09:57 -07:00
|
|
|
|
2006-11-30 20:18:51 -07:00
|
|
|
|
2007-03-27 16:12:11 -07:00
|
|
|
def get_all_peerids(self):
|
2007-06-09 21:03:57 -07:00
|
|
|
if not self.introducer_client:
|
|
|
|
return []
|
2007-07-16 19:47:42 -07:00
|
|
|
return self.introducer_client.get_all_peerids()
|
2007-03-27 16:12:11 -07:00
|
|
|
|
2007-08-09 18:30:24 -07:00
|
|
|
def get_permuted_peers(self, key, include_myself=True):
|
2007-03-29 20:19:52 -07:00
|
|
|
"""
|
|
|
|
@return: list of (permuted-peerid, peerid, connection,)
|
|
|
|
"""
|
2006-11-30 20:18:51 -07:00
|
|
|
results = []
|
2007-07-16 19:47:42 -07:00
|
|
|
for peerid, connection in self.introducer_client.get_all_peers():
|
2007-03-29 20:19:52 -07:00
|
|
|
assert isinstance(peerid, str)
|
2007-08-12 16:24:51 -07:00
|
|
|
if not include_myself and peerid == self.nodeid:
|
2007-08-09 18:30:24 -07:00
|
|
|
self.log("get_permuted_peers: removing myself from the list")
|
|
|
|
continue
|
2007-03-29 20:19:52 -07:00
|
|
|
permuted = bytes_to_long(sha.new(key + peerid).digest())
|
|
|
|
results.append((permuted, peerid, connection))
|
2006-11-30 20:18:51 -07:00
|
|
|
results.sort()
|
2007-03-29 20:19:52 -07:00
|
|
|
return results
|
2007-06-09 21:03:57 -07:00
|
|
|
|
2007-08-09 18:30:24 -07:00
|
|
|
def get_push_to_ourselves(self):
|
|
|
|
return self.push_to_ourselves
|
|
|
|
|
2007-07-12 15:33:30 -07:00
|
|
|
def get_encoding_parameters(self):
|
|
|
|
if not self.introducer_client:
|
|
|
|
return None
|
|
|
|
return self.introducer_client.encoding_parameters
|
|
|
|
|
2007-06-09 21:03:57 -07:00
|
|
|
def connected_to_introducer(self):
|
|
|
|
if self.introducer_client:
|
|
|
|
return self.introducer_client.connected_to_introducer()
|
|
|
|
return False
|