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