From 842a3a132b7b38cdea710018ea6d1fb33a00f9cd Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@lothar.com>
Date: Tue, 24 Apr 2012 01:37:28 -0400
Subject: [PATCH] introweb announcements: show serverid, not tubid

'serverid' is the pubkey (for V2 clients), falling back to the tubid (for V1
clients). This also required cleaning up the way the index is created for the
old V1 introducer.
---
 src/allmydata/introducer/common.py    | 20 +++++++++-----------
 src/allmydata/introducer/old.py       |  5 ++++-
 src/allmydata/test/test_introducer.py | 16 +++++++++++++++-
 src/allmydata/web/introducer.xhtml    |  4 ++--
 src/allmydata/web/introweb.py         |  2 +-
 5 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/src/allmydata/introducer/common.py b/src/allmydata/introducer/common.py
index c7347971..9337d4bb 100644
--- a/src/allmydata/introducer/common.py
+++ b/src/allmydata/introducer/common.py
@@ -1,21 +1,20 @@
 
 import re, simplejson
-from foolscap.api import SturdyRef
 from allmydata.util import keyutil, base32, rrefutil
 
 def make_index(ann, key_s):
     """Return something that can be used as an index (e.g. a tuple of
     strings), such that two messages that refer to the same 'thing' will have
     the same index. This is a tuple of (service-name, signing-key, None) for
-    signed announcements, or (service-name, None, tubid) for unsigned
+    signed announcements, or (service-name, None, tubid_s) for unsigned
     announcements."""
 
     service_name = str(ann["service-name"])
     if key_s:
         return (service_name, key_s, None)
     else:
-        tubid = get_tubid_string_from_ann(ann)
-        return (service_name, None, tubid)
+        tubid_s = get_tubid_string_from_ann(ann)
+        return (service_name, None, tubid_s)
 
 def get_tubid_string_from_ann(ann):
     return get_tubid_string(str(ann.get("anonymous-storage-FURL")
@@ -132,12 +131,11 @@ class AnnouncementDescriptor:
      .service_name: which service they are announcing (string)
      .version: 'my-version' portion of announcement (string)
      .nickname: their self-provided nickname, or "" (unicode)
-
-    The following attributes will be empty ([] for lists, "" for strings)
-    unless the announcement included an 'anonymous-storage-FURL'.
-
+     .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)
-     .tubid: their tubid (string)
+                            if the announcement included a key for
+                            'anonymous-storage-FURL', else an empty list.
     """
 
     def __init__(self, when, index, canary, ann_d):
@@ -148,10 +146,10 @@ class AnnouncementDescriptor:
         self.service_name = ann_d["service-name"]
         self.version = ann_d.get("my-version", "")
         self.nickname = ann_d.get("nickname", u"")
+        (service_name, key_s, tubid_s) = index
+        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.tubid = SturdyRef(furl).tubID
         else:
             self.advertised_addresses = []
-            self.tubid = ""
diff --git a/src/allmydata/introducer/old.py b/src/allmydata/introducer/old.py
index 36a9af76..702969f0 100644
--- a/src/allmydata/introducer/old.py
+++ b/src/allmydata/introducer/old.py
@@ -393,7 +393,10 @@ class IntroducerService_v1(service.MultiService, Referenceable):
                      "service-name": service_name,
                      "anonymous-storage-FURL": furl,
                      }
-            ad = AnnouncementDescriptor(when, index, None, ann_d)
+            # the V2 introducer uses (service_name, key_s, tubid_s) as an
+            # index, so match that format for AnnouncementDescriptor
+            new_index = (index[0], None, idlib.nodeid_b2a(index[1]))
+            ad = AnnouncementDescriptor(when, new_index, None, ann_d)
             announcements.append(ad)
         return announcements
 
diff --git a/src/allmydata/test/test_introducer.py b/src/allmydata/test/test_introducer.py
index 1c61ad71..6624a15b 100644
--- a/src/allmydata/test/test_introducer.py
+++ b/src/allmydata/test/test_introducer.py
@@ -20,7 +20,7 @@ from allmydata.introducer import old
 # test compatibility with old introducer .tac files
 from allmydata.introducer import IntroducerNode
 from allmydata.web import introweb
-from allmydata.util import pollmixin, keyutil
+from allmydata.util import pollmixin, keyutil, idlib
 import allmydata.test.common_util as testutil
 
 class LoggingMultiService(service.MultiService):
@@ -391,6 +391,7 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
         received_announcements = {}
         subscribing_clients = []
         publishing_clients = []
+        printable_serverids = {}
         self.the_introducer = introducer
         privkeys = {}
         expected_announcements = [0 for c in range(NUM_CLIENTS)]
@@ -430,14 +431,21 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
             if i < NUM_STORAGE:
                 if i == 0:
                     c.publish(node_furl, "storage", "ri_name")
+                    printable_serverids[i] = get_tubid_string(node_furl)
                 elif i == 1:
                     # sign the announcement
                     privkey_s, pubkey_s = keyutil.make_keypair()
                     privkey, _ignored = keyutil.parse_privkey(privkey_s)
                     privkeys[c] = privkey
                     c.publish("storage", make_ann(node_furl), privkey)
+                    if server_version == V1:
+                        printable_serverids[i] = get_tubid_string(node_furl)
+                    else:
+                        assert pubkey_s.startswith("pub-")
+                        printable_serverids[i] = pubkey_s[len("pub-"):]
                 else:
                     c.publish("storage", make_ann(node_furl))
+                    printable_serverids[i] = get_tubid_string(node_furl)
                 publishing_clients.append(c)
             else:
                 # the last one does not publish anything
@@ -576,6 +584,12 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
             text = ir.renderSynchronously().decode("utf-8")
             self.failUnlessIn(NICKNAME % "0", text) # the v1 client
             self.failUnlessIn(NICKNAME % "1", text) # a v2 client
+            for i in range(NUM_STORAGE):
+                self.failUnlessIn(printable_serverids[i], text,
+                                  (i,printable_serverids[i],text))
+                # make sure there isn't a double-base32ed string too
+                self.failIfIn(idlib.nodeid_b2a(printable_serverids[i]), text,
+                              (i,printable_serverids[i],text))
             log.msg("_check1 done")
         d.addCallback(_check1)
 
diff --git a/src/allmydata/web/introducer.xhtml b/src/allmydata/web/introducer.xhtml
index 81873ee7..06709864 100644
--- a/src/allmydata/web/introducer.xhtml
+++ b/src/allmydata/web/introducer.xhtml
@@ -29,7 +29,7 @@
   <tr n:pattern="header">
     <th class="nickname-and-peerid">
       <div class="service-nickname">Nickname</div>
-      <div class="nodeid data-chars">PeerID</div></th>
+      <div class="nodeid data-chars">ServerID</div></th>
     <th>Advertised IPs</th>
     <th>Announced</th>
     <th>Version</th>
@@ -38,7 +38,7 @@
   <tr n:pattern="item" n:render="service_row">
     <td class="nickname-and-peerid">
       <div class="nickname"><n:slot name="nickname"/></div>
-      <div class="nodeid data-chars"><n:slot name="peerid"/></div></td>
+      <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-version"><n:slot name="version"/></td>
diff --git a/src/allmydata/web/introweb.py b/src/allmydata/web/introweb.py
index fb804951..0fc45633 100644
--- a/src/allmydata/web/introweb.py
+++ b/src/allmydata/web/introweb.py
@@ -100,7 +100,7 @@ class IntroducerRoot(rend.Page):
         return services
 
     def render_service_row(self, ctx, ad):
-        ctx.fillSlots("peerid", ad.tubid)
+        ctx.fillSlots("serverid", ad.serverid)
         ctx.fillSlots("nickname", ad.nickname)
         ctx.fillSlots("advertised", " ".join(ad.advertised_addresses))
         ctx.fillSlots("connected", "?")
-- 
2.45.2