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