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