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