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