-fix
[oweals/gnunet.git] / src / include / gnunet_multicast_service.h
1 /*
2      This file is part of GNUnet.
3      (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file include/gnunet_multicast_service.h
23  * @brief multicast service; establish tunnels to distant peers
24  * @author Christian Grothoff
25  */
26
27 #ifndef GNUNET_MULTICAST_SERVICE_H
28 #define GNUNET_MULTICAST_SERVICE_H
29
30 #ifdef __cplusplus
31 extern "C"
32 {
33 #if 0                           /* keep Emacsens' auto-indent happy */
34 }
35 #endif
36 #endif
37
38 #include "gnunet_util_lib.h"
39 #include "gnunet_transport_service.h"
40
41 /**
42  * Version number of GNUnet-multicast API.
43  */
44 #define GNUNET_MULTICAST_VERSION 0x00000000
45
46
47 /**
48  * Opaque handle for a multicast group member.
49  */
50 struct GNUNET_MULTICAST_Member;
51
52 /**
53  * Handle for the origin of a multicast group.
54  */
55 struct GNUNET_MULTICAST_Origin;
56
57 /**
58  * Group membership policies.
59  */
60 enum GNUNET_MULTICAST_JoinPolicy
61 {
62   /**
63    * Anyone can join the group, without announcing his presence; all
64    * messages are always public and can be distributed freely.  Joins
65    * may be announced, but this is not required.
66    */
67   GNUNET_MULTICAST_JP_ANONYMOUS = 0,
68
69   /**
70    * Origin must approve membership to the group, messages must only be
71    * distributed to current group members.  This includes the group
72    * state as well as transient messages.
73    */
74   GNUNET_MULTICAST_JP_PRIVATE = 1
75
76 #if IDEAS_FOR_FUTURE
77   /**
78    * Anyone can freely join the group (no approval required); however,
79    * transient messages must only be distributed to current group
80    * members, so the origin must still acknowledge that the member
81    * joined before transient messages are delivered.  As approval is
82    * guaranteed, the presistent group state can de synchronized freely
83    * immediately, prior to origin confirmation
84    */
85   GNUNET_MULTICAST_JP_OPEN = 2
86 #endif
87
88 };
89
90
91 /**
92  * Opaque handle to a replay request from the multicast service.
93  */
94 struct GNUNET_MULTICAST_ReplayHandle;
95
96
97 /**
98  * Functions with this signature are called whenever the multicast
99  * service needs a message to be replayed.  Implementations of this
100  * function MUST call 'GNUNET_MULTICAST_replay' ONCE (with a message
101  * or an error); however, if the origin is destroyed or the group is
102  * left, the replay handle must no longer be used.
103  *
104  * @param cls closure (set from GNUNET_MULTICAST_origin_start/join)
105  * @param message_id which message should be replayed
106  * @param rh handle to pass to message transmit function
107  */
108 typedef void (*GNUNET_MULTICAST_ReplayCallback) (void *cls,
109                                                  uint64_t message_id,
110                                                  struct GNUNET_MULTICAST_ReplayHandle *rh);
111
112
113 /**
114  * Possible error codes during replay.
115  */
116 enum GNUNET_MULTICAST_ReplayErrorCode
117 {
118   
119   /**
120    * Everything is fine.
121    */ 
122   GNUNET_MULTICAST_REC_OK = 0,
123
124   /**
125    * Message has been discarded (likely transient message that was too old).
126    */ 
127   GNUNET_MULTICAST_REC_TRANSIENT_LOST = 1,
128
129   /**
130    * Message ID counter was larger than the highest counter this
131    * replay function has ever encountered; thus it is likely the
132    * origin never sent it and we're at the HEAD of the multicast
133    * stream as far as this node is concerned.
134    */ 
135   GNUNET_MULTICAST_REC_PAST_HEAD = 2,
136
137   /**
138    * Internal error (i.e. database error).  Try some other peer.
139    */ 
140   GNUNET_MULTICAST_REC_INTERNAL_ERROR = 3
141
142 };
143
144
145 /**
146  * Header of a multicast message.  This format is public as the replay
147  * mechanism must replay messages using the same format.
148  */
149 struct GNUNET_MULTICAST_MessageHeader
150 {
151
152   /**
153    * Header for all multicast messages from the origin.
154    */
155   struct GNUNET_MessageHeader header;
156
157   /**
158    * How many hops has this message taken since the origin?
159    * (helpful to determine shortest paths to the origin for responses
160    *  among honest peers; updated at each hop and thus not signed
161    *  and not secure)
162    */
163   uint32_t hop_counter;
164
165   /**
166    * ECC signature of the message.
167    */
168   struct GNUNET_CRYPTO_EccSignature signature;
169
170   /**
171    * Signature of the multicast message.
172    */
173   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
174
175   /**
176    * Number of the message, monotonically increasing.
177    */
178   uint64_t message_id;
179
180   /**
181    * Counter that monotonically increases whenever a member
182    * leaves the group.
183    */
184   uint64_t group_generation;
185
186   /**
187    * Difference between the current message_id and the message_id of
188    * the preceeding non-transient message.  Zero for transient
189    * messages, UINT64_MAX for the first message, or any other message
190    * creating a full state reset by the origin.  By subtracting
191    * 'state_delta' from 'message_id', it is possible to calculate the
192    * message ID of the preceeding non-transient message and thus
193    * quickly traverse all state changes up to the last full state
194    * reset by the origin.  This is useful as it allows joining clients
195    * to quickly reassemble the state while skipping over transient
196    * messages (and doing so without having to trust intermediaries to
197    * do it right, as the indices in the chain are signed).  If the
198    * state chain is getting too long, the origin can choose to
199    * originate a state message with a state_delta of UINT64_MAX,
200    * thereby starting a new chain.  The origin will then have to
201    * re-create the full state with state update messages following the
202    * state reset message.
203    */
204   uint64_t state_delta;
205
206   /**
207    * Header for the message body.  Three message types are
208    * specifically understood by multicast, namely "peer join", "peer
209    * leave", and "group terminated".  Multicast will use those
210    * messages to update its list of candidates for content
211    * distribution.  All other message types are application-specific.
212    */
213   struct GNUNET_MessageHeader body;
214
215   /* followed by message body */
216 };
217
218
219 /**
220  * Replay a message from the multicast group.
221  *
222  * @param rh replay handle identifying which replay operation was requested
223  * @param msg replayed message, NULL if unknown/error
224  * @param ec error code
225  */
226 void
227 GNUNET_MULTICAST_replay (struct GNUNET_MULTICAST_ReplayHandle *rh,
228                          const struct GNUNET_MULTICAST_MessageHeader *msg,
229                          enum GNUNET_MULTICAST_ReplayErrorCode ec);
230
231
232 /**
233  * Method called whenever another peer wants to join or has left a 
234  * multicast group.
235  *
236  * @param cls closure
237  * @param peer identity of the peer that wants to join or leave
238  * @param is_joining GNUNET_YES if the peer wants to join, GNUNET_NO if the peer left
239  * @return GNUNET_OK if joining is approved, GNUNET_SYSERR if it is disapproved;
240  *         GNUNET_NO should be returned for peers leaving 
241  */
242 typedef int (*GNUNET_MULTICAST_MembershipChangeCallback)(void *cls,
243                                                          const struct GNUNET_PeerIdentity *peer,
244                                                          int is_joining);
245
246
247 /**
248  * Method called to test if a member was in the group at a particular time.
249  *
250  * @param cls closure
251  * @param peer identity of the peer that we want to test
252  * @param message_id message ID for which we want to do the test
253  * @param group_generation the generation of the group for which we want to do the test
254  * @return GNUNET_YES if peer was a member, GNUNET_NO if peer was not a member,
255  *         GNUNET_SYSERR if we cannot answer the membership test
256  */
257 typedef int (*GNUNET_MULTICAST_MembershipTestCallback)(void *cls,
258                                                        const struct GNUNET_PeerIdentity *peer,
259                                                        uint64_t message_id,
260                                                        uint64_t group_generation);
261
262
263 /**
264  * Function called whenever a group member has transmitted a message
265  * to the origin (other than joining or leaving).
266  *
267  * @param cls closure (set from GNUNET_MULTICAST_origin_start)
268  * @param sender identity of the sender
269  * @param response_id unique counter for the response from this sender to this origin
270  * @param msg message to the origin
271  */
272 typedef void (*GNUNET_MULTICAST_ResponseCallback) (void *cls,
273                                                    const struct GNUNET_PeerIdentity *sender,
274                                                    uint64_t response_id,
275                                                    const struct GNUNET_MessageHeader *msg);
276
277
278 /**
279  * Function called whenever a group member is receiving a message from
280  * the origin.
281  *
282  * @param cls closure (set from GNUNET_MULTICAST_member_join)
283  * @param msg message from the origin, NULL if the origin shut down
284  *        (or we were kicked out, and we should thus call GNUNET_MULTICAST_member_leave next)
285  */
286 typedef void (*GNUNET_MULTICAST_MessageCallback) (void *cls,
287                                                   const struct GNUNET_MULTICAST_MessageHeader *msg);
288
289
290 /**
291  * Start a multicast group.
292  *
293  * @param cfg configuration to use
294  * @param cls closure for the various callbacks that follow
295  * @param priv_key ECC key that will be used to sign messages for this
296  *                 multicast session; public key is used to identify the
297  *                 multicast group; FIXME: we'll likely want to use
298  *                 NOT the p521 curve here, but a cheaper one in the future
299  * @param join_policy what is the membership policy of the group?
300  * @param replay_cb function that can be called to replay a message
301  * @param test_cb function multicast can use to test group membership
302  * @param join_cb function called to approve / disapprove joining of a peer
303  * @param response_cb function called with messages from group members
304  * @return handle for the origin, NULL on error 
305  */
306 struct GNUNET_MULTICAST_Origin *
307 GNUNET_MULTICAST_origin_start (const struct GNUNET_CONFIGURATION_Handle *cfg, 
308                                void *cls,
309                                struct GNUNET_CRYPTO_EccPrivateKey *priv_key,
310                                enum GNUNET_MULTICAST_JoinPolicy join_policy,
311                                GNUNET_MULITCAST_ReplayCallback replay_cb,
312                                GNUNET_MULITCAST_MembershipTestCallback test_cb,
313                                GNUNET_MULTICAST_MembershipChangeCallback join_cb,
314                                GNUNET_MULTICAST_ResponseCallback response_cb);
315
316
317 /**
318  * Send a message to the multicast group.
319  *
320  * @param origin handle to the multicast group
321  * @param msg_body body of the message to transmit
322  */
323 void
324 GNUNET_MULTICAST_origin_send_to_all (struct GNUNET_MULTICAST_Origin *origin,
325                                      const struct GNUNET_MessageHeader *msg_body);
326
327
328 /**
329  * End a multicast group.
330  *
331  * @param origin multicast group to terminate
332  */
333 void
334 GNUNET_MULTICAST_origin_end (struct GNUNET_MULTICAST_Origin *origin);
335
336
337 /**
338  * Join a multicast group.
339  *
340  * @param cfg configuration to use
341  * @param cls closure for callbacks
342  * @param pub_key ECC key that identifies the group
343  * @param max_known_message_id largest known message ID to the replay service;
344  *        all messages with IDs larger than this ID will be replayed if
345  *        possible (lower IDs will be considered known and thus only
346  *        be replayed upon explicit request)
347  * @param max_known_state_message_id largest known message ID with a non-zero
348  *                       value for the 'state_delta'; state messages with
349  *        larger IDs than this value will be replayed with high priority
350  *        (lower IDs will be considered known and thus only
351  *        be replayed upon explicit request)
352  * @param replay_cb function that can be called to replay messages
353  *        this peer already knows from this group; NULL if this
354  *        client is unable to support replay
355  * @param test_cb function multicast can use to test group membership
356  * @param message_cb function to be called for all messages we 
357  *        receive from the group, excluding those our replay_cb
358  *        already has
359  * FIXME: need some argument(s) to identify the joining member (key pair to 
360  *        bind user identity/pseudonym to peer identity, application-level
361  *        message to origin, etc.)
362  * @return handle for the member, NULL on error 
363  */
364 struct GNUNET_MULTICAST_Member *
365 GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, 
366                               void *cls,
367                               struct GNUNET_CRYPTO_EccPublicKey *pub_key,
368                               uint64_t max_known_message_id,
369                               uint64_t max_known_state_message_id,
370                               GNUNET_MULTICAST_ReplayCallback replay_cb,
371                               GNUNET_MULITCAST_MembershipTestCallback test_cb,
372                               GNUNET_MULTICAST_MessageCallback message_cb);
373
374
375 /**
376  * Request a message to be replayed.  Useful if messages below
377  * the 'max_known_*_id's given when joining are needed and not
378  * known to the client.
379  *
380  * @param member membership handle
381  * @param message_id ID of a message that this client would like to see replayed
382  */
383 void
384 GNUNET_MULTICAST_member_request_replay (struct GNUNET_MULTICAST_Member *member,
385                                         uint64_t message_id);
386
387
388 /**
389  * Leave a mutlicast group.
390  *
391  * @param member membership handle
392  */
393 void
394 GNUNET_MULTICAST_member_leave (struct GNUNET_MULTICAST_Member *member);
395
396
397 /**
398  * Send a message to the origin of the multicast group.  FIXME: how
399  * will we do routing/flow-control of responses?
400  * 
401  * @param member membership handle
402  * @param msg message to send to the origin
403  * FIXME: change to notify_transmit_ready-style to wait for ACKs...
404  */
405 void
406 GNUNET_MULTICAST_member_respond_to_origin (struct GNUNET_MULTICAST_Member *member,
407                                            const struct GNUNET_MessageHeader *msg);
408
409
410
411 #if 0                           /* keep Emacsens' auto-indent happy */
412 {
413 #endif
414 #ifdef __cplusplus
415 }
416 #endif
417
418 /* ifndef GNUNET_MULTICAST_SERVICE_H */
419 #endif
420 /* end of gnunet_multicast_service.h */