Example #1
0
    def testNameLookup(self):
        t1 = HelperTarget()
        t2 = HelperTarget()
        self.names["foo"] = t1
        self.names2["bar"] = t2
        self.names2["baz"] = t2
        self.tubB.registerNameLookupHandler(self.lookup)
        self.tubB.registerNameLookupHandler(self.lookup2)
        # hack up a new furl pointing at the same tub but with a name that
        # hasn't been registered.
        s = SturdyRef(self.url_on_b)
        s.name = "foo"

        d = self.tubA.getReference(s)

        def _check(res):
            self.assertTrue(isinstance(res, RemoteReference))
            self.assertEqual(self.lookups, ["foo"])
            # the first lookup should short-circuit the process
            self.assertEqual(self.lookups2, [])
            self.lookups = []; self.lookups2 = []
            s.name = "bar"
            return self.tubA.getReference(s)
        d.addCallback(_check)

        def _check2(res):
            self.assertTrue(isinstance(res, RemoteReference))
            # if the first lookup fails, the second handler should be asked
            self.assertEqual(self.lookups, ["bar"])
            self.assertEqual(self.lookups2, ["bar"])
            self.lookups = []; self.lookups2 = []
            # make sure that loopbacks use this too
            return self.tubB.getReference(s)
        d.addCallback(_check2)

        def _check3(res):
            self.assertTrue(isinstance(res, RemoteReference))
            self.assertEqual(self.lookups, ["bar"])
            self.assertEqual(self.lookups2, ["bar"])
            self.lookups = []; self.lookups2 = []
            # and make sure we can de-register handlers
            self.tubB.unregisterNameLookupHandler(self.lookup)
            s.name = "baz"
            return self.tubA.getReference(s)
        d.addCallback(_check3)

        def _check4(res):
            self.assertTrue(isinstance(res, RemoteReference))
            self.assertEqual(self.lookups, [])
            self.assertEqual(self.lookups2, ["baz"])
            self.lookups = []; self.lookups2 = []
        d.addCallback(_check4)

        return d
Example #2
0
    def testNameLookup(self):
        t1 = HelperTarget()
        t2 = HelperTarget()
        self.names["foo"] = t1
        self.names2["bar"] = t2
        self.names2["baz"] = t2
        self.tubB.registerNameLookupHandler(self.lookup)
        self.tubB.registerNameLookupHandler(self.lookup2)
        # hack up a new furl pointing at the same tub but with a name that
        # hasn't been registered.
        s = SturdyRef(self.url_on_b)
        s.name = "foo"

        d = self.tubA.getReference(s)

        def _check(res):
            self.failUnless(isinstance(res, RemoteReference))
            self.failUnlessEqual(self.lookups, ["foo"])
            # the first lookup should short-circuit the process
            self.failUnlessEqual(self.lookups2, [])
            self.lookups = []; self.lookups2 = []
            s.name = "bar"
            return self.tubA.getReference(s)
        d.addCallback(_check)

        def _check2(res):
            self.failUnless(isinstance(res, RemoteReference))
            # if the first lookup fails, the second handler should be asked
            self.failUnlessEqual(self.lookups, ["bar"])
            self.failUnlessEqual(self.lookups2, ["bar"])
            self.lookups = []; self.lookups2 = []
            # make sure that loopbacks use this too
            return self.tubB.getReference(s)
        d.addCallback(_check2)

        def _check3(res):
            self.failUnless(isinstance(res, RemoteReference))
            self.failUnlessEqual(self.lookups, ["bar"])
            self.failUnlessEqual(self.lookups2, ["bar"])
            self.lookups = []; self.lookups2 = []
            # and make sure we can de-register handlers
            self.tubB.unregisterNameLookupHandler(self.lookup)
            s.name = "baz"
            return self.tubA.getReference(s)
        d.addCallback(_check3)

        def _check4(res):
            self.failUnless(isinstance(res, RemoteReference))
            self.failUnlessEqual(self.lookups, [])
            self.failUnlessEqual(self.lookups2, ["baz"])
            self.lookups = []; self.lookups2 = []
        d.addCallback(_check4)

        return d
Example #3
0
    def _publish(self, announcement):
        self._debug_counts["inbound_message"] += 1
        self.log("introducer: announcement published: %s" % (announcement,) )
        (furl, service_name, ri_name, nickname_utf8, ver, oldest) = announcement
        #print "PUB", service_name, nickname_utf8

        nodeid = b32decode(SturdyRef(furl).tubID.upper())
        index = (service_name, nodeid)

        if index in self._announcements:
            (old_announcement, timestamp) = self._announcements[index]
            if old_announcement == announcement:
                self.log("but we already knew it, ignoring", level=log.NOISY)
                self._debug_counts["inbound_duplicate"] += 1
                return
            else:
                self.log("old announcement being updated", level=log.NOISY)
                self._debug_counts["inbound_update"] += 1
        self._announcements[index] = (announcement, time.time())

        for s in self._subscribers.get(service_name, []):
            self._debug_counts["outbound_message"] += 1
            self._debug_counts["outbound_announcements"] += 1
            self._debug_outstanding += 1
            d = s.callRemote("announce", set([announcement]))
            d.addBoth(self._debug_retired)
            d.addErrback(rrefutil.trap_deadref)
            d.addErrback(log.err,
                         format="subscriber errored on announcement %(ann)s",
                         ann=announcement, facility="tahoe.introducer",
                         level=log.UNUSUAL, umid="jfGMXQ")
Example #4
0
    def test_wait_for_brokers(self):
        """
        The L{Deferred} returned by L{Tub.stopService} fires only after the
        L{Broker} connections belonging to the L{Tub} have disconnected.
        """
        tub = Tub()
        tub.startService()

        another_tub = Tub()
        another_tub.startService()

        brokers = list(tub.brokerClass(None) for i in range(3))
        for n, b in enumerate(brokers):
            b.makeConnection(StringTransport())
            ref = SturdyRef(encode_furl(another_tub.tubID, [], str(n)))
            tub.brokerAttached(ref, b, isClient=(n % 2) == 1)

        stopping = tub.stopService()
        d = flushEventualQueue()

        def event(ignored):
            self.assertNoResult(stopping)
            for b in brokers:
                b.connectionLost(failure.Failure(Exception("Connection lost")))
            return flushEventualQueue()

        d.addCallback(event)

        def connectionsLost(ignored):
            self.successResultOf(stopping)

        d.addCallback(connectionsLost)

        return d
Example #5
0
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
Example #6
0
    def _process_announcement(self, ann):
        self._debug_counts["inbound_announcement"] += 1
        (furl, service_name, ri_name, nickname_utf8, ver, oldest) = ann
        if service_name not in self._subscribed_service_names:
            self.log("announcement for a service we don't care about [%s]" %
                     (service_name, ),
                     level=log.UNUSUAL,
                     umid="dIpGNA")
            self._debug_counts["wrong_service"] += 1
            return
        self.log("announcement for [%s]: %s" % (service_name, ann),
                 umid="BoKEag")
        assert type(furl) is str
        assert type(service_name) is str
        assert type(ri_name) is str
        assert type(nickname_utf8) is str
        nickname = nickname_utf8.decode("utf-8")
        assert type(nickname) is unicode
        assert type(ver) is str
        assert type(oldest) is str

        nodeid = b32decode(SturdyRef(furl).tubID.upper())
        nodeid_s = idlib.shortnodeid_b2a(nodeid)

        ann_d = {
            "version": 0,
            "service-name": service_name,
            "FURL": furl,
            "nickname": nickname,
            "app-versions": {},  # need #466 and v2 introducer
            "my-version": ver,
            "oldest-supported": oldest,
        }

        index = (service_name, nodeid)
        if self._current_announcements.get(index, None) == ann_d:
            self.log("reannouncement for [%(service)s]:%(nodeid)s, ignoring",
                     service=service_name,
                     nodeid=nodeid_s,
                     level=log.UNUSUAL,
                     umid="B1MIdA")
            self._debug_counts["duplicate_announcement"] += 1
            return
        if index in self._current_announcements:
            self._debug_counts["update"] += 1
        else:
            self._debug_counts["new_announcement"] += 1

        self._current_announcements[index] = ann_d
        # note: we never forget an index, but we might update its value

        for (service_name2, cb, args, kwargs) in self._local_subscribers:
            if service_name2 == service_name:
                eventually(cb, nodeid, ann_d, *args, **kwargs)
Example #7
0
 def _check(furl):
     sr = SturdyRef(furl)
     portnum = l.getPortnum()
     if sr.encrypted:
         for lh in sr.locationHints:
             self.failUnlessEqual(lh[2], portnum, lh)
         self.failUnless(("ipv4", "127.0.0.1",
                          portnum) in sr.locationHints)
     else:
         # TODO: unauthenticated tubs need review, I think they
         # deserve to have tubids and multiple connection hints
         pass
Example #8
0
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
Example #9
0
    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
Example #10
0
    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"
Example #11
0
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)

    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", "%s %s" % (nodeid, 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
Example #12
0
 def _check(furl):
     sr = SturdyRef(furl)
     portnum = l.getPortnum()
     for lh in sr.locationHints:
         self.failUnlessEqual(lh[2], portnum, lh)
     self.failUnless(("tcp", "127.0.0.1", portnum) in sr.locationHints)