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