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