-commenting, removing dead message types
[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 delegation to DNS.
71  */
72 #define GNUNET_NAMESTORE_TYPE_GNS2DNS 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  *        then at the end once with NULL
317  * @param proc function to call on the matching block, or with
318  *        NULL if there is no matching block
319  * @param proc_cls closure for @a proc
320  * @return a handle that can be used to cancel
321  */
322 struct GNUNET_NAMESTORE_QueueEntry *
323 GNUNET_NAMESTORE_lookup_block (struct GNUNET_NAMESTORE_Handle *h, 
324                                const struct GNUNET_HashCode *derived_hash,
325                                GNUNET_NAMESTORE_BlockProcessor proc, void *proc_cls);
326
327
328 /**
329  * Process a record that was stored in the namestore.
330  *
331  * @param cls closure
332  * @param zone private key of the zone; NULL on disconnect
333  * @param label label of the records; NULL on disconnect
334  * @param rd_count number of entries in @a rd array, 0 if label was deleted
335  * @param rd array of records with data to store
336  */
337 typedef void (*GNUNET_NAMESTORE_RecordMonitor) (void *cls,
338                                                 const struct GNUNET_CRYPTO_EccPrivateKey *zone,
339                                                 const char *label,
340                                                 unsigned int rd_count,
341                                                 const struct GNUNET_NAMESTORE_RecordData *rd);
342
343
344 /**
345  * Look for an existing PKEY delegation record for a given public key.
346  * Returns at most one result to the processor.
347  *
348  * @param h handle to the namestore
349  * @param zone public key of the zone to look up in, never NULL
350  * @param value_zone public key of the target zone (value), never NULL
351  * @param proc function to call on the matching records, or with
352  *        NULL (rd_count == 0) if there are no matching records
353  * @param proc_cls closure for @a proc
354  * @return a handle that can be used to
355  *         cancel
356  */
357 struct GNUNET_NAMESTORE_QueueEntry *
358 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, 
359                                const struct GNUNET_CRYPTO_EccPrivateKey *zone,
360                                const struct GNUNET_CRYPTO_EccPublicSignKey *value_zone,
361                                GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls);
362
363
364 /**
365  * Process a records that were decrypted from a block.
366  *
367  * @param cls closure
368  * @param rd_count number of entries in @a rd array
369  * @param rd array of records with data to store
370  */
371 typedef void (*GNUNET_NAMESTORE_RecordCallback) (void *cls,
372                                                  unsigned int rd_count,
373                                                  const struct GNUNET_NAMESTORE_RecordData *rd);
374
375
376 /**
377  * Cancel a namestore operation.  The final callback from the
378  * operation must not have been done yet.  Must be called on any
379  * namestore operation that has not yet completed prior to calling
380  * #GNUNET_NAMESTORE_disconnect.
381  *
382  * @param qe operation to cancel
383  */
384 void
385 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe);
386
387
388 /**
389  * Starts a new zone iteration (used to periodically PUT all of our
390  * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
391  * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
392  * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
393  * immediately, and then again after
394  * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
395  *
396  * @param h handle to the namestore
397  * @param zone zone to access, NULL for all zones
398  * @param proc function to call on each name from the zone; it
399  *        will be called repeatedly with a value (if available)
400  *        and always once at the end with a name of NULL.
401  * @param proc_cls closure for @a proc
402  * @return an iterator handle to use for iteration
403  */
404 struct GNUNET_NAMESTORE_ZoneIterator *
405 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
406                                        const struct GNUNET_CRYPTO_EccPrivateKey *zone,
407                                        GNUNET_NAMESTORE_RecordMonitor proc,
408                                        void *proc_cls);
409
410
411 /**
412  * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
413  * for the next record.
414  *
415  * @param it the iterator
416  */
417 void
418 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it);
419
420
421 /**
422  * Stops iteration and releases the namestore handle for further calls.  Must
423  * be called on any iteration that has not yet completed prior to calling
424  * #GNUNET_NAMESTORE_disconnect.
425  *
426  * @param it the iterator
427  */
428 void
429 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it);
430
431
432 /**
433  * Handle for a monitoring activity.
434  */
435 struct GNUNET_NAMESTORE_ZoneMonitor;
436
437
438 /**
439  * Function called once the monitor has caught up with the current 
440  * state of the database.  Will be called AGAIN after each disconnect
441  * (record monitor called with 'NULL' for zone_key) once we're again
442  * in sync.
443  *
444  * @param cls closure
445  */
446 typedef void (*GNUNET_NAMESTORE_RecordsSynchronizedCallback)(void *cls);
447
448
449 /**
450  * Begin monitoring a zone for changes.  Will first call the @a monitor function
451  * on all existing records in the selected zone(s), then calls @a sync_cb,
452  * and then calls the @a monitor whenever a record changes.  If the namestore
453  * disconnects, the @a monitor function is called with a disconnect event; if
454  * the connection is re-established, the process begins from the start (all
455  * existing records, sync, then updates).
456  *
457  * @param cfg configuration to use to connect to namestore
458  * @param zone zone to monitor
459  * @param monitor function to call on zone changes
460  * @param sync_cb function called when we're in sync with the namestore
461  * @param cls closure for @a monitor and @a sync_cb
462  * @return handle to stop monitoring
463  */
464 struct GNUNET_NAMESTORE_ZoneMonitor *
465 GNUNET_NAMESTORE_zone_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
466                                      const struct GNUNET_CRYPTO_EccPrivateKey *zone,
467                                      GNUNET_NAMESTORE_RecordMonitor monitor,
468                                      GNUNET_NAMESTORE_RecordsSynchronizedCallback sync_cb,
469                                      void *cls);
470
471
472 /**
473  * Stop monitoring a zone for changes.
474  *
475  * @param zm handle to the monitor activity to stop
476  */
477 void
478 GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
479
480
481 /* convenience APIs for serializing / deserializing GNS records */
482
483 /**
484  * Calculate how many bytes we will need to serialize the given
485  * records.
486  *
487  * @param rd_count number of records in the @a rd array
488  * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
489  * @return the required size to serialize
490  */
491 size_t
492 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
493                                    const struct GNUNET_NAMESTORE_RecordData *rd);
494
495
496 /**
497  * Serialize the given records to the given destination buffer.
498  *
499  * @param rd_count number of records in the @a rd array
500  * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
501  * @param dest_size size of the destination array @a dst
502  * @param dest where to write the result
503  * @return the size of serialized records, -1 if records do not fit
504  */
505 ssize_t
506 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
507                                     const struct GNUNET_NAMESTORE_RecordData *rd,
508                                     size_t dest_size,
509                                     char *dest);
510
511
512 /**
513  * Deserialize the given records to the given destination.
514  *
515  * @param len size of the serialized record data
516  * @param src the serialized record data
517  * @param rd_count number of records in the @a dest array
518  * @param dest where to put the data
519  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
520  */
521 int
522 GNUNET_NAMESTORE_records_deserialize (size_t len,
523                                       const char *src,
524                                       unsigned int rd_count,
525                                       struct GNUNET_NAMESTORE_RecordData *dest);
526
527
528 /**
529  * Convert the binary value @a data of a record of 
530  * type @a type to a human-readable string.
531  *
532  * @param type type of the record
533  * @param data value in binary encoding
534  * @param data_size number of bytes in @a data
535  * @return NULL on error, otherwise human-readable representation of the value
536  */
537 char *
538 GNUNET_NAMESTORE_value_to_string (uint32_t type,
539                                   const void *data,
540                                   size_t data_size);
541
542
543 /**
544  * Convert human-readable version of the value @a s of a record
545  * of type @a type to the respective binary representation.
546  *
547  * @param type type of the record
548  * @param s human-readable string
549  * @param data set to value in binary encoding (will be allocated)
550  * @param data_size set to number of bytes in @a data
551  * @return #GNUNET_OK on success
552  */
553 int
554 GNUNET_NAMESTORE_string_to_value (uint32_t type,
555                                   const char *s,
556                                   void **data,
557                                   size_t *data_size);
558
559
560 /**
561  * Convert a type name (i.e. "AAAA") to the corresponding number.
562  *
563  * @param typename name to convert
564  * @return corresponding number, UINT32_MAX on error
565  */
566 uint32_t
567 GNUNET_NAMESTORE_typename_to_number (const char *dns_typename);
568
569
570 /**
571  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
572  *
573  * @param type number of a type to convert
574  * @return corresponding typestring, NULL on error
575  */
576 const char *
577 GNUNET_NAMESTORE_number_to_typename (uint32_t type);
578
579
580 /**
581  * Test if a given record is expired.
582  * 
583  * @param rd record to test
584  * @return #GNUNET_YES if the record is expired,
585  *         #GNUNET_NO if not
586  */
587 int
588 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd);
589
590
591 /**
592  * Convert a UTF-8 string to UTF-8 lowercase
593  * @param src source string
594  * @return converted result
595  */
596 char *
597 GNUNET_NAMESTORE_normalize_string (const char *src);
598
599
600 /**
601  * Convert a zone to a string (for printing debug messages).
602  * This is one of the very few calls in the entire API that is
603  * NOT reentrant!
604  *
605  * @param z public key of a zone
606  * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s.
607  */
608 const char *
609 GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EccPublicSignKey *z);
610
611
612 /**
613  * Convert public key to the respective absolute domain name in the
614  * ".zkey" pTLD. 
615  * This is one of the very few calls in the entire API that is
616  * NOT reentrant!
617  * 
618  * @param pkey a public key with a point on the eliptic curve 
619  * @return string "X.zkey" where X is the coordinates of the public
620  *         key in an encoding suitable for DNS labels.
621  */
622 const char *
623 GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EccPublicSignKey *pkey);
624
625
626 /**
627  * Convert an absolute domain name in the ".zkey" pTLD to the
628  * respective public key.
629  * 
630  * @param zkey string "X.zkey" where X is the public
631  *         key in an encoding suitable for DNS labels.
632  * @param pkey set to a public key on the eliptic curve 
633  * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
634  */
635 int
636 GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
637                                struct GNUNET_CRYPTO_EccPublicSignKey *pkey);
638
639
640 /**
641  * Calculate the DHT query for a given @a label in a given @a zone.
642  * 
643  * @param zone private key of the zone
644  * @param label label of the record
645  * @param query hash to use for the query
646  */
647 void
648 GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *zone,
649                                          const char *label,
650                                          struct GNUNET_HashCode *query);
651
652
653 /**
654  * Calculate the DHT query for a given @a label in a given @a zone.
655  * 
656  * @param pub public key of the zone
657  * @param label label of the record
658  * @param query hash to use for the query
659  */
660 void
661 GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EccPublicSignKey *pub,
662                                         const char *label,
663                                         struct GNUNET_HashCode *query);
664
665
666 /**
667  * Sign name and records
668  *
669  * @param key the private key
670  * @param expire block expiration
671  * @param label the name for the records
672  * @param rd record data
673  * @param rd_count number of records in @a rd
674  */
675 struct GNUNET_NAMESTORE_Block *
676 GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
677                                struct GNUNET_TIME_Absolute expire,
678                                const char *label,
679                                const struct GNUNET_NAMESTORE_RecordData *rd,
680                                unsigned int rd_count);
681
682
683 /**
684  * Check if a signature is valid.  This API is used by the GNS Block
685  * to validate signatures received from the network.
686  *
687  * @param block block to verify
688  * @return #GNUNET_OK if the signature is valid
689  */
690 int
691 GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block);
692
693
694 /**
695  * Decrypt block.
696  *
697  * @param block block to decrypt
698  * @param zone_key public key of the zone
699  * @param label the name for the records
700  * @param proc function to call with the result
701  * @param proc_cls closure for @a proc
702  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was 
703  *        not well-formed
704  */
705 int
706 GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
707                                 const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key,
708                                 const char *label,
709                                 GNUNET_NAMESTORE_RecordCallback proc,
710                                 void *proc_cls);
711
712
713 /**
714  * Compares if two records are equal
715  *
716  * @param a a record
717  * @param b another record 
718  * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not.
719  */
720 int
721 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
722                               const struct GNUNET_NAMESTORE_RecordData *b);
723
724
725 /**
726  * Returns the expiration time of the given block of records. The block
727  * expiration time is the expiration time of the block with smallest
728  * expiration time.
729  *
730  * @param rd_count number of records given in @a rd
731  * @param rd array of records 
732  * @return absolute expiration time
733  */
734 struct GNUNET_TIME_Absolute
735 GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, 
736                                              const struct GNUNET_NAMESTORE_RecordData *rd);
737
738
739 #if 0                           /* keep Emacsens' auto-indent happy */
740 {
741 #endif
742 #ifdef __cplusplus
743 }
744 #endif
745
746 /* end of gnunet_namestore_service.h */
747 #endif