namestore api change: include block expiration time in record create
[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 expire block expiration time
1099  * @param name name that is being mapped (at most 255 characters long)
1100  * @param rd record data to store
1101  * @param cont continuation to call when done
1102  * @param cont_cls closure for cont
1103  * @return handle to abort the request
1104  */
1105 struct GNUNET_NAMESTORE_QueueEntry *
1106 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
1107                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1108                                 const struct GNUNET_TIME_Absolute expire,
1109                                 const char *name,
1110                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1111                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1112                                 void *cont_cls)
1113 {
1114   struct GNUNET_NAMESTORE_QueueEntry *qe;
1115   struct PendingMessage *pe;
1116   char * name_tmp;
1117   char * pkey_tmp;
1118   char * rd_tmp;
1119   size_t rd_ser_len = 0;
1120   size_t msg_size = 0;
1121   size_t name_len = 0;
1122   size_t key_len = 0;
1123   uint32_t rid = 0;
1124
1125   GNUNET_assert (NULL != h);
1126   GNUNET_assert (NULL != pkey);
1127   GNUNET_assert (NULL != name);
1128   GNUNET_assert (NULL != rd);
1129
1130   name_len = strlen(name) + 1;
1131   if (name_len > 256)
1132   {
1133     GNUNET_break (0);
1134     return NULL;
1135   }
1136
1137   rid = get_op_id(h);
1138   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1139   qe->nsh = h;
1140   qe->cont = cont;
1141   qe->cont_cls = cont_cls;
1142   qe->op_id = rid;
1143   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1144
1145   /* set msg_size*/
1146   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1147   GNUNET_assert (pkey_enc != NULL);
1148   key_len = ntohs (pkey_enc->len);
1149
1150   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1151   char rd_ser[rd_ser_len];
1152   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1153
1154   struct RecordCreateMessage * msg;
1155   msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1156
1157   /* create msg here */
1158   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1159   pe->size = msg_size;
1160   pe->is_init = GNUNET_NO;
1161   msg = (struct RecordCreateMessage *) &pe[1];
1162
1163   pkey_tmp = (char *) &msg[1];
1164   name_tmp = &pkey_tmp[key_len];
1165   rd_tmp = &name_tmp[name_len];
1166
1167   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
1168   msg->gns_header.header.size = htons (msg_size);
1169   msg->gns_header.r_id = htonl (rid);
1170   msg->name_len = htons (name_len);
1171   msg->rd_count = htons (1);
1172   msg->rd_len = htons (rd_ser_len);
1173   msg->pkey_len = htons (key_len);
1174   msg->expire = GNUNET_TIME_absolute_hton(expire);
1175   memcpy (pkey_tmp, pkey_enc, key_len);
1176   memcpy (name_tmp, name, name_len);
1177   memcpy (rd_tmp, rd_ser, rd_ser_len);
1178   GNUNET_free (pkey_enc);
1179
1180   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
1181
1182   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1183   do_transmit(h);
1184   return qe;
1185 }
1186
1187
1188 /**
1189  * Explicitly remove some content from the database.  The
1190  * "cont"inuation will be called with status "GNUNET_OK" if content
1191  * was removed, "GNUNET_NO" if no matching entry was found and
1192  * "GNUNET_SYSERR" on all other types of errors.
1193  * This API is used by the authority of a zone.
1194  *
1195  * @param h handle to the namestore
1196  * @param pkey private key of the zone
1197  * @param name name that is being mapped (at most 255 characters long)
1198  * @param rd record data
1199  * @param cont continuation to call when done
1200  * @param cont_cls closure for cont
1201  * @return handle to abort the request
1202  */
1203 struct GNUNET_NAMESTORE_QueueEntry *
1204 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
1205                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1206                                 const char *name,
1207                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1208                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1209                                 void *cont_cls)
1210 {
1211   struct GNUNET_NAMESTORE_QueueEntry *qe;
1212   struct PendingMessage *pe;
1213   char *pkey_tmp;
1214   char *rd_tmp;
1215   char *name_tmp;
1216   size_t rd_ser_len = 0;
1217   size_t msg_size = 0;
1218   size_t name_len = 0;
1219   size_t key_len = 0;
1220   uint32_t rid = 0;
1221
1222   GNUNET_assert (NULL != h);
1223
1224   rid = get_op_id(h);
1225   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1226   qe->nsh = h;
1227   qe->cont = cont;
1228   qe->cont_cls = cont_cls;
1229   qe->op_id = rid;
1230   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1231
1232   /* set msg_size*/
1233   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1234   GNUNET_assert (pkey_enc != NULL);
1235   key_len = ntohs (pkey_enc->len);
1236
1237   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1238   char rd_ser[rd_ser_len];
1239   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1240
1241   name_len = strlen (name) + 1;
1242
1243   struct RecordRemoveMessage * msg;
1244   msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1245
1246   /* create msg here */
1247   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1248   pe->size = msg_size;
1249   pe->is_init = GNUNET_NO;
1250   msg = (struct RecordRemoveMessage *) &pe[1];
1251
1252   pkey_tmp = (char *) &msg[1];
1253   name_tmp = &pkey_tmp[key_len];
1254   rd_tmp = &name_tmp[name_len];
1255
1256   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
1257   msg->gns_header.header.size = htons (msg_size);
1258   msg->gns_header.r_id = htonl (rid);
1259   msg->name_len = htons (name_len);
1260   msg->rd_len = htons (rd_ser_len);
1261   msg->rd_count = htons (1);
1262   msg->pkey_len = htons (key_len);
1263   memcpy (pkey_tmp, pkey_enc, key_len);
1264   memcpy (name_tmp, name, name_len);
1265   memcpy (rd_tmp, rd_ser, rd_ser_len);
1266
1267   GNUNET_free (pkey_enc);
1268
1269   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
1270
1271   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1272   do_transmit(h);
1273   return qe;
1274 }
1275
1276
1277 /**
1278  * Get a result for a particular key from the namestore.  The processor
1279  * will only be called once.  
1280  *
1281  * @param h handle to the namestore
1282  * @param zone zone to look up a record from
1283  * @param name name to look up
1284  * @param record_type desired record type, 0 for all
1285  * @param proc function to call on the matching records, or with
1286  *        NULL (rd_count == 0) if there are no matching records
1287  * @param proc_cls closure for proc
1288  * @return a handle that can be used to
1289  *         cancel
1290  */
1291 struct GNUNET_NAMESTORE_QueueEntry *
1292 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
1293                               const GNUNET_HashCode *zone,
1294                               const char *name,
1295                               uint32_t record_type,
1296                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1297 {
1298   struct GNUNET_NAMESTORE_QueueEntry *qe;
1299   struct PendingMessage *pe;
1300   size_t msg_size = 0;
1301   size_t name_len = 0;
1302   uint32_t rid = 0;
1303
1304   GNUNET_assert (NULL != h);
1305   GNUNET_assert (NULL != zone);
1306   GNUNET_assert (NULL != name);
1307
1308   name_len = strlen (name) + 1;
1309   if ((name_len == 0) || (name_len > 256))
1310   {
1311     GNUNET_break (0);
1312     return NULL;
1313   }
1314
1315   rid = get_op_id(h);
1316   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1317   qe->nsh = h;
1318   qe->proc = proc;
1319   qe->proc_cls = proc_cls;
1320   qe->op_id = rid;
1321   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1322
1323   /* set msg_size*/
1324   msg_size = sizeof (struct LookupNameMessage) + name_len;
1325   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1326
1327   /* create msg here */
1328   struct LookupNameMessage * msg;
1329   pe->size = msg_size;
1330   pe->is_init = GNUNET_NO;
1331   msg = (struct LookupNameMessage *) &pe[1];
1332   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1333   msg->gns_header.header.size = htons (msg_size);
1334   msg->gns_header.r_id = htonl (rid);
1335   msg->record_type = htonl (record_type);
1336   msg->name_len = htonl (name_len);
1337   msg->zone = *zone;
1338   memcpy (&msg[1], name, name_len);
1339
1340   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1341
1342   /* transmit message */
1343   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1344   do_transmit(h);
1345
1346   return qe;
1347 }
1348
1349
1350 /**
1351  * Look for an existing PKEY delegation record for a given public key.
1352  * Returns at most one result to the processor.
1353  *
1354  * @param h handle to the namestore
1355  * @param zone hash of public key of the zone to look up in, never NULL
1356  * @param value_zone hash of the public key of the target zone (value), never NULL
1357  * @param proc function to call on the matching records, or with
1358  *        NULL (rd_count == 0) if there are no matching records
1359  * @param proc_cls closure for proc
1360  * @return a handle that can be used to
1361  *         cancel
1362  */
1363 struct GNUNET_NAMESTORE_QueueEntry *
1364 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1365                                const GNUNET_HashCode *zone,
1366                                const GNUNET_HashCode *value_zone,
1367                                GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1368 {
1369   struct GNUNET_NAMESTORE_QueueEntry *qe;
1370   struct PendingMessage *pe;
1371   size_t msg_size = 0;
1372   uint32_t rid = 0;
1373
1374   GNUNET_assert (NULL != h);
1375   GNUNET_assert (NULL != zone);
1376   GNUNET_assert (NULL != value_zone);
1377
1378   rid = get_op_id(h);
1379   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1380   qe->nsh = h;
1381   qe->proc = proc;
1382   qe->proc_cls = proc_cls;
1383   qe->op_id = rid;
1384   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1385
1386   /* set msg_size*/
1387   msg_size = sizeof (struct ZoneToNameMessage);
1388   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1389
1390   /* create msg here */
1391   struct ZoneToNameMessage * msg;
1392   pe->size = msg_size;
1393   pe->is_init = GNUNET_NO;
1394   msg = (struct ZoneToNameMessage *) &pe[1];
1395   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1396   msg->gns_header.header.size = htons (msg_size);
1397   msg->gns_header.r_id = htonl (rid);
1398   msg->zone = *zone;
1399   msg->value_zone = *value_zone;
1400
1401   char * z_tmp = strdup (GNUNET_h2s (zone));
1402   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s' in zone `%s'\n",
1403       "NAMESTORE_ZONE_TO_NAME",
1404       z_tmp,
1405       GNUNET_h2s (value_zone));
1406   GNUNET_free (z_tmp);
1407
1408   /* transmit message */
1409   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1410   do_transmit(h);
1411
1412   return qe;
1413 }
1414
1415
1416
1417 /**
1418  * Starts a new zone iteration (used to periodically PUT all of our
1419  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1420  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1421  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1422  * immediately, and then again after
1423  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1424  *
1425  * @param h handle to the namestore
1426  * @param zone zone to access, NULL for all zones
1427  * @param must_have_flags flags that must be set for the record to be returned
1428  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1429  * @param proc function to call on each name from the zone; it
1430  *        will be called repeatedly with a value (if available)
1431  *        and always once at the end with a name of NULL.
1432  * @param proc_cls closure for proc
1433  * @return an iterator handle to use for iteration
1434  */
1435 struct GNUNET_NAMESTORE_ZoneIterator *
1436 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1437                                        const GNUNET_HashCode *zone,
1438                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1439                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1440                                        GNUNET_NAMESTORE_RecordProcessor proc,
1441                                        void *proc_cls)
1442 {
1443   struct GNUNET_NAMESTORE_ZoneIterator *it;
1444   struct PendingMessage *pe;
1445   size_t msg_size = 0;
1446   uint32_t rid = 0;
1447
1448   GNUNET_assert (NULL != h);
1449
1450
1451   rid = get_op_id(h);
1452   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1453   it->h = h;
1454   it->proc = proc;
1455   it->proc_cls = proc;
1456   it->op_id = rid;
1457
1458   if (NULL != zone)
1459   {
1460     it->zone = *zone;
1461     it->has_zone = GNUNET_YES;
1462   }
1463   else
1464   {
1465     memset (&it->zone, '\0', sizeof (it->zone));
1466     it->has_zone = GNUNET_NO;
1467   }
1468   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1469
1470   /* set msg_size*/
1471   msg_size = sizeof (struct ZoneIterationStartMessage);
1472   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1473
1474   /* create msg here */
1475   struct ZoneIterationStartMessage * msg;
1476   pe->size = msg_size;
1477   pe->is_init = GNUNET_NO;
1478   msg = (struct ZoneIterationStartMessage *) &pe[1];
1479   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1480   msg->gns_header.header.size = htons (msg_size);
1481   msg->gns_header.r_id = htonl (rid);
1482   if (NULL != zone)
1483   {
1484     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1485     msg->zone = *zone;
1486   }
1487   else
1488   {
1489     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for all zones\n", "ZONE_ITERATION_START");
1490     memset (&msg->zone, '\0', sizeof (msg->zone));
1491   }
1492   msg->must_have_flags = ntohs (must_have_flags);
1493   msg->must_not_have_flags = ntohs (must_not_have_flags);
1494
1495
1496
1497   /* transmit message */
1498   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1499   do_transmit(h);
1500
1501   return it;
1502 }
1503
1504
1505 /**
1506  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1507  * for the next record.
1508  *
1509  * @param it the iterator
1510  */
1511 void
1512 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1513 {
1514   struct GNUNET_NAMESTORE_Handle *h;
1515   struct PendingMessage *pe;
1516   size_t msg_size = 0;
1517
1518   GNUNET_assert (NULL != it);
1519   h = it->h;
1520
1521   /* set msg_size*/
1522   msg_size = sizeof (struct ZoneIterationNextMessage);
1523   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1524
1525   /* create msg here */
1526   struct ZoneIterationNextMessage * msg;
1527   pe->size = msg_size;
1528   pe->is_init = GNUNET_NO;
1529   msg = (struct ZoneIterationNextMessage *) &pe[1];
1530   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1531   msg->gns_header.header.size = htons (msg_size);
1532   msg->gns_header.r_id = htonl (it->op_id);
1533
1534   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_NEXT");
1535
1536   /* transmit message */
1537   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1538   do_transmit(h);
1539 }
1540
1541
1542 /**
1543  * Stops iteration and releases the namestore handle for further calls.
1544  *
1545  * @param it the iterator
1546  */
1547 void
1548 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1549 {
1550   GNUNET_assert (NULL != it);
1551   struct PendingMessage *pe;
1552   size_t msg_size = 0;
1553   struct GNUNET_NAMESTORE_Handle *h = it->h;
1554
1555   /* set msg_size*/
1556   msg_size = sizeof (struct ZoneIterationStopMessage);
1557   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1558
1559   /* create msg here */
1560   struct ZoneIterationStopMessage * msg;
1561   pe->size = msg_size;
1562   pe->is_init = GNUNET_NO;
1563   msg = (struct ZoneIterationStopMessage *) &pe[1];
1564   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1565   msg->gns_header.header.size = htons (msg_size);
1566   msg->gns_header.r_id = htonl (it->op_id);
1567
1568   if (GNUNET_YES == it->has_zone)
1569     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1570   else
1571     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for all zones\n", "ZONE_ITERATION_STOP");
1572
1573   /* transmit message */
1574   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1575   do_transmit(h);
1576 }
1577
1578
1579 /**
1580  * Cancel a namestore operation.  The final callback from the
1581  * operation must not have been done yet.
1582  *
1583  * @param qe operation to cancel
1584  */
1585 void
1586 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1587 {
1588   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1589
1590   GNUNET_assert (qe != NULL);
1591
1592   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1593   GNUNET_free(qe);
1594
1595 }
1596
1597 /* end of namestore_api.c */