- Tests did not clean up: TEST_HOME with namestore db was not removed after test
[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     break;
463   case GNUNET_YES:
464     LOG (GNUNET_ERROR_TYPE_DEBUG,
465          "Namestore has result for zone to name mapping \n");
466     name_len = ntohs (msg->name_len);
467     rd_count = ntohs (msg->rd_count);
468     rd_ser_len = ntohs (msg->rd_len);
469     name_tmp = (const char *) &msg[1];
470     if ( (name_len > 0) &&
471          ('\0' != name_tmp[name_len -1]) )
472     {
473       GNUNET_break (0);
474       return GNUNET_SYSERR;
475     }
476     rd_tmp = &name_tmp[name_len];
477     {
478       struct GNUNET_GNSRECORD_Data rd[rd_count];
479
480       if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize(rd_ser_len, rd_tmp, rd_count, rd))
481       {
482         GNUNET_break (0);
483         return GNUNET_SYSERR;
484       }
485       /* normal end, call continuation with result */
486       if (NULL != qe->proc)
487         qe->proc (qe->proc_cls,
488                   &msg->zone,
489                   name_tmp,
490                   rd_count, rd);
491       /* return is important here: break would call continuation with error! */
492       return GNUNET_OK;
493     }
494   default:
495     GNUNET_break (0);
496     return GNUNET_SYSERR;
497   }
498   /* error case, call continuation with error */
499   if (NULL != qe->proc)
500     qe->proc (qe->proc_cls, NULL, NULL, 0, NULL);
501   return GNUNET_NO;
502 }
503
504
505 /**
506  * Handle incoming messages for record operations
507  *
508  * @param qe the respective zone iteration handle
509  * @param msg the message we received
510  * @param type the message type in host byte order
511  * @param size the message size
512  * @return #GNUNET_OK on success, #GNUNET_NO if we notified the client about
513  *         the error, #GNUNET_SYSERR on error and we did NOT notify the client
514  */
515 static int
516 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
517                           const struct GNUNET_MessageHeader *msg,
518                           uint16_t type,
519                           size_t size)
520 {
521   /* handle different message type */
522   switch (type)
523   {
524   case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE:
525     if (size != sizeof (struct RecordStoreResponseMessage))
526     {
527       GNUNET_break (0);
528       return GNUNET_SYSERR;
529     }
530     return handle_record_store_response (qe, (const struct RecordStoreResponseMessage *) msg, size);
531   case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE:
532     if (size < sizeof (struct ZoneToNameResponseMessage))
533     {
534       GNUNET_break (0);
535       return GNUNET_SYSERR;
536     }
537     return handle_zone_to_name_response (qe, (const struct ZoneToNameResponseMessage *) msg, size);
538   case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT:
539     if (size < sizeof (struct RecordResultMessage))
540     {
541       GNUNET_break (0);
542       return GNUNET_SYSERR;
543     }
544     return handle_record_result (qe, (const struct RecordResultMessage *) msg, size);
545   case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE:
546     if (size < sizeof (struct LabelLookupResponseMessage))
547     {
548       GNUNET_break (0);
549       return GNUNET_SYSERR;
550     }
551     return handle_lookup_result (qe, (const struct LabelLookupResponseMessage *) msg, size);
552   default:
553     GNUNET_break (0);
554     return GNUNET_SYSERR;
555   }
556 }
557
558
559 /**
560  * Handle a response from NAMESTORE service for a zone iteration request
561  *
562  * @param ze the respective iterator for this operation
563  * @param msg the message containing the respoonse
564  * @param size the message size
565  * @return #GNUNET_YES on success, @a ze should be kept, #GNUNET_NO on success if @a ze should
566  *         not be kept any longer, #GNUNET_SYSERR on error (disconnect) and @a ze should be kept
567  */
568 static int
569 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
570                                 const struct RecordResultMessage *msg,
571                                 size_t size)
572 {
573   static struct GNUNET_CRYPTO_EcdsaPrivateKey priv_dummy;
574   size_t msg_len;
575   size_t exp_msg_len;
576   size_t name_len;
577   size_t rd_len;
578   unsigned rd_count;
579   const char *name_tmp;
580   const char *rd_ser_tmp;
581
582   LOG (GNUNET_ERROR_TYPE_DEBUG,
583        "Received `%s'\n",
584        "ZONE_ITERATION_RESPONSE");
585   msg_len = ntohs (msg->gns_header.header.size);
586   rd_len = ntohs (msg->rd_len);
587   rd_count = ntohs (msg->rd_count);
588   name_len = ntohs (msg->name_len);
589   exp_msg_len = sizeof (struct RecordResultMessage) + name_len + rd_len;
590   if (msg_len != exp_msg_len)
591   {
592     GNUNET_break (0);
593     return GNUNET_SYSERR;
594   }
595   if ( (0 == name_len) &&
596        (0 == (memcmp (&msg->private_key,
597                       &priv_dummy,
598                       sizeof (priv_dummy)))) )
599   {
600     LOG (GNUNET_ERROR_TYPE_DEBUG,
601          "Zone iteration completed!\n");
602     if (NULL != ze->proc)
603       ze->proc (ze->proc_cls, NULL, NULL, 0, NULL);
604     return GNUNET_NO;
605   }
606   name_tmp = (const char *) &msg[1];
607   if ((name_tmp[name_len -1] != '\0') || (name_len > MAX_NAME_LEN))
608   {
609     GNUNET_break (0);
610     return GNUNET_SYSERR;
611   }
612   rd_ser_tmp = (const char *) &name_tmp[name_len];
613   {
614     struct GNUNET_GNSRECORD_Data rd[rd_count];
615
616     if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (rd_len,
617                                                            rd_ser_tmp,
618                                                            rd_count,
619                                                            rd))
620     {
621       GNUNET_break (0);
622       return GNUNET_SYSERR;
623     }
624     if (NULL != ze->proc)
625       ze->proc (ze->proc_cls,
626                 &msg->private_key,
627                 name_tmp,
628                 rd_count, rd);
629     return GNUNET_YES;
630   }
631 }
632
633
634 /**
635  * Handle incoming messages for zone iterations
636  *
637  * @param ze the respective zone iteration handle
638  * @param msg the message we received
639  * @param type the message type in HBO
640  * @param size the message size
641  * @return #GNUNET_YES on success, @a ze should be kept, #GNUNET_NO on success if @a ze should
642  *         not be kept any longer, #GNUNET_SYSERR on error (disconnect) and @a ze should be kept
643  */
644 static int
645 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
646                         const struct GNUNET_MessageHeader *msg,
647                         int type, size_t size)
648 {
649   /* handle different message type */
650   switch (type)
651   {
652   case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT:
653     if (size < sizeof (struct RecordResultMessage))
654     {
655       GNUNET_break (0);
656       return GNUNET_SYSERR;
657     }
658     return handle_zone_iteration_response (ze,
659                                            (const struct RecordResultMessage *) msg,
660                                            size);
661   default:
662     GNUNET_break (0);
663     return GNUNET_SYSERR;
664   }
665 }
666
667
668 /**
669  * Type of a function to call when we receive a message
670  * from the service.
671  *
672  * @param cls the `struct GNUNET_NAMESTORE_SchedulingHandle`
673  * @param msg message received, NULL on timeout or fatal error
674  */
675 static void
676 process_namestore_message (void *cls,
677                            const struct GNUNET_MessageHeader *msg)
678 {
679   struct GNUNET_NAMESTORE_Handle *h = cls;
680   const struct GNUNET_NAMESTORE_Header *gm;
681   struct GNUNET_NAMESTORE_QueueEntry *qe;
682   struct GNUNET_NAMESTORE_ZoneIterator *ze;
683   uint16_t size;
684   uint16_t type;
685   uint32_t r_id;
686   int ret;
687
688   if (NULL == msg)
689   {
690     force_reconnect (h);
691     return;
692   }
693   size = ntohs (msg->size);
694   type = ntohs (msg->type);
695   if (size < sizeof (struct GNUNET_NAMESTORE_Header))
696   {
697     GNUNET_break_op (0);
698     GNUNET_CLIENT_receive (h->client,
699                            &process_namestore_message, h,
700                            GNUNET_TIME_UNIT_FOREVER_REL);
701     return;
702   }
703   gm = (const struct GNUNET_NAMESTORE_Header *) msg;
704   r_id = ntohl (gm->r_id);
705
706   LOG (GNUNET_ERROR_TYPE_DEBUG,
707        "Received message type %u size %u op %u\n",
708        (unsigned int) type,
709        (unsigned int) size,
710        (unsigned int) r_id);
711
712   /* Is it a record related operation ? */
713   for (qe = h->op_head; qe != NULL; qe = qe->next)
714     if (qe->op_id == r_id)
715       break;
716   if (NULL != qe)
717   {
718     ret = manage_record_operations (qe, msg, type, size);
719     if (GNUNET_SYSERR == ret)
720     {
721       /* protocol error, need to reconnect */
722       h->reconnect = GNUNET_YES;
723     }
724     else
725     {
726       /* client was notified about success or failure, clean up 'qe' */
727       GNUNET_CONTAINER_DLL_remove (h->op_head,
728                                    h->op_tail,
729                                    qe);
730       GNUNET_free (qe);
731     }
732   }
733   /* Is it a zone iteration operation? */
734   for (ze = h->z_head; ze != NULL; ze = ze->next)
735     if (ze->op_id == r_id)
736       break;
737   if (NULL != ze)
738   {
739     ret = manage_zone_operations (ze, msg, type, size);
740     if (GNUNET_NO == ret)
741     {
742       /* end of iteration, clean up 'ze' */
743       GNUNET_CONTAINER_DLL_remove (h->z_head,
744                                    h->z_tail,
745                                    ze);
746       GNUNET_free (ze);
747     }
748     if (GNUNET_SYSERR == ret)
749     {
750       /* protocol error, need to reconnect */
751       h->reconnect = GNUNET_YES;
752     }
753   }
754   if (GNUNET_YES == h->reconnect)
755   {
756     force_reconnect (h);
757     return;
758   }
759   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
760                          GNUNET_TIME_UNIT_FOREVER_REL);
761 }
762
763
764 /**
765  * Transmit messages from the message queue to the service
766  * (if there are any, and if we are not already trying).
767  *
768  * @param h handle to use
769  */
770 static void
771 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
772
773
774 /**
775  * We can now transmit a message to NAMESTORE. Do it.
776  *
777  * @param cls the `struct GNUNET_NAMESTORE_Handle`
778  * @param size number of bytes we can transmit
779  * @param buf where to copy the messages
780  * @return number of bytes copied into @a buf
781  */
782 static size_t
783 transmit_message_to_namestore (void *cls,
784                                size_t size,
785                                void *buf)
786 {
787   struct GNUNET_NAMESTORE_Handle *h = cls;
788   struct PendingMessage *p;
789   size_t ret;
790   char *cbuf;
791
792   h->th = NULL;
793   if ((0 == size) || (NULL == buf))
794   {
795     force_reconnect (h);
796     return 0;
797   }
798   ret = 0;
799   cbuf = buf;
800   while ( (NULL != (p = h->pending_head)) &&
801           (p->size <= size) )
802   {
803     memcpy (&cbuf[ret], &p[1], p->size);
804     ret += p->size;
805     size -= p->size;
806     GNUNET_CONTAINER_DLL_remove (h->pending_head,
807                                  h->pending_tail,
808                                  p);
809     if (GNUNET_NO == h->is_receiving)
810     {
811       h->is_receiving = GNUNET_YES;
812       GNUNET_CLIENT_receive (h->client,
813                              &process_namestore_message, h,
814                              GNUNET_TIME_UNIT_FOREVER_REL);
815     }
816     GNUNET_free (p);
817   }
818   do_transmit (h);
819   return ret;
820 }
821
822
823 /**
824  * Transmit messages from the message queue to the service
825  * (if there are any, and if we are not already trying).
826  *
827  * @param h handle to use
828  */
829 static void
830 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
831 {
832   struct PendingMessage *p;
833
834   if (NULL != h->th)
835     return; /* transmission request already pending */
836   if (NULL == (p = h->pending_head))
837     return; /* transmission queue empty */
838   if (NULL == h->client)
839     return;                     /* currently reconnecting */
840   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
841                                                GNUNET_TIME_UNIT_FOREVER_REL,
842                                                GNUNET_NO, &transmit_message_to_namestore,
843                                                h);
844   GNUNET_break (NULL != h->th);
845 }
846
847
848 /**
849  * Reconnect to namestore service.
850  *
851  * @param h the handle to the NAMESTORE service
852  */
853 static void
854 reconnect (struct GNUNET_NAMESTORE_Handle *h)
855 {
856   GNUNET_assert (NULL == h->client);
857   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
858   GNUNET_assert (NULL != h->client);
859   do_transmit (h);
860 }
861
862
863 /**
864  * Re-establish the connection to the service.
865  *
866  * @param cls handle to use to re-connect.
867  * @param tc scheduler context
868  */
869 static void
870 reconnect_task (void *cls,
871                 const struct GNUNET_SCHEDULER_TaskContext *tc)
872 {
873   struct GNUNET_NAMESTORE_Handle *h = cls;
874
875   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
876   reconnect (h);
877 }
878
879
880 /**
881  * Disconnect from service and then reconnect.
882  *
883  * @param h our handle
884  */
885 static void
886 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
887 {
888   if (NULL != h->th)
889   {
890     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
891     h->th = NULL;
892   }
893   h->reconnect = GNUNET_NO;
894   GNUNET_CLIENT_disconnect (h->client);
895   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
896               "Reconnecting to namestore\n");
897   h->is_receiving = GNUNET_NO;
898   h->client = NULL;
899   h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
900   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
901                                                     &reconnect_task,
902                                                     h);
903 }
904
905
906 /**
907  * Get a fresh operation id to distinguish between namestore requests
908  *
909  * @param h the namestore handle
910  * @return next operation id to use
911  */
912 static uint32_t
913 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
914 {
915   return h->last_op_id_used++;
916 }
917
918
919 /**
920  * Initialize the connection with the NAMESTORE service.
921  *
922  * @param cfg configuration to use
923  * @return handle to the GNS service, or NULL on error
924  */
925 struct GNUNET_NAMESTORE_Handle *
926 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
927 {
928   struct GNUNET_NAMESTORE_Handle *h;
929
930   h = GNUNET_new (struct GNUNET_NAMESTORE_Handle);
931   h->cfg = cfg;
932   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
933   h->last_op_id_used = 0;
934   return h;
935 }
936
937
938 /**
939  * Disconnect from the namestore service (and free associated
940  * resources).
941  *
942  * @param h handle to the namestore
943  */
944 void
945 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
946 {
947   struct PendingMessage *p;
948   struct GNUNET_NAMESTORE_QueueEntry *q;
949   struct GNUNET_NAMESTORE_ZoneIterator *z;
950
951   LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
952   GNUNET_assert (NULL != h);
953   if (NULL != h->th)
954   {
955     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
956     h->th = NULL;
957   }
958   while (NULL != (p = h->pending_head))
959   {
960     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
961     GNUNET_free (p);
962   }
963   GNUNET_break (NULL == h->op_head);
964   while (NULL != (q = h->op_head))
965   {
966     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
967     GNUNET_free (q);
968   }
969   GNUNET_break (NULL == h->z_head);
970   while (NULL != (z = h->z_head))
971   {
972     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
973     GNUNET_free (z);
974   }
975   if (NULL != h->client)
976   {
977     GNUNET_CLIENT_disconnect (h->client);
978     h->client = NULL;
979   }
980   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
981   {
982     GNUNET_SCHEDULER_cancel (h->reconnect_task);
983     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
984   }
985   GNUNET_free (h);
986 }
987
988
989 /**
990  * Store an item in the namestore.  If the item is already present,
991  * it is replaced with the new record.  Use an empty array to
992  * remove all records under the given name.
993  *
994  * @param h handle to the namestore
995  * @param pkey private key of the zone
996  * @param label name that is being mapped (at most 255 characters long)
997  * @param rd_count number of records in the 'rd' array
998  * @param rd array of records with data to store
999  * @param cont continuation to call when done
1000  * @param cont_cls closure for 'cont'
1001  * @return handle to abort the request
1002  */
1003 struct GNUNET_NAMESTORE_QueueEntry *
1004 GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h,
1005                                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1006                                 const char *label,
1007                                 unsigned int rd_count,
1008                                 const struct GNUNET_GNSRECORD_Data *rd,
1009                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1010                                 void *cont_cls)
1011 {
1012   struct GNUNET_NAMESTORE_QueueEntry *qe;
1013   struct PendingMessage *pe;
1014   char *name_tmp;
1015   char *rd_ser;
1016   size_t rd_ser_len;
1017   size_t msg_size;
1018   size_t name_len;
1019   uint32_t rid;
1020   struct RecordStoreMessage *msg;
1021
1022   GNUNET_assert (NULL != h);
1023   GNUNET_assert (NULL != pkey);
1024   GNUNET_assert (NULL != label);
1025   name_len = strlen (label) + 1;
1026   if (name_len > MAX_NAME_LEN)
1027   {
1028     GNUNET_break (0);
1029     return NULL;
1030   }
1031   rid = get_op_id (h);
1032   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1033   qe->nsh = h;
1034   qe->cont = cont;
1035   qe->cont_cls = cont_cls;
1036   qe->op_id = rid;
1037   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1038
1039   /* setup msg */
1040   rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1041   msg_size = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len;
1042   pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
1043   pe->size = msg_size;
1044   msg = (struct RecordStoreMessage *) &pe[1];
1045   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1046   msg->gns_header.header.size = htons (msg_size);
1047   msg->gns_header.r_id = htonl (rid);
1048   msg->name_len = htons (name_len);
1049   msg->rd_count = htons (rd_count);
1050   msg->rd_len = htons (rd_ser_len);
1051   msg->reserved = htons (0);
1052   msg->private_key = *pkey;
1053
1054   name_tmp = (char *) &msg[1];
1055   memcpy (name_tmp, label, name_len);
1056   rd_ser = &name_tmp[name_len];
1057   GNUNET_break (rd_ser_len ==
1058                 GNUNET_GNSRECORD_records_serialize (rd_count, rd,
1059                                                     rd_ser_len,
1060                                                     rd_ser));
1061   LOG (GNUNET_ERROR_TYPE_DEBUG,
1062        "Sending `%s' message for name `%s' with size %u and %u records\n",
1063        "NAMESTORE_RECORD_STORE", label, msg_size,
1064        rd_count);
1065   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1066   do_transmit (h);
1067   return qe;
1068 }
1069
1070 /**
1071  * Set the desired nick name for a zone
1072  *
1073  * @param h handle to the namestore
1074  * @param pkey private key of the zone
1075  * @param nick the nick name to set
1076  * @param cont continuation to call when done
1077  * @param cont_cls closure for 'cont'
1078  * @return handle to abort the request
1079  */
1080 struct GNUNET_NAMESTORE_QueueEntry *
1081 GNUNET_NAMESTORE_set_nick (struct GNUNET_NAMESTORE_Handle *h,
1082                            const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1083                            const char *nick,
1084                            GNUNET_NAMESTORE_ContinuationWithStatus cont,
1085                            void *cont_cls)
1086 {
1087   struct GNUNET_GNSRECORD_Data rd;
1088
1089   memset (&rd, 0, sizeof (rd));
1090   rd.data = nick;
1091   rd.data_size = strlen (nick) +1;
1092   rd.record_type = GNUNET_GNSRECORD_TYPE_NICK;
1093   rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
1094   rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1095   return GNUNET_NAMESTORE_records_store(h, pkey, GNUNET_GNS_MASTERZONE_STR, 1, &rd, cont, cont_cls);
1096 }
1097
1098
1099 /**
1100  * Lookup an item in the namestore.
1101  *
1102  * @param h handle to the namestore
1103  * @param pkey private key of the zone
1104  * @param label name that is being mapped (at most 255 characters long)
1105  * @param rm function to call with the result (with 0 records if we don't have that label)
1106  * @param rm_cls closure for @a rm
1107  * @return handle to abort the request
1108  */
1109 struct GNUNET_NAMESTORE_QueueEntry *
1110 GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h,
1111                                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1112                                  const char *label,
1113                                  GNUNET_NAMESTORE_RecordMonitor rm,
1114                                  void *rm_cls)
1115 {
1116   struct GNUNET_NAMESTORE_QueueEntry *qe;
1117   struct PendingMessage *pe;
1118   struct LabelLookupMessage * msg;
1119   size_t msg_size;
1120   size_t label_len;
1121
1122   GNUNET_assert (NULL != h);
1123   GNUNET_assert (NULL != pkey);
1124   GNUNET_assert (NULL != label);
1125
1126   if (1 == (label_len = strlen (label) + 1))
1127     return NULL;
1128
1129   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1130   qe->nsh = h;
1131   qe->proc = rm;
1132   qe->proc_cls = rm_cls;
1133   qe->op_id = get_op_id(h);
1134   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1135
1136   msg_size = sizeof (struct LabelLookupMessage) + label_len;
1137   pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
1138   pe->size = msg_size;
1139   msg = (struct LabelLookupMessage *) &pe[1];
1140   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1141   msg->gns_header.header.size = htons (msg_size);
1142   msg->gns_header.r_id = htonl (qe->op_id);
1143   msg->zone = *pkey;
1144   msg->label_len = htonl(label_len);
1145   memcpy (&msg[1], label, label_len);
1146
1147   /* transmit message */
1148   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1149   do_transmit (h);
1150   return qe;
1151 }
1152
1153
1154 /**
1155  * Look for an existing PKEY delegation record for a given public key.
1156  * Returns at most one result to the processor.
1157  *
1158  * @param h handle to the namestore
1159  * @param zone public key of the zone to look up in, never NULL
1160  * @param value_zone public key of the target zone (value), never NULL
1161  * @param proc function to call on the matching records, or with
1162  *        NULL (rd_count == 0) if there are no matching records
1163  * @param proc_cls closure for @a proc
1164  * @return a handle that can be used to
1165  *         cancel
1166  */
1167 struct GNUNET_NAMESTORE_QueueEntry *
1168 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1169                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1170                                const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
1171                                GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls)
1172 {
1173   struct GNUNET_NAMESTORE_QueueEntry *qe;
1174   struct PendingMessage *pe;
1175   struct ZoneToNameMessage * msg;
1176   size_t msg_size;
1177   uint32_t rid;
1178
1179   GNUNET_assert (NULL != h);
1180   GNUNET_assert (NULL != zone);
1181   GNUNET_assert (NULL != value_zone);
1182   rid = get_op_id(h);
1183   qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1184   qe->nsh = h;
1185   qe->proc = proc;
1186   qe->proc_cls = proc_cls;
1187   qe->op_id = rid;
1188   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1189
1190   msg_size = sizeof (struct ZoneToNameMessage);
1191   pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
1192   pe->size = msg_size;
1193   msg = (struct ZoneToNameMessage *) &pe[1];
1194   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1195   msg->gns_header.header.size = htons (msg_size);
1196   msg->gns_header.r_id = htonl (rid);
1197   msg->zone = *zone;
1198   msg->value_zone = *value_zone;
1199
1200   /* transmit message */
1201   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1202   do_transmit (h);
1203   return qe;
1204 }
1205
1206
1207 /**
1208  * Starts a new zone iteration (used to periodically PUT all of our
1209  * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1210  * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1211  * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1212  * immediately, and then again after
1213  * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1214  *
1215  * @param h handle to the namestore
1216  * @param zone zone to access, NULL for all zones
1217  * @param proc function to call on each name from the zone; it
1218  *        will be called repeatedly with a value (if available)
1219  *        and always once at the end with a name of NULL.
1220  * @param proc_cls closure for @a proc
1221  * @return an iterator handle to use for iteration
1222  */
1223 struct GNUNET_NAMESTORE_ZoneIterator *
1224 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1225                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1226                                        GNUNET_NAMESTORE_RecordMonitor proc,
1227                                        void *proc_cls)
1228 {
1229   struct GNUNET_NAMESTORE_ZoneIterator *it;
1230   struct PendingMessage *pe;
1231   struct ZoneIterationStartMessage * msg;
1232   size_t msg_size;
1233   uint32_t rid;
1234
1235   GNUNET_assert (NULL != h);
1236   rid = get_op_id(h);
1237   it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1238   it->h = h;
1239   it->proc = proc;
1240   it->proc_cls = proc_cls;
1241   it->op_id = rid;
1242   if (NULL != zone)
1243     it->zone = *zone;
1244   GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it);
1245
1246   msg_size = sizeof (struct ZoneIterationStartMessage);
1247   pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
1248   pe->size = msg_size;
1249   msg = (struct ZoneIterationStartMessage *) &pe[1];
1250   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1251   msg->gns_header.header.size = htons (msg_size);
1252   msg->gns_header.r_id = htonl (rid);
1253   if (NULL != zone)
1254     msg->zone = *zone;
1255   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1256   do_transmit (h);
1257   return it;
1258 }
1259
1260
1261 /**
1262  * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1263  * for the next record.
1264  *
1265  * @param it the iterator
1266  */
1267 void
1268 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1269 {
1270   struct GNUNET_NAMESTORE_Handle *h;
1271   struct ZoneIterationNextMessage * msg;
1272   struct PendingMessage *pe;
1273   size_t msg_size;
1274
1275   GNUNET_assert (NULL != it);
1276   h = it->h;
1277   msg_size = sizeof (struct ZoneIterationNextMessage);
1278   pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
1279   pe->size = msg_size;
1280   msg = (struct ZoneIterationNextMessage *) &pe[1];
1281   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1282   msg->gns_header.header.size = htons (msg_size);
1283   msg->gns_header.r_id = htonl (it->op_id);
1284   LOG (GNUNET_ERROR_TYPE_DEBUG,
1285        "Sending `%s' message\n",
1286        "ZONE_ITERATION_NEXT");
1287   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1288   do_transmit (h);
1289 }
1290
1291
1292 /**
1293  * Stops iteration and releases the namestore handle for further calls.
1294  *
1295  * @param it the iterator
1296  */
1297 void
1298 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1299 {
1300   struct GNUNET_NAMESTORE_Handle *h;
1301   struct PendingMessage *pe;
1302   size_t msg_size;
1303   struct ZoneIterationStopMessage * msg;
1304
1305   GNUNET_assert (NULL != it);
1306   h = it->h;
1307   GNUNET_CONTAINER_DLL_remove (h->z_head,
1308                                h->z_tail,
1309                                it);
1310   msg_size = sizeof (struct ZoneIterationStopMessage);
1311   pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
1312   pe->size = msg_size;
1313   msg = (struct ZoneIterationStopMessage *) &pe[1];
1314   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1315   msg->gns_header.header.size = htons (msg_size);
1316   msg->gns_header.r_id = htonl (it->op_id);
1317   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1318               "Sending `%s' message\n",
1319               "ZONE_ITERATION_STOP");
1320   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1321   do_transmit (h);
1322   GNUNET_free (it);
1323 }
1324
1325
1326 /**
1327  * Cancel a namestore operation.  The final callback from the
1328  * operation must not have been done yet.
1329  *
1330  * @param qe operation to cancel
1331  */
1332 void
1333 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1334 {
1335   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1336
1337   GNUNET_assert (NULL != qe);
1338   GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe);
1339   GNUNET_free(qe);
1340 }
1341
1342
1343 /* end of namestore_api.c */