-renaming gnunet-gns to gnunet-namestore
[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 namestore/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_crypto_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_dnsparser_lib.h"
33 #include "gnunet_arm_service.h"
34 #include "gnunet_signatures.h"
35 #include "gnunet_namestore_service.h"
36 #include "namestore.h"
37
38 #define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
39
40 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
41
42 /**
43  * A QueueEntry.
44  */
45 struct GNUNET_NAMESTORE_QueueEntry
46 {
47
48   /**
49    * Kept in a DLL.
50    */
51   struct GNUNET_NAMESTORE_QueueEntry *next;
52
53   /**
54    * Kept in a DLL.
55    */
56   struct GNUNET_NAMESTORE_QueueEntry *prev;
57
58   struct GNUNET_NAMESTORE_Handle *nsh;
59
60   uint32_t op_id;
61
62   GNUNET_NAMESTORE_ContinuationWithStatus cont;
63   void *cont_cls;
64
65   GNUNET_NAMESTORE_RecordProcessor proc;
66   void *proc_cls;
67
68   char *data; /*stub data pointer*/
69 };
70
71
72 /**
73  * Zone iterator
74  */
75 struct GNUNET_NAMESTORE_ZoneIterator
76 {
77
78   /**
79    * Kept in a DLL.
80    */
81   struct GNUNET_NAMESTORE_ZoneIterator *next;
82
83   /**
84    * Kept in a DLL.
85    */
86   struct GNUNET_NAMESTORE_ZoneIterator *prev;
87
88   uint32_t op_id;
89
90   struct GNUNET_NAMESTORE_Handle *h;
91   GNUNET_NAMESTORE_RecordProcessor proc;
92   void* proc_cls;
93   GNUNET_HashCode zone;
94   uint32_t no_flags;
95   uint32_t flags;
96 };
97
98
99 /**
100  * Message in linked list we should send to the service.  The
101  * actual binary message follows this struct.
102  */
103 struct PendingMessage
104 {
105
106   /**
107    * Kept in a DLL.
108    */
109   struct PendingMessage *next;
110
111   /**
112    * Kept in a DLL.
113    */
114   struct PendingMessage *prev;
115
116   /**
117    * Size of the message.
118    */
119   size_t size;
120
121   /**
122    * Is this the 'START' message?
123    */
124   int is_init;
125 };
126
127
128 /**
129  * Connection to the NAMESTORE service.
130  */
131 struct GNUNET_NAMESTORE_Handle
132 {
133
134   /**
135    * Configuration to use.
136    */
137   const struct GNUNET_CONFIGURATION_Handle *cfg;
138
139   /**
140    * Socket (if available).
141    */
142   struct GNUNET_CLIENT_Connection *client;
143
144   /**
145    * Currently pending transmission request (or NULL).
146    */
147   struct GNUNET_CLIENT_TransmitHandle *th;
148
149   /**
150    * Reconnect task
151    */
152   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
153
154   /**
155    * Pending messages to send to the service
156    */
157
158   struct PendingMessage * pending_head;
159   struct PendingMessage * pending_tail;
160
161   /**
162    * Should we reconnect to service due to some serious error?
163    */
164   int reconnect;
165
166
167   /**
168    * Pending namestore queue entries
169    */
170   struct GNUNET_NAMESTORE_QueueEntry * op_head;
171   struct GNUNET_NAMESTORE_QueueEntry * op_tail;
172
173   uint32_t op_id;
174
175   /**
176    * Pending namestore zone iterator entries
177    */
178   struct GNUNET_NAMESTORE_ZoneIterator * z_head;
179   struct GNUNET_NAMESTORE_ZoneIterator * z_tail;
180 };
181
182 struct GNUNET_NAMESTORE_SimpleRecord
183 {
184   /**
185    * DLL
186    */
187   struct GNUNET_NAMESTORE_SimpleRecord *next;
188
189   /**
190    * DLL
191    */
192   struct GNUNET_NAMESTORE_SimpleRecord *prev;
193   
194   const char *name;
195   const GNUNET_HashCode *zone;
196   uint32_t record_type;
197   struct GNUNET_TIME_Absolute expiration;
198   enum GNUNET_NAMESTORE_RecordFlags flags;
199   size_t data_size;
200   const void *data;
201 };
202
203
204
205 /**
206  * Convert a type name (i.e. "AAAA") to the corresponding number.
207  *
208  * @param typename name to convert
209  * @return corresponding number, UINT32_MAX on error
210  */
211 uint32_t
212 GNUNET_NAMESTORE_typename_to_number (const char *typename)
213 {
214   static struct { 
215     const char *name; 
216     uint32_t number; 
217   } map[] = {
218     { "A", GNUNET_DNSPARSER_TYPE_A },
219     { "NS", GNUNET_DNSPARSER_TYPE_NS },
220     { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
221     { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
222     { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
223     { "MX", GNUNET_DNSPARSER_TYPE_MX },
224     { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
225     { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
226     { "PKEY",  GNUNET_GNS_TYPE_PKEY },
227     { "PSEU",  GNUNET_GNS_TYPE_PSEU },
228     { NULL, UINT32_MAX }
229   };
230   unsigned int i;
231
232   i=0;
233   while ( (map[i].name != NULL) &&
234           (0 != strcasecmp (typename, map[i].name)) )
235     i++;
236   return map[i].number;  
237 }
238
239
240 /**
241  * Disconnect from service and then reconnect.
242  *
243  * @param h our handle
244  */
245 static void
246 force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
247
248 static void
249 handle_lookup_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
250                              struct LookupNameResponseMessage * msg,
251                              size_t size)
252 {
253   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
254               "LOOKUP_NAME_RESPONSE");
255
256   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
257   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
258   char *name;
259   char * rd_tmp;
260
261   struct GNUNET_CRYPTO_RsaSignature *signature = NULL;
262   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy;
263   struct GNUNET_TIME_Absolute expire;
264   size_t exp_msg_len;
265   size_t msg_len = 0;
266   size_t name_len = 0;
267   size_t rd_len = 0;
268   int contains_sig = GNUNET_NO;
269   int rd_count = 0;
270
271   rd_len = ntohs (msg->rd_len);
272   rd_count = ntohs (msg->rd_count);
273   msg_len = ntohs (msg->gns_header.header.size);
274   name_len = ntohs (msg->name_len);
275   contains_sig = ntohs (msg->contains_sig);
276   expire = GNUNET_TIME_absolute_ntoh(msg->expire);
277
278   exp_msg_len = sizeof (struct LookupNameResponseMessage) +
279       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
280       name_len +
281       rd_len +
282       contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
283
284   if (msg_len != exp_msg_len)
285   {
286     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message size describes with `%u' bytes but calculated size is %u bytes \n",
287                 msg_len, exp_msg_len);
288     GNUNET_break_op (0);
289     return;
290   }
291
292   zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
293   name = (char *) &zone_key[1];
294   rd_tmp = &name[name_len];
295
296   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
297   GNUNET_NAMESTORE_records_deserialize(rd_len, rd_tmp, rd_count, rd);
298
299   /* reset values if values not contained */
300   if (contains_sig == GNUNET_NO)
301     signature = NULL;
302   else
303     signature = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[rd_len];
304   if (name_len == 0)
305     name = NULL;
306
307   memset (&dummy, '0', sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
308   if (0 == memcmp (zone_key, &dummy, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
309       zone_key = NULL;
310
311   if (qe->proc != NULL)
312   {
313     qe->proc (qe->proc_cls, zone_key, expire, name, rd_count, (rd_count > 0) ? rd : NULL, signature);
314   }
315
316   /* Operation done, remove */
317   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
318   GNUNET_free (qe);
319 }
320
321
322 static void
323 handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
324                              struct RecordPutResponseMessage* msg,
325                              size_t size)
326 {
327   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
328               "RECORD_PUT_RESPONSE");
329
330   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
331   int res = GNUNET_OK;
332
333   if (ntohs (msg->op_result) == GNUNET_OK)
334   {
335     res = GNUNET_OK;
336     if (qe->cont != NULL)
337     {
338       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
339     }
340
341   }
342   else if (ntohs (msg->op_result) == GNUNET_NO)
343   {
344     res = GNUNET_SYSERR;
345     if (qe->cont != NULL)
346     {
347       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
348     }
349   }
350   else
351   {
352     GNUNET_break_op (0);
353     return;
354   }
355
356   /* Operation done, remove */
357   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
358
359   GNUNET_free (qe);
360 }
361
362
363 static void
364 handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
365                              struct RecordCreateResponseMessage* msg,
366                              size_t size)
367 {
368   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
369               "RECORD_CREATE_RESPONSE");
370
371   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
372
373   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' %i\n",
374               "RECORD_CREATE_RESPONSE", ntohs (msg->op_result));
375   if (ntohs (msg->op_result) == GNUNET_YES)
376   {
377     if (qe->cont != NULL)
378     {
379       qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore added record successfully"));
380     }
381
382   }
383   else if (ntohs (msg->op_result) == GNUNET_NO)
384   {
385     if (qe->cont != NULL)
386     {
387       qe->cont (qe->cont_cls, GNUNET_NO, _("Namestore record already existed"));
388     }
389   }
390   else
391   {
392     if (qe->cont != NULL)
393     {
394       qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Namestore failed to add record\n"));
395     }
396   }
397
398   /* Operation done, remove */
399   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
400
401   GNUNET_free (qe);
402 }
403
404
405 static void
406 handle_record_remove_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
407                              struct RecordRemoveResponseMessage* msg,
408                              size_t size)
409 {
410   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
411               "RECORD_REMOVE_RESPONSE");
412
413   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
414   int res = ntohs (msg->op_result);
415
416   /**
417    *  result:
418    *  0 : successful
419    *  1 : No records for entry
420    *  2 : Could not find record to remove
421    *  3 : Failed to create new signature
422    *  4 : Failed to put new set of records in database
423    */
424   switch (res) {
425     case 0:
426       if (qe->cont != NULL)
427       {
428         qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore removed record successfully"));
429       }
430
431       break;
432     case 1:
433       if (qe->cont != NULL)
434       {
435         qe->cont (qe->cont_cls, GNUNET_NO, _("No records for entry"));
436       }
437
438       break;
439     case 2:
440       if (qe->cont != NULL)
441       {
442         qe->cont (qe->cont_cls, GNUNET_NO, _("Could not find record to remove"));
443       }
444
445       break;
446     case 3:
447       if (qe->cont != NULL)
448       {
449         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to create new signature"));
450       }
451
452       break;
453     case 4:
454       if (qe->cont != NULL)
455       {
456         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to put new set of records in database"));
457       }
458       break;
459     default:
460         GNUNET_break_op (0);
461       break;
462   }
463
464   /* Operation done, remove */
465   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
466
467   GNUNET_free (qe);
468 }
469
470
471 static void
472 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
473                           const struct GNUNET_MessageHeader *msg,
474                           int type, size_t size)
475 {
476
477   /* handle different message type */
478   switch (type) {
479     case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
480         if (size < sizeof (struct LookupNameResponseMessage))
481         {
482           GNUNET_break_op (0);
483           break;
484         }
485         handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size);
486       break;
487     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
488         if (size != sizeof (struct RecordPutResponseMessage))
489         {
490           GNUNET_break_op (0);
491           break;
492         }
493         handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size);
494       break;
495     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE:
496         if (size != sizeof (struct RecordCreateResponseMessage))
497         {
498           GNUNET_break_op (0);
499           break;
500         }
501         handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size);
502       break;
503     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE:
504         if (size != sizeof (struct RecordRemoveResponseMessage))
505         {
506           GNUNET_break_op (0);
507           break;
508         }
509         handle_record_remove_response (qe, (struct RecordRemoveResponseMessage *) msg, size);
510       break;
511     default:
512       GNUNET_break_op (0);
513       break;
514   }
515 }
516
517 static void
518 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
519                                 struct ZoneIterationResponseMessage *msg,
520                                 size_t size)
521 {
522   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
523               "ZONE_ITERATION_RESPONSE");
524
525
526   if (ze->proc != NULL)
527   {
528     // FIXME
529     ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL);
530   }
531 }
532
533
534 static void
535 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
536                         const struct GNUNET_MessageHeader *msg,
537                         int type, size_t size)
538 {
539
540   /* handle different message type */
541   switch (type) {
542     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
543         if (size < sizeof (struct ZoneIterationResponseMessage))
544         {
545           GNUNET_break_op (0);
546           break;
547         }
548         handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size);
549       break;
550     default:
551       GNUNET_break_op (0);
552       break;
553   }
554 }
555
556 /**
557  * Type of a function to call when we receive a message
558  * from the service.
559  *
560  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
561  * @param msg message received, NULL on timeout or fatal error
562  */
563 static void
564 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
565 {
566   struct GNUNET_NAMESTORE_Handle *h = cls;
567   struct GNUNET_NAMESTORE_Header * gm;
568   struct GNUNET_NAMESTORE_QueueEntry *qe;
569   struct GNUNET_NAMESTORE_ZoneIterator *ze;
570   uint16_t size;
571   uint16_t type;
572   uint32_t r_id = UINT32_MAX;
573
574   if (NULL == msg)
575   {
576     force_reconnect (h);
577     return;
578   }
579
580   size = ntohs (msg->size);
581   type = ntohs (msg->type);
582
583   if (size < sizeof (struct GNUNET_NAMESTORE_Header))
584   {
585     GNUNET_break_op (0);
586     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
587                            GNUNET_TIME_UNIT_FOREVER_REL);
588     return;
589   }
590
591   gm = (struct GNUNET_NAMESTORE_Header *) msg;
592   r_id = ntohl (gm->r_id);
593
594   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, r_id);
595
596   /* Find matching operation */
597   if (r_id > h->op_id)
598   {
599     /* No matching pending operation found */
600     GNUNET_break_op (0);
601     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
602                            GNUNET_TIME_UNIT_FOREVER_REL);
603     return;
604   }
605
606   /* Is it a record related operation ? */
607   for (qe = h->op_head; qe != NULL; qe = qe->next)
608   {
609     if (qe->op_id == r_id)
610       break;
611   }
612   if (qe != NULL)
613   {
614     manage_record_operations (qe, msg, type, size);
615   }
616
617   /* Is it a zone iteration operation ? */
618   for (ze = h->z_head; ze != NULL; ze = ze->next)
619   {
620     if (ze->op_id == r_id)
621       break;
622   }
623   if (ze != NULL)
624   {
625     manage_zone_operations (ze, msg, type, size);
626   }
627
628   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
629                          GNUNET_TIME_UNIT_FOREVER_REL);
630
631   if (GNUNET_YES == h->reconnect)
632     force_reconnect (h);
633
634 }
635
636
637 /**
638  * Transmit messages from the message queue to the service
639  * (if there are any, and if we are not already trying).
640  *
641  * @param h handle to use
642  */
643 static void
644 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
645
646
647 /**
648  * We can now transmit a message to NAMESTORE. Do it.
649  *
650  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
651  * @param size number of bytes we can transmit
652  * @param buf where to copy the messages
653  * @return number of bytes copied into buf
654  */
655 static size_t
656 transmit_message_to_namestore (void *cls, size_t size, void *buf)
657 {
658   struct GNUNET_NAMESTORE_Handle *h = cls;
659   struct PendingMessage *p;
660   size_t ret;
661   char *cbuf;
662
663   h->th = NULL;
664   if ((size == 0) || (buf == NULL))
665   {
666     force_reconnect (h);
667     return 0;
668   }
669   ret = 0;
670   cbuf = buf;
671   while ((NULL != (p = h->pending_head)) && (p->size <= size))
672   {
673     memcpy (&cbuf[ret], &p[1], p->size);
674     ret += p->size;
675     size -= p->size;
676     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
677     if (GNUNET_YES == p->is_init)
678       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
679                              GNUNET_TIME_UNIT_FOREVER_REL);
680     GNUNET_free (p);
681   }
682   do_transmit (h);
683   return ret;
684 }
685
686
687 /**
688  * Transmit messages from the message queue to the service
689  * (if there are any, and if we are not already trying).
690  *
691  * @param h handle to use
692  */
693 static void
694 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
695 {
696   struct PendingMessage *p;
697
698   if (NULL != h->th)
699     return;
700   if (NULL == (p = h->pending_head))
701     return;
702   if (NULL == h->client)
703     return;                     /* currently reconnecting */
704
705   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
706                                            GNUNET_TIME_UNIT_FOREVER_REL,
707                                            GNUNET_NO, &transmit_message_to_namestore,
708                                            h);
709 }
710
711
712 /**
713  * Reconnect to namestore service.
714  *
715  * @param h the handle to the namestore service
716  */
717 static void
718 reconnect (struct GNUNET_NAMESTORE_Handle *h)
719 {
720   struct PendingMessage *p;
721   struct StartMessage *init;
722
723   GNUNET_assert (NULL == h->client);
724   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
725   GNUNET_assert (NULL != h->client);
726
727   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
728   {
729     p = GNUNET_malloc (sizeof (struct PendingMessage) +
730                        sizeof (struct StartMessage));
731     p->size = sizeof (struct StartMessage);
732     p->is_init = GNUNET_YES;
733     init = (struct StartMessage *) &p[1];
734     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
735     init->header.size = htons (sizeof (struct StartMessage));
736     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
737   }
738   do_transmit (h);
739 }
740
741 /**
742  * Re-establish the connection to the service.
743  *
744  * @param cls handle to use to re-connect.
745  * @param tc scheduler context
746  */
747 static void
748 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
749 {
750   struct GNUNET_NAMESTORE_Handle *h = cls;
751
752   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
753   reconnect (h);
754 }
755
756
757 /**
758  * Disconnect from service and then reconnect.
759  *
760  * @param h our handle
761  */
762 static void
763 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
764 {
765   h->reconnect = GNUNET_NO;
766   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
767   h->client = NULL;
768   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
769                                     &reconnect_task,
770                                     h);
771 }
772
773 static uint32_t
774 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
775 {
776   uint32_t op_id = h->op_id;
777   h->op_id ++;
778   return op_id;
779 }
780
781 /**
782  * Initialize the connection with the NAMESTORE service.
783  *
784  * @param cfg configuration to use
785  * @return handle to the GNS service, or NULL on error
786  */
787 struct GNUNET_NAMESTORE_Handle *
788 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
789 {
790   struct GNUNET_NAMESTORE_Handle *h;
791
792   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
793   h->cfg = cfg;
794   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
795   h->op_id = 0;
796   return h;
797 }
798
799 struct DisconnectContext
800 {
801   struct GNUNET_NAMESTORE_Handle *h;
802   int drop;
803 };
804
805 static void
806 clean_up_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
807 {
808   struct PendingMessage *p;
809   struct GNUNET_NAMESTORE_QueueEntry *q;
810   struct GNUNET_NAMESTORE_ZoneIterator *z;
811   struct GNUNET_NAMESTORE_Handle *h = cls;
812   GNUNET_assert (h != NULL);
813   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
814   while (NULL != (p = h->pending_head))
815   {
816     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
817     GNUNET_free (p);
818   }
819
820   while (NULL != (q = h->op_head))
821   {
822     GNUNET_break (0);
823     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
824     GNUNET_free (q);
825   }
826
827   while (NULL != (z = h->z_head))
828   {
829     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
830     GNUNET_free (z);
831   }
832
833   if (NULL != h->client)
834   {
835     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
836     h->client = NULL;
837   }
838   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
839   {
840     GNUNET_SCHEDULER_cancel (h->reconnect_task);
841     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
842   }
843   GNUNET_free(h);
844   h = NULL;
845 };
846
847 static size_t
848 transmit_disconnect_to_namestore (void *cls, size_t size, void *buf)
849 {
850   struct DisconnectContext * d_ctx = cls;
851   struct DisconnectMessage d_msg;
852   struct GNUNET_NAMESTORE_Handle *h = d_ctx->h;
853   int res;
854
855   d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_DISCONNECT);
856   d_msg.header.size = htons (sizeof (struct DisconnectMessage));
857   d_msg.drop = htonl (d_ctx->drop);
858
859   h->th = NULL;
860   if ((size == 0) || (buf == NULL) || (size < sizeof (struct DisconnectMessage)))
861   {
862     GNUNET_break (0);
863     res = 0;
864   }
865   else
866   {
867     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to service \n", "NAMESTORE_DISCONNECT");
868     memcpy (buf, &d_msg, sizeof (struct DisconnectMessage));
869     res = sizeof (struct DisconnectMessage);
870   }
871
872   GNUNET_SCHEDULER_add_now (&clean_up_task, h);
873   GNUNET_free (d_ctx);
874   return res;
875 }
876
877 /**
878  * Disconnect from the namestore service (and free associated
879  * resources).
880  *
881  * @param h handle to the namestore
882  * @param drop set to GNUNET_YES to delete all data in namestore (!)
883  */
884 void
885 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
886 {
887   if (h->th != NULL)
888   {
889     GNUNET_CLIENT_notify_transmit_ready_cancel(h->th);
890     h->th = NULL;
891   }
892   if (h->client != NULL)
893   {
894     struct DisconnectContext *d_ctx = GNUNET_malloc (sizeof (struct DisconnectContext));
895     d_ctx->h = h;
896     d_ctx->drop = drop;
897
898     h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct DisconnectMessage),
899                                            GNUNET_TIME_UNIT_FOREVER_REL,
900                                            GNUNET_NO, &transmit_disconnect_to_namestore,
901                                            d_ctx);
902   }
903   else
904   {
905     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not send disconnect notification to namestore service, we are not connected!\n");
906     if (GNUNET_YES == drop)
907       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "NAMESTORE will not drop content\n");
908     GNUNET_SCHEDULER_add_now (&clean_up_task, h);
909   }
910 }
911
912
913 /**
914  * Store an item in the namestore.  If the item is already present,
915  * the expiration time is updated to the max of the existing time and
916  * the new time.  This API is used when we cache signatures from other
917  * authorities.
918  *
919  * @param h handle to the namestore
920  * @param zone_key public key of the zone
921  * @param name name that is being mapped (at most 255 characters long)
922  * @param expire when does the corresponding block in the DHT expire (until
923  *               when should we never do a DHT lookup for the same name again)?
924  * @param rd_count number of entries in 'rd' array
925  * @param rd array of records with data to store
926  * @param signature signature for all the records in the zone under the given name
927  * @param cont continuation to call when done
928  * @param cont_cls closure for cont
929  * @return handle to abort the request
930  */
931 struct GNUNET_NAMESTORE_QueueEntry *
932 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
933                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
934                              const char *name,
935                              struct GNUNET_TIME_Absolute expire,
936                              unsigned int rd_count,
937                              const struct GNUNET_NAMESTORE_RecordData *rd,
938                              const struct GNUNET_CRYPTO_RsaSignature *signature,
939                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
940                              void *cont_cls)
941 {
942   struct GNUNET_NAMESTORE_QueueEntry *qe;
943   struct PendingMessage *pe;
944
945   /* pointer to elements */
946   char * zone_key_tmp;
947   char * rd_tmp;
948   char * name_tmp;
949
950   size_t msg_size = 0;
951   size_t name_len = 0;
952   size_t rd_ser_len = 0;
953   size_t pubkey_len = 0;
954   uint32_t rid = 0;
955
956   GNUNET_assert (NULL != h);
957   GNUNET_assert (NULL != zone_key);
958   GNUNET_assert (NULL != name);
959   GNUNET_assert (NULL != rd);
960   GNUNET_assert (NULL != signature);
961
962   name_len = strlen(name) + 1;
963   if (name_len > 256)
964   {
965     GNUNET_break (0);
966     return NULL;
967   }
968
969   rid = get_op_id(h);
970   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
971   qe->nsh = h;
972   qe->cont = cont;
973   qe->cont_cls = cont_cls;
974   qe->op_id = rid;
975   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
976
977   /* set msg_size*/
978   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
979   char rd_ser[rd_ser_len];
980   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
981
982   pubkey_len = sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded);
983   struct RecordPutMessage * msg;
984   msg_size = sizeof (struct RecordPutMessage) + pubkey_len + name_len  + rd_ser_len;
985
986   /* create msg here */
987   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
988   pe->size = msg_size;
989   pe->is_init = GNUNET_NO;
990   msg = (struct RecordPutMessage *) &pe[1];
991   zone_key_tmp = (char *) &msg[1];
992   name_tmp = (char *) &zone_key_tmp[pubkey_len];
993   rd_tmp = &name_tmp[name_len];
994
995   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
996   msg->gns_header.header.size = htons (msg_size);
997   msg->gns_header.r_id = htonl (rid);
998   msg->key_len = htons (pubkey_len);
999   memcpy (zone_key_tmp, zone_key, pubkey_len);
1000   msg->signature = *signature;
1001   msg->name_len = htons (name_len);
1002   memcpy (name_tmp, name, name_len);
1003   msg->expire = GNUNET_TIME_absolute_hton (expire);
1004   msg->rd_len = htons (rd_ser_len);
1005   msg->rd_count = htons (rd_count);
1006
1007   memcpy (rd_tmp, rd_ser, rd_ser_len);
1008
1009   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
1010
1011   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1012   do_transmit(h);
1013
1014   return qe;
1015 }
1016
1017
1018 /**
1019  * Check if a signature is valid.  This API is used by the GNS Block
1020  * to validate signatures received from the network.
1021  *
1022  * @param public_key public key of the zone
1023  * @param name name that is being mapped (at most 255 characters long)
1024  * @param rd_count number of entries in 'rd' array
1025  * @param rd array of records with data to store
1026  * @param signature signature for all the records in the zone under the given name
1027  * @return GNUNET_OK if the signature is valid
1028  */
1029 int
1030 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
1031                                    const char *name,
1032                                    unsigned int rd_count,
1033                                    const struct GNUNET_NAMESTORE_RecordData *rd,
1034                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
1035 {
1036   int res = GNUNET_SYSERR;
1037   size_t rd_ser_len = 0;
1038   size_t name_len = 0;
1039   char * name_tmp;
1040   char * rd_tmp;
1041   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
1042
1043   GNUNET_assert (public_key != NULL);
1044   GNUNET_assert (name != NULL);
1045   GNUNET_assert (signature != NULL);
1046
1047   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1048   char rd_ser[rd_ser_len];
1049   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1050
1051   name_len = strlen (name) + 1;
1052
1053   sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + rd_ser_len + name_len);
1054   sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len);
1055   sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
1056   name_tmp = (char *) &sig_purpose[1];
1057   rd_tmp = &name_tmp[name_len];
1058   memcpy (name_tmp, name, name_len);
1059   memcpy (rd_tmp, rd_ser, rd_ser_len);
1060
1061   res = GNUNET_CRYPTO_rsa_verify(GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key);
1062
1063   GNUNET_free (sig_purpose);
1064
1065   return res;
1066 }
1067
1068 /**
1069  * Store an item in the namestore.  If the item is already present,
1070  * the expiration time is updated to the max of the existing time and
1071  * the new time.  This API is used by the authority of a zone.
1072  *
1073  * @param h handle to the namestore
1074  * @param pkey private key of the zone
1075  * @param name name that is being mapped (at most 255 characters long)
1076  * @param rd record data to store
1077  * @param cont continuation to call when done
1078  * @param cont_cls closure for cont
1079  * @return handle to abort the request
1080  */
1081 struct GNUNET_NAMESTORE_QueueEntry *
1082 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
1083                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1084                                 const char *name,
1085                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1086                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1087                                 void *cont_cls)
1088 {
1089   struct GNUNET_NAMESTORE_QueueEntry *qe;
1090   struct PendingMessage *pe;
1091   char * name_tmp;
1092   char * pkey_tmp;
1093   char * rd_tmp;
1094   size_t rd_ser_len = 0;
1095   size_t msg_size = 0;
1096   size_t name_len = 0;
1097   size_t key_len = 0;
1098   uint32_t rid = 0;
1099
1100   GNUNET_assert (NULL != h);
1101   GNUNET_assert (NULL != pkey);
1102   GNUNET_assert (NULL != name);
1103   GNUNET_assert (NULL != rd);
1104
1105   name_len = strlen(name) + 1;
1106   if (name_len > 256)
1107   {
1108     GNUNET_break (0);
1109     return NULL;
1110   }
1111
1112   rid = get_op_id(h);
1113   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1114   qe->nsh = h;
1115   qe->cont = cont;
1116   qe->cont_cls = cont_cls;
1117   qe->op_id = rid;
1118   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1119
1120   /* set msg_size*/
1121   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1122   GNUNET_assert (pkey_enc != NULL);
1123   key_len = ntohs (pkey_enc->len);
1124
1125   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1126   char rd_ser[rd_ser_len];
1127   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1128
1129   struct RecordCreateMessage * msg;
1130   msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1131
1132   /* create msg here */
1133   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1134   pe->size = msg_size;
1135   pe->is_init = GNUNET_NO;
1136   msg = (struct RecordCreateMessage *) &pe[1];
1137
1138   pkey_tmp = (char *) &msg[1];
1139   name_tmp = &pkey_tmp[key_len];
1140   rd_tmp = &name_tmp[name_len];
1141
1142   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
1143   msg->gns_header.header.size = htons (msg_size);
1144   msg->gns_header.r_id = htonl (rid);
1145   msg->name_len = htons (name_len);
1146   msg->rd_count = htons (1);
1147   msg->rd_len = htons (rd_ser_len);
1148   msg->pkey_len = htons (key_len);
1149   memcpy (pkey_tmp, pkey_enc, key_len);
1150   memcpy (name_tmp, name, name_len);
1151   memcpy (rd_tmp, rd_ser, rd_ser_len);
1152   GNUNET_free (pkey_enc);
1153
1154   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
1155
1156   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1157   do_transmit(h);
1158   return qe;
1159 }
1160
1161
1162 /**
1163  * Explicitly remove some content from the database.  The
1164  * "cont"inuation will be called with status "GNUNET_OK" if content
1165  * was removed, "GNUNET_NO" if no matching entry was found and
1166  * "GNUNET_SYSERR" on all other types of errors.
1167  * This API is used by the authority of a zone.
1168  *
1169  * @param h handle to the namestore
1170  * @param pkey private key of the zone
1171  * @param name name that is being mapped (at most 255 characters long)
1172  * @param rd record data
1173  * @param cont continuation to call when done
1174  * @param cont_cls closure for cont
1175  * @return handle to abort the request
1176  */
1177 struct GNUNET_NAMESTORE_QueueEntry *
1178 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
1179                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1180                                 const char *name,
1181                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1182                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1183                                 void *cont_cls)
1184 {
1185   struct GNUNET_NAMESTORE_QueueEntry *qe;
1186   struct PendingMessage *pe;
1187   char *pkey_tmp;
1188   char *rd_tmp;
1189   char *name_tmp;
1190   size_t rd_ser_len = 0;
1191   size_t msg_size = 0;
1192   size_t name_len = 0;
1193   size_t key_len = 0;
1194   uint32_t rid = 0;
1195
1196   GNUNET_assert (NULL != h);
1197
1198   rid = get_op_id(h);
1199   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1200   qe->nsh = h;
1201   qe->cont = cont;
1202   qe->cont_cls = cont_cls;
1203   qe->op_id = rid;
1204   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1205
1206   /* set msg_size*/
1207   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1208   GNUNET_assert (pkey_enc != NULL);
1209   key_len = ntohs (pkey_enc->len);
1210
1211   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1212   char rd_ser[rd_ser_len];
1213   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1214
1215   name_len = strlen (name) + 1;
1216
1217   struct RecordRemoveMessage * msg;
1218   msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1219
1220   /* create msg here */
1221   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1222   pe->size = msg_size;
1223   pe->is_init = GNUNET_NO;
1224   msg = (struct RecordRemoveMessage *) &pe[1];
1225
1226   pkey_tmp = (char *) &msg[1];
1227   name_tmp = &pkey_tmp[key_len];
1228   rd_tmp = &name_tmp[name_len];
1229
1230   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
1231   msg->gns_header.header.size = htons (msg_size);
1232   msg->gns_header.r_id = htonl (rid);
1233   msg->name_len = htons (name_len);
1234   msg->rd_len = htons (rd_ser_len);
1235   msg->rd_count = htons (1);
1236   msg->key_len = htons (key_len);
1237   memcpy (pkey_tmp, pkey_enc, key_len);
1238   memcpy (name_tmp, name, name_len);
1239   memcpy (rd_tmp, rd_ser, rd_ser_len);
1240
1241   GNUNET_free (pkey_enc);
1242
1243   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
1244
1245   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1246   do_transmit(h);
1247   return qe;
1248 }
1249
1250
1251 /**
1252  * Get a result for a particular key from the namestore.  The processor
1253  * will only be called once.  
1254  *
1255  * @param h handle to the namestore
1256  * @param zone zone to look up a record from
1257  * @param name name to look up
1258  * @param record_type desired record type, 0 for all
1259  * @param proc function to call on the matching records, or with
1260  *        NULL (rd_count == 0) if there are no matching records
1261  * @param proc_cls closure for proc
1262  * @return a handle that can be used to
1263  *         cancel
1264  */
1265 struct GNUNET_NAMESTORE_QueueEntry *
1266 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
1267                               const GNUNET_HashCode *zone,
1268                               const char *name,
1269                               uint32_t record_type,
1270                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1271 {
1272   struct GNUNET_NAMESTORE_QueueEntry *qe;
1273   struct PendingMessage *pe;
1274   size_t msg_size = 0;
1275   size_t name_len = 0;
1276   uint32_t rid = 0;
1277
1278   GNUNET_assert (NULL != h);
1279   GNUNET_assert (NULL != zone);
1280   GNUNET_assert (NULL != name);
1281
1282   name_len = strlen (name) + 1;
1283   if ((name_len == 0) || (name_len > 256))
1284   {
1285     GNUNET_break (0);
1286     return NULL;
1287   }
1288
1289   rid = get_op_id(h);
1290   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1291   qe->nsh = h;
1292   qe->proc = proc;
1293   qe->proc_cls = proc_cls;
1294   qe->op_id = rid;
1295   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1296
1297   /* set msg_size*/
1298   msg_size = sizeof (struct LookupNameMessage) + name_len;
1299   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1300
1301   /* create msg here */
1302   struct LookupNameMessage * msg;
1303   pe->size = msg_size;
1304   pe->is_init = GNUNET_NO;
1305   msg = (struct LookupNameMessage *) &pe[1];
1306   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1307   msg->gns_header.header.size = htons (msg_size);
1308   msg->gns_header.r_id = htonl (rid);
1309   msg->record_type = htonl (record_type);
1310   msg->zone = *zone;
1311   msg->name_len = htonl (name_len);
1312   memcpy (&msg[1], name, name_len);
1313
1314   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1315
1316   /* transmit message */
1317   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1318   do_transmit(h);
1319
1320   return qe;
1321 }
1322
1323
1324
1325 /**
1326  * Starts a new zone iteration (used to periodically PUT all of our
1327  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1328  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1329  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1330  * immediately, and then again after
1331  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1332  *
1333  * @param h handle to the namestore
1334  * @param zone zone to access, NULL for all zones
1335  * @param must_have_flags flags that must be set for the record to be returned
1336  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1337  * @param proc function to call on each name from the zone; it
1338  *        will be called repeatedly with a value (if available)
1339  *        and always once at the end with a name of NULL.
1340  * @param proc_cls closure for proc
1341  * @return an iterator handle to use for iteration
1342  */
1343 struct GNUNET_NAMESTORE_ZoneIterator *
1344 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1345                                        const GNUNET_HashCode *zone,
1346                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1347                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1348                                        GNUNET_NAMESTORE_RecordProcessor proc,
1349                                        void *proc_cls)
1350 {
1351   struct GNUNET_NAMESTORE_ZoneIterator *it;
1352   struct PendingMessage *pe;
1353   size_t msg_size = 0;
1354   uint32_t rid = 0;
1355
1356   GNUNET_assert (NULL != h);
1357   GNUNET_assert (NULL != zone);
1358
1359   rid = get_op_id(h);
1360   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1361   it->h = h;
1362   it->proc = proc;
1363   it->proc_cls = proc;
1364   it->op_id = rid;
1365   it->zone = *zone;
1366   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1367
1368   /* set msg_size*/
1369   msg_size = sizeof (struct ZoneIterationStartMessage);
1370   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1371
1372   /* create msg here */
1373   struct ZoneIterationStartMessage * msg;
1374   pe->size = msg_size;
1375   pe->is_init = GNUNET_NO;
1376   msg = (struct ZoneIterationStartMessage *) &pe[1];
1377   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1378   msg->gns_header.header.size = htons (msg_size);
1379   msg->gns_header.r_id = htonl (rid);
1380   msg->zone = *zone;
1381   msg->must_have_flags = ntohs (must_have_flags);
1382   msg->must_not_have_flags = ntohs (must_not_have_flags);
1383
1384   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1385
1386   /* transmit message */
1387   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1388   do_transmit(h);
1389
1390   return it;
1391 }
1392
1393
1394 /**
1395  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1396  * for the next record.
1397  *
1398  * @param it the iterator
1399  */
1400 void
1401 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1402 {
1403   struct GNUNET_NAMESTORE_Handle *h;
1404   struct PendingMessage *pe;
1405   size_t msg_size = 0;
1406
1407   GNUNET_assert (NULL != it);
1408   h = it->h;
1409
1410   /* set msg_size*/
1411   msg_size = sizeof (struct ZoneIterationNextMessage);
1412   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1413
1414   /* create msg here */
1415   struct ZoneIterationNextMessage * msg;
1416   pe->size = msg_size;
1417   pe->is_init = GNUNET_NO;
1418   msg = (struct ZoneIterationNextMessage *) &pe[1];
1419   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1420   msg->gns_header.header.size = htons (msg_size);
1421   msg->gns_header.r_id = htonl (it->op_id);
1422
1423   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1424
1425   /* transmit message */
1426   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1427   do_transmit(h);
1428 }
1429
1430
1431 /**
1432  * Stops iteration and releases the namestore handle for further calls.
1433  *
1434  * @param it the iterator
1435  */
1436 void
1437 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1438 {
1439   GNUNET_assert (NULL != it);
1440   struct PendingMessage *pe;
1441   size_t msg_size = 0;
1442   struct GNUNET_NAMESTORE_Handle *h = it->h;
1443
1444   /* set msg_size*/
1445   msg_size = sizeof (struct ZoneIterationStopMessage);
1446   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1447
1448   /* create msg here */
1449   struct ZoneIterationStopMessage * msg;
1450   pe->size = msg_size;
1451   pe->is_init = GNUNET_NO;
1452   msg = (struct ZoneIterationStopMessage *) &pe[1];
1453   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1454   msg->gns_header.header.size = htons (msg_size);
1455   msg->gns_header.r_id = htonl (it->op_id);
1456
1457   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1458
1459   /* transmit message */
1460   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1461   do_transmit(h);
1462 }
1463
1464
1465 /**
1466  * Cancel a namestore operation.  The final callback from the
1467  * operation must not have been done yet.
1468  *
1469  * @param qe operation to cancel
1470  */
1471 void
1472 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1473 {
1474   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1475
1476   GNUNET_assert (qe != NULL);
1477
1478   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1479   GNUNET_free(qe);
1480
1481 }
1482
1483 /* end of namestore_api.c */