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