- fixes
[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_NAMESTORE_TYPE_PKEY },
227     { "PSEU",  GNUNET_NAMESTORE_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   char *name;
258   char * rd_tmp;
259
260   struct GNUNET_CRYPTO_RsaSignature *signature = NULL;
261   struct GNUNET_TIME_Absolute expire;
262   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key_tmp;
263   size_t exp_msg_len;
264   size_t msg_len = 0;
265   size_t name_len = 0;
266   size_t rd_len = 0;
267   int contains_sig = GNUNET_NO;
268   int rd_count = 0;
269
270   rd_len = ntohs (msg->rd_len);
271   rd_count = ntohs (msg->rd_count);
272   msg_len = ntohs (msg->gns_header.header.size);
273   name_len = ntohs (msg->name_len);
274   contains_sig = ntohs (msg->contains_sig);
275   expire = GNUNET_TIME_absolute_ntoh(msg->expire);
276
277   exp_msg_len = sizeof (struct LookupNameResponseMessage) +
278       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
279       name_len + rd_len;
280
281   if (msg_len != exp_msg_len)
282   {
283     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message size describes with `%u' bytes but calculated size is %u bytes \n",
284                 msg_len, exp_msg_len);
285     GNUNET_break_op (0);
286     return;
287   }
288
289   name = (char *) &msg[1];
290   rd_tmp = &name[name_len];
291
292   /* deserialize records */
293   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
294   GNUNET_NAMESTORE_records_deserialize(rd_len, rd_tmp, rd_count, rd);
295
296   /* reset values if values not contained */
297   if (contains_sig == GNUNET_NO)
298     signature = NULL;
299   else
300     signature = &msg->signature;
301   if (name_len == 0)
302     name = NULL;
303   if ((name != NULL) && (signature != NULL) && (rd_count > 0))
304       public_key_tmp =  &msg->public_key;
305   else
306       public_key_tmp = NULL;
307
308   if (qe->proc != NULL)
309   {
310     qe->proc (qe->proc_cls, public_key_tmp, expire, name, rd_count, (rd_count > 0) ? rd : NULL, signature);
311   }
312
313   /* Operation done, remove */
314   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
315   GNUNET_free (qe);
316 }
317
318
319 static void
320 handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
321                              struct RecordPutResponseMessage* msg,
322                              size_t size)
323 {
324   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
325               "RECORD_PUT_RESPONSE");
326
327   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
328
329   if (ntohs (msg->op_result) == GNUNET_OK)
330   {
331     if (qe->cont != NULL)
332     {
333       qe->cont (qe->cont_cls, GNUNET_OK, _("Namestore added record successfully"));
334     }
335
336   }
337   else if (ntohs (msg->op_result) == GNUNET_SYSERR)
338   {
339     if (qe->cont != NULL)
340     {
341       qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Namestore failed to add record"));
342     }
343   }
344   else
345   {
346     GNUNET_break_op (0);
347     return;
348   }
349
350   /* Operation done, remove */
351   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
352
353   GNUNET_free (qe);
354 }
355
356
357 static void
358 handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
359                              struct RecordCreateResponseMessage* msg,
360                              size_t size)
361 {
362   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
363               "RECORD_CREATE_RESPONSE");
364
365   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
366
367   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' %i\n",
368               "RECORD_CREATE_RESPONSE", ntohs (msg->op_result));
369   if (ntohs (msg->op_result) == GNUNET_YES)
370   {
371     if (qe->cont != NULL)
372     {
373       qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore added record successfully"));
374     }
375
376   }
377   else if (ntohs (msg->op_result) == GNUNET_NO)
378   {
379     if (qe->cont != NULL)
380     {
381       qe->cont (qe->cont_cls, GNUNET_NO, _("Namestore record already existed"));
382     }
383   }
384   else
385   {
386     if (qe->cont != NULL)
387     {
388       qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Namestore failed to add record\n"));
389     }
390   }
391
392   /* Operation done, remove */
393   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
394
395   GNUNET_free (qe);
396 }
397
398
399 static void
400 handle_record_remove_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
401                              struct RecordRemoveResponseMessage* msg,
402                              size_t size)
403 {
404   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
405               "RECORD_REMOVE_RESPONSE");
406
407   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
408   int res = ntohs (msg->op_result);
409
410   /**
411    *  result:
412    *  0 : successful
413    *  1 : No records for entry
414    *  2 : Could not find record to remove
415    *  3 : Failed to create new signature
416    *  4 : Failed to put new set of records in database
417    */
418   switch (res) {
419     case 0:
420       if (qe->cont != NULL)
421       {
422         qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore removed record successfully"));
423       }
424
425       break;
426     case 1:
427       if (qe->cont != NULL)
428       {
429         qe->cont (qe->cont_cls, GNUNET_NO, _("No records for entry"));
430       }
431
432       break;
433     case 2:
434       if (qe->cont != NULL)
435       {
436         qe->cont (qe->cont_cls, GNUNET_NO, _("Could not find record to remove"));
437       }
438
439       break;
440     case 3:
441       if (qe->cont != NULL)
442       {
443         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to create new signature"));
444       }
445
446       break;
447     case 4:
448       if (qe->cont != NULL)
449       {
450         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to put new set of records in database"));
451       }
452       break;
453     default:
454         GNUNET_break_op (0);
455       break;
456   }
457
458   /* Operation done, remove */
459   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
460
461   GNUNET_free (qe);
462 }
463
464 static void
465 handle_zone_to_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
466                              struct ZoneToNameResponseMessage* msg,
467                              size_t size)
468 {
469   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
470               "ZONE_TO_NAME_RESPONSE");
471
472   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
473   int res = ntohs (msg->res);
474
475   struct GNUNET_TIME_Absolute expire;
476   size_t name_len;
477   size_t rd_ser_len;
478   unsigned int rd_count;
479
480   char * name_tmp;
481   char * rd_tmp;
482
483   if (res == GNUNET_SYSERR)
484   {
485     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "An error occured during zone to name operation\n");
486     if (qe->proc != NULL)
487       qe->proc (qe->proc_cls, NULL, GNUNET_TIME_absolute_get_zero(), NULL, 0, NULL, NULL);
488   }
489   else if (res == GNUNET_NO)
490   {
491       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore has no result for zone to name mapping \n");
492       if (qe->proc != NULL)
493         qe->proc (qe->proc_cls, NULL, GNUNET_TIME_absolute_get_zero(), NULL, 0, NULL, NULL);
494   }
495   else if (res == GNUNET_YES)
496   {
497     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore has result for zone to name mapping \n");
498
499     name_len = ntohs (msg->name_len);
500     rd_count = ntohs (msg->rd_count);
501     rd_ser_len = ntohs (msg->rd_len);
502     expire = GNUNET_TIME_absolute_ntoh(msg->expire);
503
504     name_tmp = (char *) &msg[1];
505     rd_tmp = &name_tmp[name_len];
506
507     struct GNUNET_NAMESTORE_RecordData rd[rd_count];
508     GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_tmp, rd_count, rd);
509
510     if (qe->proc != NULL)
511       qe->proc (qe->proc_cls, &msg->zone_key, expire, name_tmp, rd_count, rd, &msg->signature);
512   }
513   else
514     GNUNET_break_op (0);
515
516   /* Operation done, remove */
517   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
518   GNUNET_free (qe);
519 }
520
521
522 static void
523 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
524                           const struct GNUNET_MessageHeader *msg,
525                           int type, size_t size)
526 {
527
528   /* handle different message type */
529   switch (type) {
530     case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
531         if (size < sizeof (struct LookupNameResponseMessage))
532         {
533           GNUNET_break_op (0);
534           break;
535         }
536         handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size);
537       break;
538     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
539         if (size != sizeof (struct RecordPutResponseMessage))
540         {
541           GNUNET_break_op (0);
542           break;
543         }
544         handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size);
545       break;
546     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE:
547         if (size != sizeof (struct RecordCreateResponseMessage))
548         {
549           GNUNET_break_op (0);
550           break;
551         }
552         handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size);
553       break;
554     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE:
555         if (size != sizeof (struct RecordRemoveResponseMessage))
556         {
557           GNUNET_break_op (0);
558           break;
559         }
560         handle_record_remove_response (qe, (struct RecordRemoveResponseMessage *) msg, size);
561       break;
562     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE:
563         if (size < sizeof (struct ZoneToNameResponseMessage))
564         {
565           GNUNET_break_op (0);
566           break;
567         }
568         handle_zone_to_name_response (qe, (struct ZoneToNameResponseMessage *) msg, size);
569       break;
570     default:
571       GNUNET_break_op (0);
572       break;
573   }
574 }
575
576 static void
577 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
578                                 struct ZoneIterationResponseMessage *msg,
579                                 size_t size)
580 {
581   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
582               "ZONE_ITERATION_RESPONSE");
583
584
585   if (ze->proc != NULL)
586   {
587     // FIXME
588     ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL);
589   }
590 }
591
592
593 static void
594 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
595                         const struct GNUNET_MessageHeader *msg,
596                         int type, size_t size)
597 {
598
599   /* handle different message type */
600   switch (type) {
601     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
602         if (size < sizeof (struct ZoneIterationResponseMessage))
603         {
604           GNUNET_break_op (0);
605           break;
606         }
607         handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size);
608       break;
609     default:
610       GNUNET_break_op (0);
611       break;
612   }
613 }
614
615 /**
616  * Type of a function to call when we receive a message
617  * from the service.
618  *
619  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
620  * @param msg message received, NULL on timeout or fatal error
621  */
622 static void
623 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
624 {
625   struct GNUNET_NAMESTORE_Handle *h = cls;
626   struct GNUNET_NAMESTORE_Header * gm;
627   struct GNUNET_NAMESTORE_QueueEntry *qe;
628   struct GNUNET_NAMESTORE_ZoneIterator *ze;
629   uint16_t size;
630   uint16_t type;
631   uint32_t r_id = UINT32_MAX;
632
633   if (NULL == msg)
634   {
635     force_reconnect (h);
636     return;
637   }
638
639   size = ntohs (msg->size);
640   type = ntohs (msg->type);
641
642   if (size < sizeof (struct GNUNET_NAMESTORE_Header))
643   {
644     GNUNET_break_op (0);
645     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
646                            GNUNET_TIME_UNIT_FOREVER_REL);
647     return;
648   }
649
650   gm = (struct GNUNET_NAMESTORE_Header *) msg;
651   r_id = ntohl (gm->r_id);
652
653   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, r_id);
654
655   /* Find matching operation */
656   if (r_id > h->op_id)
657   {
658     /* No matching pending operation found */
659     GNUNET_break_op (0);
660     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
661                            GNUNET_TIME_UNIT_FOREVER_REL);
662     return;
663   }
664
665   /* Is it a record related operation ? */
666   for (qe = h->op_head; qe != NULL; qe = qe->next)
667   {
668     if (qe->op_id == r_id)
669       break;
670   }
671   if (qe != NULL)
672   {
673     manage_record_operations (qe, msg, type, size);
674   }
675
676   /* Is it a zone iteration operation ? */
677   for (ze = h->z_head; ze != NULL; ze = ze->next)
678   {
679     if (ze->op_id == r_id)
680       break;
681   }
682   if (ze != NULL)
683   {
684     manage_zone_operations (ze, msg, type, size);
685   }
686
687   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
688                          GNUNET_TIME_UNIT_FOREVER_REL);
689
690   if (GNUNET_YES == h->reconnect)
691     force_reconnect (h);
692
693 }
694
695
696 /**
697  * Transmit messages from the message queue to the service
698  * (if there are any, and if we are not already trying).
699  *
700  * @param h handle to use
701  */
702 static void
703 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
704
705
706 /**
707  * We can now transmit a message to NAMESTORE. Do it.
708  *
709  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
710  * @param size number of bytes we can transmit
711  * @param buf where to copy the messages
712  * @return number of bytes copied into buf
713  */
714 static size_t
715 transmit_message_to_namestore (void *cls, size_t size, void *buf)
716 {
717   struct GNUNET_NAMESTORE_Handle *h = cls;
718   struct PendingMessage *p;
719   size_t ret;
720   char *cbuf;
721
722   h->th = NULL;
723   if ((size == 0) || (buf == NULL))
724   {
725     force_reconnect (h);
726     return 0;
727   }
728   ret = 0;
729   cbuf = buf;
730   while ((NULL != (p = h->pending_head)) && (p->size <= size))
731   {
732     memcpy (&cbuf[ret], &p[1], p->size);
733     ret += p->size;
734     size -= p->size;
735     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
736     if (GNUNET_YES == p->is_init)
737       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
738                              GNUNET_TIME_UNIT_FOREVER_REL);
739     GNUNET_free (p);
740   }
741   do_transmit (h);
742   return ret;
743 }
744
745
746 /**
747  * Transmit messages from the message queue to the service
748  * (if there are any, and if we are not already trying).
749  *
750  * @param h handle to use
751  */
752 static void
753 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
754 {
755   struct PendingMessage *p;
756
757   if (NULL != h->th)
758     return;
759   if (NULL == (p = h->pending_head))
760     return;
761   if (NULL == h->client)
762     return;                     /* currently reconnecting */
763
764   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
765                                            GNUNET_TIME_UNIT_FOREVER_REL,
766                                            GNUNET_NO, &transmit_message_to_namestore,
767                                            h);
768 }
769
770
771 /**
772  * Reconnect to namestore service.
773  *
774  * @param h the handle to the namestore service
775  */
776 static void
777 reconnect (struct GNUNET_NAMESTORE_Handle *h)
778 {
779   struct PendingMessage *p;
780   struct StartMessage *init;
781
782   GNUNET_assert (NULL == h->client);
783   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
784   GNUNET_assert (NULL != h->client);
785
786   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
787   {
788     p = GNUNET_malloc (sizeof (struct PendingMessage) +
789                        sizeof (struct StartMessage));
790     p->size = sizeof (struct StartMessage);
791     p->is_init = GNUNET_YES;
792     init = (struct StartMessage *) &p[1];
793     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
794     init->header.size = htons (sizeof (struct StartMessage));
795     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
796   }
797   do_transmit (h);
798 }
799
800 /**
801  * Re-establish the connection to the service.
802  *
803  * @param cls handle to use to re-connect.
804  * @param tc scheduler context
805  */
806 static void
807 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
808 {
809   struct GNUNET_NAMESTORE_Handle *h = cls;
810
811   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
812   reconnect (h);
813 }
814
815
816 /**
817  * Disconnect from service and then reconnect.
818  *
819  * @param h our handle
820  */
821 static void
822 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
823 {
824   h->reconnect = GNUNET_NO;
825   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
826   h->client = NULL;
827   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
828                                     &reconnect_task,
829                                     h);
830 }
831
832 static uint32_t
833 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
834 {
835   uint32_t op_id = h->op_id;
836   h->op_id ++;
837   return op_id;
838 }
839
840 /**
841  * Initialize the connection with the NAMESTORE service.
842  *
843  * @param cfg configuration to use
844  * @return handle to the GNS service, or NULL on error
845  */
846 struct GNUNET_NAMESTORE_Handle *
847 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
848 {
849   struct GNUNET_NAMESTORE_Handle *h;
850
851   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
852   h->cfg = cfg;
853   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
854   h->op_id = 0;
855   return h;
856 }
857
858 static void
859 clean_up_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
860 {
861   struct PendingMessage *p;
862   struct GNUNET_NAMESTORE_QueueEntry *q;
863   struct GNUNET_NAMESTORE_ZoneIterator *z;
864   struct GNUNET_NAMESTORE_Handle *h = cls;
865   GNUNET_assert (h != NULL);
866   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
867   while (NULL != (p = h->pending_head))
868   {
869     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
870     GNUNET_free (p);
871   }
872
873   while (NULL != (q = h->op_head))
874   {
875     GNUNET_break (0);
876     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
877     GNUNET_free (q);
878   }
879
880   while (NULL != (z = h->z_head))
881   {
882     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
883     GNUNET_free (z);
884   }
885
886   if (NULL != h->client)
887   {
888     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
889     h->client = NULL;
890   }
891   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
892   {
893     GNUNET_SCHEDULER_cancel (h->reconnect_task);
894     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
895   }
896   GNUNET_free(h);
897   h = NULL;
898 };
899
900 /**
901  * Disconnect from the namestore service (and free associated
902  * resources).
903  *
904  * @param h handle to the namestore
905  * @param drop set to GNUNET_YES to delete all data in namestore (!)
906  */
907 void
908 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
909 {
910   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Disconnecting from namestore service\n");
911     GNUNET_SCHEDULER_add_now (&clean_up_task, h);
912 }
913
914
915 /**
916  * Store an item in the namestore.  If the item is already present,
917  * the expiration time is updated to the max of the existing time and
918  * the new time.  This API is used when we cache signatures from other
919  * authorities.
920  *
921  * @param h handle to the namestore
922  * @param zone_key public key of the zone
923  * @param name name that is being mapped (at most 255 characters long)
924  * @param expire when does the corresponding block in the DHT expire (until
925  *               when should we never do a DHT lookup for the same name again)?
926  * @param rd_count number of entries in 'rd' array
927  * @param rd array of records with data to store
928  * @param signature signature for all the records in the zone under the given name
929  * @param cont continuation to call when done
930  * @param cont_cls closure for cont
931  * @return handle to abort the request
932  */
933 struct GNUNET_NAMESTORE_QueueEntry *
934 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
935                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
936                              const char *name,
937                              struct GNUNET_TIME_Absolute expire,
938                              unsigned int rd_count,
939                              const struct GNUNET_NAMESTORE_RecordData *rd,
940                              const struct GNUNET_CRYPTO_RsaSignature *signature,
941                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
942                              void *cont_cls)
943 {
944   struct GNUNET_NAMESTORE_QueueEntry *qe;
945   struct PendingMessage *pe;
946
947   /* pointer to elements */
948   char * rd_tmp;
949   char * name_tmp;
950
951   size_t msg_size = 0;
952   size_t name_len = 0;
953   size_t rd_ser_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   struct RecordPutMessage * msg;
983   msg_size = sizeof (struct RecordPutMessage) + name_len  + rd_ser_len;
984
985   /* create msg here */
986   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
987   pe->size = msg_size;
988   pe->is_init = GNUNET_NO;
989   msg = (struct RecordPutMessage *) &pe[1];
990   name_tmp = (char *) &msg[1];
991   rd_tmp = &name_tmp[name_len];
992
993   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
994   msg->gns_header.header.size = htons (msg_size);
995   msg->gns_header.r_id = htonl (rid);
996   msg->signature = *signature;
997   msg->name_len = htons (name_len);
998   msg->expire = GNUNET_TIME_absolute_hton (expire);
999   msg->rd_len = htons (rd_ser_len);
1000   msg->rd_count = htons (rd_count);
1001
1002   msg->public_key = *zone_key;
1003   memcpy (name_tmp, name, name_len);
1004   memcpy (rd_tmp, rd_ser, rd_ser_len);
1005
1006   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
1007
1008   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1009   do_transmit(h);
1010
1011   return qe;
1012 }
1013
1014
1015 /**
1016  * Check if a signature is valid.  This API is used by the GNS Block
1017  * to validate signatures received from the network.
1018  *
1019  * @param public_key public key of the zone
1020  * @param name name that is being mapped (at most 255 characters long)
1021  * @param rd_count number of entries in 'rd' array
1022  * @param rd array of records with data to store
1023  * @param signature signature for all the records in the zone under the given name
1024  * @return GNUNET_OK if the signature is valid
1025  */
1026 int
1027 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
1028                                    const char *name,
1029                                    unsigned int rd_count,
1030                                    const struct GNUNET_NAMESTORE_RecordData *rd,
1031                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
1032 {
1033   int res = GNUNET_SYSERR;
1034   size_t rd_ser_len = 0;
1035   size_t name_len = 0;
1036   char * name_tmp;
1037   char * rd_tmp;
1038   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
1039
1040   GNUNET_assert (public_key != NULL);
1041   GNUNET_assert (name != NULL);
1042   GNUNET_assert (rd != NULL);
1043   GNUNET_assert (signature != NULL);
1044
1045
1046   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1047   char rd_ser[rd_ser_len];
1048   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1049
1050   name_len = strlen (name) + 1;
1051   if (name_len > 256)
1052   {
1053     GNUNET_break (0);
1054     return GNUNET_SYSERR;
1055   }
1056
1057   sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + rd_ser_len + name_len);
1058   sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len);
1059   sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
1060   name_tmp = (char *) &sig_purpose[1];
1061   rd_tmp = &name_tmp[name_len];
1062   memcpy (name_tmp, name, name_len);
1063   memcpy (rd_tmp, rd_ser, rd_ser_len);
1064
1065   res = GNUNET_CRYPTO_rsa_verify(GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key);
1066
1067   GNUNET_free (sig_purpose);
1068
1069   return res;
1070 }
1071
1072 /**
1073  * Store an item in the namestore.  If the item is already present,
1074  * the expiration time is updated to the max of the existing time and
1075  * the new time.  This API is used by the authority of a zone.
1076  *
1077  * @param h handle to the namestore
1078  * @param pkey private key of the zone
1079  * @param name name that is being mapped (at most 255 characters long)
1080  * @param rd record data to store
1081  * @param cont continuation to call when done
1082  * @param cont_cls closure for cont
1083  * @return handle to abort the request
1084  */
1085 struct GNUNET_NAMESTORE_QueueEntry *
1086 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
1087                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1088                                 const char *name,
1089                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1090                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1091                                 void *cont_cls)
1092 {
1093   struct GNUNET_NAMESTORE_QueueEntry *qe;
1094   struct PendingMessage *pe;
1095   char * name_tmp;
1096   char * pkey_tmp;
1097   char * rd_tmp;
1098   size_t rd_ser_len = 0;
1099   size_t msg_size = 0;
1100   size_t name_len = 0;
1101   size_t key_len = 0;
1102   uint32_t rid = 0;
1103
1104   GNUNET_assert (NULL != h);
1105   GNUNET_assert (NULL != pkey);
1106   GNUNET_assert (NULL != name);
1107   GNUNET_assert (NULL != rd);
1108
1109   name_len = strlen(name) + 1;
1110   if (name_len > 256)
1111   {
1112     GNUNET_break (0);
1113     return NULL;
1114   }
1115
1116   rid = get_op_id(h);
1117   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1118   qe->nsh = h;
1119   qe->cont = cont;
1120   qe->cont_cls = cont_cls;
1121   qe->op_id = rid;
1122   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1123
1124   /* set msg_size*/
1125   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1126   GNUNET_assert (pkey_enc != NULL);
1127   key_len = ntohs (pkey_enc->len);
1128
1129   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1130   char rd_ser[rd_ser_len];
1131   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1132
1133   struct RecordCreateMessage * msg;
1134   msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1135
1136   /* create msg here */
1137   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1138   pe->size = msg_size;
1139   pe->is_init = GNUNET_NO;
1140   msg = (struct RecordCreateMessage *) &pe[1];
1141
1142   pkey_tmp = (char *) &msg[1];
1143   name_tmp = &pkey_tmp[key_len];
1144   rd_tmp = &name_tmp[name_len];
1145
1146   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
1147   msg->gns_header.header.size = htons (msg_size);
1148   msg->gns_header.r_id = htonl (rid);
1149   msg->name_len = htons (name_len);
1150   msg->rd_count = htons (1);
1151   msg->rd_len = htons (rd_ser_len);
1152   msg->pkey_len = htons (key_len);
1153   memcpy (pkey_tmp, pkey_enc, key_len);
1154   memcpy (name_tmp, name, name_len);
1155   memcpy (rd_tmp, rd_ser, rd_ser_len);
1156   GNUNET_free (pkey_enc);
1157
1158   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
1159
1160   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1161   do_transmit(h);
1162   return qe;
1163 }
1164
1165
1166 /**
1167  * Explicitly remove some content from the database.  The
1168  * "cont"inuation will be called with status "GNUNET_OK" if content
1169  * was removed, "GNUNET_NO" if no matching entry was found and
1170  * "GNUNET_SYSERR" on all other types of errors.
1171  * This API is used by the authority of a zone.
1172  *
1173  * @param h handle to the namestore
1174  * @param pkey private key of the zone
1175  * @param name name that is being mapped (at most 255 characters long)
1176  * @param rd record data
1177  * @param cont continuation to call when done
1178  * @param cont_cls closure for cont
1179  * @return handle to abort the request
1180  */
1181 struct GNUNET_NAMESTORE_QueueEntry *
1182 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
1183                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1184                                 const char *name,
1185                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1186                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1187                                 void *cont_cls)
1188 {
1189   struct GNUNET_NAMESTORE_QueueEntry *qe;
1190   struct PendingMessage *pe;
1191   char *pkey_tmp;
1192   char *rd_tmp;
1193   char *name_tmp;
1194   size_t rd_ser_len = 0;
1195   size_t msg_size = 0;
1196   size_t name_len = 0;
1197   size_t key_len = 0;
1198   uint32_t rid = 0;
1199
1200   GNUNET_assert (NULL != h);
1201
1202   rid = get_op_id(h);
1203   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1204   qe->nsh = h;
1205   qe->cont = cont;
1206   qe->cont_cls = cont_cls;
1207   qe->op_id = rid;
1208   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1209
1210   /* set msg_size*/
1211   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1212   GNUNET_assert (pkey_enc != NULL);
1213   key_len = ntohs (pkey_enc->len);
1214
1215   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1216   char rd_ser[rd_ser_len];
1217   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1218
1219   name_len = strlen (name) + 1;
1220
1221   struct RecordRemoveMessage * msg;
1222   msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1223
1224   /* create msg here */
1225   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1226   pe->size = msg_size;
1227   pe->is_init = GNUNET_NO;
1228   msg = (struct RecordRemoveMessage *) &pe[1];
1229
1230   pkey_tmp = (char *) &msg[1];
1231   name_tmp = &pkey_tmp[key_len];
1232   rd_tmp = &name_tmp[name_len];
1233
1234   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
1235   msg->gns_header.header.size = htons (msg_size);
1236   msg->gns_header.r_id = htonl (rid);
1237   msg->name_len = htons (name_len);
1238   msg->rd_len = htons (rd_ser_len);
1239   msg->rd_count = htons (1);
1240   msg->pkey_len = htons (key_len);
1241   memcpy (pkey_tmp, pkey_enc, key_len);
1242   memcpy (name_tmp, name, name_len);
1243   memcpy (rd_tmp, rd_ser, rd_ser_len);
1244
1245   GNUNET_free (pkey_enc);
1246
1247   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
1248
1249   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1250   do_transmit(h);
1251   return qe;
1252 }
1253
1254
1255 /**
1256  * Get a result for a particular key from the namestore.  The processor
1257  * will only be called once.  
1258  *
1259  * @param h handle to the namestore
1260  * @param zone zone to look up a record from
1261  * @param name name to look up
1262  * @param record_type desired record type, 0 for all
1263  * @param proc function to call on the matching records, or with
1264  *        NULL (rd_count == 0) if there are no matching records
1265  * @param proc_cls closure for proc
1266  * @return a handle that can be used to
1267  *         cancel
1268  */
1269 struct GNUNET_NAMESTORE_QueueEntry *
1270 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
1271                               const GNUNET_HashCode *zone,
1272                               const char *name,
1273                               uint32_t record_type,
1274                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1275 {
1276   struct GNUNET_NAMESTORE_QueueEntry *qe;
1277   struct PendingMessage *pe;
1278   size_t msg_size = 0;
1279   size_t name_len = 0;
1280   uint32_t rid = 0;
1281
1282   GNUNET_assert (NULL != h);
1283   GNUNET_assert (NULL != zone);
1284   GNUNET_assert (NULL != name);
1285
1286   name_len = strlen (name) + 1;
1287   if ((name_len == 0) || (name_len > 256))
1288   {
1289     GNUNET_break (0);
1290     return NULL;
1291   }
1292
1293   rid = get_op_id(h);
1294   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1295   qe->nsh = h;
1296   qe->proc = proc;
1297   qe->proc_cls = proc_cls;
1298   qe->op_id = rid;
1299   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1300
1301   /* set msg_size*/
1302   msg_size = sizeof (struct LookupNameMessage) + name_len;
1303   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1304
1305   /* create msg here */
1306   struct LookupNameMessage * msg;
1307   pe->size = msg_size;
1308   pe->is_init = GNUNET_NO;
1309   msg = (struct LookupNameMessage *) &pe[1];
1310   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1311   msg->gns_header.header.size = htons (msg_size);
1312   msg->gns_header.r_id = htonl (rid);
1313   msg->record_type = htonl (record_type);
1314   msg->zone = *zone;
1315   msg->name_len = htonl (name_len);
1316   memcpy (&msg[1], name, name_len);
1317
1318   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1319
1320   /* transmit message */
1321   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1322   do_transmit(h);
1323
1324   return qe;
1325 }
1326
1327
1328 /**
1329  * Look for an existing PKEY delegation record for a given public key.
1330  * Returns at most one result to the processor.
1331  *
1332  * @param h handle to the namestore
1333  * @param zone hash of public key of the zone to look up in, never NULL
1334  * @param value_zone hash of the public key of the target zone (value), never NULL
1335  * @param proc function to call on the matching records, or with
1336  *        NULL (rd_count == 0) if there are no matching records
1337  * @param proc_cls closure for proc
1338  * @return a handle that can be used to
1339  *         cancel
1340  */
1341 struct GNUNET_NAMESTORE_QueueEntry *
1342 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1343                                const GNUNET_HashCode *zone,
1344                                const GNUNET_HashCode *value_zone,
1345                                GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1346 {
1347   struct GNUNET_NAMESTORE_QueueEntry *qe;
1348   struct PendingMessage *pe;
1349   size_t msg_size = 0;
1350   uint32_t rid = 0;
1351
1352   GNUNET_assert (NULL != h);
1353   GNUNET_assert (NULL != zone);
1354   GNUNET_assert (NULL != value_zone);
1355
1356   rid = get_op_id(h);
1357   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1358   qe->nsh = h;
1359   qe->proc = proc;
1360   qe->proc_cls = proc_cls;
1361   qe->op_id = rid;
1362   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1363
1364   /* set msg_size*/
1365   msg_size = sizeof (struct ZoneToNameMessage);
1366   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1367
1368   /* create msg here */
1369   struct ZoneToNameMessage * msg;
1370   pe->size = msg_size;
1371   pe->is_init = GNUNET_NO;
1372   msg = (struct ZoneToNameMessage *) &pe[1];
1373   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1374   msg->gns_header.header.size = htons (msg_size);
1375   msg->gns_header.r_id = htonl (rid);
1376   msg->zone = *zone;
1377   msg->value_zone = *value_zone;
1378
1379   char * z_tmp = strdup (GNUNET_h2s (zone));
1380   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s' in zone `%s'\n",
1381       "NAMESTORE_ZONE_TO_NAME",
1382       z_tmp,
1383       GNUNET_h2s (value_zone));
1384   GNUNET_free (z_tmp);
1385
1386   /* transmit message */
1387   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1388   do_transmit(h);
1389
1390   return qe;
1391 }
1392
1393
1394
1395 /**
1396  * Starts a new zone iteration (used to periodically PUT all of our
1397  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1398  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1399  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1400  * immediately, and then again after
1401  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1402  *
1403  * @param h handle to the namestore
1404  * @param zone zone to access, NULL for all zones
1405  * @param must_have_flags flags that must be set for the record to be returned
1406  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1407  * @param proc function to call on each name from the zone; it
1408  *        will be called repeatedly with a value (if available)
1409  *        and always once at the end with a name of NULL.
1410  * @param proc_cls closure for proc
1411  * @return an iterator handle to use for iteration
1412  */
1413 struct GNUNET_NAMESTORE_ZoneIterator *
1414 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1415                                        const GNUNET_HashCode *zone,
1416                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1417                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1418                                        GNUNET_NAMESTORE_RecordProcessor proc,
1419                                        void *proc_cls)
1420 {
1421   struct GNUNET_NAMESTORE_ZoneIterator *it;
1422   struct PendingMessage *pe;
1423   size_t msg_size = 0;
1424   uint32_t rid = 0;
1425
1426   GNUNET_assert (NULL != h);
1427   GNUNET_assert (NULL != zone);
1428
1429   rid = get_op_id(h);
1430   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1431   it->h = h;
1432   it->proc = proc;
1433   it->proc_cls = proc;
1434   it->op_id = rid;
1435   it->zone = *zone;
1436   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1437
1438   /* set msg_size*/
1439   msg_size = sizeof (struct ZoneIterationStartMessage);
1440   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1441
1442   /* create msg here */
1443   struct ZoneIterationStartMessage * msg;
1444   pe->size = msg_size;
1445   pe->is_init = GNUNET_NO;
1446   msg = (struct ZoneIterationStartMessage *) &pe[1];
1447   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1448   msg->gns_header.header.size = htons (msg_size);
1449   msg->gns_header.r_id = htonl (rid);
1450   msg->zone = *zone;
1451   msg->must_have_flags = ntohs (must_have_flags);
1452   msg->must_not_have_flags = ntohs (must_not_have_flags);
1453
1454   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1455
1456   /* transmit message */
1457   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1458   do_transmit(h);
1459
1460   return it;
1461 }
1462
1463
1464 /**
1465  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1466  * for the next record.
1467  *
1468  * @param it the iterator
1469  */
1470 void
1471 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1472 {
1473   struct GNUNET_NAMESTORE_Handle *h;
1474   struct PendingMessage *pe;
1475   size_t msg_size = 0;
1476
1477   GNUNET_assert (NULL != it);
1478   h = it->h;
1479
1480   /* set msg_size*/
1481   msg_size = sizeof (struct ZoneIterationNextMessage);
1482   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1483
1484   /* create msg here */
1485   struct ZoneIterationNextMessage * msg;
1486   pe->size = msg_size;
1487   pe->is_init = GNUNET_NO;
1488   msg = (struct ZoneIterationNextMessage *) &pe[1];
1489   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1490   msg->gns_header.header.size = htons (msg_size);
1491   msg->gns_header.r_id = htonl (it->op_id);
1492
1493   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1494
1495   /* transmit message */
1496   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1497   do_transmit(h);
1498 }
1499
1500
1501 /**
1502  * Stops iteration and releases the namestore handle for further calls.
1503  *
1504  * @param it the iterator
1505  */
1506 void
1507 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1508 {
1509   GNUNET_assert (NULL != it);
1510   struct PendingMessage *pe;
1511   size_t msg_size = 0;
1512   struct GNUNET_NAMESTORE_Handle *h = it->h;
1513
1514   /* set msg_size*/
1515   msg_size = sizeof (struct ZoneIterationStopMessage);
1516   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1517
1518   /* create msg here */
1519   struct ZoneIterationStopMessage * msg;
1520   pe->size = msg_size;
1521   pe->is_init = GNUNET_NO;
1522   msg = (struct ZoneIterationStopMessage *) &pe[1];
1523   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1524   msg->gns_header.header.size = htons (msg_size);
1525   msg->gns_header.r_id = htonl (it->op_id);
1526
1527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1528
1529   /* transmit message */
1530   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1531   do_transmit(h);
1532 }
1533
1534
1535 /**
1536  * Cancel a namestore operation.  The final callback from the
1537  * operation must not have been done yet.
1538  *
1539  * @param qe operation to cancel
1540  */
1541 void
1542 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1543 {
1544   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1545
1546   GNUNET_assert (qe != NULL);
1547
1548   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1549   GNUNET_free(qe);
1550
1551 }
1552
1553 /* end of namestore_api.c */