/usr/share/pyshared/allmydata/web/introweb.py is in tahoe-lafs 1.9.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | import time, os
from nevow import rend, inevow
from nevow.static import File as nevow_File
from nevow.util import resource_filename
from foolscap.api import SturdyRef
from twisted.internet import address
import allmydata
import simplejson
from allmydata import get_package_versions_string
from allmydata.util import idlib
from allmydata.web.common import getxmlfile, get_arg
class IntroducerRoot(rend.Page):
addSlash = True
docFactory = getxmlfile("introducer.xhtml")
child_operations = None
def __init__(self, introducer_node):
self.introducer_node = introducer_node
self.introducer_service = introducer_node.getServiceNamed("introducer")
rend.Page.__init__(self, introducer_node)
static_dir = resource_filename("allmydata.web", "static")
for filen in os.listdir(static_dir):
self.putChild(filen, nevow_File(os.path.join(static_dir, filen)))
def renderHTTP(self, ctx):
t = get_arg(inevow.IRequest(ctx), "t")
if t == "json":
return self.render_JSON(ctx)
return rend.Page.renderHTTP(self, ctx)
def render_JSON(self, ctx):
res = {}
clients = self.introducer_service.get_subscribers()
subscription_summary = dict([ (name, len(clients[name]))
for name in clients ])
res["subscription_summary"] = subscription_summary
announcement_summary = {}
service_hosts = {}
for (ann,when) in self.introducer_service.get_announcements().values():
(furl, service_name, ri_name, nickname, ver, oldest) = ann
if service_name not in announcement_summary:
announcement_summary[service_name] = 0
announcement_summary[service_name] += 1
if service_name not in service_hosts:
service_hosts[service_name] = set()
# it's nice to know how many distinct hosts are available for
# each service. We define a "host" by a set of addresses
# (hostnames or ipv4 addresses), which we extract from the
# connection hints. In practice, this is usually close
# enough: when multiple services are run on a single host,
# they're usually either configured with the same addresses,
# or setLocationAutomatically picks up the same interfaces.
locations = SturdyRef(furl).getTubRef().getLocations()
# list of tuples, ("ipv4", host, port)
host = frozenset([hint[1]
for hint in locations
if hint[0] == "ipv4"])
service_hosts[service_name].add(host)
res["announcement_summary"] = announcement_summary
distinct_hosts = dict([(name, len(hosts))
for (name, hosts)
in service_hosts.iteritems()])
res["announcement_distinct_hosts"] = distinct_hosts
return simplejson.dumps(res, indent=1) + "\n"
# FIXME: This code is duplicated in root.py and introweb.py.
def data_version(self, ctx, data):
return get_package_versions_string()
def data_import_path(self, ctx, data):
return str(allmydata).replace("/", "/ ") # XXX kludge for wrapping
def data_my_nodeid(self, ctx, data):
return idlib.nodeid_b2a(self.introducer_node.nodeid)
def render_announcement_summary(self, ctx, data):
services = {}
for (ann,when) in self.introducer_service.get_announcements().values():
(furl, service_name, ri_name, nickname, ver, oldest) = ann
if service_name not in services:
services[service_name] = 0
services[service_name] += 1
service_names = services.keys()
service_names.sort()
return ", ".join(["%s: %d" % (service_name, services[service_name])
for service_name in service_names])
def render_client_summary(self, ctx, data):
clients = self.introducer_service.get_subscribers()
service_names = clients.keys()
service_names.sort()
return ", ".join(["%s: %d" % (service_name, len(clients[service_name]))
for service_name in service_names])
def data_services(self, ctx, data):
introsvc = self.introducer_service
ann = [(since,a)
for (a,since) in introsvc.get_announcements().values()
if a[1] != "stub_client"]
ann.sort(lambda a,b: cmp( (a[1][1], a), (b[1][1], b) ) )
return ann
def render_service_row(self, ctx, (since,announcement)):
(furl, service_name, ri_name, nickname, ver, oldest) = announcement
sr = SturdyRef(furl)
nodeid = sr.tubID
advertised = self.show_location_hints(sr)
ctx.fillSlots("peerid", nodeid)
ctx.fillSlots("nickname", nickname)
ctx.fillSlots("advertised", " ".join(advertised))
ctx.fillSlots("connected", "?")
TIME_FORMAT = "%H:%M:%S %d-%b-%Y"
ctx.fillSlots("announced",
time.strftime(TIME_FORMAT, time.localtime(since)))
ctx.fillSlots("version", ver)
ctx.fillSlots("service_name", service_name)
return ctx.tag
def data_subscribers(self, ctx, data):
# use the "stub_client" announcements to get information per nodeid
clients = {}
for (ann,when) in self.introducer_service.get_announcements().values():
if ann[1] != "stub_client":
continue
(furl, service_name, ri_name, nickname, ver, oldest) = ann
sr = SturdyRef(furl)
nodeid = sr.tubID
clients[nodeid] = ann
# then we actually provide information per subscriber
s = []
introsvc = self.introducer_service
for service_name, subscribers in introsvc.get_subscribers().items():
for (rref, timestamp) in subscribers.items():
sr = rref.getSturdyRef()
nodeid = sr.tubID
ann = clients.get(nodeid)
s.append( (service_name, rref, timestamp, ann) )
s.sort()
return s
def render_subscriber_row(self, ctx, s):
(service_name, rref, since, ann) = s
nickname = "?"
version = "?"
if ann:
(furl, service_name_2, ri_name, nickname, version, oldest) = ann
sr = rref.getSturdyRef()
# if the subscriber didn't do Tub.setLocation, nodeid will be None
nodeid = sr.tubID or "?"
ctx.fillSlots("peerid", nodeid)
ctx.fillSlots("nickname", nickname)
advertised = self.show_location_hints(sr)
ctx.fillSlots("advertised", " ".join(advertised))
remote_host = rref.tracker.broker.transport.getPeer()
if isinstance(remote_host, address.IPv4Address):
remote_host_s = "%s:%d" % (remote_host.host, remote_host.port)
else:
# loopback is a non-IPv4Address
remote_host_s = str(remote_host)
ctx.fillSlots("connected", remote_host_s)
TIME_FORMAT = "%H:%M:%S %d-%b-%Y"
ctx.fillSlots("since",
time.strftime(TIME_FORMAT, time.localtime(since)))
ctx.fillSlots("version", version)
ctx.fillSlots("service_name", service_name)
return ctx.tag
def show_location_hints(self, sr, ignore_localhost=True):
advertised = []
for hint in sr.locationHints:
if isinstance(hint, str):
# Foolscap-0.2.5 and earlier used strings in .locationHints
if ignore_localhost and hint.startswith("127.0.0.1"):
continue
advertised.append(hint.split(":")[0])
else:
# Foolscap-0.2.6 and later use tuples of ("ipv4", host, port)
if hint[0] == "ipv4":
host = hint[1]
if ignore_localhost and host == "127.0.0.1":
continue
advertised.append(hint[1])
return advertised
|