more v1 removal cleanup

Historical note: V2 introducers have been around for three years
now (released in 1.10.0), so it's time to drop v1. This branch removes a
lot of fallback code, and tests which exercised it. refs ticket:2784

This patch removes some now-unused code: v1-related support functions on
the client, "stub-client" handlers, and v1-tolerant remote methods on
the server. The unit tests have been cleaned up a bit too, now that
there are fewer cases to exercise.
This commit is contained in:
Brian Warner 2016-06-29 22:58:14 -07:00
parent 7feee8a25e
commit c64ff7b310
6 changed files with 79 additions and 323 deletions

View File

@ -2,13 +2,12 @@
import time, yaml
from zope.interface import implements
from twisted.application import service
from twisted.internet import defer
from foolscap.api import Referenceable, eventually, RemoteInterface
from foolscap.api import Referenceable, eventually
from allmydata.interfaces import InsufficientVersionError
from allmydata.introducer.interfaces import IIntroducerClient, \
RIIntroducerSubscriberClient_v2
from allmydata.introducer.common import sign_to_foolscap, unsign_from_foolscap,\
make_index, get_tubid_string_from_ann, get_tubid_string
make_index, get_tubid_string_from_ann
from allmydata.util import log
from allmydata.util.rrefutil import add_version_to_remote_reference
from allmydata.util.keyutil import BadSignatureError
@ -16,7 +15,6 @@ from allmydata.util.keyutil import BadSignatureError
class InvalidCacheError(Exception):
pass
V1 = "http://allmydata.org/tahoe/protocols/introducer/v1"
V2 = "http://allmydata.org/tahoe/protocols/introducer/v2"
class IntroducerClient(service.Service, Referenceable):
@ -128,7 +126,7 @@ class IntroducerClient(service.Service, Referenceable):
def _got_introducer(self, publisher):
self.log("connected to introducer, getting versions")
default = { "http://allmydata.org/tahoe/protocols/introducer/v2":
default = { "http://allmydata.org/tahoe/protocols/introducer/v1":
{ },
"application-version": "unknown: no get_version()",
}
@ -178,14 +176,11 @@ class IntroducerClient(service.Service, Referenceable):
if service_name in self._subscriptions:
continue
self._subscriptions.add(service_name)
if V2 in self._publisher.version:
self._debug_outstanding += 1
d = self._publisher.callRemote("subscribe_v2",
self, service_name,
self._my_subscriber_info)
d.addBoth(self._debug_retired)
else:
d = defer.fail(InsufficientVersionError("V2", self._publisher.version))
self._debug_outstanding += 1
d = self._publisher.callRemote("subscribe_v2",
self, service_name,
self._my_subscriber_info)
d.addBoth(self._debug_retired)
d.addErrback(log.err, facility="tahoe.introducer.client",
level=log.WEIRD, umid="2uMScQ")
@ -225,13 +220,9 @@ class IntroducerClient(service.Service, Referenceable):
# this re-publishes everything. The Introducer ignores duplicates
for ann_t in self._published_announcements.values():
self._debug_counts["outbound_message"] += 1
if V2 in self._publisher.version:
self._debug_outstanding += 1
d = self._publisher.callRemote("publish_v2", ann_t,
self._canary)
d.addBoth(self._debug_retired)
else:
d = defer.fail(InsufficientVersionError("V2", self._publisher.version))
self._debug_outstanding += 1
d = self._publisher.callRemote("publish_v2", ann_t, self._canary)
d.addBoth(self._debug_retired)
d.addErrback(log.err, ann_t=ann_t,
facility="tahoe.introducer.client",
level=log.WEIRD, umid="xs9pVQ")
@ -241,7 +232,6 @@ class IntroducerClient(service.Service, Referenceable):
return self.got_announcements(announcements, lp)
def got_announcements(self, announcements, lp=None):
# this is the common entry point for announcements
self._debug_counts["inbound_message"] += 1
for ann_t in announcements:
try:

View File

@ -25,40 +25,6 @@ def get_tubid_string(furl):
assert m
return m.group(1).lower()
def convert_announcement_v1_to_v2(ann_t):
(furl, service_name, ri_name, nickname, ver, oldest) = ann_t
assert type(furl) is str
assert type(service_name) is str
# ignore ri_name
assert type(nickname) is str
assert type(ver) is str
assert type(oldest) is str
ann = {"version": 0,
"nickname": nickname.decode("utf-8", "replace"),
"app-versions": {},
"my-version": ver,
"oldest-supported": oldest,
"service-name": service_name,
"anonymous-storage-FURL": furl,
"permutation-seed-base32": get_tubid_string(furl),
}
msg = simplejson.dumps(ann).encode("utf-8")
return (msg, None, None)
def convert_announcement_v2_to_v1(ann_v2):
(msg, sig, pubkey) = ann_v2
ann = simplejson.loads(msg)
assert ann["version"] == 0
ann_t = (str(ann["anonymous-storage-FURL"]),
str(ann["service-name"]),
"remoteinterface-name is unused",
ann["nickname"].encode("utf-8"),
str(ann["my-version"]),
str(ann["oldest-supported"]),
)
return ann_t
def sign_to_foolscap(ann, sk):
# return (bytes, None, None) or (bytes, sig-str, pubkey-str). A future

View File

@ -1,11 +1,30 @@
from zope.interface import Interface
from foolscap.api import StringConstraint, TupleOf, SetOf, DictOf, Any, \
from foolscap.api import StringConstraint, SetOf, DictOf, Any, \
RemoteInterface, Referenceable
FURL = StringConstraint(1000)
# v2 protocol over foolscap: Announcements are 3-tuples of (bytes, str, str)
# or (bytes, none, none)
# v2 protocol over foolscap: Announcements are 3-tuples of (msg, sig_vs,
# claimed_key_vs):
# * msg (bytes): UTF-8(json(ann_dict))
# * ann_dict has IntroducerClient-provided keys like "version", "nickname",
# "app-versions", "my-version", "oldest-supported", and "service-name".
# Plus service-specific keys like "anonymous-storage-FURL" and
# "permutation-seed-base32" (both for service="storage").
# * sig_vs (str): "v0-"+base32(signature(msg))
# * claimed_key_vs (str): "v0-"+base32(pubkey)
# (nickname, my_version, oldest_supported) refer to the client as a whole.
# The my_version/oldest_supported strings can be parsed by an
# allmydata.util.version.Version instance, and then compared. The first goal
# is to make sure that nodes are not confused by speaking to an incompatible
# peer. The second goal is to enable the development of
# backwards-compatibility code.
# Note that old v1 clients (which are gone now) did not sign messages, so v2
# servers would deliver v2-format messages with sig_vs=claimed_key_vs=None.
# These days we should always get a signature and a pubkey.
Announcement_v2 = Any()
class RIIntroducerSubscriberClient_v2(RemoteInterface):

View File

@ -9,9 +9,8 @@ from allmydata.util import log, rrefutil
from allmydata.util.fileutil import abspath_expanduser_unicode
from allmydata.introducer.interfaces import \
RIIntroducerPublisherAndSubscriberService_v2
from allmydata.introducer.common import convert_announcement_v1_to_v2, \
convert_announcement_v2_to_v1, unsign_from_foolscap, make_index, \
get_tubid_string_from_ann, SubscriberDescriptor, AnnouncementDescriptor
from allmydata.introducer.common import unsign_from_foolscap, make_index, \
SubscriberDescriptor, AnnouncementDescriptor
class FurlFileConflictError(Exception):
pass
@ -63,42 +62,12 @@ class IntroducerNode(node.Node):
ws = IntroducerWebishServer(self, webport, nodeurl_path, staticdir)
self.add_service(ws)
class WrapV1SubscriberInV2Interface: # for_v1
"""I wrap a RemoteReference that points at an old v1 subscriber, enabling
it to be treated like a v2 subscriber.
"""
def __init__(self, original):
self.original = original # also used for tests
def __eq__(self, them):
return self.original == them
def __ne__(self, them):
return self.original != them
def __hash__(self):
return hash(self.original)
def getRemoteTubID(self):
return self.original.getRemoteTubID()
def getSturdyRef(self):
return self.original.getSturdyRef()
def getPeer(self):
return self.original.getPeer()
def getLocationHints(self):
return self.original.getLocationHints()
def callRemote(self, methname, *args, **kwargs):
m = getattr(self, "wrap_" + methname)
return m(*args, **kwargs)
def wrap_announce_v2(self, announcements):
anns_v1 = [convert_announcement_v2_to_v1(ann) for ann in announcements]
return self.original.callRemote("announce", set(anns_v1))
def notifyOnDisconnect(self, *args, **kwargs):
return self.original.notifyOnDisconnect(*args, **kwargs)
class IntroducerService(service.MultiService, Referenceable):
implements(RIIntroducerPublisherAndSubscriberService_v2)
name = "introducer"
# v1 is the original protocol, supported since 1.0 (but only advertised
# starting in 1.3). v2 is the new signed protocol, supported after 1.9
VERSION = { "http://allmydata.org/tahoe/protocols/introducer/v1": { },
# v1 is the original protocol, added in 1.0 (but only advertised starting
# in 1.3), removed in 1.12. v2 is the new signed protocol, added in 1.10
VERSION = { #"http://allmydata.org/tahoe/protocols/introducer/v1": { },
"http://allmydata.org/tahoe/protocols/introducer/v2": { },
"application-version": str(allmydata.__full_version__),
}
@ -118,16 +87,11 @@ class IntroducerService(service.MultiService, Referenceable):
# self._subscribers is a dict mapping servicename to subscriptions
# 'subscriptions' is a dict mapping rref to a subscription
# 'subscription' is a tuple of (subscriber_info, timestamp)
# 'subscriber_info' is a dict, provided directly for v2 clients, or
# synthesized for v1 clients. The expected keys are:
# version, nickname, app-versions, my-version, oldest-supported
# 'subscriber_info' is a dict, provided directly by v2 clients. The
# expected keys are: version, nickname, app-versions, my-version,
# oldest-supported
self._subscribers = {}
# self._stub_client_announcements contains the information provided
# by v1 clients. We stash this so we can match it up with their
# subscriptions.
self._stub_client_announcements = {} # maps tubid to sinfo # for_v1
self._debug_counts = {"inbound_message": 0,
"inbound_duplicate": 0,
"inbound_no_seqnum": 0,
@ -136,7 +100,7 @@ class IntroducerService(service.MultiService, Referenceable):
"outbound_message": 0,
"outbound_announcements": 0,
"inbound_subscribe": 0}
self._debug_outstanding = 0 # also covers WrapV1SubscriberInV2Interface
self._debug_outstanding = 0
def _debug_retired(self, res):
self._debug_outstanding -= 1
@ -147,13 +111,10 @@ class IntroducerService(service.MultiService, Referenceable):
kwargs["facility"] = "tahoe.introducer.server"
return log.msg(*args, **kwargs)
def get_announcements(self, include_stub_clients=True):
def get_announcements(self):
"""Return a list of AnnouncementDescriptor for all announcements"""
announcements = []
for (index, (_, canary, ann, when)) in self._announcements.items():
if ann["service-name"] == "stub_client":
if not include_stub_clients:
continue
ad = AnnouncementDescriptor(when, index, canary, ann)
announcements.append(ad)
return announcements
@ -170,9 +131,6 @@ class IntroducerService(service.MultiService, Referenceable):
remote_address = rrefutil.stringify_remote_address(rref)
# these three assume subscriber_info["version"]==0, but
# should tolerate other versions
if not subscriber_info:
# V1 clients that haven't yet sent their stub_info data
subscriber_info = {}
nickname = subscriber_info.get("nickname", u"?")
version = subscriber_info.get("my-version", u"?")
app_versions = subscriber_info.get("app-versions", {})
@ -186,12 +144,6 @@ class IntroducerService(service.MultiService, Referenceable):
def remote_get_version(self):
return self.VERSION
def remote_publish(self, ann_t): # for_v1
lp = self.log("introducer: old (v1) announcement published: %s"
% (ann_t,), umid="6zGOIw")
ann_v2 = convert_announcement_v1_to_v2(ann_t)
return self.publish(ann_v2, None, lp)
def remote_publish_v2(self, ann_t, canary):
lp = self.log("introducer: announcement (v2) published", umid="L2QXkQ")
return self.publish(ann_t, canary, lp)
@ -213,9 +165,6 @@ class IntroducerService(service.MultiService, Referenceable):
index = make_index(ann, key)
service_name = str(ann["service-name"])
if service_name == "stub_client": # for_v1
self._attach_stub_client(ann, lp)
return
old = self._announcements.get(index)
if old:
@ -263,56 +212,6 @@ class IntroducerService(service.MultiService, Referenceable):
ann=ann_t, facility="tahoe.introducer",
level=log.UNUSUAL, umid="jfGMXQ")
def _attach_stub_client(self, ann, lp):
# There might be a v1 subscriber for whom this is a stub_client.
# We might have received the subscription before the stub_client
# announcement, in which case we now need to fix up the record in
# self._subscriptions .
# record it for later, in case the stub_client arrived before the
# subscription
subscriber_info = self._get_subscriber_info_from_ann(ann)
ann_tubid = get_tubid_string_from_ann(ann)
self._stub_client_announcements[ann_tubid] = subscriber_info
lp2 = self.log("stub_client announcement, "
"looking for matching subscriber",
parent=lp, level=log.NOISY, umid="BTywDg")
for sn in self._subscribers:
s = self._subscribers[sn]
for (subscriber, info) in s.items():
# we correlate these by looking for a subscriber whose tubid
# matches this announcement
sub_tubid = subscriber.getRemoteTubID()
if sub_tubid == ann_tubid:
self.log(format="found a match, nodeid=%(nodeid)s",
nodeid=sub_tubid,
level=log.NOISY, parent=lp2, umid="xsWs1A")
# found a match. Does it need info?
if not info[0]:
self.log(format="replacing info",
level=log.NOISY, parent=lp2, umid="m5kxwA")
# yup
s[subscriber] = (subscriber_info, info[1])
# and we don't remember or announce stub_clients beyond what we
# need to get the subscriber_info set up
def _get_subscriber_info_from_ann(self, ann): # for_v1
sinfo = { "version": ann["version"],
"nickname": ann["nickname"],
"app-versions": ann["app-versions"],
"my-version": ann["my-version"],
"oldest-supported": ann["oldest-supported"],
}
return sinfo
def remote_subscribe(self, subscriber, service_name): # for_v1
self.log("introducer: old (v1) subscription[%s] request at %s"
% (service_name, subscriber), umid="hJlGUg")
return self.add_subscriber(WrapV1SubscriberInV2Interface(subscriber),
service_name, None)
def remote_subscribe_v2(self, subscriber, service_name, subscriber_info):
self.log("introducer: subscription[%s] request at %s"
% (service_name, subscriber), umid="U3uzLg")
@ -328,14 +227,7 @@ class IntroducerService(service.MultiService, Referenceable):
level=log.UNUSUAL, umid="Sy9EfA")
return
if not subscriber_info: # for_v1
# v1 clients don't provide subscriber_info, but they should
# publish a 'stub client' record which contains the same
# information. If we've already received this, it will be in
# self._stub_client_announcements
tubid = subscriber.getRemoteTubID()
if tubid in self._stub_client_announcements:
subscriber_info = self._stub_client_announcements[tubid]
assert subscriber_info
subscribers[subscriber] = (subscriber_info, time.time())
def _remove():

View File

@ -87,7 +87,6 @@ class ServiceMixin:
return d
class Introducer(ServiceMixin, unittest.TestCase, pollmixin.PollMixin):
def test_create(self):
ic = IntroducerClient(None, "introducer.furl", u"my_nickname",
"my_version", "oldest_version", {}, fakeseq,
@ -98,57 +97,6 @@ class Introducer(ServiceMixin, unittest.TestCase, pollmixin.PollMixin):
i = IntroducerService()
i.setServiceParent(self.parent)
def test_duplicate_publish(self):
i = IntroducerService()
self.failUnlessEqual(len(i.get_announcements()), 0)
self.failUnlessEqual(len(i.get_subscribers()), 0)
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@192.168.69.247:36106,127.0.0.1:36106/gydnpigj2ja2qr2srq4ikjwnl7xfgbra"
furl2 = "pb://ttwwooyunnyhzs7r6vdonnm2hpi52w6y@192.168.69.247:36111,127.0.0.1:36106/ttwwoogj2ja2qr2srq4ikjwnl7xfgbra"
ann1 = (furl1, "storage", "RIStorage", "nick1", "ver23", "ver0")
ann1b = (furl1, "storage", "RIStorage", "nick1", "ver24", "ver0")
ann2 = (furl2, "storage", "RIStorage", "nick2", "ver30", "ver0")
i.remote_publish(ann1)
self.failUnlessEqual(len(i.get_announcements()), 1)
self.failUnlessEqual(len(i.get_subscribers()), 0)
i.remote_publish(ann2)
self.failUnlessEqual(len(i.get_announcements()), 2)
self.failUnlessEqual(len(i.get_subscribers()), 0)
i.remote_publish(ann1b)
self.failUnlessEqual(len(i.get_announcements()), 2)
self.failUnlessEqual(len(i.get_subscribers()), 0)
def test_id_collision(self):
# test replacement case where tubid equals a keyid (one should
# not replace the other)
i = IntroducerService()
ic = IntroducerClient(None,
"introducer.furl", u"my_nickname",
"my_version", "oldest_version", {}, fakeseq,
FilePath(self.mktemp()))
sk_s, vk_s = keyutil.make_keypair()
sk, _ignored = keyutil.parse_privkey(sk_s)
keyid = keyutil.remove_prefix(vk_s, "pub-v0-")
furl1 = "pb://onug64tu@127.0.0.1:123/short" # base32("short")
ann_t = make_ann_t(ic, furl1, sk, 1)
i.remote_publish_v2(ann_t, Referenceable())
announcements = i.get_announcements()
self.failUnlessEqual(len(announcements), 1)
key1 = ("storage", "v0-"+keyid, None)
self.failUnlessEqual(announcements[0].index, key1)
ann1_out = announcements[0].announcement
self.failUnlessEqual(ann1_out["anonymous-storage-FURL"], furl1)
furl2 = "pb://%s@127.0.0.1:36106/swissnum" % keyid
ann2 = (furl2, "storage", "RIStorage", "nick1", "ver23", "ver0")
i.remote_publish(ann2)
announcements = i.get_announcements()
self.failUnlessEqual(len(announcements), 2)
key2 = ("storage", None, keyid)
wanted = [ad for ad in announcements if ad.index == key2]
self.failUnlessEqual(len(wanted), 1)
ann2_out = wanted[0].announcement
self.failUnlessEqual(ann2_out["anonymous-storage-FURL"], furl2)
def fakeseq():
return 1, "nonce"
@ -424,7 +372,6 @@ class Queue(SystemTestMixin, unittest.TestCase):
return d
V1 = "v1"; V2 = "v2"
class SystemTest(SystemTestMixin, unittest.TestCase):
def do_system_test(self):
@ -470,21 +417,16 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
{"component": "component-v1"}, fakeseq,
FilePath(self.mktemp()))
received_announcements[c] = {}
def got(key_s_or_tubid, ann, announcements, i):
if i == 0:
index = get_tubid_string_from_ann(ann)
else:
index = key_s_or_tubid or get_tubid_string_from_ann(ann)
def got(key_s_or_tubid, ann, announcements):
index = key_s_or_tubid or get_tubid_string_from_ann(ann)
announcements[index] = ann
c.subscribe_to("storage", got, received_announcements[c], i)
c.subscribe_to("storage", got, received_announcements[c])
subscribing_clients.append(c)
expected_announcements[i] += 1 # all expect a 'storage' announcement
node_furl = tub.registerReference(Referenceable())
if i < NUM_STORAGE:
if i == 0:
pass
elif i == 1:
if i == 1:
# sign the announcement
privkey_s, pubkey_s = keyutil.make_keypair()
privkey, _ignored = keyutil.parse_privkey(privkey_s)
@ -500,14 +442,6 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
# the last one does not publish anything
pass
if i == 0:
# users of the V1 client were required to publish a
# 'stub_client' record (somewhat after they published the
# 'storage' record), so the introducer could see their
# version. Match that behavior.
#c.publish(node_furl, "stub_client", "stub_ri_name")
pass
if i == 2:
# also publish something that nobody cares about
boring_furl = tub.registerReference(Referenceable())
@ -560,8 +494,8 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
log.msg("doing _check1")
dc = self.the_introducer._debug_counts
# each storage server publishes a record. There is also one
# "stub_client" and one "boring"
self.failUnlessEqual(dc["inbound_message"], NUM_STORAGE)
# "boring"
self.failUnlessEqual(dc["inbound_message"], NUM_STORAGE+1)
self.failUnlessEqual(dc["inbound_duplicate"], 0)
self.failUnlessEqual(dc["inbound_update"], 0)
self.failUnlessEqual(dc["inbound_subscribe"], NUM_CLIENTS)
@ -570,28 +504,42 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
self.failUnless(dc["outbound_message"] > 0)
# each client subscribes to "storage", and each server publishes
self.failUnlessEqual(dc["outbound_announcements"],
NUM_STORAGE*NUM_CLIENTS-6) # XXX correct?
NUM_STORAGE*NUM_CLIENTS)
for c in subscribing_clients:
cdc = c._debug_counts
self.failUnless(cdc["inbound_message"])
self.failUnlessEqual(cdc["inbound_announcement"],
NUM_STORAGE-1)
NUM_STORAGE)
self.failUnlessEqual(cdc["wrong_service"], 0)
self.failUnlessEqual(cdc["duplicate_announcement"], 0)
self.failUnlessEqual(cdc["update"], 0)
self.failUnlessEqual(cdc["new_announcement"],
NUM_STORAGE-1)
NUM_STORAGE)
anns = received_announcements[c]
self.failUnlessEqual(len(anns), NUM_STORAGE-1)
self.failUnlessEqual(len(anns), NUM_STORAGE)
nodeid0 = tubs[clients[0]].tubID
ann = anns[nodeid0]
nick = ann["nickname"]
self.failUnlessEqual(type(nick), unicode)
self.failUnlessEqual(nick, NICKNAME % "0")
for c in publishing_clients:
cdc = c._debug_counts
expected = 1
if c in [clients[2], # boring
]:
expected = 2
self.failUnlessEqual(cdc["outbound_message"], expected)
# now check the web status, make sure it renders without error
ir = introweb.IntroducerRoot(self.parent)
self.parent.nodeid = "NODEID"
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(1,NUM_STORAGE):
self.failUnlessIn(NICKNAME % "0", text) # a v2 client
self.failUnlessIn(NICKNAME % "1", text) # another 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))
@ -646,16 +594,16 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
# subscriber
dc = self.the_introducer._debug_counts
self.failUnlessEqual(dc["outbound_announcements"],
NUM_STORAGE*NUM_CLIENTS-6)
NUM_STORAGE*NUM_CLIENTS)
self.failUnless(dc["outbound_message"] > 0)
self.failUnlessEqual(dc["inbound_subscribe"], NUM_CLIENTS)
for c in subscribing_clients:
cdc = c._debug_counts
self.failUnlessEqual(cdc["inbound_message"], 1)
self.failUnlessEqual(cdc["inbound_announcement"], NUM_STORAGE-1)
self.failUnlessEqual(cdc["inbound_announcement"], NUM_STORAGE)
self.failUnlessEqual(cdc["new_announcement"], 0)
self.failUnlessEqual(cdc["wrong_service"], 0)
self.failUnlessEqual(cdc["duplicate_announcement"], NUM_STORAGE-1)
self.failUnlessEqual(cdc["duplicate_announcement"], NUM_STORAGE)
d.addCallback(_check2)
# Then force an introducer restart, by shutting down the Tub,
@ -693,16 +641,16 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
log.msg("doing _check3")
dc = self.the_introducer._debug_counts
self.failUnlessEqual(dc["outbound_announcements"],
NUM_STORAGE*NUM_CLIENTS-6)
NUM_STORAGE*NUM_CLIENTS)
self.failUnless(dc["outbound_message"] > 0)
self.failUnlessEqual(dc["inbound_subscribe"], NUM_CLIENTS)
for c in subscribing_clients:
cdc = c._debug_counts
self.failUnless(cdc["inbound_message"] > 0)
self.failUnlessEqual(cdc["inbound_announcement"], NUM_STORAGE-1)
self.failUnlessEqual(cdc["inbound_announcement"], NUM_STORAGE)
self.failUnlessEqual(cdc["new_announcement"], 0)
self.failUnlessEqual(cdc["wrong_service"], 0)
self.failUnlessEqual(cdc["duplicate_announcement"], NUM_STORAGE-1)
self.failUnlessEqual(cdc["duplicate_announcement"], NUM_STORAGE)
d.addCallback(_check3)
return d
@ -745,46 +693,6 @@ class ClientInfo(unittest.TestCase):
self.failUnlessEqual(s0.nickname, NICKNAME % u"v2")
self.failUnlessEqual(s0.version, "my_version")
def test_client_v1(self):
introducer = IntroducerService()
subscriber = FakeRemoteReference()
introducer.remote_subscribe(subscriber, "storage")
# the v1 subscribe interface had no subscriber_info: that was usually
# sent in a separate stub_client pseudo-announcement
subs = introducer.get_subscribers()
self.failUnlessEqual(len(subs), 1)
s0 = subs[0]
self.failUnlessEqual(s0.nickname, u"?") # not known yet
self.failUnlessEqual(s0.service_name, "storage")
# now submit the stub_client announcement
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
ann = (furl1, "stub_client", "RIStubClient",
(NICKNAME % u"v1").encode("utf-8"), "my_version", "oldest")
introducer.remote_publish(ann)
# the server should correlate the two
subs = introducer.get_subscribers()
self.failUnlessEqual(len(subs), 1)
s0 = subs[0]
self.failUnlessEqual(s0.service_name, "storage")
# v1 announcements do not contain app-versions
self.failUnlessEqual(s0.app_versions, {})
self.failUnlessEqual(s0.nickname, NICKNAME % u"v1")
self.failUnlessEqual(s0.version, "my_version")
# a subscription that arrives after the stub_client announcement
# should be correlated too
subscriber2 = FakeRemoteReference()
introducer.remote_subscribe(subscriber2, "thing2")
subs = introducer.get_subscribers()
self.failUnlessEqual(len(subs), 2)
s0 = [s for s in subs if s.service_name == "thing2"][0]
# v1 announcements do not contain app-versions
self.failUnlessEqual(s0.app_versions, {})
self.failUnlessEqual(s0.nickname, NICKNAME % u"v1")
self.failUnlessEqual(s0.version, "my_version")
class Announcements(unittest.TestCase):
def test_client_v2_unsigned(self):
introducer = IntroducerService()
@ -832,25 +740,6 @@ class Announcements(unittest.TestCase):
self.failUnlessEqual(a[0].version, "my_version")
self.failUnlessEqual(a[0].announcement["anonymous-storage-FURL"], furl1)
def test_client_v1(self):
introducer = IntroducerService()
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
tubid = "62ubehyunnyhzs7r6vdonnm2hpi52w6y"
ann = (furl1, "storage", "RIStorage",
u"nick-v1".encode("utf-8"), "my_version", "oldest")
introducer.remote_publish(ann)
a = introducer.get_announcements()
self.failUnlessEqual(len(a), 1)
self.failUnlessEqual(a[0].index, ("storage", None, tubid))
self.failUnlessEqual(a[0].canary, None)
self.failUnlessEqual(a[0].announcement["app-versions"], {})
self.failUnlessEqual(a[0].nickname, u"nick-v1".encode("utf-8"))
self.failUnlessEqual(a[0].service_name, "storage")
self.failUnlessEqual(a[0].version, "my_version")
self.failUnlessEqual(a[0].announcement["anonymous-storage-FURL"], furl1)
def _load_cache(self, cache_filepath):
def construct_unicode(loader, node):
return node.value
@ -1013,7 +902,7 @@ class TooNewServer(IntroducerService):
}
class NonV1Server(SystemTestMixin, unittest.TestCase):
# if the 1.3.0 client connects to a server that doesn't provide the 'v1'
# if the client connects to a server that doesn't provide the 'v2'
# protocol, it is supposed to provide a useful error instead of a weird
# exception.

View File

@ -82,7 +82,7 @@ class IntroducerRoot(rend.Page):
for name in sorted(counts.keys()) ] )
def data_services(self, ctx, data):
services = self.introducer_service.get_announcements(False)
services = self.introducer_service.get_announcements()
services.sort(key=lambda ad: (ad.service_name, ad.nickname))
return services