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