reduce loop counters to more practical levels
[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   ssize_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   rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1049                                                   rd);
1050   if (rd_ser_len < 0)
1051   {
1052     GNUNET_break (0);
1053     return NULL;
1054   }
1055   if (rd_ser_len > UINT16_MAX)
1056   {
1057     GNUNET_break (0);
1058     return NULL;
1059   }
1060   rid = get_op_id (h);
1061   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1062   qe->h = h;
1063   qe->cont = cont;
1064   qe->cont_cls = cont_cls;
1065   qe->op_id = rid;
1066   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1067                                     h->op_tail,
1068                                     qe);
1069
1070   /* setup msg */
1071   env = GNUNET_MQ_msg_extra (msg,
1072                              name_len + rd_ser_len,
1073                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1074   msg->gns_header.r_id = htonl (rid);
1075   msg->name_len = htons (name_len);
1076   msg->rd_count = htons (rd_count);
1077   msg->rd_len = htons (rd_ser_len);
1078   msg->reserved = htons (0);
1079   msg->private_key = *pkey;
1080
1081   name_tmp = (char *) &msg[1];
1082   GNUNET_memcpy (name_tmp,
1083                  label,
1084                  name_len);
1085   rd_ser = &name_tmp[name_len];
1086   sret = GNUNET_GNSRECORD_records_serialize (rd_count,
1087                                              rd,
1088                                              rd_ser_len,
1089                                              rd_ser);
1090   if ( (0 > sret) ||
1091        (sret != rd_ser_len) )
1092   {
1093     GNUNET_break (0);
1094     GNUNET_free (env);
1095     return NULL;
1096   }
1097   GNUNET_assert (rd_ser_len == (size_t) sret);
1098   LOG (GNUNET_ERROR_TYPE_DEBUG,
1099        "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
1100        label,
1101        rd_count);
1102   qe->timeout_task = GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE,
1103                                                    &warn_delay,
1104                                                    qe);
1105   if (NULL == h->mq)
1106   {
1107     qe->env = env;
1108     LOG (GNUNET_ERROR_TYPE_WARNING,
1109          "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n");
1110   }
1111   else
1112   {
1113     GNUNET_MQ_send (h->mq,
1114                     env);
1115   }
1116   return qe;
1117 }
1118
1119
1120 /**
1121  * Set the desired nick name for a zone
1122  *
1123  * @param h handle to the namestore
1124  * @param pkey private key of the zone
1125  * @param nick the nick name to set
1126  * @param cont continuation to call when done
1127  * @param cont_cls closure for @a cont
1128  * @return handle to abort the request
1129  */
1130 struct GNUNET_NAMESTORE_QueueEntry *
1131 GNUNET_NAMESTORE_set_nick (struct GNUNET_NAMESTORE_Handle *h,
1132                            const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1133                            const char *nick,
1134                            GNUNET_NAMESTORE_ContinuationWithStatus cont,
1135                            void *cont_cls)
1136 {
1137   struct GNUNET_GNSRECORD_Data rd;
1138
1139   if (NULL == h->mq)
1140     return NULL;
1141   memset (&rd, 0, sizeof (rd));
1142   rd.data = nick;
1143   rd.data_size = strlen (nick) +1;
1144   rd.record_type = GNUNET_GNSRECORD_TYPE_NICK;
1145   rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
1146   rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1147   return GNUNET_NAMESTORE_records_store (h,
1148                                          pkey,
1149                                          GNUNET_GNS_EMPTY_LABEL_AT,
1150                                          1,
1151                                          &rd,
1152                                          cont,
1153                                          cont_cls);
1154 }
1155
1156
1157 /**
1158  * Lookup an item in the namestore.
1159  *
1160  * @param h handle to the namestore
1161  * @param pkey private key of the zone
1162  * @param label name that is being mapped (at most 255 characters long)
1163  * @param error_cb function to call on error (i.e. disconnect)
1164  * @param error_cb_cls closure for @a error_cb
1165  * @param rm function to call with the result (with 0 records if we don't have that label)
1166  * @param rm_cls closure for @a rm
1167  * @return handle to abort the request
1168  */
1169 struct GNUNET_NAMESTORE_QueueEntry *
1170 GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h,
1171                                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1172                                  const char *label,
1173                                  GNUNET_SCHEDULER_TaskCallback error_cb,
1174                                  void *error_cb_cls,
1175                                  GNUNET_NAMESTORE_RecordMonitor rm,
1176                                  void *rm_cls)
1177 {
1178   struct GNUNET_NAMESTORE_QueueEntry *qe;
1179   struct GNUNET_MQ_Envelope *env;
1180   struct LabelLookupMessage *msg;
1181   size_t label_len;
1182
1183   if (1 == (label_len = strlen (label) + 1))
1184   {
1185     GNUNET_break (0);
1186     return NULL;
1187   }
1188
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 = rm;
1194   qe->proc_cls = rm_cls;
1195   qe->op_id = get_op_id(h);
1196   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1197                                     h->op_tail,
1198                                     qe);
1199
1200   env = GNUNET_MQ_msg_extra (msg,
1201                              label_len,
1202                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1203   msg->gns_header.r_id = htonl (qe->op_id);
1204   msg->zone = *pkey;
1205   msg->label_len = htonl (label_len);
1206   GNUNET_memcpy (&msg[1],
1207           label,
1208           label_len);
1209   if (NULL == h->mq)
1210     qe->env = env;
1211   else
1212     GNUNET_MQ_send (h->mq,
1213                     env);
1214   return qe;
1215 }
1216
1217
1218 /**
1219  * Look for an existing PKEY delegation record for a given public key.
1220  * Returns at most one result to the processor.
1221  *
1222  * @param h handle to the namestore
1223  * @param zone public key of the zone to look up in, never NULL
1224  * @param value_zone public key of the target zone (value), never NULL
1225  * @param error_cb function to call on error (i.e. disconnect)
1226  * @param error_cb_cls closure for @a error_cb
1227  * @param proc function to call on the matching records, or with
1228  *        NULL (rd_count == 0) if there are no matching records
1229  * @param proc_cls closure for @a proc
1230  * @return a handle that can be used to
1231  *         cancel
1232  */
1233 struct GNUNET_NAMESTORE_QueueEntry *
1234 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1235                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1236                                const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
1237                                GNUNET_SCHEDULER_TaskCallback error_cb,
1238                                void *error_cb_cls,
1239                                GNUNET_NAMESTORE_RecordMonitor proc,
1240                                void *proc_cls)
1241 {
1242   struct GNUNET_NAMESTORE_QueueEntry *qe;
1243   struct GNUNET_MQ_Envelope *env;
1244   struct ZoneToNameMessage *msg;
1245   uint32_t rid;
1246
1247   rid = get_op_id(h);
1248   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1249   qe->h = h;
1250   qe->error_cb = error_cb;
1251   qe->error_cb_cls = error_cb_cls;
1252   qe->proc = proc;
1253   qe->proc_cls = proc_cls;
1254   qe->op_id = rid;
1255   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1256                                     h->op_tail,
1257                                     qe);
1258
1259   env = GNUNET_MQ_msg (msg,
1260                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1261   msg->gns_header.r_id = htonl (rid);
1262   msg->zone = *zone;
1263   msg->value_zone = *value_zone;
1264   if (NULL == h->mq)
1265     qe->env = env;
1266   else
1267     GNUNET_MQ_send (h->mq,
1268                     env);
1269   return qe;
1270 }
1271
1272
1273 /**
1274  * Starts a new zone iteration (used to periodically PUT all of our
1275  * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1276  * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1277  * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1278  * immediately, and then again after
1279  * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1280  *
1281  * @param h handle to the namestore
1282  * @param zone zone to access, NULL for all zones
1283  * @param error_cb function to call on error (i.e. disconnect)
1284  * @param error_cb_cls closure for @a error_cb
1285  * @param proc function to call on each name from the zone; it
1286  *        will be called repeatedly with a value (if available)
1287  * @param proc_cls closure for @a proc
1288  * @param finish_cb function to call on completion
1289  * @param finish_cb_cls closure for @a finish_cb
1290  * @return an iterator handle to use for iteration
1291  */
1292 struct GNUNET_NAMESTORE_ZoneIterator *
1293 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1294                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1295                                        GNUNET_SCHEDULER_TaskCallback error_cb,
1296                                        void *error_cb_cls,
1297                                        GNUNET_NAMESTORE_RecordMonitor proc,
1298                                        void *proc_cls,
1299                                        GNUNET_SCHEDULER_TaskCallback finish_cb,
1300                                        void *finish_cb_cls)
1301 {
1302   struct GNUNET_NAMESTORE_ZoneIterator *it;
1303   struct GNUNET_MQ_Envelope *env;
1304   struct ZoneIterationStartMessage *msg;
1305   uint32_t rid;
1306
1307   LOG (GNUNET_ERROR_TYPE_DEBUG,
1308        "Sending ZONE_ITERATION_START message\n");
1309   rid = get_op_id (h);
1310   it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1311   it->h = h;
1312   it->error_cb = error_cb;
1313   it->error_cb_cls = error_cb_cls;
1314   it->finish_cb = finish_cb;
1315   it->finish_cb_cls = finish_cb_cls;
1316   it->proc = proc;
1317   it->proc_cls = proc_cls;
1318   it->op_id = rid;
1319   if (NULL != zone)
1320     it->zone = *zone;
1321   GNUNET_CONTAINER_DLL_insert_tail (h->z_head,
1322                                     h->z_tail,
1323                                     it);
1324   env = GNUNET_MQ_msg (msg,
1325                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1326   msg->gns_header.r_id = htonl (rid);
1327   if (NULL != zone)
1328     msg->zone = *zone;
1329   if (NULL == h->mq)
1330     it->env = env;
1331   else
1332     GNUNET_MQ_send (h->mq,
1333                     env);
1334   return it;
1335 }
1336
1337
1338 /**
1339  * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1340  * for the next record.
1341  *
1342  * @param it the iterator
1343  * @param limit number of records to return to the iterator in one shot
1344  *         (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
1345  */
1346 void
1347 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
1348                                      uint64_t limit)
1349 {
1350   struct GNUNET_NAMESTORE_Handle *h = it->h;
1351   struct ZoneIterationNextMessage *msg;
1352   struct GNUNET_MQ_Envelope *env;
1353
1354   LOG (GNUNET_ERROR_TYPE_DEBUG,
1355        "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
1356        (unsigned long long) limit);
1357   env = GNUNET_MQ_msg (msg,
1358                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1359   msg->gns_header.r_id = htonl (it->op_id);
1360   msg->limit = GNUNET_htonll (limit);
1361   GNUNET_MQ_send (h->mq,
1362                   env);
1363 }
1364
1365
1366 /**
1367  * Stops iteration and releases the namestore handle for further calls.
1368  *
1369  * @param it the iterator
1370  */
1371 void
1372 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1373 {
1374   struct GNUNET_NAMESTORE_Handle *h = it->h;
1375   struct GNUNET_MQ_Envelope *env;
1376   struct ZoneIterationStopMessage *msg;
1377
1378   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1379               "Sending ZONE_ITERATION_STOP message\n");
1380   if (NULL != h->mq)
1381   {
1382     env = GNUNET_MQ_msg (msg,
1383                          GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1384     msg->gns_header.r_id = htonl (it->op_id);
1385     GNUNET_MQ_send (h->mq,
1386                     env);
1387   }
1388   free_ze (it);
1389 }
1390
1391
1392 /**
1393  * Cancel a namestore operation.  The final callback from the
1394  * operation must not have been done yet.
1395  *
1396  * @param qe operation to cancel
1397  */
1398 void
1399 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1400 {
1401   free_qe (qe);
1402 }
1403
1404
1405 /* end of namestore_api.c */