]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/introducer/interfaces.py
53d875ac942ff2bd9622b7d410bba6230cea357e
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / introducer / interfaces.py
1
2 from zope.interface import Interface
3 from foolscap.api import StringConstraint, TupleOf, SetOf, DictOf, Any, \
4     RemoteInterface, Referenceable
5 from old import RIIntroducerSubscriberClient_v1
6 FURL = StringConstraint(1000)
7
8 # old introducer protocol (v1):
9 #
10 # Announcements are (FURL, service_name, remoteinterface_name,
11 #                    nickname, my_version, oldest_supported)
12 #  the (FURL, service_name, remoteinterface_name) refer to the service being
13 #  announced. The (nickname, my_version, oldest_supported) refer to the
14 #  client as a whole. The my_version/oldest_supported strings can be parsed
15 #  by an allmydata.util.version.Version instance, and then compared. The
16 #  first goal is to make sure that nodes are not confused by speaking to an
17 #  incompatible peer. The second goal is to enable the development of
18 #  backwards-compatibility code.
19
20 Announcement_v1 = TupleOf(FURL, str, str,
21                           str, str, str)
22
23 # v2 protocol over foolscap: Announcements are 3-tuples of (bytes, str, str)
24 # or (bytes, none, none)
25 Announcement_v2 = Any()
26
27 class RIIntroducerSubscriberClient_v2(RemoteInterface):
28     __remote_name__ = "RIIntroducerSubscriberClient_v2.tahoe.allmydata.com"
29
30     def announce_v2(announcements=SetOf(Announcement_v2)):
31         """I accept announcements from the publisher."""
32         return None
33
34     def set_encoding_parameters(parameters=(int, int, int)):
35         """Advise the client of the recommended k-of-n encoding parameters
36         for this grid. 'parameters' is a tuple of (k, desired, n), where 'n'
37         is the total number of shares that will be created for any given
38         file, while 'k' is the number of shares that must be retrieved to
39         recover that file, and 'desired' is the minimum number of shares that
40         must be placed before the uploader will consider its job a success.
41         n/k is the expansion ratio, while k determines the robustness.
42
43         Introducers should specify 'n' according to the expected size of the
44         grid (there is no point to producing more shares than there are
45         peers), and k according to the desired reliability-vs-overhead goals.
46
47         Note that setting k=1 is equivalent to simple replication.
48         """
49         return None
50
51 SubscriberInfo = DictOf(str, Any())
52
53 class RIIntroducerPublisherAndSubscriberService_v2(RemoteInterface):
54     """To publish a service to the world, connect to me and give me your
55     announcement message. I will deliver a copy to all connected subscribers.
56     To hear about services, connect to me and subscribe to a specific
57     service_name."""
58     __remote_name__ = "RIIntroducerPublisherAndSubscriberService_v2.tahoe.allmydata.com"
59     def get_version():
60         return DictOf(str, Any())
61     def publish(announcement=Announcement_v1):
62         return None
63     def publish_v2(announcement=Announcement_v2, canary=Referenceable):
64         return None
65     def subscribe(subscriber=RIIntroducerSubscriberClient_v1, service_name=str):
66         return None
67     def subscribe_v2(subscriber=RIIntroducerSubscriberClient_v2,
68                      service_name=str, subscriber_info=SubscriberInfo):
69         """Give me a subscriber reference, and I will call its announce_v2()
70         method with any announcements that match the desired service name. I
71         will ignore duplicate subscriptions. The subscriber_info dictionary
72         tells me about the subscriber, and is used for diagnostic/status
73         displays."""
74         return None
75
76 class IIntroducerClient(Interface):
77     """I provide service introduction facilities for a node. I help nodes
78     publish their services to the rest of the world, and I help them learn
79     about services available on other nodes."""
80
81     def publish(service_name, ann, signing_key=None):
82         """Publish the given announcement dictionary (which must be
83         JSON-serializable), plus some additional keys, to the world.
84
85         Each announcement is characterized by a (service_name, serverid)
86         pair. When the server sees two announcements with the same pair, the
87         later one will replace the earlier one. The serverid is derived from
88         the signing_key, if present, otherwise it is derived from the
89         'anonymous-storage-FURL' key.
90
91         If signing_key= is set to an instance of SigningKey, it will be
92         used to sign the announcement."""
93
94     def subscribe_to(service_name, callback, *args, **kwargs):
95         """Call this if you will eventually want to use services with the
96         given SERVICE_NAME. This will prompt me to subscribe to announcements
97         of those services. Your callback will be invoked with at least two
98         arguments: a pubkey and an announcement dictionary, followed by any
99         additional callback args/kwargs you gave me. The pubkey will be None
100         unless the announcement was signed by the corresponding pubkey, in
101         which case it will be a printable string like 'v0-base32..'.
102
103         I will run your callback for both new announcements and for
104         announcements that have changed, but you must be prepared to tolerate
105         duplicates.
106
107         The announcement that I give you comes from some other client. It
108         will be a JSON-serializable dictionary which (by convention) is
109         expected to have at least the following keys:
110
111          version: 0
112          nickname: unicode
113          app-versions: {}
114          my-version: str
115          oldest-supported: str
116
117          service-name: str('storage')
118          anonymous-storage-FURL: str(furl)
119
120         Note that app-version will be an empty dictionary if either the
121         publishing client or the Introducer are running older code.
122         """
123
124     def connected_to_introducer():
125         """Returns a boolean, True if we are currently connected to the
126         introducer, False if not."""
127