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