add statistic on namestore iteration delay
[oweals/gnunet.git] / src / namestore / namestore_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010-2013, 2016 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, 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  * @author Christian Grothoff
27  */
28
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_crypto_lib.h"
32 #include "gnunet_constants.h"
33 #include "gnunet_dnsparser_lib.h"
34 #include "gnunet_arm_service.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet_gns_service.h"
37 #include "gnunet_namestore_service.h"
38 #include "namestore.h"
39
40
41 #define LOG(kind,...) GNUNET_log_from (kind, "namestore-api",__VA_ARGS__)
42
43
44 /**
45  * An QueueEntry used to store information for a pending
46  * NAMESTORE record operation
47  */
48 struct GNUNET_NAMESTORE_QueueEntry
49 {
50
51   /**
52    * Kept in a DLL.
53    */
54   struct GNUNET_NAMESTORE_QueueEntry *next;
55
56   /**
57    * Kept in a DLL.
58    */
59   struct GNUNET_NAMESTORE_QueueEntry *prev;
60
61   /**
62    * Main handle to access the namestore.
63    */
64   struct GNUNET_NAMESTORE_Handle *h;
65
66   /**
67    * Continuation to call
68    */
69   GNUNET_NAMESTORE_ContinuationWithStatus cont;
70
71   /**
72    * Closure for @e cont.
73    */
74   void *cont_cls;
75
76   /**
77    * Function to call with the records we get back; or NULL.
78    */
79   GNUNET_NAMESTORE_RecordMonitor proc;
80
81   /**
82    * Closure for @e proc.
83    */
84   void *proc_cls;
85
86   /**
87    * Function to call on errors.
88    */
89   GNUNET_SCHEDULER_TaskCallback error_cb;
90
91   /**
92    * Closure for @e error_cb.
93    */
94   void *error_cb_cls;
95
96   /**
97    * Envelope of the message to send to the service, if not yet
98    * sent.
99    */
100   struct GNUNET_MQ_Envelope *env;
101
102   /**
103    * The operation id this zone iteration operation has
104    */
105   uint32_t op_id;
106
107 };
108
109
110 /**
111  * Handle for a zone iterator operation
112  */
113 struct GNUNET_NAMESTORE_ZoneIterator
114 {
115
116   /**
117    * Kept in a DLL.
118    */
119   struct GNUNET_NAMESTORE_ZoneIterator *next;
120
121   /**
122    * Kept in a DLL.
123    */
124   struct GNUNET_NAMESTORE_ZoneIterator *prev;
125
126   /**
127    * Main handle to access the namestore.
128    */
129   struct GNUNET_NAMESTORE_Handle *h;
130
131   /**
132    * Function to call on completion.
133    */
134   GNUNET_SCHEDULER_TaskCallback finish_cb;
135
136   /**
137    * Closure for @e error_cb.
138    */
139   void *finish_cb_cls;
140
141   /**
142    * The continuation to call with the results
143    */
144   GNUNET_NAMESTORE_RecordMonitor proc;
145
146   /**
147    * Closure for @e proc.
148    */
149   void *proc_cls;
150
151   /**
152    * Function to call on errors.
153    */
154   GNUNET_SCHEDULER_TaskCallback error_cb;
155
156   /**
157    * Closure for @e error_cb.
158    */
159   void *error_cb_cls;
160
161   /**
162    * Envelope of the message to send to the service, if not yet
163    * sent.
164    */
165   struct GNUNET_MQ_Envelope *env;
166
167   /**
168    * Private key of the zone.
169    */
170   struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
171
172   /**
173    * The operation id this zone iteration operation has
174    */
175   uint32_t op_id;
176
177 };
178
179
180 /**
181  * Connection to the NAMESTORE service.
182  */
183 struct GNUNET_NAMESTORE_Handle
184 {
185
186   /**
187    * Configuration to use.
188    */
189   const struct GNUNET_CONFIGURATION_Handle *cfg;
190
191   /**
192    * Connection to the service (if available).
193    */
194   struct GNUNET_MQ_Handle *mq;
195
196   /**
197    * Head of pending namestore queue entries
198    */
199   struct GNUNET_NAMESTORE_QueueEntry *op_head;
200
201   /**
202    * Tail of pending namestore queue entries
203    */
204   struct GNUNET_NAMESTORE_QueueEntry *op_tail;
205
206   /**
207    * Head of pending namestore zone iterator entries
208    */
209   struct GNUNET_NAMESTORE_ZoneIterator *z_head;
210
211   /**
212    * Tail of pending namestore zone iterator entries
213    */
214   struct GNUNET_NAMESTORE_ZoneIterator *z_tail;
215
216   /**
217    * Reconnect task
218    */
219   struct GNUNET_SCHEDULER_Task *reconnect_task;
220
221   /**
222    * Delay introduced before we reconnect.
223    */
224   struct GNUNET_TIME_Relative reconnect_delay;
225
226   /**
227    * Should we reconnect to service due to some serious error?
228    */
229   int reconnect;
230
231   /**
232    * The last operation id used for a NAMESTORE operation
233    */
234   uint32_t last_op_id_used;
235
236 };
237
238
239 /**
240  * Disconnect from service and then reconnect.
241  *
242  * @param h our handle
243  */
244 static void
245 force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
246
247
248 /**
249  * Find the queue entry that matches the @a rid
250  *
251  * @param h namestore handle
252  * @param rid id to look up
253  * @return NULL if @a rid was not found
254  */
255 static struct GNUNET_NAMESTORE_QueueEntry *
256 find_qe (struct GNUNET_NAMESTORE_Handle *h,
257          uint32_t rid)
258 {
259   struct GNUNET_NAMESTORE_QueueEntry *qe;
260
261   for (qe = h->op_head; qe != NULL; qe = qe->next)
262     if (qe->op_id == rid)
263       return qe;
264   return NULL;
265 }
266
267
268 /**
269  * Find the zone iteration entry that matches the @a rid
270  *
271  * @param h namestore handle
272  * @param rid id to look up
273  * @return NULL if @a rid was not found
274  */
275 static struct GNUNET_NAMESTORE_ZoneIterator *
276 find_zi (struct GNUNET_NAMESTORE_Handle *h,
277          uint32_t rid)
278 {
279   struct GNUNET_NAMESTORE_ZoneIterator *ze;
280
281   for (ze = h->z_head; ze != NULL; ze = ze->next)
282     if (ze->op_id == rid)
283       return ze;
284   return NULL;
285 }
286
287
288 /**
289  * Free @a qe.
290  *
291  * @param qe entry to free
292  */
293 static void
294 free_qe (struct GNUNET_NAMESTORE_QueueEntry *qe)
295 {
296   struct GNUNET_NAMESTORE_Handle *h = qe->h;
297
298   GNUNET_CONTAINER_DLL_remove (h->op_head,
299                                h->op_tail,
300                                qe);
301   if (NULL != qe->env)
302     GNUNET_MQ_discard (qe->env);
303   GNUNET_free (qe);
304 }
305
306
307 /**
308  * Free @a ze.
309  *
310  * @param ze entry to free
311  */
312 static void
313 free_ze (struct GNUNET_NAMESTORE_ZoneIterator *ze)
314 {
315   struct GNUNET_NAMESTORE_Handle *h = ze->h;
316
317   GNUNET_CONTAINER_DLL_remove (h->z_head,
318                                h->z_tail,
319                                ze);
320   if (NULL != ze->env)
321     GNUNET_MQ_discard (ze->env);
322   GNUNET_free (ze);
323 }
324
325
326 /**
327  * Check that @a rd_buf of lenght @a rd_len contains
328  * @a rd_count records.
329  *
330  * @param rd_len length of @a rd_buf
331  * @param rd_buf buffer with serialized records
332  * @param rd_count number of records expected
333  * @return #GNUNET_OK if @a rd_buf is well-formed
334  */
335 static int
336 check_rd (size_t rd_len,
337           const void *rd_buf,
338           unsigned int rd_count)
339 {
340   struct GNUNET_GNSRECORD_Data rd[rd_count];
341
342   if (GNUNET_OK !=
343       GNUNET_GNSRECORD_records_deserialize (rd_len,
344                                             rd_buf,
345                                             rd_count,
346                                             rd))
347   {
348     GNUNET_break (0);
349     return GNUNET_SYSERR;
350   }
351   return GNUNET_OK;
352 }
353
354
355 /**
356  * Handle an incoming message of type
357  * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
358  *
359  * @param cls
360  * @param msg the message we received
361  */
362 static void
363 handle_record_store_response (void *cls,
364                               const struct RecordStoreResponseMessage *msg)
365 {
366   struct GNUNET_NAMESTORE_Handle *h = cls;
367   struct GNUNET_NAMESTORE_QueueEntry *qe;
368   int res;
369   const char *emsg;
370
371   qe = find_qe (h,
372                 ntohl (msg->gns_header.r_id));
373   res = ntohl (msg->op_result);
374   LOG (GNUNET_ERROR_TYPE_DEBUG,
375        "Received RECORD_STORE_RESPONSE with result %d\n",
376        res);
377   /* TODO: add actual error message from namestore to response... */
378   if (GNUNET_SYSERR == res)
379     emsg = _("Namestore failed to store record\n");
380   else
381     emsg = NULL;
382   if (NULL != qe->cont)
383     qe->cont (qe->cont_cls,
384               res,
385               emsg);
386   free_qe (qe);
387 }
388
389
390 /**
391  * Check validity of an incoming message of type
392  * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
393  *
394  * @param cls
395  * @param msg the message we received
396  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
397  */
398 static int
399 check_lookup_result (void *cls,
400                      const struct LabelLookupResponseMessage *msg)
401 {
402   const char *name;
403   size_t exp_msg_len;
404   size_t msg_len;
405   size_t name_len;
406   size_t rd_len;
407
408   (void) cls;
409   rd_len = ntohs (msg->rd_len);
410   msg_len = ntohs (msg->gns_header.header.size);
411   name_len = ntohs (msg->name_len);
412   exp_msg_len = sizeof (*msg) + name_len + rd_len;
413   if (msg_len != exp_msg_len)
414   {
415     GNUNET_break (0);
416     return GNUNET_SYSERR;
417   }
418   name = (const char *) &msg[1];
419   if ( (name_len > 0) &&
420        ('\0' != name[name_len -1]) )
421   {
422     GNUNET_break (0);
423     return GNUNET_SYSERR;
424   }
425   if (GNUNET_NO == ntohs (msg->found))
426   {
427     if (0 != ntohs (msg->rd_count))
428     {
429       GNUNET_break (0);
430       return GNUNET_SYSERR;
431     }
432     return GNUNET_OK;
433   }
434   return check_rd (rd_len,
435                    &name[name_len],
436                    ntohs (msg->rd_count));
437 }
438
439
440 /**
441  * Handle an incoming message of type
442  * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
443  *
444  * @param cls
445  * @param msg the message we received
446  */
447 static void
448 handle_lookup_result (void *cls,
449                       const struct LabelLookupResponseMessage *msg)
450 {
451   struct GNUNET_NAMESTORE_Handle *h = cls;
452   struct GNUNET_NAMESTORE_QueueEntry *qe;
453   const char *name;
454   const char *rd_tmp;
455   size_t name_len;
456   size_t rd_len;
457   unsigned int rd_count;
458
459   LOG (GNUNET_ERROR_TYPE_DEBUG,
460        "Received RECORD_LOOKUP_RESULT\n");
461   qe = find_qe (h,
462                 ntohl (msg->gns_header.r_id));
463   if (NULL == qe)
464     return;
465   rd_len = ntohs (msg->rd_len);
466   rd_count = ntohs (msg->rd_count);
467   name_len = ntohs (msg->name_len);
468   name = (const char *) &msg[1];
469   if (GNUNET_NO == ntohs (msg->found))
470   {
471     /* label was not in namestore */
472     if (NULL != qe->proc)
473       qe->proc (qe->proc_cls,
474                 &msg->private_key,
475                 name,
476                 0,
477                 NULL);
478     free_qe (qe);
479     return;
480   }
481
482   rd_tmp = &name[name_len];
483   {
484     struct GNUNET_GNSRECORD_Data rd[rd_count];
485
486     GNUNET_assert (GNUNET_OK ==
487                    GNUNET_GNSRECORD_records_deserialize (rd_len,
488                                                          rd_tmp,
489                                                          rd_count,
490                                                          rd));
491     if (0 == name_len)
492       name = NULL;
493     if (NULL != qe->proc)
494       qe->proc (qe->proc_cls,
495                 &msg->private_key,
496                 name,
497                 rd_count,
498                 (rd_count > 0) ? rd : NULL);
499   }
500   free_qe (qe);
501 }
502
503
504 /**
505  * Handle an incoming message of type
506  * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
507  *
508  * @param cls
509  * @param msg the message we received
510  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
511  */
512 static int
513 check_record_result (void *cls,
514                      const struct RecordResultMessage *msg)
515 {
516   const char *name;
517   size_t msg_len;
518   size_t name_len;
519   size_t rd_len;
520
521   (void) cls;
522   rd_len = ntohs (msg->rd_len);
523   msg_len = ntohs (msg->gns_header.header.size);
524   name_len = ntohs (msg->name_len);
525   if (0 != ntohs (msg->reserved))
526   {
527     GNUNET_break (0);
528     return GNUNET_SYSERR;
529   }
530   if (msg_len != sizeof (struct RecordResultMessage) + name_len + rd_len)
531   {
532     GNUNET_break (0);
533     return GNUNET_SYSERR;
534   }
535   name = (const char *) &msg[1];
536   if ( (name_len > 0) &&
537        ('\0' != name[name_len -1]) )
538   {
539     GNUNET_break (0);
540     return GNUNET_SYSERR;
541   }
542   return check_rd (rd_len,
543                    &name[name_len],
544                    ntohs (msg->rd_count));
545 }
546
547
548 /**
549  * Handle an incoming message of type
550  * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
551  *
552  * @param cls
553  * @param msg the message we received
554  */
555 static void
556 handle_record_result (void *cls,
557                       const struct RecordResultMessage *msg)
558 {
559   static struct GNUNET_CRYPTO_EcdsaPrivateKey priv_dummy;
560   struct GNUNET_NAMESTORE_Handle *h = cls;
561   struct GNUNET_NAMESTORE_QueueEntry *qe;
562   struct GNUNET_NAMESTORE_ZoneIterator *ze;
563   const char *name;
564   const char *rd_tmp;
565   size_t name_len;
566   size_t rd_len;
567   unsigned int rd_count;
568
569   LOG (GNUNET_ERROR_TYPE_DEBUG,
570        "Received RECORD_RESULT\n");
571   rd_len = ntohs (msg->rd_len);
572   rd_count = ntohs (msg->rd_count);
573   name_len = ntohs (msg->name_len);
574   ze = find_zi (h,
575                 ntohl (msg->gns_header.r_id));
576   qe = find_qe (h,
577                 ntohl (msg->gns_header.r_id));
578   if ( (NULL == ze) &&
579        (NULL == qe) )
580     return; /* rid not found */
581   if ( (NULL != ze) &&
582        (NULL != qe) )
583   {
584     GNUNET_break (0);   /* rid ambigous */
585     force_reconnect (h);
586     return;
587   }
588   if ( (0 == name_len) &&
589        (0 == (memcmp (&msg->private_key,
590                       &priv_dummy,
591                       sizeof (priv_dummy)))) )
592   {
593     LOG (GNUNET_ERROR_TYPE_DEBUG,
594          "Zone iteration completed!\n");
595     if (NULL == ze)
596     {
597       GNUNET_break (0);
598       force_reconnect (h);
599       return;
600     }
601     if (NULL != ze->finish_cb)
602       ze->finish_cb (ze->finish_cb_cls);
603     free_ze (ze);
604     return;
605   }
606
607   name = (const char *) &msg[1];
608   rd_tmp = &name[name_len];
609   {
610     struct GNUNET_GNSRECORD_Data rd[rd_count];
611
612     GNUNET_assert (GNUNET_OK ==
613                    GNUNET_GNSRECORD_records_deserialize(rd_len,
614                                                         rd_tmp,
615                                                         rd_count,
616                                                         rd));
617     if (0 == name_len)
618       name = NULL;
619     if (NULL != qe)
620     {
621       if (NULL != qe->proc)
622         qe->proc (qe->proc_cls,
623                   &msg->private_key,
624                   name,
625                   rd_count,
626                   (rd_count > 0) ? rd : NULL);
627       free_qe (qe);
628       return;
629     }
630     if (NULL != ze)
631     {
632       if (NULL != ze->proc)
633         ze->proc (ze->proc_cls,
634                   &msg->private_key,
635                   name,
636                   rd_count,
637                   rd);
638       return;
639     }
640   }
641   GNUNET_assert (0);
642 }
643
644
645 /**
646  * Handle an incoming message of type
647  * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
648  *
649  * @param qe the respective entry in the message queue
650  * @param msg the message we received
651  * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
652  */
653 static int
654 check_zone_to_name_response (void *cls,
655                              const struct ZoneToNameResponseMessage *msg)
656 {
657   size_t name_len;
658   size_t rd_ser_len;
659   const char *name_tmp;
660
661   (void) cls;
662   if (GNUNET_OK != ntohs (msg->res))
663     return GNUNET_OK;
664   name_len = ntohs (msg->name_len);
665   rd_ser_len = ntohs (msg->rd_len);
666   if (ntohs (msg->gns_header.header.size) !=
667       sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len)
668   {
669     GNUNET_break (0);
670     return GNUNET_SYSERR;
671   }
672   name_tmp = (const char *) &msg[1];
673   if ( (name_len > 0) &&
674        ('\0' != name_tmp[name_len -1]) )
675   {
676     GNUNET_break (0);
677     return GNUNET_SYSERR;
678   }
679   return check_rd (rd_ser_len,
680                    &name_tmp[name_len],
681                    ntohs (msg->rd_count));
682 }
683
684
685 /**
686  * Handle an incoming message of type
687  * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
688  *
689  * @param cls
690  * @param msg the message we received
691  */
692 static void
693 handle_zone_to_name_response (void *cls,
694                               const struct ZoneToNameResponseMessage *msg)
695 {
696   struct GNUNET_NAMESTORE_Handle *h = cls;
697   struct GNUNET_NAMESTORE_QueueEntry *qe;
698   int res;
699   size_t name_len;
700   size_t rd_ser_len;
701   unsigned int rd_count;
702   const char *name_tmp;
703   const char *rd_tmp;
704
705   LOG (GNUNET_ERROR_TYPE_DEBUG,
706        "Received ZONE_TO_NAME_RESPONSE\n");
707   qe = find_qe (h,
708                 ntohl (msg->gns_header.r_id));
709   res = ntohs (msg->res);
710   switch (res)
711   {
712   case GNUNET_SYSERR:
713     LOG (GNUNET_ERROR_TYPE_DEBUG,
714          "An error occured during zone to name operation\n");
715     break;
716   case GNUNET_NO:
717     LOG (GNUNET_ERROR_TYPE_DEBUG,
718          "Namestore has no result for zone to name mapping \n");
719     if (NULL != qe->proc)
720       qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL);
721     free_qe (qe);
722     return;
723   case GNUNET_YES:
724     LOG (GNUNET_ERROR_TYPE_DEBUG,
725          "Namestore has result for zone to name mapping \n");
726     name_len = ntohs (msg->name_len);
727     rd_count = ntohs (msg->rd_count);
728     rd_ser_len = ntohs (msg->rd_len);
729     name_tmp = (const char *) &msg[1];
730     rd_tmp = &name_tmp[name_len];
731     {
732       struct GNUNET_GNSRECORD_Data rd[rd_count];
733
734       GNUNET_assert (GNUNET_OK ==
735                      GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
736                                                            rd_tmp,
737                                                            rd_count,
738                                                            rd));
739       /* normal end, call continuation with result */
740       if (NULL != qe->proc)
741         qe->proc (qe->proc_cls,
742                   &msg->zone,
743                   name_tmp,
744                   rd_count,
745                   rd);
746       /* return is important here: break would call continuation with error! */
747       free_qe (qe);
748       return;
749     }
750   default:
751     GNUNET_break (0);
752     force_reconnect (h);
753     return;
754   }
755   /* error case, call continuation with error */
756   if (NULL != qe->error_cb)
757     qe->error_cb (qe->error_cb_cls);
758   free_qe (qe);
759 }
760
761
762
763 /**
764  * Generic error handler, called with the appropriate error code and
765  * the same closure specified at the creation of the message queue.
766  * Not every message queue implementation supports an error handler.
767  *
768  * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *`
769  * @param error error code
770  */
771 static void
772 mq_error_handler (void *cls,
773                   enum GNUNET_MQ_Error error)
774 {
775   struct GNUNET_NAMESTORE_Handle *h = cls;
776
777   (void) error;
778   force_reconnect (h);
779 }
780
781
782 /**
783  * Reconnect to namestore service.
784  *
785  * @param h the handle to the NAMESTORE service
786  */
787 static void
788 reconnect (struct GNUNET_NAMESTORE_Handle *h)
789 {
790   struct GNUNET_MQ_MessageHandler handlers[] = {
791     GNUNET_MQ_hd_fixed_size (record_store_response,
792                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
793                              struct RecordStoreResponseMessage,
794                              h),
795     GNUNET_MQ_hd_var_size (zone_to_name_response,
796                            GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
797                            struct ZoneToNameResponseMessage,
798                            h),
799     GNUNET_MQ_hd_var_size (record_result,
800                            GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
801                            struct RecordResultMessage,
802                            h),
803     GNUNET_MQ_hd_var_size (lookup_result,
804                            GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
805                            struct LabelLookupResponseMessage,
806                            h),
807     GNUNET_MQ_handler_end ()
808   };
809   struct GNUNET_NAMESTORE_ZoneIterator *it;
810   struct GNUNET_NAMESTORE_QueueEntry *qe;
811
812   GNUNET_assert (NULL == h->mq);
813   h->mq = GNUNET_CLIENT_connect (h->cfg,
814                                  "namestore",
815                                  handlers,
816                                  &mq_error_handler,
817                                  h);
818   if (NULL == h->mq)
819     return;
820   /* re-transmit pending requests that waited for a reconnect... */
821   for (it = h->z_head; NULL != it; it = it->next)
822   {
823     GNUNET_MQ_send (h->mq,
824                     it->env);
825     it->env = NULL;
826   }
827   for (qe = h->op_head; NULL != qe; qe = qe->next)
828   {
829     GNUNET_MQ_send (h->mq,
830                     qe->env);
831     qe->env = NULL;
832   }
833 }
834
835
836 /**
837  * Re-establish the connection to the service.
838  *
839  * @param cls handle to use to re-connect.
840  */
841 static void
842 reconnect_task (void *cls)
843 {
844   struct GNUNET_NAMESTORE_Handle *h = cls;
845
846   h->reconnect_task = NULL;
847   reconnect (h);
848 }
849
850
851 /**
852  * Disconnect from service and then reconnect.
853  *
854  * @param h our handle
855  */
856 static void
857 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
858 {
859   struct GNUNET_NAMESTORE_ZoneIterator *ze;
860   struct GNUNET_NAMESTORE_QueueEntry *qe;
861
862   GNUNET_MQ_destroy (h->mq);
863   h->mq = NULL;
864   while (NULL != (ze = h->z_head))
865   {
866     if (NULL != ze->error_cb)
867       ze->error_cb (ze->error_cb_cls);
868     free_ze (ze);
869   }
870   while (NULL != (qe = h->op_head))
871   {
872     if (NULL != qe->error_cb)
873       qe->error_cb (qe->error_cb_cls);
874     if (NULL != qe->cont)
875       qe->cont (qe->cont_cls,
876                 GNUNET_SYSERR,
877                 "failure in communication with namestore service");
878     free_qe (qe);
879   }
880
881   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
882               "Reconnecting to namestore\n");
883   h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
884   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
885                                                     &reconnect_task,
886                                                     h);
887 }
888
889
890 /**
891  * Get a fresh operation id to distinguish between namestore requests
892  *
893  * @param h the namestore handle
894  * @return next operation id to use
895  */
896 static uint32_t
897 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
898 {
899   return h->last_op_id_used++;
900 }
901
902
903 /**
904  * Initialize the connection with the NAMESTORE service.
905  *
906  * @param cfg configuration to use
907  * @return handle to the GNS service, or NULL on error
908  */
909 struct GNUNET_NAMESTORE_Handle *
910 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
911 {
912   struct GNUNET_NAMESTORE_Handle *h;
913
914   h = GNUNET_new (struct GNUNET_NAMESTORE_Handle);
915   h->cfg = cfg;
916   reconnect (h);
917   if (NULL == h->mq)
918   {
919     GNUNET_free (h);
920     return NULL;
921   }
922   return h;
923 }
924
925
926 /**
927  * Disconnect from the namestore service (and free associated
928  * resources).
929  *
930  * @param h handle to the namestore
931  */
932 void
933 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
934 {
935   struct GNUNET_NAMESTORE_QueueEntry *q;
936   struct GNUNET_NAMESTORE_ZoneIterator *z;
937
938   LOG (GNUNET_ERROR_TYPE_DEBUG,
939        "Cleaning up\n");
940   GNUNET_break (NULL == h->op_head);
941   while (NULL != (q = h->op_head))
942   {
943     GNUNET_CONTAINER_DLL_remove (h->op_head,
944                                  h->op_tail,
945                                  q);
946     GNUNET_free (q);
947   }
948   GNUNET_break (NULL == h->z_head);
949   while (NULL != (z = h->z_head))
950   {
951     GNUNET_CONTAINER_DLL_remove (h->z_head,
952                                  h->z_tail,
953                                  z);
954     GNUNET_free (z);
955   }
956   if (NULL != h->mq)
957   {
958     GNUNET_MQ_destroy (h->mq);
959     h->mq = NULL;
960   }
961   if (NULL != h->reconnect_task)
962   {
963     GNUNET_SCHEDULER_cancel (h->reconnect_task);
964     h->reconnect_task = NULL;
965   }
966   GNUNET_free (h);
967 }
968
969
970 /**
971  * Store an item in the namestore.  If the item is already present,
972  * it is replaced with the new record.  Use an empty array to
973  * remove all records under the given name.
974  *
975  * @param h handle to the namestore
976  * @param pkey private key of the zone
977  * @param label name that is being mapped (at most 255 characters long)
978  * @param rd_count number of records in the @a rd array
979  * @param rd array of records with data to store
980  * @param cont continuation to call when done
981  * @param cont_cls closure for @a cont
982  * @return handle to abort the request
983  */
984 struct GNUNET_NAMESTORE_QueueEntry *
985 GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h,
986                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
987                                 const char *label,
988                                 unsigned int rd_count,
989                                 const struct GNUNET_GNSRECORD_Data *rd,
990                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
991                                 void *cont_cls)
992 {
993   struct GNUNET_NAMESTORE_QueueEntry *qe;
994   struct GNUNET_MQ_Envelope *env;
995   char *name_tmp;
996   char *rd_ser;
997   size_t rd_ser_len;
998   size_t name_len;
999   uint32_t rid;
1000   struct RecordStoreMessage *msg;
1001   ssize_t sret;
1002
1003   name_len = strlen (label) + 1;
1004   if (name_len > MAX_NAME_LEN)
1005   {
1006     GNUNET_break (0);
1007     return NULL;
1008   }
1009   rid = get_op_id (h);
1010   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1011   qe->h = h;
1012   qe->cont = cont;
1013   qe->cont_cls = cont_cls;
1014   qe->op_id = rid;
1015   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1016                                     h->op_tail,
1017                                     qe);
1018
1019   /* setup msg */
1020   rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1021                                                   rd);
1022   env = GNUNET_MQ_msg_extra (msg,
1023                              name_len + rd_ser_len,
1024                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1025   msg->gns_header.r_id = htonl (rid);
1026   msg->name_len = htons (name_len);
1027   msg->rd_count = htons (rd_count);
1028   msg->rd_len = htons (rd_ser_len);
1029   msg->reserved = htons (0);
1030   msg->private_key = *pkey;
1031
1032   name_tmp = (char *) &msg[1];
1033   GNUNET_memcpy (name_tmp,
1034                  label,
1035                  name_len);
1036   rd_ser = &name_tmp[name_len];
1037   sret = GNUNET_GNSRECORD_records_serialize (rd_count,
1038                                              rd,
1039                                              rd_ser_len,
1040                                              rd_ser);
1041   if (0 > sret)
1042   {
1043     GNUNET_free (env);
1044     return NULL;
1045   }
1046   GNUNET_assert (rd_ser_len == (size_t) sret);
1047   LOG (GNUNET_ERROR_TYPE_DEBUG,
1048        "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
1049        label,
1050        rd_count);
1051
1052   if (NULL == h->mq)
1053     qe->env = env;
1054   else
1055     GNUNET_MQ_send (h->mq,
1056                     env);
1057   return qe;
1058 }
1059
1060
1061 /**
1062  * Set the desired nick name for a zone
1063  *
1064  * @param h handle to the namestore
1065  * @param pkey private key of the zone
1066  * @param nick the nick name to set
1067  * @param cont continuation to call when done
1068  * @param cont_cls closure for @a cont
1069  * @return handle to abort the request
1070  */
1071 struct GNUNET_NAMESTORE_QueueEntry *
1072 GNUNET_NAMESTORE_set_nick (struct GNUNET_NAMESTORE_Handle *h,
1073                            const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1074                            const char *nick,
1075                            GNUNET_NAMESTORE_ContinuationWithStatus cont,
1076                            void *cont_cls)
1077 {
1078   struct GNUNET_GNSRECORD_Data rd;
1079
1080   if (NULL == h->mq)
1081     return NULL;
1082   memset (&rd, 0, sizeof (rd));
1083   rd.data = nick;
1084   rd.data_size = strlen (nick) +1;
1085   rd.record_type = GNUNET_GNSRECORD_TYPE_NICK;
1086   rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
1087   rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1088   return GNUNET_NAMESTORE_records_store (h,
1089                                          pkey,
1090                                          GNUNET_GNS_EMPTY_LABEL_AT,
1091                                          1,
1092                                          &rd,
1093                                          cont,
1094                                          cont_cls);
1095 }
1096
1097
1098 /**
1099  * Lookup an item in the namestore.
1100  *
1101  * @param h handle to the namestore
1102  * @param pkey private key of the zone
1103  * @param label name that is being mapped (at most 255 characters long)
1104  * @param error_cb function to call on error (i.e. disconnect)
1105  * @param error_cb_cls closure for @a error_cb
1106  * @param rm function to call with the result (with 0 records if we don't have that label)
1107  * @param rm_cls closure for @a rm
1108  * @return handle to abort the request
1109  */
1110 struct GNUNET_NAMESTORE_QueueEntry *
1111 GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h,
1112                                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1113                                  const char *label,
1114                                  GNUNET_SCHEDULER_TaskCallback error_cb,
1115                                  void *error_cb_cls,
1116                                  GNUNET_NAMESTORE_RecordMonitor rm,
1117                                  void *rm_cls)
1118 {
1119   struct GNUNET_NAMESTORE_QueueEntry *qe;
1120   struct GNUNET_MQ_Envelope *env;
1121   struct LabelLookupMessage *msg;
1122   size_t label_len;
1123
1124   if (1 == (label_len = strlen (label) + 1))
1125   {
1126     GNUNET_break (0);
1127     return NULL;
1128   }
1129
1130   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1131   qe->h = h;
1132   qe->error_cb = error_cb;
1133   qe->error_cb_cls = error_cb_cls;
1134   qe->proc = rm;
1135   qe->proc_cls = rm_cls;
1136   qe->op_id = get_op_id(h);
1137   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1138                                     h->op_tail,
1139                                     qe);
1140
1141   env = GNUNET_MQ_msg_extra (msg,
1142                              label_len,
1143                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1144   msg->gns_header.r_id = htonl (qe->op_id);
1145   msg->zone = *pkey;
1146   msg->label_len = htonl (label_len);
1147   GNUNET_memcpy (&msg[1],
1148           label,
1149           label_len);
1150   if (NULL == h->mq)
1151     qe->env = env;
1152   else
1153     GNUNET_MQ_send (h->mq,
1154                     env);
1155   return qe;
1156 }
1157
1158
1159 /**
1160  * Look for an existing PKEY delegation record for a given public key.
1161  * Returns at most one result to the processor.
1162  *
1163  * @param h handle to the namestore
1164  * @param zone public key of the zone to look up in, never NULL
1165  * @param value_zone public key of the target zone (value), never NULL
1166  * @param error_cb function to call on error (i.e. disconnect)
1167  * @param error_cb_cls closure for @a error_cb
1168  * @param proc function to call on the matching records, or with
1169  *        NULL (rd_count == 0) if there are no matching records
1170  * @param proc_cls closure for @a proc
1171  * @return a handle that can be used to
1172  *         cancel
1173  */
1174 struct GNUNET_NAMESTORE_QueueEntry *
1175 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1176                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1177                                const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
1178                                GNUNET_SCHEDULER_TaskCallback error_cb,
1179                                void *error_cb_cls,
1180                                GNUNET_NAMESTORE_RecordMonitor proc,
1181                                void *proc_cls)
1182 {
1183   struct GNUNET_NAMESTORE_QueueEntry *qe;
1184   struct GNUNET_MQ_Envelope *env;
1185   struct ZoneToNameMessage *msg;
1186   uint32_t rid;
1187
1188   rid = get_op_id(h);
1189   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1190   qe->h = h;
1191   qe->error_cb = error_cb;
1192   qe->error_cb_cls = error_cb_cls;
1193   qe->proc = proc;
1194   qe->proc_cls = proc_cls;
1195   qe->op_id = rid;
1196   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1197                                     h->op_tail,
1198                                     qe);
1199
1200   env = GNUNET_MQ_msg (msg,
1201                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1202   msg->gns_header.r_id = htonl (rid);
1203   msg->zone = *zone;
1204   msg->value_zone = *value_zone;
1205   if (NULL == h->mq)
1206     qe->env = env;
1207   else
1208     GNUNET_MQ_send (h->mq,
1209                     env);
1210   return qe;
1211 }
1212
1213
1214 /**
1215  * Starts a new zone iteration (used to periodically PUT all of our
1216  * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1217  * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1218  * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1219  * immediately, and then again after
1220  * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1221  *
1222  * @param h handle to the namestore
1223  * @param zone zone to access, NULL for all zones
1224  * @param error_cb function to call on error (i.e. disconnect)
1225  * @param error_cb_cls closure for @a error_cb
1226  * @param proc function to call on each name from the zone; it
1227  *        will be called repeatedly with a value (if available)
1228  * @param proc_cls closure for @a proc
1229  * @param finish_cb function to call on completion
1230  * @param finish_cb_cls closure for @a finish_cb
1231  * @return an iterator handle to use for iteration
1232  */
1233 struct GNUNET_NAMESTORE_ZoneIterator *
1234 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1235                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1236                                        GNUNET_SCHEDULER_TaskCallback error_cb,
1237                                        void *error_cb_cls,
1238                                        GNUNET_NAMESTORE_RecordMonitor proc,
1239                                        void *proc_cls,
1240                                        GNUNET_SCHEDULER_TaskCallback finish_cb,
1241                                        void *finish_cb_cls)
1242 {
1243   struct GNUNET_NAMESTORE_ZoneIterator *it;
1244   struct GNUNET_MQ_Envelope *env;
1245   struct ZoneIterationStartMessage *msg;
1246   uint32_t rid;
1247
1248   LOG (GNUNET_ERROR_TYPE_DEBUG,
1249        "Sending ZONE_ITERATION_START message\n");
1250   rid = get_op_id (h);
1251   it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1252   it->h = h;
1253   it->error_cb = error_cb;
1254   it->error_cb_cls = error_cb_cls;
1255   it->finish_cb = finish_cb;
1256   it->finish_cb_cls = finish_cb_cls;
1257   it->proc = proc;
1258   it->proc_cls = proc_cls;
1259   it->op_id = rid;
1260   if (NULL != zone)
1261     it->zone = *zone;
1262   GNUNET_CONTAINER_DLL_insert_tail (h->z_head,
1263                                     h->z_tail,
1264                                     it);
1265   env = GNUNET_MQ_msg (msg,
1266                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1267   msg->gns_header.r_id = htonl (rid);
1268   if (NULL != zone)
1269     msg->zone = *zone;
1270   if (NULL == h->mq)
1271     it->env = env;
1272   else
1273     GNUNET_MQ_send (h->mq,
1274                     env);
1275   return it;
1276 }
1277
1278
1279 /**
1280  * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1281  * for the next record.
1282  *
1283  * @param it the iterator
1284  * @param limit number of records to return to the iterator in one shot
1285  *         (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
1286  */
1287 void
1288 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
1289                                      uint64_t limit)
1290 {
1291   struct GNUNET_NAMESTORE_Handle *h = it->h;
1292   struct ZoneIterationNextMessage *msg;
1293   struct GNUNET_MQ_Envelope *env;
1294
1295   LOG (GNUNET_ERROR_TYPE_DEBUG,
1296        "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
1297        (unsigned long long) limit);
1298   env = GNUNET_MQ_msg (msg,
1299                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1300   msg->gns_header.r_id = htonl (it->op_id);
1301   msg->limit = GNUNET_htonll (limit);
1302   GNUNET_MQ_send (h->mq,
1303                   env);
1304 }
1305
1306
1307 /**
1308  * Stops iteration and releases the namestore handle for further calls.
1309  *
1310  * @param it the iterator
1311  */
1312 void
1313 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1314 {
1315   struct GNUNET_NAMESTORE_Handle *h = it->h;
1316   struct GNUNET_MQ_Envelope *env;
1317   struct ZoneIterationStopMessage *msg;
1318
1319   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1320               "Sending ZONE_ITERATION_STOP message\n");
1321   if (NULL != h->mq)
1322   {
1323     env = GNUNET_MQ_msg (msg,
1324                          GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1325     msg->gns_header.r_id = htonl (it->op_id);
1326     GNUNET_MQ_send (h->mq,
1327                     env);
1328   }
1329   free_ze (it);
1330 }
1331
1332
1333 /**
1334  * Cancel a namestore operation.  The final callback from the
1335  * operation must not have been done yet.
1336  *
1337  * @param qe operation to cancel
1338  */
1339 void
1340 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1341 {
1342   free_qe (qe);
1343 }
1344
1345
1346 /* end of namestore_api.c */