89eb0afa4d38284422066c85ae1f977893829601
[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 it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
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   static struct GNUNET_CRYPTO_EcdsaPrivateKey priv_dummy;
529   const char *name;
530   size_t msg_len;
531   size_t name_len;
532   size_t rd_len;
533
534   (void) cls;
535   rd_len = ntohs (msg->rd_len);
536   msg_len = ntohs (msg->gns_header.header.size);
537   name_len = ntohs (msg->name_len);
538   if (0 != ntohs (msg->reserved))
539   {
540     GNUNET_break (0);
541     return GNUNET_SYSERR;
542   }
543   if (msg_len != sizeof (struct RecordResultMessage) + name_len + rd_len)
544   {
545     GNUNET_break (0);
546     return GNUNET_SYSERR;
547   }
548   name = (const char *) &msg[1];
549   if ( (0 == name_len) ||
550        ('\0' != name[name_len -1]) )
551   {
552     GNUNET_break (0);
553     return GNUNET_SYSERR;
554   }
555   if (0 == memcmp (&msg->private_key,
556                    &priv_dummy,
557                    sizeof (priv_dummy)) )
558   {
559     GNUNET_break (0);
560     return GNUNET_SYSERR;
561   }
562   return check_rd (rd_len,
563                    &name[name_len],
564                    ntohs (msg->rd_count));
565 }
566
567
568 /**
569  * Handle an incoming message of type
570  * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
571  *
572  * @param cls
573  * @param msg the message we received
574  */
575 static void
576 handle_record_result (void *cls,
577                       const struct RecordResultMessage *msg)
578 {
579   struct GNUNET_NAMESTORE_Handle *h = cls;
580   struct GNUNET_NAMESTORE_QueueEntry *qe;
581   struct GNUNET_NAMESTORE_ZoneIterator *ze;
582   const char *name;
583   const char *rd_tmp;
584   size_t name_len;
585   size_t rd_len;
586   unsigned int rd_count;
587
588   LOG (GNUNET_ERROR_TYPE_DEBUG,
589        "Received RECORD_RESULT\n");
590   rd_len = ntohs (msg->rd_len);
591   rd_count = ntohs (msg->rd_count);
592   name_len = ntohs (msg->name_len);
593   ze = find_zi (h,
594                 ntohl (msg->gns_header.r_id));
595   qe = find_qe (h,
596                 ntohl (msg->gns_header.r_id));
597   if ( (NULL == ze) &&
598        (NULL == qe) )
599     return; /* rid not found */
600   if ( (NULL != ze) &&
601        (NULL != qe) )
602   {
603     GNUNET_break (0);   /* rid ambigous */
604     force_reconnect (h);
605     return;
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_RECORD_RESULT_END
648  *
649  * @param cls
650  * @param msg the message we received
651  */
652 static void
653 handle_record_result_end (void *cls,
654                           const struct GNUNET_NAMESTORE_Header *msg)
655 {
656   struct GNUNET_NAMESTORE_Handle *h = cls;
657   struct GNUNET_NAMESTORE_QueueEntry *qe;
658   struct GNUNET_NAMESTORE_ZoneIterator *ze;
659
660   LOG (GNUNET_ERROR_TYPE_DEBUG,
661        "Received RECORD_RESULT_END\n");
662   ze = find_zi (h,
663                 ntohl (msg->r_id));
664   qe = find_qe (h,
665                 ntohl (msg->r_id));
666   if ( (NULL == ze) &&
667        (NULL == qe) )
668     return; /* rid not found */
669   if ( (NULL != ze) &&
670        (NULL != qe) )
671   {
672     GNUNET_break (0);   /* rid ambigous */
673     force_reconnect (h);
674     return;
675   }
676   LOG (GNUNET_ERROR_TYPE_DEBUG,
677        "Zone iteration completed!\n");
678   if (NULL == ze)
679   {
680     GNUNET_break (0);
681     force_reconnect (h);
682     return;
683   }
684   if (NULL != ze->finish_cb)
685     ze->finish_cb (ze->finish_cb_cls);
686   free_ze (ze);
687 }
688
689
690 /**
691  * Handle an incoming message of type
692  * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
693  *
694  * @param qe the respective entry in the message queue
695  * @param msg the message we received
696  * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
697  */
698 static int
699 check_zone_to_name_response (void *cls,
700                              const struct ZoneToNameResponseMessage *msg)
701 {
702   size_t name_len;
703   size_t rd_ser_len;
704   const char *name_tmp;
705
706   (void) cls;
707   if (GNUNET_OK != ntohs (msg->res))
708     return GNUNET_OK;
709   name_len = ntohs (msg->name_len);
710   rd_ser_len = ntohs (msg->rd_len);
711   if (ntohs (msg->gns_header.header.size) !=
712       sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len)
713   {
714     GNUNET_break (0);
715     return GNUNET_SYSERR;
716   }
717   name_tmp = (const char *) &msg[1];
718   if ( (name_len > 0) &&
719        ('\0' != name_tmp[name_len -1]) )
720   {
721     GNUNET_break (0);
722     return GNUNET_SYSERR;
723   }
724   return check_rd (rd_ser_len,
725                    &name_tmp[name_len],
726                    ntohs (msg->rd_count));
727 }
728
729
730 /**
731  * Handle an incoming message of type
732  * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
733  *
734  * @param cls
735  * @param msg the message we received
736  */
737 static void
738 handle_zone_to_name_response (void *cls,
739                               const struct ZoneToNameResponseMessage *msg)
740 {
741   struct GNUNET_NAMESTORE_Handle *h = cls;
742   struct GNUNET_NAMESTORE_QueueEntry *qe;
743   int res;
744   size_t name_len;
745   size_t rd_ser_len;
746   unsigned int rd_count;
747   const char *name_tmp;
748   const char *rd_tmp;
749
750   LOG (GNUNET_ERROR_TYPE_DEBUG,
751        "Received ZONE_TO_NAME_RESPONSE\n");
752   qe = find_qe (h,
753                 ntohl (msg->gns_header.r_id));
754   res = ntohs (msg->res);
755   switch (res)
756   {
757   case GNUNET_SYSERR:
758     LOG (GNUNET_ERROR_TYPE_DEBUG,
759          "An error occurred during zone to name operation\n");
760     break;
761   case GNUNET_NO:
762     LOG (GNUNET_ERROR_TYPE_DEBUG,
763          "Namestore has no result for zone to name mapping \n");
764     if (NULL != qe->proc)
765       qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL);
766     free_qe (qe);
767     return;
768   case GNUNET_YES:
769     LOG (GNUNET_ERROR_TYPE_DEBUG,
770          "Namestore has result for zone to name mapping \n");
771     name_len = ntohs (msg->name_len);
772     rd_count = ntohs (msg->rd_count);
773     rd_ser_len = ntohs (msg->rd_len);
774     name_tmp = (const char *) &msg[1];
775     rd_tmp = &name_tmp[name_len];
776     {
777       struct GNUNET_GNSRECORD_Data rd[rd_count];
778
779       GNUNET_assert (GNUNET_OK ==
780                      GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
781                                                            rd_tmp,
782                                                            rd_count,
783                                                            rd));
784       /* normal end, call continuation with result */
785       if (NULL != qe->proc)
786         qe->proc (qe->proc_cls,
787                   &msg->zone,
788                   name_tmp,
789                   rd_count,
790                   rd);
791       /* return is important here: break would call continuation with error! */
792       free_qe (qe);
793       return;
794     }
795   default:
796     GNUNET_break (0);
797     force_reconnect (h);
798     return;
799   }
800   /* error case, call continuation with error */
801   if (NULL != qe->error_cb)
802     qe->error_cb (qe->error_cb_cls);
803   free_qe (qe);
804 }
805
806
807
808 /**
809  * Generic error handler, called with the appropriate error code and
810  * the same closure specified at the creation of the message queue.
811  * Not every message queue implementation supports an error handler.
812  *
813  * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *`
814  * @param error error code
815  */
816 static void
817 mq_error_handler (void *cls,
818                   enum GNUNET_MQ_Error error)
819 {
820   struct GNUNET_NAMESTORE_Handle *h = cls;
821
822   (void) error;
823   force_reconnect (h);
824 }
825
826
827 /**
828  * Reconnect to namestore service.
829  *
830  * @param h the handle to the NAMESTORE service
831  */
832 static void
833 reconnect (struct GNUNET_NAMESTORE_Handle *h)
834 {
835   struct GNUNET_MQ_MessageHandler handlers[] = {
836     GNUNET_MQ_hd_fixed_size (record_store_response,
837                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
838                              struct RecordStoreResponseMessage,
839                              h),
840     GNUNET_MQ_hd_var_size (zone_to_name_response,
841                            GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
842                            struct ZoneToNameResponseMessage,
843                            h),
844     GNUNET_MQ_hd_var_size (record_result,
845                            GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
846                            struct RecordResultMessage,
847                            h),
848     GNUNET_MQ_hd_fixed_size (record_result_end,
849                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END,
850                              struct GNUNET_NAMESTORE_Header,
851                              h),
852     GNUNET_MQ_hd_var_size (lookup_result,
853                            GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
854                            struct LabelLookupResponseMessage,
855                            h),
856     GNUNET_MQ_handler_end ()
857   };
858   struct GNUNET_NAMESTORE_ZoneIterator *it;
859   struct GNUNET_NAMESTORE_QueueEntry *qe;
860
861   GNUNET_assert (NULL == h->mq);
862   h->mq = GNUNET_CLIENT_connect (h->cfg,
863                                  "namestore",
864                                  handlers,
865                                  &mq_error_handler,
866                                  h);
867   if (NULL == h->mq)
868     return;
869   /* re-transmit pending requests that waited for a reconnect... */
870   for (it = h->z_head; NULL != it; it = it->next)
871   {
872     GNUNET_MQ_send (h->mq,
873                     it->env);
874     it->env = NULL;
875   }
876   for (qe = h->op_head; NULL != qe; qe = qe->next)
877   {
878     GNUNET_MQ_send (h->mq,
879                     qe->env);
880     qe->env = NULL;
881   }
882 }
883
884
885 /**
886  * Re-establish the connection to the service.
887  *
888  * @param cls handle to use to re-connect.
889  */
890 static void
891 reconnect_task (void *cls)
892 {
893   struct GNUNET_NAMESTORE_Handle *h = cls;
894
895   h->reconnect_task = NULL;
896   reconnect (h);
897 }
898
899
900 /**
901  * Disconnect from service and then reconnect.
902  *
903  * @param h our handle
904  */
905 static void
906 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
907 {
908   struct GNUNET_NAMESTORE_ZoneIterator *ze;
909   struct GNUNET_NAMESTORE_QueueEntry *qe;
910
911   GNUNET_MQ_destroy (h->mq);
912   h->mq = NULL;
913   while (NULL != (ze = h->z_head))
914   {
915     if (NULL != ze->error_cb)
916       ze->error_cb (ze->error_cb_cls);
917     free_ze (ze);
918   }
919   while (NULL != (qe = h->op_head))
920   {
921     if (NULL != qe->error_cb)
922       qe->error_cb (qe->error_cb_cls);
923     if (NULL != qe->cont)
924       qe->cont (qe->cont_cls,
925                 GNUNET_SYSERR,
926                 "failure in communication with namestore service");
927     free_qe (qe);
928   }
929
930   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931               "Reconnecting to namestore\n");
932   h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
933   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
934                                                     &reconnect_task,
935                                                     h);
936 }
937
938
939 /**
940  * Get a fresh operation id to distinguish between namestore requests
941  *
942  * @param h the namestore handle
943  * @return next operation id to use
944  */
945 static uint32_t
946 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
947 {
948   return h->last_op_id_used++;
949 }
950
951
952 /**
953  * Initialize the connection with the NAMESTORE service.
954  *
955  * @param cfg configuration to use
956  * @return handle to the GNS service, or NULL on error
957  */
958 struct GNUNET_NAMESTORE_Handle *
959 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
960 {
961   struct GNUNET_NAMESTORE_Handle *h;
962
963   h = GNUNET_new (struct GNUNET_NAMESTORE_Handle);
964   h->cfg = cfg;
965   reconnect (h);
966   if (NULL == h->mq)
967   {
968     GNUNET_free (h);
969     return NULL;
970   }
971   return h;
972 }
973
974
975 /**
976  * Disconnect from the namestore service (and free associated
977  * resources).
978  *
979  * @param h handle to the namestore
980  */
981 void
982 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
983 {
984   struct GNUNET_NAMESTORE_QueueEntry *q;
985   struct GNUNET_NAMESTORE_ZoneIterator *z;
986
987   LOG (GNUNET_ERROR_TYPE_DEBUG,
988        "Cleaning up\n");
989   GNUNET_break (NULL == h->op_head);
990   while (NULL != (q = h->op_head))
991   {
992     GNUNET_CONTAINER_DLL_remove (h->op_head,
993                                  h->op_tail,
994                                  q);
995     GNUNET_free (q);
996   }
997   GNUNET_break (NULL == h->z_head);
998   while (NULL != (z = h->z_head))
999   {
1000     GNUNET_CONTAINER_DLL_remove (h->z_head,
1001                                  h->z_tail,
1002                                  z);
1003     GNUNET_free (z);
1004   }
1005   if (NULL != h->mq)
1006   {
1007     GNUNET_MQ_destroy (h->mq);
1008     h->mq = NULL;
1009   }
1010   if (NULL != h->reconnect_task)
1011   {
1012     GNUNET_SCHEDULER_cancel (h->reconnect_task);
1013     h->reconnect_task = NULL;
1014   }
1015   GNUNET_free (h);
1016 }
1017
1018
1019 /**
1020  * Task launched to warn the user that the namestore is
1021  * excessively slow and that a query was thus dropped.
1022  *
1023  * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *`
1024  */
1025 static void
1026 warn_delay (void *cls)
1027 {
1028   struct GNUNET_NAMESTORE_QueueEntry *qe = cls;
1029
1030   qe->timeout_task = NULL;
1031   LOG (GNUNET_ERROR_TYPE_WARNING,
1032        "Did not receive response from namestore after %s!\n",
1033        GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE,
1034                                                GNUNET_YES));
1035   if (NULL != qe->cont)
1036   {
1037     qe->cont (qe->cont_cls,
1038               GNUNET_SYSERR,
1039               "timeout");
1040     qe->cont = NULL;
1041   }
1042   GNUNET_NAMESTORE_cancel (qe);
1043 }
1044
1045
1046 /**
1047  * Store an item in the namestore.  If the item is already present,
1048  * it is replaced with the new record.  Use an empty array to
1049  * remove all records under the given name.
1050  *
1051  * @param h handle to the namestore
1052  * @param pkey private key of the zone
1053  * @param label name that is being mapped (at most 255 characters long)
1054  * @param rd_count number of records in the @a rd array
1055  * @param rd array of records with data to store
1056  * @param cont continuation to call when done
1057  * @param cont_cls closure for @a cont
1058  * @return handle to abort the request
1059  */
1060 struct GNUNET_NAMESTORE_QueueEntry *
1061 GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h,
1062                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1063                                 const char *label,
1064                                 unsigned int rd_count,
1065                                 const struct GNUNET_GNSRECORD_Data *rd,
1066                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1067                                 void *cont_cls)
1068 {
1069   struct GNUNET_NAMESTORE_QueueEntry *qe;
1070   struct GNUNET_MQ_Envelope *env;
1071   char *name_tmp;
1072   char *rd_ser;
1073   ssize_t rd_ser_len;
1074   size_t name_len;
1075   uint32_t rid;
1076   struct RecordStoreMessage *msg;
1077   ssize_t sret;
1078
1079   name_len = strlen (label) + 1;
1080   if (name_len > MAX_NAME_LEN)
1081   {
1082     GNUNET_break (0);
1083     return NULL;
1084   }
1085   rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1086                                                   rd);
1087   if (rd_ser_len < 0)
1088   {
1089     GNUNET_break (0);
1090     return NULL;
1091   }
1092   if (rd_ser_len > UINT16_MAX)
1093   {
1094     GNUNET_break (0);
1095     return NULL;
1096   }
1097   rid = get_op_id (h);
1098   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1099   qe->h = h;
1100   qe->cont = cont;
1101   qe->cont_cls = cont_cls;
1102   qe->op_id = rid;
1103   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1104                                     h->op_tail,
1105                                     qe);
1106
1107   /* setup msg */
1108   env = GNUNET_MQ_msg_extra (msg,
1109                              name_len + rd_ser_len,
1110                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1111   msg->gns_header.r_id = htonl (rid);
1112   msg->name_len = htons (name_len);
1113   msg->rd_count = htons (rd_count);
1114   msg->rd_len = htons (rd_ser_len);
1115   msg->reserved = htons (0);
1116   msg->private_key = *pkey;
1117
1118   name_tmp = (char *) &msg[1];
1119   GNUNET_memcpy (name_tmp,
1120                  label,
1121                  name_len);
1122   rd_ser = &name_tmp[name_len];
1123   sret = GNUNET_GNSRECORD_records_serialize (rd_count,
1124                                              rd,
1125                                              rd_ser_len,
1126                                              rd_ser);
1127   if ( (0 > sret) ||
1128        (sret != rd_ser_len) )
1129   {
1130     GNUNET_break (0);
1131     GNUNET_free (env);
1132     return NULL;
1133   }
1134   GNUNET_assert (rd_ser_len == (size_t) sret);
1135   LOG (GNUNET_ERROR_TYPE_DEBUG,
1136        "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
1137        label,
1138        rd_count);
1139   qe->timeout_task = GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE,
1140                                                    &warn_delay,
1141                                                    qe);
1142   if (NULL == h->mq)
1143   {
1144     qe->env = env;
1145     LOG (GNUNET_ERROR_TYPE_WARNING,
1146          "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n");
1147   }
1148   else
1149   {
1150     GNUNET_MQ_send (h->mq,
1151                     env);
1152   }
1153   return qe;
1154 }
1155
1156
1157 /**
1158  * Set the desired nick name for a zone
1159  *
1160  * @param h handle to the namestore
1161  * @param pkey private key of the zone
1162  * @param nick the nick name to set
1163  * @param cont continuation to call when done
1164  * @param cont_cls closure for @a cont
1165  * @return handle to abort the request
1166  */
1167 struct GNUNET_NAMESTORE_QueueEntry *
1168 GNUNET_NAMESTORE_set_nick (struct GNUNET_NAMESTORE_Handle *h,
1169                            const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1170                            const char *nick,
1171                            GNUNET_NAMESTORE_ContinuationWithStatus cont,
1172                            void *cont_cls)
1173 {
1174   struct GNUNET_GNSRECORD_Data rd;
1175
1176   if (NULL == h->mq)
1177     return NULL;
1178   memset (&rd, 0, sizeof (rd));
1179   rd.data = nick;
1180   rd.data_size = strlen (nick) +1;
1181   rd.record_type = GNUNET_GNSRECORD_TYPE_NICK;
1182   rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
1183   rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1184   return GNUNET_NAMESTORE_records_store (h,
1185                                          pkey,
1186                                          GNUNET_GNS_EMPTY_LABEL_AT,
1187                                          1,
1188                                          &rd,
1189                                          cont,
1190                                          cont_cls);
1191 }
1192
1193
1194 /**
1195  * Lookup an item in the namestore.
1196  *
1197  * @param h handle to the namestore
1198  * @param pkey private key of the zone
1199  * @param label name that is being mapped (at most 255 characters long)
1200  * @param error_cb function to call on error (i.e. disconnect)
1201  * @param error_cb_cls closure for @a error_cb
1202  * @param rm function to call with the result (with 0 records if we don't have that label)
1203  * @param rm_cls closure for @a rm
1204  * @return handle to abort the request
1205  */
1206 struct GNUNET_NAMESTORE_QueueEntry *
1207 GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h,
1208                                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1209                                  const char *label,
1210                                  GNUNET_SCHEDULER_TaskCallback error_cb,
1211                                  void *error_cb_cls,
1212                                  GNUNET_NAMESTORE_RecordMonitor rm,
1213                                  void *rm_cls)
1214 {
1215   struct GNUNET_NAMESTORE_QueueEntry *qe;
1216   struct GNUNET_MQ_Envelope *env;
1217   struct LabelLookupMessage *msg;
1218   size_t label_len;
1219
1220   if (1 == (label_len = strlen (label) + 1))
1221   {
1222     GNUNET_break (0);
1223     return NULL;
1224   }
1225
1226   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1227   qe->h = h;
1228   qe->error_cb = error_cb;
1229   qe->error_cb_cls = error_cb_cls;
1230   qe->proc = rm;
1231   qe->proc_cls = rm_cls;
1232   qe->op_id = get_op_id(h);
1233   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1234                                     h->op_tail,
1235                                     qe);
1236
1237   env = GNUNET_MQ_msg_extra (msg,
1238                              label_len,
1239                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1240   msg->gns_header.r_id = htonl (qe->op_id);
1241   msg->zone = *pkey;
1242   msg->label_len = htonl (label_len);
1243   GNUNET_memcpy (&msg[1],
1244           label,
1245           label_len);
1246   if (NULL == h->mq)
1247     qe->env = env;
1248   else
1249     GNUNET_MQ_send (h->mq,
1250                     env);
1251   return qe;
1252 }
1253
1254
1255 /**
1256  * Look for an existing PKEY delegation record for a given public key.
1257  * Returns at most one result to the processor.
1258  *
1259  * @param h handle to the namestore
1260  * @param zone public key of the zone to look up in, never NULL
1261  * @param value_zone public key of the target zone (value), never NULL
1262  * @param error_cb function to call on error (i.e. disconnect)
1263  * @param error_cb_cls closure for @a error_cb
1264  * @param proc function to call on the matching records, or with
1265  *        NULL (rd_count == 0) if there are no matching records
1266  * @param proc_cls closure for @a proc
1267  * @return a handle that can be used to
1268  *         cancel
1269  */
1270 struct GNUNET_NAMESTORE_QueueEntry *
1271 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1272                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1273                                const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
1274                                GNUNET_SCHEDULER_TaskCallback error_cb,
1275                                void *error_cb_cls,
1276                                GNUNET_NAMESTORE_RecordMonitor proc,
1277                                void *proc_cls)
1278 {
1279   struct GNUNET_NAMESTORE_QueueEntry *qe;
1280   struct GNUNET_MQ_Envelope *env;
1281   struct ZoneToNameMessage *msg;
1282   uint32_t rid;
1283
1284   rid = get_op_id(h);
1285   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1286   qe->h = h;
1287   qe->error_cb = error_cb;
1288   qe->error_cb_cls = error_cb_cls;
1289   qe->proc = proc;
1290   qe->proc_cls = proc_cls;
1291   qe->op_id = rid;
1292   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
1293                                     h->op_tail,
1294                                     qe);
1295
1296   env = GNUNET_MQ_msg (msg,
1297                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1298   msg->gns_header.r_id = htonl (rid);
1299   msg->zone = *zone;
1300   msg->value_zone = *value_zone;
1301   if (NULL == h->mq)
1302     qe->env = env;
1303   else
1304     GNUNET_MQ_send (h->mq,
1305                     env);
1306   return qe;
1307 }
1308
1309
1310 /**
1311  * Starts a new zone iteration (used to periodically PUT all of our
1312  * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1313  * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1314  * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1315  * immediately, and then again after
1316  * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1317  *
1318  * @param h handle to the namestore
1319  * @param zone zone to access, NULL for all zones
1320  * @param error_cb function to call on error (i.e. disconnect)
1321  * @param error_cb_cls closure for @a error_cb
1322  * @param proc function to call on each name from the zone; it
1323  *        will be called repeatedly with a value (if available)
1324  * @param proc_cls closure for @a proc
1325  * @param finish_cb function to call on completion
1326  * @param finish_cb_cls closure for @a finish_cb
1327  * @return an iterator handle to use for iteration
1328  */
1329 struct GNUNET_NAMESTORE_ZoneIterator *
1330 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1331                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1332                                        GNUNET_SCHEDULER_TaskCallback error_cb,
1333                                        void *error_cb_cls,
1334                                        GNUNET_NAMESTORE_RecordMonitor proc,
1335                                        void *proc_cls,
1336                                        GNUNET_SCHEDULER_TaskCallback finish_cb,
1337                                        void *finish_cb_cls)
1338 {
1339   struct GNUNET_NAMESTORE_ZoneIterator *it;
1340   struct GNUNET_MQ_Envelope *env;
1341   struct ZoneIterationStartMessage *msg;
1342   uint32_t rid;
1343
1344   LOG (GNUNET_ERROR_TYPE_DEBUG,
1345        "Sending ZONE_ITERATION_START message\n");
1346   rid = get_op_id (h);
1347   it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1348   it->h = h;
1349   it->error_cb = error_cb;
1350   it->error_cb_cls = error_cb_cls;
1351   it->finish_cb = finish_cb;
1352   it->finish_cb_cls = finish_cb_cls;
1353   it->proc = proc;
1354   it->proc_cls = proc_cls;
1355   it->op_id = rid;
1356   if (NULL != zone)
1357     it->zone = *zone;
1358   GNUNET_CONTAINER_DLL_insert_tail (h->z_head,
1359                                     h->z_tail,
1360                                     it);
1361   env = GNUNET_MQ_msg (msg,
1362                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1363   msg->gns_header.r_id = htonl (rid);
1364   if (NULL != zone)
1365     msg->zone = *zone;
1366   if (NULL == h->mq)
1367     it->env = env;
1368   else
1369     GNUNET_MQ_send (h->mq,
1370                     env);
1371   return it;
1372 }
1373
1374
1375 /**
1376  * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1377  * for the next record.
1378  *
1379  * @param it the iterator
1380  * @param limit number of records to return to the iterator in one shot
1381  *         (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
1382  */
1383 void
1384 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
1385                                      uint64_t limit)
1386 {
1387   struct GNUNET_NAMESTORE_Handle *h = it->h;
1388   struct ZoneIterationNextMessage *msg;
1389   struct GNUNET_MQ_Envelope *env;
1390
1391   LOG (GNUNET_ERROR_TYPE_DEBUG,
1392        "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
1393        (unsigned long long) limit);
1394   env = GNUNET_MQ_msg (msg,
1395                        GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1396   msg->gns_header.r_id = htonl (it->op_id);
1397   msg->limit = GNUNET_htonll (limit);
1398   GNUNET_MQ_send (h->mq,
1399                   env);
1400 }
1401
1402
1403 /**
1404  * Stops iteration and releases the namestore handle for further calls.
1405  *
1406  * @param it the iterator
1407  */
1408 void
1409 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1410 {
1411   struct GNUNET_NAMESTORE_Handle *h = it->h;
1412   struct GNUNET_MQ_Envelope *env;
1413   struct ZoneIterationStopMessage *msg;
1414
1415   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1416               "Sending ZONE_ITERATION_STOP message\n");
1417   if (NULL != h->mq)
1418   {
1419     env = GNUNET_MQ_msg (msg,
1420                          GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1421     msg->gns_header.r_id = htonl (it->op_id);
1422     GNUNET_MQ_send (h->mq,
1423                     env);
1424   }
1425   free_ze (it);
1426 }
1427
1428
1429 /**
1430  * Cancel a namestore operation.  The final callback from the
1431  * operation must not have been done yet.
1432  *
1433  * @param qe operation to cancel
1434  */
1435 void
1436 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1437 {
1438   free_qe (qe);
1439 }
1440
1441
1442 /* end of namestore_api.c */