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