- changes
[oweals/gnunet.git] / src / namestore / namestore_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 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 gns/namestore_api.c
23  * @brief API to access the NAMESTORE service
24  * @author Martin Schanzenbach
25  * @author Matthias Wachs
26  */
27
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_arm_service.h"
32 #include "gnunet_namestore_service.h"
33 #include "namestore.h"
34 #define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
35
36 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
37
38 /**
39  * A QueueEntry.
40  */
41 struct GNUNET_NAMESTORE_QueueEntry
42 {
43   struct GNUNET_NAMESTORE_QueueEntry *next;
44   struct GNUNET_NAMESTORE_QueueEntry *prev;
45
46   uint64_t op_id;
47
48   GNUNET_NAMESTORE_ContinuationWithStatus cont;
49   void *cont_cls;
50
51   GNUNET_NAMESTORE_RecordProcessor proc;
52   void *proc_cls;
53
54   char *data; /*stub data pointer*/
55 };
56
57
58 /**
59  * Message in linked list we should send to the service.  The
60  * actual binary message follows this struct.
61  */
62 struct PendingMessage
63 {
64
65   /**
66    * Kept in a DLL.
67    */
68   struct PendingMessage *next;
69
70   /**
71    * Kept in a DLL.
72    */
73   struct PendingMessage *prev;
74
75   /**
76    * Size of the message.
77    */
78   size_t size;
79
80   /**
81    * Is this the 'START' message?
82    */
83   int is_init;
84 };
85
86
87 /**
88  * Connection to the NAMESTORE service.
89  */
90 struct GNUNET_NAMESTORE_Handle
91 {
92
93   /**
94    * Configuration to use.
95    */
96   const struct GNUNET_CONFIGURATION_Handle *cfg;
97
98   /**
99    * Socket (if available).
100    */
101   struct GNUNET_CLIENT_Connection *client;
102
103   /**
104    * Currently pending transmission request (or NULL).
105    */
106   struct GNUNET_CLIENT_TransmitHandle *th;
107
108   /**
109    * Reconnect task
110    */
111   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
112
113   /**
114    * Pending messages to send to the service
115    */
116
117   struct PendingMessage * pending_head;
118   struct PendingMessage * pending_tail;
119
120   /**
121    * Should we reconnect to service due to some serious error?
122    */
123   int reconnect;
124
125
126   /**
127    * Pending namestore operations
128    */
129
130   struct GNUNET_NAMESTORE_QueueEntry * op_head;
131   struct GNUNET_NAMESTORE_QueueEntry * op_tail;
132
133   uint64_t op_id;
134 };
135
136 struct GNUNET_NAMESTORE_SimpleRecord
137 {
138   /**
139    * DLL
140    */
141   struct GNUNET_NAMESTORE_SimpleRecord *next;
142
143   /**
144    * DLL
145    */
146   struct GNUNET_NAMESTORE_SimpleRecord *prev;
147   
148   const char *name;
149   const GNUNET_HashCode *zone;
150   uint32_t record_type;
151   struct GNUNET_TIME_Absolute expiration;
152   enum GNUNET_NAMESTORE_RecordFlags flags;
153   size_t data_size;
154   const void *data;
155 };
156
157 /**
158  * Disconnect from service and then reconnect.
159  *
160  * @param nsh our handle
161  */
162 static void
163 force_reconnect (struct GNUNET_NAMESTORE_Handle *nsh);
164
165
166 /**
167  * Type of a function to call when we receive a message
168  * from the service.
169  *
170  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
171  * @param msg message received, NULL on timeout or fatal error
172  */
173 static void
174 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
175 {
176   struct GNUNET_NAMESTORE_Handle *nsh = cls;
177   struct GNUNET_NAMESTORE_QueueEntry *qe;
178   uint16_t size;
179   uint16_t type;
180   uint64_t op_id = UINT64_MAX;
181
182   if (NULL == msg)
183   {
184     force_reconnect (nsh);
185     return;
186   }
187
188   size = ntohs (msg->size);
189   type = ntohs (msg->type);
190
191   /* find matching operation */
192   if (op_id > nsh->op_id)
193   {
194     GNUNET_break_op (0);
195     GNUNET_CLIENT_receive (nsh->client, &process_namestore_message, nsh,
196                            GNUNET_TIME_UNIT_FOREVER_REL);
197     return;
198   }
199   for (qe = nsh->op_head; qe != NULL; qe = qe->next)
200   {
201     if (qe->op_id == op_id)
202       break;
203   }
204   if (qe == NULL)
205   {
206     GNUNET_break_op (0);
207     GNUNET_CLIENT_receive (nsh->client, &process_namestore_message, nsh,
208                            GNUNET_TIME_UNIT_FOREVER_REL);
209     return;
210   }
211
212   switch (type) {
213     case GNUNET_MESSAGE_TYPE_TEST:
214       /* handle message here */
215       break;
216     default:
217       break;
218   }
219   size++; // FIXME: just working around compiler warning here...
220   GNUNET_CLIENT_receive (nsh->client, &process_namestore_message, nsh,
221                          GNUNET_TIME_UNIT_FOREVER_REL);
222
223   if (GNUNET_YES == nsh->reconnect)
224     force_reconnect (nsh);
225 }
226
227
228 /**
229  * Transmit messages from the message queue to the service
230  * (if there are any, and if we are not already trying).
231  *
232  * @param nsh handle to use
233  */
234 static void
235 do_transmit (struct GNUNET_NAMESTORE_Handle *nsh);
236
237
238 /**
239  * We can now transmit a message to NAMESTORE. Do it.
240  *
241  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
242  * @param size number of bytes we can transmit
243  * @param buf where to copy the messages
244  * @return number of bytes copied into buf
245  */
246 static size_t
247 transmit_message_to_namestore (void *cls, size_t size, void *buf)
248 {
249   struct GNUNET_NAMESTORE_Handle *nsh = cls;
250   struct PendingMessage *p;
251   size_t ret;
252   char *cbuf;
253
254   nsh->th = NULL;
255   if ((size == 0) || (buf == NULL))
256   {
257     force_reconnect (nsh);
258     return 0;
259   }
260   ret = 0;
261   cbuf = buf;
262   while ((NULL != (p = nsh->pending_head)) && (p->size <= size))
263   {
264     memcpy (&cbuf[ret], &p[1], p->size);
265     ret += p->size;
266     size -= p->size;
267     GNUNET_CONTAINER_DLL_remove (nsh->pending_head, nsh->pending_tail, p);
268     if (GNUNET_YES == p->is_init)
269       GNUNET_CLIENT_receive (nsh->client, &process_namestore_message, nsh,
270                              GNUNET_TIME_UNIT_FOREVER_REL);
271     GNUNET_free (p);
272   }
273   do_transmit (nsh);
274   return ret;
275 }
276
277
278 /**
279  * Transmit messages from the message queue to the service
280  * (if there are any, and if we are not already trying).
281  *
282  * @param nsh handle to use
283  */
284 static void
285 do_transmit (struct GNUNET_NAMESTORE_Handle *nsh)
286 {
287   struct PendingMessage *p;
288
289   if (NULL != nsh->th)
290     return;
291   if (NULL == (p = nsh->pending_head))
292     return;
293   if (NULL == nsh->client)
294     return;                     /* currently reconnecting */
295
296   nsh->th = GNUNET_CLIENT_notify_transmit_ready (nsh->client, p->size,
297                                            GNUNET_TIME_UNIT_FOREVER_REL,
298                                            GNUNET_NO, &transmit_message_to_namestore,
299                                            nsh);
300 }
301
302
303 /**
304  * Try again to connect to namestore service.
305  *
306  * @param cls the handle to the namestore service
307  * @param tc scheduler context
308  */
309 static void
310 reconnect (struct GNUNET_NAMESTORE_Handle *nsh)
311 {
312   struct PendingMessage *p;
313   struct StartMessage *init;
314
315   GNUNET_assert (NULL == nsh->client);
316   nsh->client = GNUNET_CLIENT_connect ("namestore", nsh->cfg);
317   GNUNET_assert (NULL != nsh->client);
318
319   if ((NULL == (p = nsh->pending_head)) || (GNUNET_YES != p->is_init))
320   {
321     p = GNUNET_malloc (sizeof (struct PendingMessage) +
322                        sizeof (struct StartMessage));
323     p->size = sizeof (struct StartMessage);
324     p->is_init = GNUNET_YES;
325     init = (struct StartMessage *) &p[1];
326     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
327     init->header.size = htons (sizeof (struct StartMessage));
328     GNUNET_CONTAINER_DLL_insert (nsh->pending_head, nsh->pending_tail, p);
329   }
330   do_transmit (nsh);
331 }
332
333 /**
334  * Re-establish the connection to the service.
335  *
336  * @param cls handle to use to re-connect.
337  * @param tc scheduler context
338  */
339 static void
340 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
341 {
342   struct GNUNET_NAMESTORE_Handle *nsh = cls;
343
344   nsh->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
345   reconnect (nsh);
346 }
347
348
349 /**
350  * Disconnect from service and then reconnect.
351  *
352  * @param nsh our handle
353  */
354 static void
355 force_reconnect (struct GNUNET_NAMESTORE_Handle *nsh)
356 {
357   nsh->reconnect = GNUNET_NO;
358   GNUNET_CLIENT_disconnect (nsh->client, GNUNET_NO);
359   nsh->client = NULL;
360   nsh->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
361                                     &reconnect_task,
362                                     nsh);
363 }
364
365 static void
366 enqeue_namestore_operation (struct GNUNET_NAMESTORE_Handle *nsh, struct GNUNET_NAMESTORE_QueueEntry *qe)
367 {
368   qe->op_id = nsh->op_id;
369   nsh->op_id ++;
370   GNUNET_CONTAINER_DLL_insert(nsh->op_head, nsh->op_tail, qe);
371 }
372
373 /**
374  * Initialize the connection with the NAMESTORE service.
375  *
376  * @param cfg configuration to use
377  * @return handle to the GNS service, or NULL on error
378  */
379 struct GNUNET_NAMESTORE_Handle *
380 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
381 {
382   struct GNUNET_NAMESTORE_Handle *nsh;
383
384   nsh = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
385   nsh->cfg = cfg;
386   nsh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, nsh);
387   nsh->op_id = 0;
388   return nsh;
389 }
390
391 /**
392  * Shutdown connection with the NAMESTORE service.
393  *
394  * @param handle handle of the NAMESTORE connection to stop
395  */
396 void
397 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *nsh, int drop)
398 {
399   struct PendingMessage *p;
400   struct GNUNET_NAMESTORE_QueueEntry *q;
401
402   while (NULL != (p = nsh->pending_head))
403   {
404     GNUNET_CONTAINER_DLL_remove (nsh->pending_head, nsh->pending_tail, p);
405     GNUNET_free (p);
406   }
407
408   while (NULL != (q = nsh->op_head))
409   {
410     GNUNET_CONTAINER_DLL_remove (nsh->op_head, nsh->op_tail, q);
411     GNUNET_free (q);
412   }
413
414   if (NULL != nsh->client)
415   {
416     GNUNET_CLIENT_disconnect (nsh->client, GNUNET_NO);
417     nsh->client = NULL;
418   }
419   if (GNUNET_SCHEDULER_NO_TASK != nsh->reconnect_task)
420   {
421     GNUNET_SCHEDULER_cancel (nsh->reconnect_task);
422     nsh->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
423   }
424   GNUNET_free(nsh);
425   nsh = NULL;
426 }
427
428
429 /**
430  * Store an item in the namestore.  If the item is already present,
431  * the expiration time is updated to the max of the existing time and
432  * the new time.  This API is used when we cache signatures from other
433  * authorities.
434  *
435  * @param h handle to the namestore
436  * @param zone hash of the public key of the zone
437  * @param name name that is being mapped (at most 255 characters long)
438  * @param expire when does the corresponding block in the DHT expire (until
439  *               when should we never do a DHT lookup for the same name again)?
440  * @param rd_count number of entries in 'rd' array
441  * @param rd array of records with data to store
442  * @param signature signature for all the records in the zone under the given name
443  * @param cont continuation to call when done
444  * @param cont_cls closure for cont
445  * @return handle to abort the request
446  */
447 struct GNUNET_NAMESTORE_QueueEntry *
448 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
449                              const GNUNET_HashCode *zone,
450                              const char *name,
451                              struct GNUNET_TIME_Absolute expire,
452                              unsigned int rd_count,
453                              const struct GNUNET_NAMESTORE_RecordData *rd,
454                              const struct GNUNET_CRYPTO_RsaSignature *signature,
455                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
456                              void *cont_cls)
457 {
458   struct GNUNET_NAMESTORE_QueueEntry *qe;
459   struct PendingMessage *pe;
460   size_t msg_size = 0;
461
462   GNUNET_assert (NULL != h);
463
464   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
465   qe->cont = cont;
466   qe->cont_cls = cont_cls;
467   enqeue_namestore_operation(h, qe);
468
469   /* set msg_size*/
470   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
471
472   /* create msg here */
473
474   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
475   do_transmit(h);
476
477 #if 0
478   struct GNUNET_NAMESTORE_SimpleRecord *sr;
479   sr = GNUNET_malloc(sizeof(struct GNUNET_NAMESTORE_SimpleRecord));
480   sr->name = name;
481   sr->record_type = record_type;
482   sr->expiration = expiration;
483   sr->flags = flags;
484   sr->data_size = data_size;
485   sr->data = data;
486   GNUNET_CONTAINER_DLL_insert(h->records_head, h->records_tail, sr);
487 #endif
488   return qe;
489 }
490
491
492 /**
493  * Check if a signature is valid.  This API is used by the GNS Block
494  * to validate signatures received from the network.
495  *
496  * @param public_key public key of the zone
497  * @param name name that is being mapped (at most 255 characters long)
498  * @param rd_count number of entries in 'rd' array
499  * @param rd array of records with data to store
500  * @param signature signature for all the records in the zone under the given name
501  * @return GNUNET_OK if the signature is valid
502  */
503 int
504 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
505                                    const char *name,
506                                    unsigned int rd_count,
507                                    const struct GNUNET_NAMESTORE_RecordData *rd,
508                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
509 {
510   return GNUNET_SYSERR;
511 }
512
513 /**
514  * Store an item in the namestore.  If the item is already present,
515  * the expiration time is updated to the max of the existing time and
516  * the new time.  This API is used by the authority of a zone.
517  *
518  * @param h handle to the namestore
519  * @param pkey private key of the zone
520  * @param name name that is being mapped (at most 255 characters long)
521  * @param rd record data to store
522  * @param cont continuation to call when done
523  * @param cont_cls closure for cont
524  * @return handle to abort the request
525  */
526 struct GNUNET_NAMESTORE_QueueEntry *
527 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
528                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
529                                 const char *name,
530                                 const struct GNUNET_NAMESTORE_RecordData *rd,
531                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
532                                 void *cont_cls)
533 {
534   struct GNUNET_NAMESTORE_QueueEntry *qe;
535   struct PendingMessage *pe;
536   size_t msg_size = 0;
537
538   GNUNET_assert (NULL != h);
539
540   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
541   qe->cont = cont;
542   qe->cont_cls = cont_cls;
543   enqeue_namestore_operation(h, qe);
544
545   /* set msg_size*/
546   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
547
548   /* create msg here */
549
550   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
551   do_transmit(h);
552   return qe;
553 }
554
555
556 /**
557  * Explicitly remove some content from the database.  The
558  * "cont"inuation will be called with status "GNUNET_OK" if content
559  * was removed, "GNUNET_NO" if no matching entry was found and
560  * "GNUNET_SYSERR" on all other types of errors.
561  * This API is used by the authority of a zone.
562  *
563  * @param h handle to the namestore
564  * @param pkey private key of the zone
565  * @param name name that is being mapped (at most 255 characters long)
566  * @param rd record data
567  * @param cont continuation to call when done
568  * @param cont_cls closure for cont
569  * @return handle to abort the request
570  */
571 struct GNUNET_NAMESTORE_QueueEntry *
572 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
573                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
574                                 const char *name,
575                                 const struct GNUNET_NAMESTORE_RecordData *rd,
576                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
577                                 void *cont_cls)
578 {
579   struct GNUNET_NAMESTORE_QueueEntry *qe;
580   struct PendingMessage *pe;
581   size_t msg_size = 0;
582
583   GNUNET_assert (NULL != h);
584
585   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
586   qe->cont = cont;
587   qe->cont_cls = cont_cls;
588   enqeue_namestore_operation(h, qe);
589
590   /* set msg_size*/
591   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
592
593   /* create msg here */
594
595   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
596   do_transmit(h);
597
598 #if 0
599   struct GNUNET_NAMESTORE_SimpleRecord *iter;
600   for (iter=h->records_head; iter != NULL; iter=iter->next)
601   {
602     if (strcmp ( iter->name, name ) &&
603         iter->record_type == record_type &&
604         GNUNET_CRYPTO_hash_cmp (iter->zone, zone))
605       break;
606   }
607   if (iter)
608     GNUNET_CONTAINER_DLL_remove(h->records_head,
609                                 h->records_tail,
610                                 iter);
611 #endif
612   return qe;
613 }
614
615
616 /**
617  * Get a result for a particular key from the namestore.  The processor
618  * will only be called once.  
619  *
620  * @param h handle to the namestore
621  * @param zone zone to look up a record from
622  * @param name name to look up
623  * @param record_type desired record type, 0 for all
624  * @param proc function to call on the matching records, or with
625  *        NULL (rd_count == 0) if there are no matching records
626  * @param proc_cls closure for proc
627  * @return a handle that can be used to
628  *         cancel
629  */
630 struct GNUNET_NAMESTORE_QueueEntry *
631 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
632                               const GNUNET_HashCode *zone,
633                               const char *name,
634                               uint32_t record_type,
635                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
636 {
637   struct GNUNET_NAMESTORE_QueueEntry *qe;
638   struct PendingMessage *pe;
639   size_t msg_size = 0;
640
641   GNUNET_assert (NULL != h);
642
643   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
644   qe->proc = proc;
645   qe->proc_cls = proc_cls;
646   enqeue_namestore_operation(h, qe);
647
648   /* set msg_size*/
649   msg_size = sizeof (struct LookupNameMessage);
650   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
651
652   /* create msg here */
653
654   struct LookupNameMessage * msg;
655   pe->size = msg_size;
656   pe->is_init = GNUNET_NO;
657   msg = (struct LookupNameMessage *) &pe[1];
658   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
659   msg->header.size = htons (msg_size);
660
661   /* create msg done */
662
663   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
664   do_transmit(h);
665
666 #if 0
667   struct GNUNET_NAMESTORE_SimpleRecord *iter;
668   for (iter=h->records_head; iter != NULL; iter=iter->next)
669   {
670     proc(proc_cls, iter->zone, iter->name, iter->record_type,
671        iter->expiration,
672        iter->flags,
673        NULL /*sig loc*/,
674        iter->data_size /*size*/,
675        iter->data /* data */);
676   }
677   proc(proc_cls, zone, name, record_type,
678        GNUNET_TIME_absolute_get_forever(), 0, NULL, 0, NULL); /*TERMINATE*/
679 #endif
680
681
682
683   return qe;
684 }
685
686
687
688 /**
689  * Starts a new zone iteration (used to periodically PUT all of our
690  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
691  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
692  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
693  * immediately, and then again after
694  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
695  *
696  * @param h handle to the namestore
697  * @param zone zone to access, NULL for all zones
698  * @param must_have_flags flags that must be set for the record to be returned
699  * @param must_not_have_flags flags that must NOT be set for the record to be returned
700  * @param proc function to call on each name from the zone; it
701  *        will be called repeatedly with a value (if available)
702  *        and always once at the end with a name of NULL.
703  * @param proc_cls closure for proc
704  * @return an iterator handle to use for iteration
705  */
706 struct GNUNET_NAMESTORE_ZoneIterator *
707 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
708                                        const GNUNET_HashCode *zone,
709                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
710                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
711                                        GNUNET_NAMESTORE_RecordProcessor proc,
712                                        void *proc_cls)
713 {
714   return NULL;
715 }
716
717
718 /**
719  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
720  * for the next record.
721  *
722  * @param it the iterator
723  */
724 void
725 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
726 {
727 }
728
729
730 /**
731  * Stops iteration and releases the namestore handle for further calls.
732  *
733  * @param it the iterator
734  */
735 void
736 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
737 {
738 }
739
740
741 /**
742  * Cancel a namestore operation.  The final callback from the
743  * operation must not have been done yet.
744  *
745  * @param qe operation to cancel
746  */
747 void
748 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
749 {
750   if (qe)
751     GNUNET_free(qe);
752 }
753
754 /* end of namestore_api.c */