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