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