-doxygen fixes
[oweals/gnunet.git] / src / include / gnunet_psyc_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_psyc_service.h
23  * @brief PSYC service; high-level access to the PSYC protocol
24  *        note that clients of this API are NOT expected to
25  *        understand the PSYC message format, only the semantics!
26  *        Parsing (and serializing) the PSYC stream format is done
27  *        within the implementation of the libgnunetpsyc library,
28  *        and this API deliberately exposes as little as possible
29  *        of the actual data stream format to the application!
30  * @author Christian Grothoff
31  *
32  * NOTE:
33  * - this API does not know about psyc's "root" and "places";
34  *   there is no 'root' in GNUnet-Psyc as we're decentralized;
35  *   'places' and 'persons' are combined within the same 
36  *   abstraction, that of a "channel".  Channels are identified
37  *   and accessed in this API using a public/private key.  
38  *   Higher-level applications should use NAMES within GADS
39  *   to obtain public keys, and the distinction between 
40  *   'places' and 'persons' can then be made with the help
41  *   of the naming system (and/or conventions).
42  *   Channels are (as in PSYC) organized into a hierarchy; each
43  *   channel owner (the one with the private key) is then
44  *   the operator of the multicast group (its Origin in 
45  *   the terminology of the multicast API).
46  * - The API supports passing large amounts of data using
47  *   'streaming' for the argument passed to a method.  State
48  *   and variables must fit into memory and cannot be streamed
49  *   (thus, no passing of 4 GB of data in a variable; 
50  *   once we implement this, we might want to create a
51  *   @c #define for the maximum size of a variable).
52  * - PSYC defines standard variables, methods, etc.  This
53  *   library deliberately abstracts over all of these; a
54  *   higher-level API should combine the naming system (GADS)
55  *   and standard methods (message, join, leave, warn,
56  *   fail, error) and variables (action, color, time,
57  *   tag, etc.).  However, this API does take over the
58  *   routing variables, specifically 'context' (channel),
59  *   and 'source'.  We only kind-of support 'target', as
60  *   the target is either everyone in the group or the
61  *   origin, and never just a single member of the group;
62  *   for such individual messages, an application needs to
63  *   construct an 'inbox' channel where the owner (only)
64  *   receives messages (but never forwards; private responses
65  *   would be transmitted by joining the senders 'inbox'
66  *   channel -- or a inbox#bob subchannel).  The
67  *   goal for all of this is to keep the abstractions in this 
68  *   API minimal: interaction with multicast, try \& slice,
69  *   state/variable/channel management.  Higher-level
70  *   operations belong elsewhere (so maybe this API should
71  *   be called 'PSYC-low', whereas a higher-level API
72  *   implementing defaults for standard methods and
73  *   variables might be called 'PSYC-std' or 'PSYC-high'.
74  */
75
76 #ifndef GNUNET_PSYC_SERVICE_H
77 #define GNUNET_PSYC_SERVICE_H
78
79 #ifdef __cplusplus
80 extern "C"
81 {
82 #if 0                           /* keep Emacsens' auto-indent happy */
83 }
84 #endif
85 #endif
86
87 #include "gnunet_util_lib.h"
88 #include "gnunet_multicast_service.h"
89
90
91 /** 
92  * Version number of GNUnet-PSYC API.
93  */
94 #define GNUNET_PSYC_VERSION 0x00000000
95
96
97 /** 
98  * Information flags for data fragments set via PSYC.
99  */
100 enum GNUNET_PSYC_FragmentStatus
101 {
102   /** 
103    * This is the first part of data for the given method call.
104    */
105   GNUNET_PSYC_FS_FIRST = 1,
106   
107   /** 
108    * This is the last part of data for the given method call.
109    */
110   GNUNET_PSYC_FS_LAST = 2,
111
112   /** 
113    * OR'ed flags if payload is not fragmented.
114    */
115   GNUNET_PSYC_FS_NOT_FRAGMENTED = (GNUNET_PSYC_FS_FIRST | GNUNET_PSYC_FS_LAST)
116 };
117
118
119 /** 
120  * Method called from PSYC upon receiving a message indicating a call
121  * to a @e method.  
122  *
123  * @param cls Closure.
124  * @param full_method_name Original method name from PSYC (may be more
125  *        specific than the registered method name due to try-and-slice matching).
126  * @param sender Who transmitted the message (origin, except for messages
127  *        from one of the members to the origin).
128  * @param message_id Unique message counter for this message;
129  *                   (unique only in combination with the given sender for
130  *                    this channel).
131  * @param group_generation Group generation counter for this message
132  *                   (always zero for messages from members to channel owner); FIXME: needed?
133  * @param data_off Byte offset of @a data in the overall data of the method.
134  * @param data_size Number of bytes in @a data.
135  * @param data Data stream given to the method (might not be zero-terminated 
136  *             if data is binary).
137  * @param frag Fragmentation status for the data.
138  */
139 typedef int (*GNUNET_PSYC_Method)(void *cls,
140                                   const char *full_method_name,
141                                   const struct GNUNET_PeerIdentity *sender,
142                                   uint64_t message_id,
143                                   uint64_t group_generation,
144                                   uint64_t data_off,
145                                   size_t data_size,
146                                   const void *data,
147                                   enum GNUNET_PSYC_FragmentStatus frag);
148
149
150 /** 
151  * Handle for the channel of a PSYC group.
152  */
153 struct GNUNET_PSYC_Channel;
154
155
156 /** 
157  * Create a PSYC channel.
158  *
159  * Will create a multicast group identified by the given ECC key.  Messages
160  * received from group members will be given to the respective handler methods.
161  * If a new member wants to join a group, the "join" method handler will be
162  * invoked; the join handler must then generate a "join" message to approve the
163  * joining of the new member.  The channel can also change group membership
164  * without explicit requests.  Note that PSYC doesn't itself "understand" join
165  * or leave messages, the respective methods must call other PSYC functions to
166  * inform PSYC about the meaning of the respective events.
167  *
168  * @param cfg Configuration to use (to connect to PSYC service).
169  * @param method Function to invoke on messages received from members,
170  *                typcially at least contains functions for @e join and @e leave.
171  * @param method_cls Closure for @a method.
172  * @param priv_key ECC key that will be used to sign messages for this
173  *                 PSYC session; public key is used to identify the
174  *                 PSYC group; FIXME: we'll likely want to use
175  *                 NOT the p521 curve here, but a cheaper one in the future
176  *                 Note that end-users will usually not use the private key
177  *                 directly, but rather look it up in GADS for groups 
178  *                 managed by other users, or select a file with the private
179  *                 key(s) when setting up their own channels
180  * @param join_policy What is the membership policy of the group?
181  *                 Used to automate group management decisions.
182  * @return Handle for the channel, NULL on error.
183  */
184 struct GNUNET_PSYC_Channel *
185 GNUNET_PSYC_channel_create (const struct GNUNET_CONFIGURATION_Handle *cfg, 
186                             GNUNET_PSYC_Method method,
187                             void *method_cls,
188                             const struct GNUNET_CRYPTO_EccPrivateKey *priv_key,
189                             enum GNUNET_MULTICAST_JoinPolicy join_policy);
190
191
192 /** 
193  * Possible operations on PSYC state (persistent) and variables (per message).
194  */
195 enum GNUNET_PSYC_Operator
196 {
197   /** 
198    * Replace the full state with the new value ("=").
199    */
200   GNUNET_PSYC_SOT_SET_STATE = 0,
201   
202   /** 
203    * Delete the complete entry from the state (given data must be
204    * empty).  Equivalent to @a SET with empty data, but more
205    * explicit ("=");
206    */
207   GNUNET_PSYC_SOT_DELETE = 0,
208   
209   /** 
210    * Set the value of a variable to a new value (":").
211    */
212   GNUNET_PSYC_SOT_SET_VARIABLE,
213   
214   /** 
215    * Add the given value to the set of values in the state ("+").
216    */
217   GNUNET_PSYC_SOT_ADD_STATE,
218   
219   /** 
220    * Remove the given value from the set of values in the state ("-").
221    */
222   GNUNET_PSYC_SOT_REMOVE_STATE
223   
224 };
225
226
227 /** 
228  * Update channel state (or set a variable).
229  *
230  * The state of a channel must fit into the memory of each member (and the
231  * channel); large values that require streaming must only be passed as the
232  * stream arguments to methods.  State updates might not be transmitted to group
233  * members until the next call to GNUNET_PSYC_channel_notify_transmit_ready().
234  * Variable updates must be given just before the call to the respective method
235  * that needs the variables.
236  *
237  * @param channel Handle to the PSYC group / channel.
238  * @param full_state_name Name of the field in the channel state to change.
239  * @param type Kind of update operation (add, remove, replace, delete).
240  * @param data_size Number of bytes in data.
241  * @param data New state value.
242  * @return #GNUNET_OK on success, #GNUNET_SYSERR on internal error
243  *        (i.e. state too large).
244  */
245 int
246 GNUNET_PSYC_channel_state_update (struct GNUNET_PSYC_Channel *channel,
247                                   const char *full_state_name,
248                                   enum GNUNET_PSYC_Operator type,
249                                   size_t data_size,
250                                   const void *data);
251
252
253 /** 
254  * Function called to provide data for a transmission via PSYC.
255  *
256  * Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO)
257  * invalidates the respective transmission handle.
258  *
259  * @param cls Closure.
260  * @param message_id Set to the unique message ID that was generated for
261  *        this message.
262  * @param group_generation Set to the group generation used for this
263  *        message.
264  * @param data_size[in,out] Initially set to the number of bytes available in @a data,
265  *        should be set to the number of bytes written to data (IN/OUT).
266  * @param data[out] Where to write the body of the message to give to the method;
267  *        function must copy at most @a *data_size bytes to @a data.
268  * @return #GNUNET_SYSERR on error (fatal, aborts transmission)
269  *         #GNUNET_NO on success, if more data is to be transmitted later 
270  *         (should be used if @a *data_size was not big enough to take all the data)
271  *         #GNUNET_YES if this completes the transmission (all data supplied)
272  */
273 typedef int (*GNUNET_PSYC_ChannelReadyNotify)(void *cls,
274                                               uint64_t message_id,
275                                               uint64_t group_generation,
276                                               size_t *data_size,
277                                               void *data);
278
279
280 /** 
281  * Handle for a pending PSYC transmission operation.
282  */
283 struct GNUNET_PSYC_ChannelTransmitHandle;
284
285
286 /** 
287  * Send a message to call a method to all members in the PSYC channel.
288  *
289  * @param channel Handle to the PSYC multicast group.
290  * @param increment_group_generation #GNUNET_YES if we need to increment
291  *        the group generation counter after transmitting this message.
292  * @param full_method_name Which method should be invoked.
293  * @param notify Function to call to obtain the arguments.
294  * @param notify_cls Closure for @a notify.
295  * @return Transmission handle, NULL on error (i.e. more than one request queued).
296  */
297 struct GNUNET_PSYC_ChannelTransmitHandle *
298 GNUNET_PSYC_channel_notify_transmit_ready (struct GNUNET_PSYC_Channel *channel,
299                                            int increment_group_generation,
300                                            const char *full_method_name,
301                                            GNUNET_PSYC_ChannelReadyNotify notify,
302                                            void *notify_cls);
303
304
305 /** 
306  * Abort transmission request to channel.
307  *
308  * @param th Handle of the request that is being aborted.
309  */
310 void
311 GNUNET_PSYC_channel_notify_transmit_ready_cancel (struct GNUNET_PSYC_ChannelTransmitHandle *th);
312
313
314 /** 
315  * Destroy a PSYC channel.
316  *
317  * @param channel PSYC channel to terminate.
318  */
319 tvoid
320 GNUNET_PSYC_channel_destroy (struct GNUNET_PSYC_Channel *channel);
321
322
323 /** 
324  * Handle to access PSYC group operations for all members.
325  */
326 struct GNUNET_PSYC_Group;
327
328
329 /** 
330  * Convert @a channel to a @e group handle to access the @e group APIs.
331  * 
332  * @param channel Channel handle.
333  * @return Group handle, valid for as long as @a channel is valid.
334  */ 
335 struct GNUNET_PSYC_Group *
336 GNUNET_PSYC_channel_get_group (struct GNUNET_PSYC_Channel *channel);
337
338
339 /** 
340  * Convert @a member to a @e group handle to access the @e group APIs.
341  * 
342  * @param member Membership handle.
343  * @return Group handle, valid for as long as @a member is valid.
344  */ 
345 struct GNUNET_PSYC_Group *
346 GNUNET_PSYC_member_get_group (struct GNUNET_PSYC_Member *member);
347
348
349 /** 
350  * Add a member to the group.
351  *
352  * Note that this will NOT generate any PSYC traffic, it will merely update the
353  * local data base to modify how we react to <em>membership test</em> queries.  The
354  * channel still needs to explicitly transmit a @e join message to notify other
355  * group members and they then also must still call this function in their
356  * respective methods handling the @e join message.  This way, how @e join and
357  * @e leave operations are exactly implemented is still up to the application;
358  * for example, there might be a @e leave_all method to kick out everyone.
359  *
360  * Note that group members are explicitly trusted to execute such 
361  * methods correctly; not doing so correctly will result in either
362  * denying members access or offering access to group data to
363  * non-members.
364  *
365  * @param group Group handle.
366  * @param member Which peer to add.
367  * @param message_id Message ID for the message that changed the membership.
368  * @param group_generation The generation ID where the change went into effect.
369  */
370 void
371 GNUNET_PSYC_group_member_add (struct GNUNET_PSYC_Group *group,
372                               const struct GNUNET_PeerIdentity *member,
373                               uint64_t message_id,
374                               uint64_t group_generation);
375
376
377 /** 
378  * Remove a member from the group.
379  *
380  * Note that this will NOT generate any PSYC traffic, it will merely update the
381  * local data base to modify how we react to <em>membership test</em> queries.  The
382  * channel still needs to explicitly transmit a @e leave message to notify other
383  * group members and they then also must still call this function in their
384  * respective methods handling the @e leave message.  This way, how @e join and
385  * @e leave operations are exactly implemented is still up to the application;
386  * for example, there might be a @e leave_all message to kick out everyone.
387  *
388  * Note that group members are explicitly trusted to perform these
389  * operations correctly; not doing so correctly will result in either
390  * denying members access or offering access to group data to
391  * non-members.
392  *
393  * @param group Group handle.
394  * @param member Which peer to remove.
395  * @param message_id Message ID for the message that changed the membership.
396  * @param group_generation The generation ID where the change went into effect.
397  */
398 void
399 GNUNET_PSYC_group_member_remove (struct GNUNET_PSYC_Group *group,
400                                  const struct GNUNET_PeerIdentity *member,
401                                  uint64_t message_id,
402                                  uint64_t group_generation);
403
404
405 /** 
406  * Function called to inform a member about state changes for a channel.
407  *
408  * Note that (for sets) only the delta is communicated, not the full state.
409  *
410  * @param cls Closure.
411  * @param full_state_name Full name of the state.
412  * @param type How to interpret the change.
413  * @param state_value Information about the new state.
414  * @param state_value_size Number of bytes in @a state_value.
415  */
416 typedef void (*GNUNET_PSYC_StateCallback)(void *cls,
417                                           const char *full_state_name,
418                                           enum GNUNET_PSYC_Operator type,
419                                           const void *state_value,
420                                           size_t state_value_size);
421
422
423 /** 
424  * Descriptor for an event handler handling PSYC state updates.
425  */
426 struct GNUNET_PSYC_StateHandler
427 {
428
429   /** 
430    * Name of the state variable this handler calls about, used in try-and-slice matching.
431    */
432   const char *state_name;
433
434   /** 
435    * Function to call whenever the respective state changes.
436    */
437   GNUNET_PSYC_StateCallback event_handler;
438
439   /** 
440    * Closure for the @a event_handler function.
441    */
442   void *event_handler_cls;
443
444 };
445
446
447 /** 
448  * Join a PSYC group.
449  *
450  * The entity joining is always the local peer.  The user must immediately use
451  * the GNUNET_PSYC_member_send_to_host() (and possibly
452  * GNUNET_PSYC_member_host_variable_set()) functions to transmit a @e join_msg to
453  * the channel; if the join request succeeds, the channel state (and @e recent
454  * method calls) will be replayed to the joining member.  There is no explicit
455  * notification on failure (as the channel may simply take days to approve, and
456  * disapproval is simply being ignored).
457  *
458  * @param cfg Configuration to use.
459  * @param pub_key ECC key that identifies the channel we wish to join
460  * @param method Function to invoke on messages received from the channel,
461  *                typically at least contains functions for @e join and @e leave.
462  * @param method_cls Closure for @a method.
463  * @param state_count Number of @a state_handlers.
464  * @param state_handlers Array of state event handlers.
465  * @return Handle for the member, NULL on error.
466  */
467 struct GNUNET_PSYC_Member *
468 GNUNET_PSYC_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, 
469                          const struct GNUNET_CRYPTO_EccPublicKey *pub_key,
470                          GNUNET_PSYC_Method method,
471                          void *method_cls,
472                          unsigned int state_count,
473                          struct GNUNET_PSYC_StateHandler *state_handlers);
474
475
476 /** 
477  * Leave a multicast group.
478  *
479  * Will terminate the connection to the PSYC service.  Polite clients should
480  * first explicitly send a @e leave request (via
481  * GNUNET_PSYC_member_send_to_host()).
482  *
483  * @param member membership handle
484  */
485 void
486 GNUNET_PSYC_member_leave (struct GNUNET_PSYC_Member *member);
487
488
489 /** 
490  * Function called to provide data for a transmission to the channel
491  * owner (aka the @e host of the channel).
492  *
493  * Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO)
494  * invalidates the respective transmission handle.
495  *
496  * @param cls Closure.
497  * @param data_size[in,out] Initially set to the number of bytes available in @a data,
498  *        should be set to the number of bytes written to data (IN/OUT).
499  * @param data[out] Where to write the body of the message to give to the method;
500  *        function must copy at most @a *data_size bytes to @a data.
501  * @return #GNUNET_SYSERR on error (fatal, aborts transmission).
502  *         #GNUNET_NO on success, if more data is to be transmitted later.
503  *         #GNUNET_YES if this completes the transmission (all data supplied).
504  */
505 typedef int (*GNUNET_PSYC_OriginReadyNotify)(void *cls,
506                                              size_t *data_size,
507                                              char *data);
508
509
510 /** 
511  * Handle for a pending PSYC transmission operation.
512  */
513 struct GNUNET_PSYC_OriginTransmitHandle;
514
515
516 /** 
517  * Request a message to be sent to the channel origin.
518  *
519  * @param member Membership handle.
520  * @param method_name Which (PSYC) method should be invoked (on host).
521  * @param notify Function to call when we are allowed to transmit (to get data).
522  * @param notify_cls Closure for @a notify.
523  * @return Transmission handle, NULL on error (i.e. more than one request queued).
524  */
525 struct GNUNET_PSYC_OriginTransmitHandle *
526 GNUNET_PSYC_member_send_to_origin (struct GNUNET_PSYC_Member *member,
527                                    const char *method_name,
528                                    GNUNET_PSYC_OriginReadyNotify notify,
529                                    void *notify_cls);
530
531
532 /** 
533  * Set a (temporary, ":") variable for the next message being transmitted
534  * via GNUNET_PSYC_member_send_to_host().
535  *
536  * If GNUNET_PSYC_member_send_to_host() is called and then cancelled, all
537  * variables that were set using this function will be unset (lost/forgotten).
538  * To clear a variable state after setting it, you can also call this function
539  * again with NULL/0 for the @a value.
540  *
541  * @param member Membership handle.
542  * @param variable_name Name of the variable to set.
543  * @param value Value to set for the given variable.
544  * @param value_size Number of bytes in @a value.
545  */
546 uint64_t
547 GNUNET_PSYC_member_origin_variable_set (struct GNUNET_PSYC_Member *member,
548                                         const char *variable_name,
549                                         const void *value,
550                                         size_t value_size);
551
552
553 /** 
554  * Abort transmission request to origin.
555  *
556  * @param th Handle of the request that is being aborted.
557  */
558 void
559 GNUNET_PSYC_member_send_to_origin_cancel (struct GNUNET_PSYC_OriginTransmitHandle *th);
560
561
562 /** 
563  * Handle to a story telling operation.
564  */
565 struct GNUNET_PSYC_Story;
566
567
568 /** 
569  * Request to be told the message history of the channel.
570  *
571  * Historic messages (but NOT the state at the time) will be replayed (given to
572  * the normal method handlers) if available and if access is permitted.
573  *
574  * @param member Which channel should be replayed?
575  * @param start Earliest interesting point in history.
576  * @param end Last (exclusive) interesting point in history.
577  * @param method Function to invoke on messages received from the story.
578  * @param method_cls Closure for @a method.
579  * @param finish_cb Function to call when the requested story has been fully 
580  *        told (counting message IDs might not suffice, as some messages
581  *        might be secret and thus the listener would not know the story is 
582  *        finished without being told explicitly); once this function
583  *        has been called, the client must not call
584  *        GNUNET_PSYC_member_story_tell_cancel() anymore.
585  * @param finish_cb_cls Closure to finish_cb.
586  * @return Handle to cancel story telling operation.
587  */
588 struct GNUNET_PSYC_Story *
589 GNUNET_PSYC_member_story_tell (struct GNUNET_PSYC_Member *member,
590                                uint64_t start,
591                                uint64_t end,
592                                GNUNET_PSYC_Method method,
593                                void *method_cls,
594                                void (*finish_cb)(void *),
595                                void *finish_cb_cls);
596
597
598 /** 
599  * Abort story telling.
600  *
601  * This function must not be called from within method handlers (as given to
602  * GNUNET_PSYC_member_join()) of the member.
603  *
604  * @param story Story telling operation to stop.
605  */
606 void
607 GNUNET_PSYC_member_story_tell_cancel (struct GNUNET_PSYC_Story *story);
608
609
610 /** 
611  * Call the given callback on all matching values (including variables) in the
612  * channel state.
613  *
614  * The callback is invoked synchronously on all matching states (as the state is
615  * fully replicated in the library in this process; channel states should be
616  * small, large data is to be passed as streaming data to methods).
617  *
618  * A name matches if it includes the @a state_name prefix, thus requesting the
619  * empty state ("") will match all values; requesting "a_b" will also return
620  * values stored under "a_b_c".
621  *
622  * @param member Membership handle.
623  * @param state_name Name of the state to query (full name 
624  *        might be longer, this is only the prefix that must match).
625  * @param cb Function to call on the matching state values.
626  * @param cb_cls Closure for @a cb.
627  * @return Message ID for which the state was returned (last seen
628  *         message ID).
629  */
630 uint64_t
631 GNUNET_PSYC_member_state_get_all (struct GNUNET_PSYC_Member *member,
632                                   const char *state_name,
633                                   GNUNET_PSYC_StateCallback cb,
634                                   void *cb_cls);
635
636
637 /** 
638  * Obtain the current value of the best-matching value in the state
639  * (including variables).
640  *
641  * Note that variables are only valid during a #GNUNET_PSYC_Method invocation, as
642  * variables are only valid for the duration of a method invocation.
643  *
644  * If the requested variable name does not have an exact state in
645  * the state, the nearest less-specific name is matched; for example,
646  * requesting "a_b" will match "a" if "a_b" does not exist.
647  *
648  * @param member Membership handle.
649  * @param variable_name Name of the variable to query.
650  * @param return_value_size Set to number of bytes in variable, 
651  *        needed as variables might contain binary data and
652  *        might also not be 0-terminated; set to 0 on errors.
653  * @return NULL on error (no matching state or variable), pointer
654           to the respective value otherwise.
655  */
656 const void *
657 GNUNET_PSYC_member_state_get (struct GNUNET_PSYC_Member *member,
658                               const char *variable_name,
659                               size_t *return_value_size);
660
661
662
663 #if 0                           /* keep Emacsens' auto-indent happy */
664 {
665 #endif
666 #ifdef __cplusplus
667 }
668 #endif
669
670 /* ifndef GNUNET_PSYC_SERVICE_H */
671 #endif
672 /* end of gnunet_psyc_service.h */