-clarify API
[oweals/gnunet.git] / src / include / gnunet_namestore_service.h
1
2 /*
3      This file is part of GNUnet
4      (C) 2012, 2013 Christian Grothoff (and other contributing authors)
5
6      GNUnet is free software; you can redistribute it and/or modify
7      it under the terms of the GNU General Public License as published
8      by the Free Software Foundation; either version 3, or (at your
9      option) any later version.
10
11      GNUnet is distributed in the hope that it will be useful, but
12      WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      General Public License for more details.
15
16      You should have received a copy of the GNU General Public License
17      along with GNUnet; see the file COPYING.  If not, write to the
18      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19      Boston, MA 02111-1307, USA.
20 */
21
22 /**
23  * @file include/gnunet_namestore_service.h
24  * @brief API that can be used to store naming information on a GNUnet node;
25  *        Naming information can either be records for which this peer/user
26  *        is authoritative, or blocks which are cached, encrypted naming
27  *        data from other peers.
28  * @author Christian Grothoff
29  */
30 #ifndef GNUNET_NAMESTORE_SERVICE_H
31 #define GNUNET_NAMESTORE_SERVICE_H
32
33 #include "gnunet_util_lib.h"
34 #include "gnunet_block_lib.h"
35
36 #ifdef __cplusplus
37 extern "C"
38 {
39 #if 0                           /* keep Emacsens' auto-indent happy */
40 }
41 #endif
42 #endif
43
44 /**
45  * Record type indicating any record/'*'
46  */
47 #define GNUNET_NAMESTORE_TYPE_ANY 0
48
49 /**
50  * Record type for GNS zone transfer ("PKEY").
51  */
52 #define GNUNET_NAMESTORE_TYPE_PKEY 65536
53
54 /**
55  * Record type for GNS zone transfer ("PSEU").
56  */
57 #define GNUNET_NAMESTORE_TYPE_PSEU 65537
58
59 /**
60  * Record type for GNS legacy hostnames ("LEHO").
61  */
62 #define GNUNET_NAMESTORE_TYPE_LEHO 65538
63
64 /**
65  * Record type for VPN resolution
66  */
67 #define GNUNET_NAMESTORE_TYPE_VPN 65539
68
69 /**
70  * Record type for zone revocation
71  */
72 #define GNUNET_NAMESTORE_TYPE_REV 65540
73
74 /**
75  * Record type for a social place.
76  */
77 #define GNUNET_NAMESTORE_TYPE_PLACE 65541
78
79 /**
80  * Entry in the queue.
81  */
82 struct GNUNET_NAMESTORE_QueueEntry;
83
84 /**
85  * Handle to the namestore service.
86  */
87 struct GNUNET_NAMESTORE_Handle;
88
89 /**
90  * Handle to the namestore zone iterator.
91  */
92 struct GNUNET_NAMESTORE_ZoneIterator;
93
94 /**
95  * Maximum size of a value that can be stored in the namestore.
96  */
97 #define GNUNET_NAMESTORE_MAX_VALUE_SIZE (63 * 1024)
98
99
100 /**
101  * Connect to the namestore service.
102  *
103  * @param cfg configuration to use
104  * @return handle to use to access the service
105  */
106 struct GNUNET_NAMESTORE_Handle *
107 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
108
109
110 /**
111  * Disconnect from the namestore service (and free associated
112  * resources).  Must not be called from within operation callbacks of
113  * the API.
114  *
115  * @param h handle to the namestore
116  */
117 void
118 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h);
119
120
121 /**
122  * Continuation called to notify client about result of the
123  * operation.
124  *
125  * @param cls closure
126  * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
127  *                #GNUNET_NO if content was already there or not found
128  *                #GNUNET_YES (or other positive value) on success
129  * @param emsg NULL on success, otherwise an error message
130  */
131 typedef void (*GNUNET_NAMESTORE_ContinuationWithStatus) (void *cls,
132                                                          int32_t success,
133                                                          const char *emsg);
134
135
136 /**
137  * Flags that can be set for a record.
138  */
139 enum GNUNET_NAMESTORE_RecordFlags
140 {
141   
142   /**
143    * No special options.
144    */
145   GNUNET_NAMESTORE_RF_NONE = 0,
146
147   /**
148    * This is a private record of this peer and it should
149    * thus not be handed out to other peers.
150    */
151   GNUNET_NAMESTORE_RF_PRIVATE = 2,
152
153   /**
154    * This record was added automatically by the system
155    * and is pending user confimation.
156    */
157   GNUNET_NAMESTORE_RF_PENDING = 4,
158
159   /**
160    * This expiration time of the record is a relative
161    * time (not an absolute time).
162    */
163   GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION = 8,
164
165   /**
166    * This record should not be used unless all (other) records with an absolute
167    * expiration time have expired.
168    */
169   GNUNET_NAMESTORE_RF_SHADOW_RECORD = 16
170
171   /**
172    * When comparing flags for record equality for removal,
173    * which flags should must match (in addition to the type,
174    * name, expiration value and data of the record)?  All flags
175    * that are not listed here will be ignored for this purpose.
176    * (for example, we don't expect that users will remember to
177    * pass the '--private' option when removing a record from
178    * the namestore, hence we don't require this particular option
179    * to match upon removal).  See also
180    * #GNUNET_NAMESTORE_records_cmp.
181    */
182 #define GNUNET_NAMESTORE_RF_RCMP_FLAGS (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
183 };
184
185
186 /**
187  * A GNS record.
188  */
189 struct GNUNET_NAMESTORE_RecordData
190 {
191
192   /**
193    * Binary value stored in the DNS record.  Note: "data" must never
194    * be individually 'malloc'ed, but instead always points into some
195    * existing data area.
196    */
197   const void *data;
198
199   /**
200    * Expiration time for the DNS record.  Can be relative
201    * or absolute, depending on 'flags'.  Measured in the same
202    * unit as GNUnet time (microseconds).
203    */
204   uint64_t expiration_time;
205
206   /**
207    * Number of bytes in 'data'.
208    */
209   size_t data_size;
210
211   /**
212    * Type of the GNS/DNS record.
213    */
214   uint32_t record_type;
215
216   /**
217    * Flags for the record.
218    */
219   enum GNUNET_NAMESTORE_RecordFlags flags;
220 };
221
222
223
224 GNUNET_NETWORK_STRUCT_BEGIN
225
226
227 /**
228  * Information we have in an encrypted block with record data (i.e. in the DHT).
229  */
230 struct GNUNET_NAMESTORE_Block
231 {
232
233   /**
234    * Signature of the block.
235    */
236   struct GNUNET_CRYPTO_EccSignature signature;
237
238   /**
239    * Derived key used for signing; hash of this is the query.
240    */
241   struct GNUNET_CRYPTO_EccPublicSignKey derived_key;
242
243   /**
244    * Number of bytes signed; also specifies the number of bytes
245    * of encrypted data that follow.
246    */
247   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
248   
249   /**
250    * Expiration time of the block.
251    */
252   struct GNUNET_TIME_AbsoluteNBO expiration_time;
253
254   /* followed by encrypted data */
255 };
256
257 GNUNET_NETWORK_STRUCT_END
258
259 /**
260  * Store an item in the namestore.  If the item is already present,
261  * it is replaced with the new record.  
262  *
263  * @param h handle to the namestore
264  * @param block block to store
265  * @param cont continuation to call when done
266  * @param cont_cls closure for @a cont
267  * @return handle to abort the request
268  */
269 struct GNUNET_NAMESTORE_QueueEntry *
270 GNUNET_NAMESTORE_block_cache (struct GNUNET_NAMESTORE_Handle *h,
271                               const struct GNUNET_NAMESTORE_Block *block,
272                               GNUNET_NAMESTORE_ContinuationWithStatus cont,
273                               void *cont_cls);
274
275
276 /**
277  * Store an item in the namestore.  If the item is already present,
278  * it is replaced with the new record.  Use an empty array to
279  * remove all records under the given name.
280  *
281  * @param h handle to the namestore
282  * @param pkey private key of the zone
283  * @param label name that is being mapped (at most 255 characters long)
284  * @param rd_count number of records in the 'rd' array
285  * @param rd array of records with data to store
286  * @param cont continuation to call when done
287  * @param cont_cls closure for @a cont
288  * @return handle to abort the request
289  */
290 struct GNUNET_NAMESTORE_QueueEntry *
291 GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h,
292                                 const struct GNUNET_CRYPTO_EccPrivateKey *pkey,
293                                 const char *label,
294                                 unsigned int rd_count,
295                                 const struct GNUNET_NAMESTORE_RecordData *rd,
296                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
297                                 void *cont_cls);
298
299
300 /**
301  * Process a record that was stored in the namestore.
302  *
303  * @param cls closure
304  * @param block block that was stored in the namestore
305  */
306 typedef void (*GNUNET_NAMESTORE_BlockProcessor) (void *cls,
307                                                  const struct GNUNET_NAMESTORE_Block *block);
308
309
310 /**
311  * Get a result for a particular key from the namestore.  The processor
312  * will only be called once.  
313  *
314  * @param h handle to the namestore
315  * @param derived_hash hash of zone key combined with name to lookup
316  * @param proc function to call on the matching block, or with
317  *        NULL if there is no matching block
318  * @param proc_cls closure for @a proc
319  * @return a handle that can be used to cancel
320  */
321 struct GNUNET_NAMESTORE_QueueEntry *
322 GNUNET_NAMESTORE_lookup_block (struct GNUNET_NAMESTORE_Handle *h, 
323                                const struct GNUNET_HashCode *derived_hash,
324                                GNUNET_NAMESTORE_BlockProcessor proc, void *proc_cls);
325
326
327 /**
328  * Process a record that was stored in the namestore.
329  *
330  * @param cls closure
331  * @param zone private key of the zone; NULL on disconnect
332  * @param label label of the records; NULL on disconnect
333  * @param rd_count number of entries in @a rd array, 0 if label was deleted
334  * @param rd array of records with data to store
335  */
336 typedef void (*GNUNET_NAMESTORE_RecordMonitor) (void *cls,
337                                                 const struct GNUNET_CRYPTO_EccPrivateKey *zone,
338                                                 const char *label,
339                                                 unsigned int rd_count,
340                                                 const struct GNUNET_NAMESTORE_RecordData *rd);
341
342
343 /**
344  * Look for an existing PKEY delegation record for a given public key.
345  * Returns at most one result to the processor.
346  *
347  * @param h handle to the namestore
348  * @param zone public key of the zone to look up in, never NULL
349  * @param value_zone public key of the target zone (value), never NULL
350  * @param proc function to call on the matching records, or with
351  *        NULL (rd_count == 0) if there are no matching records
352  * @param proc_cls closure for @a proc
353  * @return a handle that can be used to
354  *         cancel
355  */
356 struct GNUNET_NAMESTORE_QueueEntry *
357 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, 
358                                const struct GNUNET_CRYPTO_EccPrivateKey *zone,
359                                const struct GNUNET_CRYPTO_EccPublicSignKey *value_zone,
360                                GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls);
361
362
363 /**
364  * Process a records that were decrypted from a block.
365  *
366  * @param cls closure
367  * @param rd_count number of entries in @a rd array
368  * @param rd array of records with data to store
369  */
370 typedef void (*GNUNET_NAMESTORE_RecordCallback) (void *cls,
371                                                  unsigned int rd_count,
372                                                  const struct GNUNET_NAMESTORE_RecordData *rd);
373
374
375 /**
376  * Cancel a namestore operation.  The final callback from the
377  * operation must not have been done yet.  Must be called on any
378  * namestore operation that has not yet completed prior to calling
379  * #GNUNET_NAMESTORE_disconnect.
380  *
381  * @param qe operation to cancel
382  */
383 void
384 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe);
385
386
387 /**
388  * Starts a new zone iteration (used to periodically PUT all of our
389  * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
390  * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
391  * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
392  * immediately, and then again after
393  * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
394  *
395  * @param h handle to the namestore
396  * @param zone zone to access, NULL for all zones
397  * @param proc function to call on each name from the zone; it
398  *        will be called repeatedly with a value (if available)
399  *        and always once at the end with a name of NULL.
400  * @param proc_cls closure for @a proc
401  * @return an iterator handle to use for iteration
402  */
403 struct GNUNET_NAMESTORE_ZoneIterator *
404 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
405                                        const struct GNUNET_CRYPTO_EccPrivateKey *zone,
406                                        GNUNET_NAMESTORE_RecordMonitor proc,
407                                        void *proc_cls);
408
409
410 /**
411  * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
412  * for the next record.
413  *
414  * @param it the iterator
415  */
416 void
417 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it);
418
419
420 /**
421  * Stops iteration and releases the namestore handle for further calls.  Must
422  * be called on any iteration that has not yet completed prior to calling
423  * #GNUNET_NAMESTORE_disconnect.
424  *
425  * @param it the iterator
426  */
427 void
428 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it);
429
430
431 /**
432  * Handle for a monitoring activity.
433  */
434 struct GNUNET_NAMESTORE_ZoneMonitor;
435
436
437 /**
438  * Function called once the monitor has caught up with the current 
439  * state of the database.  Will be called AGAIN after each disconnect
440  * (record monitor called with 'NULL' for zone_key) once we're again
441  * in sync.
442  *
443  * @param cls closure
444  */
445 typedef void (*GNUNET_NAMESTORE_RecordsSynchronizedCallback)(void *cls);
446
447
448 /**
449  * Begin monitoring a zone for changes.  Will first call the @a monitor function
450  * on all existing records in the selected zone(s), then calls @a sync_cb,
451  * and then calls the @a monitor whenever a record changes.  If the namestore
452  * disconnects, the @a monitor function is called with a disconnect event; if
453  * the connection is re-established, the process begins from the start (all
454  * existing records, sync, then updates).
455  *
456  * @param cfg configuration to use to connect to namestore
457  * @param zone zone to monitor
458  * @param monitor function to call on zone changes
459  * @param sync_cb function called when we're in sync with the namestore
460  * @param cls closure for @a monitor and @a sync_cb
461  * @return handle to stop monitoring
462  */
463 struct GNUNET_NAMESTORE_ZoneMonitor *
464 GNUNET_NAMESTORE_zone_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
465                                      const struct GNUNET_CRYPTO_EccPrivateKey *zone,
466                                      GNUNET_NAMESTORE_RecordMonitor monitor,
467                                      GNUNET_NAMESTORE_RecordsSynchronizedCallback sync_cb,
468                                      void *cls);
469
470
471 /**
472  * Stop monitoring a zone for changes.
473  *
474  * @param zm handle to the monitor activity to stop
475  */
476 void
477 GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
478
479
480 /* convenience APIs for serializing / deserializing GNS records */
481
482 /**
483  * Calculate how many bytes we will need to serialize the given
484  * records.
485  *
486  * @param rd_count number of records in the @a rd array
487  * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
488  * @return the required size to serialize
489  */
490 size_t
491 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
492                                    const struct GNUNET_NAMESTORE_RecordData *rd);
493
494
495 /**
496  * Serialize the given records to the given destination buffer.
497  *
498  * @param rd_count number of records in the @a rd array
499  * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
500  * @param dest_size size of the destination array @a dst
501  * @param dest where to write the result
502  * @return the size of serialized records, -1 if records do not fit
503  */
504 ssize_t
505 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
506                                     const struct GNUNET_NAMESTORE_RecordData *rd,
507                                     size_t dest_size,
508                                     char *dest);
509
510
511 /**
512  * Deserialize the given records to the given destination.
513  *
514  * @param len size of the serialized record data
515  * @param src the serialized record data
516  * @param rd_count number of records in the @a dest array
517  * @param dest where to put the data
518  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
519  */
520 int
521 GNUNET_NAMESTORE_records_deserialize (size_t len,
522                                       const char *src,
523                                       unsigned int rd_count,
524                                       struct GNUNET_NAMESTORE_RecordData *dest);
525
526
527 /**
528  * Convert the binary value @a data of a record of 
529  * type @a type to a human-readable string.
530  *
531  * @param type type of the record
532  * @param data value in binary encoding
533  * @param data_size number of bytes in @a data
534  * @return NULL on error, otherwise human-readable representation of the value
535  */
536 char *
537 GNUNET_NAMESTORE_value_to_string (uint32_t type,
538                                   const void *data,
539                                   size_t data_size);
540
541
542 /**
543  * Convert human-readable version of the value @a s of a record
544  * of type @a type to the respective binary representation.
545  *
546  * @param type type of the record
547  * @param s human-readable string
548  * @param data set to value in binary encoding (will be allocated)
549  * @param data_size set to number of bytes in @a data
550  * @return #GNUNET_OK on success
551  */
552 int
553 GNUNET_NAMESTORE_string_to_value (uint32_t type,
554                                   const char *s,
555                                   void **data,
556                                   size_t *data_size);
557
558
559 /**
560  * Convert a type name (i.e. "AAAA") to the corresponding number.
561  *
562  * @param typename name to convert
563  * @return corresponding number, UINT32_MAX on error
564  */
565 uint32_t
566 GNUNET_NAMESTORE_typename_to_number (const char *typename);
567
568
569 /**
570  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
571  *
572  * @param type number of a type to convert
573  * @return corresponding typestring, NULL on error
574  */
575 const char *
576 GNUNET_NAMESTORE_number_to_typename (uint32_t type);
577
578
579 /**
580  * Test if a given record is expired.
581  * 
582  * @param rd record to test
583  * @return #GNUNET_YES if the record is expired,
584  *         #GNUNET_NO if not
585  */
586 int
587 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd);
588
589
590 /**
591  * Convert a UTF-8 string to UTF-8 lowercase
592  * @param src source string
593  * @return converted result
594  */
595 char *
596 GNUNET_NAMESTORE_normalize_string (const char *src);
597
598
599 /**
600  * Convert a zone to a string (for printing debug messages).
601  * This is one of the very few calls in the entire API that is
602  * NOT reentrant!
603  *
604  * @param z public key of a zone
605  * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s.
606  */
607 const char *
608 GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EccPublicSignKey *z);
609
610
611 /**
612  * Convert public key to the respective absolute domain name in the
613  * ".zkey" pTLD. 
614  * This is one of the very few calls in the entire API that is
615  * NOT reentrant!
616  * 
617  * @param pkey a public key with a point on the eliptic curve 
618  * @return string "X.zkey" where X is the coordinates of the public
619  *         key in an encoding suitable for DNS labels.
620  */
621 const char *
622 GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EccPublicSignKey *pkey);
623
624
625 /**
626  * Convert an absolute domain name in the ".zkey" pTLD to the
627  * respective public key.
628  * 
629  * @param zkey string "X.zkey" where X is the public
630  *         key in an encoding suitable for DNS labels.
631  * @param pkey set to a public key on the eliptic curve 
632  * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
633  */
634 int
635 GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
636                                struct GNUNET_CRYPTO_EccPublicSignKey *pkey);
637
638
639 /**
640  * Calculate the DHT query for a given @a label in a given @a zone.
641  * 
642  * @param zone private key of the zone
643  * @param label label of the record
644  * @param query hash to use for the query
645  */
646 void
647 GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *zone,
648                                          const char *label,
649                                          struct GNUNET_HashCode *query);
650
651
652 /**
653  * Calculate the DHT query for a given @a label in a given @a zone.
654  * 
655  * @param pub public key of the zone
656  * @param label label of the record
657  * @param query hash to use for the query
658  */
659 void
660 GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EccPublicSignKey *pub,
661                                         const char *label,
662                                         struct GNUNET_HashCode *query);
663
664
665 /**
666  * Sign name and records
667  *
668  * @param key the private key
669  * @param expire block expiration
670  * @param label the name for the records
671  * @param rd record data
672  * @param rd_count number of records in @a rd
673  */
674 struct GNUNET_NAMESTORE_Block *
675 GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
676                                struct GNUNET_TIME_Absolute expire,
677                                const char *label,
678                                const struct GNUNET_NAMESTORE_RecordData *rd,
679                                unsigned int rd_count);
680
681
682 /**
683  * Check if a signature is valid.  This API is used by the GNS Block
684  * to validate signatures received from the network.
685  *
686  * @param block block to verify
687  * @return #GNUNET_OK if the signature is valid
688  */
689 int
690 GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block);
691
692
693 /**
694  * Decrypt block.
695  *
696  * @param block block to decrypt
697  * @param zone_key public key of the zone
698  * @param label the name for the records
699  * @param proc function to call with the result
700  * @param proc_cls closure for @a proc
701  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was 
702  *        not well-formed
703  */
704 int
705 GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
706                                 const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key,
707                                 const char *label,
708                                 GNUNET_NAMESTORE_RecordCallback proc,
709                                 void *proc_cls);
710
711
712 /**
713  * Compares if two records are equal
714  *
715  * @param a a record
716  * @param b another record 
717  * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not.
718  */
719 int
720 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
721                               const struct GNUNET_NAMESTORE_RecordData *b);
722
723
724 /**
725  * Returns the expiration time of the given block of records. The block
726  * expiration time is the expiration time of the block with smallest
727  * expiration time.
728  *
729  * @param rd_count number of records given in @a rd
730  * @param rd array of records 
731  * @return absolute expiration time
732  */
733 struct GNUNET_TIME_Absolute
734 GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, 
735                                              const struct GNUNET_NAMESTORE_RecordData *rd);
736
737
738 #if 0                           /* keep Emacsens' auto-indent happy */
739 {
740 #endif
741 #ifdef __cplusplus
742 }
743 #endif
744
745 /* end of gnunet_namestore_service.h */
746 #endif