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