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