A long time ago, the introducer's status web page would show the
advertised IP addresses for all published services, by parsing their
FURL's connection hints. This hasn't worked since about 12-Aug-2014 when
foolscap-0.6.5 changed the internal format of these hints (the column
has been empty this whole time).
This removes the "Advertised IPs" column from the Service Announcements
table. Instead, the service's full connection hints (not just the IP
address) is displayed in a tooltip/popup on the "Announced" timestamp
column.
The code that pulls these connection hints is now tolerant of all three
foolscap styles:
* foolscap<=0.6.4 : tuples of ("ipv4",host,port)
* 0.6.5 .. 0.8.0 : tuples of ("tcp",host,port)
* foolscap>=0.9.0 : strings
fixes ticket:2510
.nickname: their self-provided nickname, or "" (unicode)
.serverid: the server identifier. This is a pubkey (for V2 clients),
or a tubid (for V1 clients).
.nickname: their self-provided nickname, or "" (unicode)
.serverid: the server identifier. This is a pubkey (for V2 clients),
or a tubid (for V1 clients).
- .advertised_addresses: which hosts they listen on (list of strings)
- if the announcement included a key for
- 'anonymous-storage-FURL', else an empty list.
+ .connection_hints: where they listen (list of strings) if the
+ announcement included a key for
+ 'anonymous-storage-FURL', else an empty list.
"""
def __init__(self, when, index, canary, ann_d):
"""
def __init__(self, when, index, canary, ann_d):
self.serverid = key_s or tubid_s
furl = ann_d.get("anonymous-storage-FURL")
if furl:
self.serverid = key_s or tubid_s
furl = ann_d.get("anonymous-storage-FURL")
if furl:
- self.advertised_addresses = rrefutil.hosts_for_furl(furl)
+ self.connection_hints = rrefutil.connection_hints_for_furl(furl)
- self.advertised_addresses = []
+ self.connection_hints = []
class FakeRemoteReference:
def notifyOnDisconnect(self, *args, **kwargs): pass
def getRemoteTubID(self): return "62ubehyunnyhzs7r6vdonnm2hpi52w6y"
class FakeRemoteReference:
def notifyOnDisconnect(self, *args, **kwargs): pass
def getRemoteTubID(self): return "62ubehyunnyhzs7r6vdonnm2hpi52w6y"
- def getLocationHints(self): return [("ipv4", "here.example.com", "1234"),
- ("ipv4", "there.example.com", "2345")]
+ def getLocationHints(self): return ["tcp:here.example.com:1234",
+ "tcp:there.example.com2345"]
def getPeer(self): return address.IPv4Address("TCP", "remote.example.com",
3456)
def getPeer(self): return address.IPv4Address("TCP", "remote.example.com",
3456)
return trap_and_discard(f, DeadReferenceError)
return trap_and_discard(f, DeadReferenceError)
-def hosts_for_furl(furl, ignore_localhost=True):
- advertised = []
- for hint in SturdyRef(furl).locationHints:
- assert not isinstance(hint, str), hint
- if hint[0] == "ipv4":
- host = hint[1]
- if ignore_localhost and host == "127.0.0.1":
- continue
- advertised.append(host)
- return advertised
+def connection_hints_for_furl(furl):
+ hints = []
+ for h in SturdyRef(furl).locationHints:
+ # Foolscap-0.2.5 and earlier used strings in .locationHints, 0.2.6
+ # through 0.6.4 used tuples of ("ipv4",host,port), 0.6.5 through
+ # 0.8.0 used tuples of ("tcp",host,port), and >=0.9.0 uses strings
+ # again. Tolerate them all.
+ if isinstance(h, tuple):
+ hints.append(":".join([str(s) for s in h]))
+ else:
+ hints.append(h)
+ return hints
def stringify_remote_address(rref):
remote = rref.getPeer()
def stringify_remote_address(rref):
remote = rref.getPeer()
<th class="nickname-and-peerid">
<div class="service-nickname">Nickname</div>
<div class="nodeid data-chars">ServerID</div></th>
<th class="nickname-and-peerid">
<div class="service-nickname">Nickname</div>
<div class="nodeid data-chars">ServerID</div></th>
- <th>Advertised IPs</th>
<th>Announced</th>
<th>Version</th>
<th>Service Name</th>
<th>Announced</th>
<th>Version</th>
<th>Service Name</th>
<td class="nickname-and-peerid">
<div class="nickname"><n:slot name="nickname"/></div>
<div class="nodeid data-chars"><n:slot name="serverid"/></div></td>
<td class="nickname-and-peerid">
<div class="nickname"><n:slot name="nickname"/></div>
<div class="nodeid data-chars"><n:slot name="serverid"/></div></td>
- <td><n:slot name="advertised"/></td>
- <td class="service-announced"><n:slot name="announced"/></td>
+ <td class="service-announced"><n:attr name="title"><n:slot name="connection-hints"/></n:attr><n:slot name="announced"/></td>
<td class="service-version"><n:slot name="version"/></td>
<td class="service-service-name"><n:slot name="service_name"/></td>
</tr>
<td class="service-version"><n:slot name="version"/></td>
<td class="service-service-name"><n:slot name="service_name"/></td>
</tr>
def render_service_row(self, ctx, ad):
ctx.fillSlots("serverid", ad.serverid)
ctx.fillSlots("nickname", ad.nickname)
def render_service_row(self, ctx, ad):
ctx.fillSlots("serverid", ad.serverid)
ctx.fillSlots("nickname", ad.nickname)
- ctx.fillSlots("advertised", " ".join(ad.advertised_addresses))
+ ctx.fillSlots("connection-hints",
+ "connection hints: " + " ".join(ad.connection_hints))
ctx.fillSlots("connected", "?")
when_s = time.strftime("%H:%M:%S %d-%b-%Y", time.localtime(ad.when))
ctx.fillSlots("announced", when_s)
ctx.fillSlots("connected", "?")
when_s = time.strftime("%H:%M:%S %d-%b-%Y", time.localtime(ad.when))
ctx.fillSlots("announced", when_s)