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