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