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