source: trunk/src/allmydata/introducer/

Last change on this file was 0e248cb, checked in by Jason R. Coombs <jaraco@…>, at 2020-12-18T15:59:53Z

Declare signing key as required in introducer client publish.

  • Property mode set to 100644
File size: 5.6 KB
2Ported to Python 3.
5from __future__ import unicode_literals
6from __future__ import absolute_import
7from __future__ import division
8from __future__ import print_function
10from future.utils import PY2, native_str
11if PY2:
12    # Omitted types (bytes etc.) so future variants don't confuse Foolscap.
13    from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, object, range, max, min  # noqa: F401
15from zope.interface import Interface
16from foolscap.api import StringConstraint, SetOf, DictOf, Any, \
17    RemoteInterface, Referenceable
18FURL = StringConstraint(1000)
20# v2 protocol over foolscap: Announcements are 3-tuples of (msg, sig_vs,
21# claimed_key_vs):
22# * msg (bytes): UTF-8(json(ann_dict))
23#   * ann_dict has IntroducerClient-provided keys like "version", "nickname",
24#     "app-versions", "my-version", "oldest-supported", and "service-name".
25#     Plus service-specific keys like "anonymous-storage-FURL" and
26#     "permutation-seed-base32" (both for service="storage").
27# * sig_vs (bytes): "v0-"+base32(signature(msg))
28# * claimed_key_vs (bytes): "v0-"+base32(pubkey)
30# (nickname, my_version, oldest_supported) refer to the client as a whole.
31# The my_version/oldest_supported strings can be parsed by an
32# allmydata.util.version.Version instance, and then compared. The first goal
33# is to make sure that nodes are not confused by speaking to an incompatible
34# peer. The second goal is to enable the development of
35# backwards-compatibility code.
37# Note that old v1 clients (which are gone now) did not sign messages, so v2
38# servers would deliver v2-format messages with sig_vs=claimed_key_vs=None.
39# These days we should always get a signature and a pubkey.
41Announcement_v2 = Any()
43class RIIntroducerSubscriberClient_v2(RemoteInterface):
44    __remote_name__ = native_str("")
46    def announce_v2(announcements=SetOf(Announcement_v2)):
47        """I accept announcements from the publisher."""
48        return None
50SubscriberInfo = DictOf(bytes, Any())
52class RIIntroducerPublisherAndSubscriberService_v2(RemoteInterface):
53    """To publish a service to the world, connect to me and give me your
54    announcement message. I will deliver a copy to all connected subscribers.
55    To hear about services, connect to me and subscribe to a specific
56    service_name."""
57    __remote_name__ = native_str("")
58    def get_version():
59        return DictOf(bytes, Any())
60    def publish_v2(announcement=Announcement_v2, canary=Referenceable):
61        return None
62    def subscribe_v2(subscriber=RIIntroducerSubscriberClient_v2,
63                     service_name=bytes, subscriber_info=SubscriberInfo):
64        """Give me a subscriber reference, and I will call its announce_v2()
65        method with any announcements that match the desired service name. I
66        will ignore duplicate subscriptions. The subscriber_info dictionary
67        tells me about the subscriber, and is used for diagnostic/status
68        displays."""
69        return None
71class IIntroducerClient(Interface):
72    """I provide service introduction facilities for a node. I help nodes
73    publish their services to the rest of the world, and I help them learn
74    about services available on other nodes."""
76    def publish(service_name, ann, signing_key):
77        """Publish the given announcement dictionary (which must be
78        JSON-serializable), plus some additional keys, to the world.
80        Each announcement is characterized by a (service_name, serverid)
81        pair. When the server sees two announcements with the same pair, the
82        later one will replace the earlier one. The serverid is derived from
83        the signing_key, if present, otherwise it is derived from the
84        'anonymous-storage-FURL' key.
86        signing_key (a SigningKey) will be used to sign the announcement."""
88    def subscribe_to(service_name, callback, *args, **kwargs):
89        """Call this if you will eventually want to use services with the
90        given SERVICE_NAME. This will prompt me to subscribe to announcements
91        of those services. Your callback will be invoked with at least two
92        arguments: a pubkey and an announcement dictionary, followed by any
93        additional callback args/kwargs you gave me. The pubkey will be None
94        unless the announcement was signed by the corresponding pubkey, in
95        which case it will be a printable string like 'v0-base32..'.
97        I will run your callback for both new announcements and for
98        announcements that have changed, but you must be prepared to tolerate
99        duplicates.
101        The announcement that I give you comes from some other client. It
102        will be a JSON-serializable dictionary which (by convention) is
103        expected to have at least the following keys:
105         version: 0
106         nickname: unicode
107         app-versions: {}
108         my-version: bytes
109         oldest-supported: bytes
111         service-name: bytes('storage')
112         anonymous-storage-FURL: bytes(furl)
114        In order to be JSON-serializable, all byte strings are assumed to be
115        ASCII-encoded, and the receiver can therefore decode them into Unicode
116        strings if they wish. Representation of these fields elsewhere in Tahoe
117        may differ, e.g. by being unicode strings.
119        Note that app-version will be an empty dictionary if either the
120        publishing client or the Introducer are running older code.
121        """
123    def connected_to_introducer():
124        """Returns a boolean, True if we are currently connected to the
125        introducer, False if not."""
Note: See TracBrowser for help on using the repository browser.