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