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