- changes
[oweals/gnunet.git] / src / namestore / namestore_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 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  */
27
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_crypto_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_dnsparser_lib.h"
33 #include "gnunet_arm_service.h"
34 #include "gnunet_signatures.h"
35 #include "gnunet_namestore_service.h"
36 #include "namestore.h"
37
38 #define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
39
40 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
41
42 /**
43  * A QueueEntry.
44  */
45 struct GNUNET_NAMESTORE_QueueEntry
46 {
47
48   /**
49    * Kept in a DLL.
50    */
51   struct GNUNET_NAMESTORE_QueueEntry *next;
52
53   /**
54    * Kept in a DLL.
55    */
56   struct GNUNET_NAMESTORE_QueueEntry *prev;
57
58   struct GNUNET_NAMESTORE_Handle *nsh;
59
60   uint32_t op_id;
61
62   GNUNET_NAMESTORE_ContinuationWithStatus cont;
63   void *cont_cls;
64
65   GNUNET_NAMESTORE_RecordProcessor proc;
66   void *proc_cls;
67
68   char *data; /*stub data pointer*/
69 };
70
71
72 /**
73  * Zone iterator
74  */
75 struct GNUNET_NAMESTORE_ZoneIterator
76 {
77
78   /**
79    * Kept in a DLL.
80    */
81   struct GNUNET_NAMESTORE_ZoneIterator *next;
82
83   /**
84    * Kept in a DLL.
85    */
86   struct GNUNET_NAMESTORE_ZoneIterator *prev;
87
88   uint32_t op_id;
89
90   struct GNUNET_NAMESTORE_Handle *h;
91   GNUNET_NAMESTORE_RecordProcessor proc;
92   void* proc_cls;
93   GNUNET_HashCode zone;
94   uint32_t no_flags;
95   uint32_t flags;
96 };
97
98
99 /**
100  * Message in linked list we should send to the service.  The
101  * actual binary message follows this struct.
102  */
103 struct PendingMessage
104 {
105
106   /**
107    * Kept in a DLL.
108    */
109   struct PendingMessage *next;
110
111   /**
112    * Kept in a DLL.
113    */
114   struct PendingMessage *prev;
115
116   /**
117    * Size of the message.
118    */
119   size_t size;
120
121   /**
122    * Is this the 'START' message?
123    */
124   int is_init;
125 };
126
127
128 /**
129  * Connection to the NAMESTORE service.
130  */
131 struct GNUNET_NAMESTORE_Handle
132 {
133
134   /**
135    * Configuration to use.
136    */
137   const struct GNUNET_CONFIGURATION_Handle *cfg;
138
139   /**
140    * Socket (if available).
141    */
142   struct GNUNET_CLIENT_Connection *client;
143
144   /**
145    * Currently pending transmission request (or NULL).
146    */
147   struct GNUNET_CLIENT_TransmitHandle *th;
148
149   /**
150    * Reconnect task
151    */
152   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
153
154   /**
155    * Pending messages to send to the service
156    */
157
158   struct PendingMessage * pending_head;
159   struct PendingMessage * pending_tail;
160
161   /**
162    * Should we reconnect to service due to some serious error?
163    */
164   int reconnect;
165
166
167   /**
168    * Pending namestore queue entries
169    */
170   struct GNUNET_NAMESTORE_QueueEntry * op_head;
171   struct GNUNET_NAMESTORE_QueueEntry * op_tail;
172
173   uint32_t op_id;
174
175   /**
176    * Pending namestore zone iterator entries
177    */
178   struct GNUNET_NAMESTORE_ZoneIterator * z_head;
179   struct GNUNET_NAMESTORE_ZoneIterator * z_tail;
180 };
181
182 struct GNUNET_NAMESTORE_SimpleRecord
183 {
184   /**
185    * DLL
186    */
187   struct GNUNET_NAMESTORE_SimpleRecord *next;
188
189   /**
190    * DLL
191    */
192   struct GNUNET_NAMESTORE_SimpleRecord *prev;
193   
194   const char *name;
195   const GNUNET_HashCode *zone;
196   uint32_t record_type;
197   struct GNUNET_TIME_Absolute expiration;
198   enum GNUNET_NAMESTORE_RecordFlags flags;
199   size_t data_size;
200   const void *data;
201 };
202
203
204
205 /**
206  * Convert a type name (i.e. "AAAA") to the corresponding number.
207  *
208  * @param typename name to convert
209  * @return corresponding number, UINT32_MAX on error
210  */
211 uint32_t
212 GNUNET_NAMESTORE_typename_to_number (const char *typename)
213 {
214   static struct { 
215     const char *name; 
216     uint32_t number; 
217   } map[] = {
218     { "A", GNUNET_DNSPARSER_TYPE_A },
219     { "NS", GNUNET_DNSPARSER_TYPE_NS },
220     { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
221     { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
222     { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
223     { "MX", GNUNET_DNSPARSER_TYPE_MX },
224     { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
225     { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
226     { "PKEY",  GNUNET_NAMESTORE_TYPE_PKEY },
227     { "PSEU",  GNUNET_NAMESTORE_TYPE_PSEU },
228     { NULL, UINT32_MAX }
229   };
230   unsigned int i;
231
232   i=0;
233   while ( (map[i].name != NULL) &&
234           (0 != strcasecmp (typename, map[i].name)) )
235     i++;
236   return map[i].number;  
237 }
238
239
240 /**
241  * Disconnect from service and then reconnect.
242  *
243  * @param h our handle
244  */
245 static void
246 force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
247
248 static void
249 handle_lookup_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
250                              struct LookupNameResponseMessage * msg,
251                              size_t size)
252 {
253   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
254               "LOOKUP_NAME_RESPONSE");
255
256   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
257   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
258   char *name;
259   char * rd_tmp;
260
261   struct GNUNET_CRYPTO_RsaSignature *signature = NULL;
262   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy;
263   struct GNUNET_TIME_Absolute expire;
264   size_t exp_msg_len;
265   size_t msg_len = 0;
266   size_t name_len = 0;
267   size_t rd_len = 0;
268   int contains_sig = GNUNET_NO;
269   int rd_count = 0;
270
271   rd_len = ntohs (msg->rd_len);
272   rd_count = ntohs (msg->rd_count);
273   msg_len = ntohs (msg->gns_header.header.size);
274   name_len = ntohs (msg->name_len);
275   contains_sig = ntohs (msg->contains_sig);
276   expire = GNUNET_TIME_absolute_ntoh(msg->expire);
277
278   exp_msg_len = sizeof (struct LookupNameResponseMessage) +
279       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
280       name_len +
281       rd_len +
282       contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
283
284   if (msg_len != exp_msg_len)
285   {
286     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message size describes with `%u' bytes but calculated size is %u bytes \n",
287                 msg_len, exp_msg_len);
288     GNUNET_break_op (0);
289     return;
290   }
291
292   zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
293   name = (char *) &zone_key[1];
294   rd_tmp = &name[name_len];
295
296   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
297   GNUNET_NAMESTORE_records_deserialize(rd_len, rd_tmp, rd_count, rd);
298
299   /* reset values if values not contained */
300   if (contains_sig == GNUNET_NO)
301     signature = NULL;
302   else
303     signature = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[rd_len];
304   if (name_len == 0)
305     name = NULL;
306
307   memset (&dummy, '0', sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
308   if (0 == memcmp (zone_key, &dummy, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
309       zone_key = NULL;
310
311   if (qe->proc != NULL)
312   {
313     qe->proc (qe->proc_cls, zone_key, expire, name, rd_count, (rd_count > 0) ? rd : NULL, signature);
314   }
315
316   /* Operation done, remove */
317   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
318   GNUNET_free (qe);
319 }
320
321
322 static void
323 handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
324                              struct RecordPutResponseMessage* msg,
325                              size_t size)
326 {
327   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
328               "RECORD_PUT_RESPONSE");
329
330   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
331   int res = GNUNET_OK;
332
333   if (ntohs (msg->op_result) == GNUNET_OK)
334   {
335     res = GNUNET_OK;
336     if (qe->cont != NULL)
337     {
338       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
339     }
340
341   }
342   else if (ntohs (msg->op_result) == GNUNET_NO)
343   {
344     res = GNUNET_SYSERR;
345     if (qe->cont != NULL)
346     {
347       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
348     }
349   }
350   else
351   {
352     GNUNET_break_op (0);
353     return;
354   }
355
356   /* Operation done, remove */
357   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
358
359   GNUNET_free (qe);
360 }
361
362
363 static void
364 handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
365                              struct RecordCreateResponseMessage* msg,
366                              size_t size)
367 {
368   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
369               "RECORD_CREATE_RESPONSE");
370
371   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
372
373   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' %i\n",
374               "RECORD_CREATE_RESPONSE", ntohs (msg->op_result));
375   if (ntohs (msg->op_result) == GNUNET_YES)
376   {
377     if (qe->cont != NULL)
378     {
379       qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore added record successfully"));
380     }
381
382   }
383   else if (ntohs (msg->op_result) == GNUNET_NO)
384   {
385     if (qe->cont != NULL)
386     {
387       qe->cont (qe->cont_cls, GNUNET_NO, _("Namestore record already existed"));
388     }
389   }
390   else
391   {
392     if (qe->cont != NULL)
393     {
394       qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Namestore failed to add record\n"));
395     }
396   }
397
398   /* Operation done, remove */
399   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
400
401   GNUNET_free (qe);
402 }
403
404
405 static void
406 handle_record_remove_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
407                              struct RecordRemoveResponseMessage* msg,
408                              size_t size)
409 {
410   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
411               "RECORD_REMOVE_RESPONSE");
412
413   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
414   int res = ntohs (msg->op_result);
415
416   /**
417    *  result:
418    *  0 : successful
419    *  1 : No records for entry
420    *  2 : Could not find record to remove
421    *  3 : Failed to create new signature
422    *  4 : Failed to put new set of records in database
423    */
424   switch (res) {
425     case 0:
426       if (qe->cont != NULL)
427       {
428         qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore removed record successfully"));
429       }
430
431       break;
432     case 1:
433       if (qe->cont != NULL)
434       {
435         qe->cont (qe->cont_cls, GNUNET_NO, _("No records for entry"));
436       }
437
438       break;
439     case 2:
440       if (qe->cont != NULL)
441       {
442         qe->cont (qe->cont_cls, GNUNET_NO, _("Could not find record to remove"));
443       }
444
445       break;
446     case 3:
447       if (qe->cont != NULL)
448       {
449         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to create new signature"));
450       }
451
452       break;
453     case 4:
454       if (qe->cont != NULL)
455       {
456         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to put new set of records in database"));
457       }
458       break;
459     default:
460         GNUNET_break_op (0);
461       break;
462   }
463
464   /* Operation done, remove */
465   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
466
467   GNUNET_free (qe);
468 }
469
470 static void
471 handle_zone_to_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
472                              struct ZoneToNameResponseMessage* msg,
473                              size_t size)
474 {
475   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
476               "ZONE_TO_NAME_RESPONSE");
477
478   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
479   int res = ntohs (msg->res);
480
481   switch (res) {
482     case GNUNET_SYSERR:
483       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "An error occured during zone to name operation\n");
484       if (qe->proc != NULL)
485         qe->proc (qe->proc_cls, NULL, GNUNET_TIME_absolute_get_zero(), NULL, 0, NULL, NULL);
486       break;
487     case GNUNET_NO:
488       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore has no result for zone to name mapping \n");
489       if (qe->proc != NULL)
490         qe->proc (qe->proc_cls, NULL, GNUNET_TIME_absolute_get_zero(), NULL, 0, NULL, NULL);
491       break;
492     default:
493       break;
494   }
495
496   /* Operation done, remove */
497   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
498   GNUNET_free (qe);
499 }
500
501
502 static void
503 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
504                           const struct GNUNET_MessageHeader *msg,
505                           int type, size_t size)
506 {
507
508   /* handle different message type */
509   switch (type) {
510     case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
511         if (size < sizeof (struct LookupNameResponseMessage))
512         {
513           GNUNET_break_op (0);
514           break;
515         }
516         handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size);
517       break;
518     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
519         if (size != sizeof (struct RecordPutResponseMessage))
520         {
521           GNUNET_break_op (0);
522           break;
523         }
524         handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size);
525       break;
526     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE:
527         if (size != sizeof (struct RecordCreateResponseMessage))
528         {
529           GNUNET_break_op (0);
530           break;
531         }
532         handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size);
533       break;
534     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE:
535         if (size != sizeof (struct RecordRemoveResponseMessage))
536         {
537           GNUNET_break_op (0);
538           break;
539         }
540         handle_record_remove_response (qe, (struct RecordRemoveResponseMessage *) msg, size);
541       break;
542     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE:
543         if (size < sizeof (struct ZoneToNameResponseMessage))
544         {
545           GNUNET_break_op (0);
546           break;
547         }
548         handle_zone_to_name_response (qe, (struct ZoneToNameResponseMessage *) msg, size);
549       break;
550     default:
551       GNUNET_break_op (0);
552       break;
553   }
554 }
555
556 static void
557 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
558                                 struct ZoneIterationResponseMessage *msg,
559                                 size_t size)
560 {
561   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
562               "ZONE_ITERATION_RESPONSE");
563
564
565   if (ze->proc != NULL)
566   {
567     // FIXME
568     ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL);
569   }
570 }
571
572
573 static void
574 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
575                         const struct GNUNET_MessageHeader *msg,
576                         int type, size_t size)
577 {
578
579   /* handle different message type */
580   switch (type) {
581     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
582         if (size < sizeof (struct ZoneIterationResponseMessage))
583         {
584           GNUNET_break_op (0);
585           break;
586         }
587         handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size);
588       break;
589     default:
590       GNUNET_break_op (0);
591       break;
592   }
593 }
594
595 /**
596  * Type of a function to call when we receive a message
597  * from the service.
598  *
599  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
600  * @param msg message received, NULL on timeout or fatal error
601  */
602 static void
603 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
604 {
605   struct GNUNET_NAMESTORE_Handle *h = cls;
606   struct GNUNET_NAMESTORE_Header * gm;
607   struct GNUNET_NAMESTORE_QueueEntry *qe;
608   struct GNUNET_NAMESTORE_ZoneIterator *ze;
609   uint16_t size;
610   uint16_t type;
611   uint32_t r_id = UINT32_MAX;
612
613   if (NULL == msg)
614   {
615     force_reconnect (h);
616     return;
617   }
618
619   size = ntohs (msg->size);
620   type = ntohs (msg->type);
621
622   if (size < sizeof (struct GNUNET_NAMESTORE_Header))
623   {
624     GNUNET_break_op (0);
625     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
626                            GNUNET_TIME_UNIT_FOREVER_REL);
627     return;
628   }
629
630   gm = (struct GNUNET_NAMESTORE_Header *) msg;
631   r_id = ntohl (gm->r_id);
632
633   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, r_id);
634
635   /* Find matching operation */
636   if (r_id > h->op_id)
637   {
638     /* No matching pending operation found */
639     GNUNET_break_op (0);
640     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
641                            GNUNET_TIME_UNIT_FOREVER_REL);
642     return;
643   }
644
645   /* Is it a record related operation ? */
646   for (qe = h->op_head; qe != NULL; qe = qe->next)
647   {
648     if (qe->op_id == r_id)
649       break;
650   }
651   if (qe != NULL)
652   {
653     manage_record_operations (qe, msg, type, size);
654   }
655
656   /* Is it a zone iteration operation ? */
657   for (ze = h->z_head; ze != NULL; ze = ze->next)
658   {
659     if (ze->op_id == r_id)
660       break;
661   }
662   if (ze != NULL)
663   {
664     manage_zone_operations (ze, msg, type, size);
665   }
666
667   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
668                          GNUNET_TIME_UNIT_FOREVER_REL);
669
670   if (GNUNET_YES == h->reconnect)
671     force_reconnect (h);
672
673 }
674
675
676 /**
677  * Transmit messages from the message queue to the service
678  * (if there are any, and if we are not already trying).
679  *
680  * @param h handle to use
681  */
682 static void
683 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
684
685
686 /**
687  * We can now transmit a message to NAMESTORE. Do it.
688  *
689  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
690  * @param size number of bytes we can transmit
691  * @param buf where to copy the messages
692  * @return number of bytes copied into buf
693  */
694 static size_t
695 transmit_message_to_namestore (void *cls, size_t size, void *buf)
696 {
697   struct GNUNET_NAMESTORE_Handle *h = cls;
698   struct PendingMessage *p;
699   size_t ret;
700   char *cbuf;
701
702   h->th = NULL;
703   if ((size == 0) || (buf == NULL))
704   {
705     force_reconnect (h);
706     return 0;
707   }
708   ret = 0;
709   cbuf = buf;
710   while ((NULL != (p = h->pending_head)) && (p->size <= size))
711   {
712     memcpy (&cbuf[ret], &p[1], p->size);
713     ret += p->size;
714     size -= p->size;
715     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
716     if (GNUNET_YES == p->is_init)
717       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
718                              GNUNET_TIME_UNIT_FOREVER_REL);
719     GNUNET_free (p);
720   }
721   do_transmit (h);
722   return ret;
723 }
724
725
726 /**
727  * Transmit messages from the message queue to the service
728  * (if there are any, and if we are not already trying).
729  *
730  * @param h handle to use
731  */
732 static void
733 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
734 {
735   struct PendingMessage *p;
736
737   if (NULL != h->th)
738     return;
739   if (NULL == (p = h->pending_head))
740     return;
741   if (NULL == h->client)
742     return;                     /* currently reconnecting */
743
744   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
745                                            GNUNET_TIME_UNIT_FOREVER_REL,
746                                            GNUNET_NO, &transmit_message_to_namestore,
747                                            h);
748 }
749
750
751 /**
752  * Reconnect to namestore service.
753  *
754  * @param h the handle to the namestore service
755  */
756 static void
757 reconnect (struct GNUNET_NAMESTORE_Handle *h)
758 {
759   struct PendingMessage *p;
760   struct StartMessage *init;
761
762   GNUNET_assert (NULL == h->client);
763   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
764   GNUNET_assert (NULL != h->client);
765
766   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
767   {
768     p = GNUNET_malloc (sizeof (struct PendingMessage) +
769                        sizeof (struct StartMessage));
770     p->size = sizeof (struct StartMessage);
771     p->is_init = GNUNET_YES;
772     init = (struct StartMessage *) &p[1];
773     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
774     init->header.size = htons (sizeof (struct StartMessage));
775     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
776   }
777   do_transmit (h);
778 }
779
780 /**
781  * Re-establish the connection to the service.
782  *
783  * @param cls handle to use to re-connect.
784  * @param tc scheduler context
785  */
786 static void
787 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
788 {
789   struct GNUNET_NAMESTORE_Handle *h = cls;
790
791   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
792   reconnect (h);
793 }
794
795
796 /**
797  * Disconnect from service and then reconnect.
798  *
799  * @param h our handle
800  */
801 static void
802 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
803 {
804   h->reconnect = GNUNET_NO;
805   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
806   h->client = NULL;
807   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
808                                     &reconnect_task,
809                                     h);
810 }
811
812 static uint32_t
813 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
814 {
815   uint32_t op_id = h->op_id;
816   h->op_id ++;
817   return op_id;
818 }
819
820 /**
821  * Initialize the connection with the NAMESTORE service.
822  *
823  * @param cfg configuration to use
824  * @return handle to the GNS service, or NULL on error
825  */
826 struct GNUNET_NAMESTORE_Handle *
827 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
828 {
829   struct GNUNET_NAMESTORE_Handle *h;
830
831   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
832   h->cfg = cfg;
833   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
834   h->op_id = 0;
835   return h;
836 }
837
838 struct DisconnectContext
839 {
840   struct GNUNET_NAMESTORE_Handle *h;
841   int drop;
842 };
843
844 static void
845 clean_up_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
846 {
847   struct PendingMessage *p;
848   struct GNUNET_NAMESTORE_QueueEntry *q;
849   struct GNUNET_NAMESTORE_ZoneIterator *z;
850   struct GNUNET_NAMESTORE_Handle *h = cls;
851   GNUNET_assert (h != NULL);
852   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
853   while (NULL != (p = h->pending_head))
854   {
855     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
856     GNUNET_free (p);
857   }
858
859   while (NULL != (q = h->op_head))
860   {
861     GNUNET_break (0);
862     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
863     GNUNET_free (q);
864   }
865
866   while (NULL != (z = h->z_head))
867   {
868     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
869     GNUNET_free (z);
870   }
871
872   if (NULL != h->client)
873   {
874     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
875     h->client = NULL;
876   }
877   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
878   {
879     GNUNET_SCHEDULER_cancel (h->reconnect_task);
880     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
881   }
882   GNUNET_free(h);
883   h = NULL;
884 };
885
886 static size_t
887 transmit_disconnect_to_namestore (void *cls, size_t size, void *buf)
888 {
889   struct DisconnectContext * d_ctx = cls;
890   struct DisconnectMessage d_msg;
891   struct GNUNET_NAMESTORE_Handle *h = d_ctx->h;
892   int res;
893
894   d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_DISCONNECT);
895   d_msg.header.size = htons (sizeof (struct DisconnectMessage));
896   d_msg.drop = htonl (d_ctx->drop);
897
898   h->th = NULL;
899   if ((size == 0) || (buf == NULL) || (size < sizeof (struct DisconnectMessage)))
900   {
901     GNUNET_break (0);
902     res = 0;
903   }
904   else
905   {
906     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to service \n", "NAMESTORE_DISCONNECT");
907     memcpy (buf, &d_msg, sizeof (struct DisconnectMessage));
908     res = sizeof (struct DisconnectMessage);
909   }
910
911   GNUNET_SCHEDULER_add_now (&clean_up_task, h);
912   GNUNET_free (d_ctx);
913   return res;
914 }
915
916 /**
917  * Disconnect from the namestore service (and free associated
918  * resources).
919  *
920  * @param h handle to the namestore
921  * @param drop set to GNUNET_YES to delete all data in namestore (!)
922  */
923 void
924 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
925 {
926   if (h->th != NULL)
927   {
928     GNUNET_CLIENT_notify_transmit_ready_cancel(h->th);
929     h->th = NULL;
930   }
931   if (h->client != NULL)
932   {
933     struct DisconnectContext *d_ctx = GNUNET_malloc (sizeof (struct DisconnectContext));
934     d_ctx->h = h;
935     d_ctx->drop = drop;
936
937     h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct DisconnectMessage),
938                                            GNUNET_TIME_UNIT_FOREVER_REL,
939                                            GNUNET_NO, &transmit_disconnect_to_namestore,
940                                            d_ctx);
941   }
942   else
943   {
944     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not send disconnect notification to namestore service, we are not connected!\n");
945     if (GNUNET_YES == drop)
946       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "NAMESTORE will not drop content\n");
947     GNUNET_SCHEDULER_add_now (&clean_up_task, h);
948   }
949 }
950
951
952 /**
953  * Store an item in the namestore.  If the item is already present,
954  * the expiration time is updated to the max of the existing time and
955  * the new time.  This API is used when we cache signatures from other
956  * authorities.
957  *
958  * @param h handle to the namestore
959  * @param zone_key public key of the zone
960  * @param name name that is being mapped (at most 255 characters long)
961  * @param expire when does the corresponding block in the DHT expire (until
962  *               when should we never do a DHT lookup for the same name again)?
963  * @param rd_count number of entries in 'rd' array
964  * @param rd array of records with data to store
965  * @param signature signature for all the records in the zone under the given name
966  * @param cont continuation to call when done
967  * @param cont_cls closure for cont
968  * @return handle to abort the request
969  */
970 struct GNUNET_NAMESTORE_QueueEntry *
971 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
972                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
973                              const char *name,
974                              struct GNUNET_TIME_Absolute expire,
975                              unsigned int rd_count,
976                              const struct GNUNET_NAMESTORE_RecordData *rd,
977                              const struct GNUNET_CRYPTO_RsaSignature *signature,
978                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
979                              void *cont_cls)
980 {
981   struct GNUNET_NAMESTORE_QueueEntry *qe;
982   struct PendingMessage *pe;
983
984   /* pointer to elements */
985   char * zone_key_tmp;
986   char * rd_tmp;
987   char * name_tmp;
988
989   size_t msg_size = 0;
990   size_t name_len = 0;
991   size_t rd_ser_len = 0;
992   size_t pubkey_len = 0;
993   uint32_t rid = 0;
994
995   GNUNET_assert (NULL != h);
996   GNUNET_assert (NULL != zone_key);
997   GNUNET_assert (NULL != name);
998   GNUNET_assert (NULL != rd);
999   GNUNET_assert (NULL != signature);
1000
1001   name_len = strlen(name) + 1;
1002   if (name_len > 256)
1003   {
1004     GNUNET_break (0);
1005     return NULL;
1006   }
1007
1008   rid = get_op_id(h);
1009   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1010   qe->nsh = h;
1011   qe->cont = cont;
1012   qe->cont_cls = cont_cls;
1013   qe->op_id = rid;
1014   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1015
1016   /* set msg_size*/
1017   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1018   char rd_ser[rd_ser_len];
1019   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1020
1021   pubkey_len = sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded);
1022   struct RecordPutMessage * msg;
1023   msg_size = sizeof (struct RecordPutMessage) + pubkey_len + name_len  + rd_ser_len;
1024
1025   /* create msg here */
1026   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1027   pe->size = msg_size;
1028   pe->is_init = GNUNET_NO;
1029   msg = (struct RecordPutMessage *) &pe[1];
1030   zone_key_tmp = (char *) &msg[1];
1031   name_tmp = (char *) &zone_key_tmp[pubkey_len];
1032   rd_tmp = &name_tmp[name_len];
1033
1034   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
1035   msg->gns_header.header.size = htons (msg_size);
1036   msg->gns_header.r_id = htonl (rid);
1037   msg->key_len = htons (pubkey_len);
1038   memcpy (zone_key_tmp, zone_key, pubkey_len);
1039   msg->signature = *signature;
1040   msg->name_len = htons (name_len);
1041   memcpy (name_tmp, name, name_len);
1042   msg->expire = GNUNET_TIME_absolute_hton (expire);
1043   msg->rd_len = htons (rd_ser_len);
1044   msg->rd_count = htons (rd_count);
1045
1046   memcpy (rd_tmp, rd_ser, rd_ser_len);
1047
1048   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
1049
1050   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1051   do_transmit(h);
1052
1053   return qe;
1054 }
1055
1056
1057 /**
1058  * Check if a signature is valid.  This API is used by the GNS Block
1059  * to validate signatures received from the network.
1060  *
1061  * @param public_key public key of the zone
1062  * @param name name that is being mapped (at most 255 characters long)
1063  * @param rd_count number of entries in 'rd' array
1064  * @param rd array of records with data to store
1065  * @param signature signature for all the records in the zone under the given name
1066  * @return GNUNET_OK if the signature is valid
1067  */
1068 int
1069 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
1070                                    const char *name,
1071                                    unsigned int rd_count,
1072                                    const struct GNUNET_NAMESTORE_RecordData *rd,
1073                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
1074 {
1075   int res = GNUNET_SYSERR;
1076   size_t rd_ser_len = 0;
1077   size_t name_len = 0;
1078   char * name_tmp;
1079   char * rd_tmp;
1080   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
1081
1082   GNUNET_assert (public_key != NULL);
1083   GNUNET_assert (name != NULL);
1084   GNUNET_assert (signature != NULL);
1085
1086   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1087   char rd_ser[rd_ser_len];
1088   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1089
1090   name_len = strlen (name) + 1;
1091
1092   sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + rd_ser_len + name_len);
1093   sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len);
1094   sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
1095   name_tmp = (char *) &sig_purpose[1];
1096   rd_tmp = &name_tmp[name_len];
1097   memcpy (name_tmp, name, name_len);
1098   memcpy (rd_tmp, rd_ser, rd_ser_len);
1099
1100   res = GNUNET_CRYPTO_rsa_verify(GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key);
1101
1102   GNUNET_free (sig_purpose);
1103
1104   return res;
1105 }
1106
1107 /**
1108  * Store an item in the namestore.  If the item is already present,
1109  * the expiration time is updated to the max of the existing time and
1110  * the new time.  This API is used by the authority of a zone.
1111  *
1112  * @param h handle to the namestore
1113  * @param pkey private key of the zone
1114  * @param name name that is being mapped (at most 255 characters long)
1115  * @param rd record data to store
1116  * @param cont continuation to call when done
1117  * @param cont_cls closure for cont
1118  * @return handle to abort the request
1119  */
1120 struct GNUNET_NAMESTORE_QueueEntry *
1121 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
1122                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1123                                 const char *name,
1124                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1125                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1126                                 void *cont_cls)
1127 {
1128   struct GNUNET_NAMESTORE_QueueEntry *qe;
1129   struct PendingMessage *pe;
1130   char * name_tmp;
1131   char * pkey_tmp;
1132   char * rd_tmp;
1133   size_t rd_ser_len = 0;
1134   size_t msg_size = 0;
1135   size_t name_len = 0;
1136   size_t key_len = 0;
1137   uint32_t rid = 0;
1138
1139   GNUNET_assert (NULL != h);
1140   GNUNET_assert (NULL != pkey);
1141   GNUNET_assert (NULL != name);
1142   GNUNET_assert (NULL != rd);
1143
1144   name_len = strlen(name) + 1;
1145   if (name_len > 256)
1146   {
1147     GNUNET_break (0);
1148     return NULL;
1149   }
1150
1151   rid = get_op_id(h);
1152   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1153   qe->nsh = h;
1154   qe->cont = cont;
1155   qe->cont_cls = cont_cls;
1156   qe->op_id = rid;
1157   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1158
1159   /* set msg_size*/
1160   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1161   GNUNET_assert (pkey_enc != NULL);
1162   key_len = ntohs (pkey_enc->len);
1163
1164   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1165   char rd_ser[rd_ser_len];
1166   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1167
1168   struct RecordCreateMessage * msg;
1169   msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1170
1171   /* create msg here */
1172   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1173   pe->size = msg_size;
1174   pe->is_init = GNUNET_NO;
1175   msg = (struct RecordCreateMessage *) &pe[1];
1176
1177   pkey_tmp = (char *) &msg[1];
1178   name_tmp = &pkey_tmp[key_len];
1179   rd_tmp = &name_tmp[name_len];
1180
1181   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
1182   msg->gns_header.header.size = htons (msg_size);
1183   msg->gns_header.r_id = htonl (rid);
1184   msg->name_len = htons (name_len);
1185   msg->rd_count = htons (1);
1186   msg->rd_len = htons (rd_ser_len);
1187   msg->pkey_len = htons (key_len);
1188   memcpy (pkey_tmp, pkey_enc, key_len);
1189   memcpy (name_tmp, name, name_len);
1190   memcpy (rd_tmp, rd_ser, rd_ser_len);
1191   GNUNET_free (pkey_enc);
1192
1193   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
1194
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  * Explicitly remove some content from the database.  The
1203  * "cont"inuation will be called with status "GNUNET_OK" if content
1204  * was removed, "GNUNET_NO" if no matching entry was found and
1205  * "GNUNET_SYSERR" on all other types of errors.
1206  * This API is used by the authority of a zone.
1207  *
1208  * @param h handle to the namestore
1209  * @param pkey private key of the zone
1210  * @param name name that is being mapped (at most 255 characters long)
1211  * @param rd record data
1212  * @param cont continuation to call when done
1213  * @param cont_cls closure for cont
1214  * @return handle to abort the request
1215  */
1216 struct GNUNET_NAMESTORE_QueueEntry *
1217 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
1218                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1219                                 const char *name,
1220                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1221                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1222                                 void *cont_cls)
1223 {
1224   struct GNUNET_NAMESTORE_QueueEntry *qe;
1225   struct PendingMessage *pe;
1226   char *pkey_tmp;
1227   char *rd_tmp;
1228   char *name_tmp;
1229   size_t rd_ser_len = 0;
1230   size_t msg_size = 0;
1231   size_t name_len = 0;
1232   size_t key_len = 0;
1233   uint32_t rid = 0;
1234
1235   GNUNET_assert (NULL != h);
1236
1237   rid = get_op_id(h);
1238   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1239   qe->nsh = h;
1240   qe->cont = cont;
1241   qe->cont_cls = cont_cls;
1242   qe->op_id = rid;
1243   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1244
1245   /* set msg_size*/
1246   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1247   GNUNET_assert (pkey_enc != NULL);
1248   key_len = ntohs (pkey_enc->len);
1249
1250   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1251   char rd_ser[rd_ser_len];
1252   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1253
1254   name_len = strlen (name) + 1;
1255
1256   struct RecordRemoveMessage * msg;
1257   msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1258
1259   /* create msg here */
1260   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1261   pe->size = msg_size;
1262   pe->is_init = GNUNET_NO;
1263   msg = (struct RecordRemoveMessage *) &pe[1];
1264
1265   pkey_tmp = (char *) &msg[1];
1266   name_tmp = &pkey_tmp[key_len];
1267   rd_tmp = &name_tmp[name_len];
1268
1269   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
1270   msg->gns_header.header.size = htons (msg_size);
1271   msg->gns_header.r_id = htonl (rid);
1272   msg->name_len = htons (name_len);
1273   msg->rd_len = htons (rd_ser_len);
1274   msg->rd_count = htons (1);
1275   msg->key_len = htons (key_len);
1276   memcpy (pkey_tmp, pkey_enc, key_len);
1277   memcpy (name_tmp, name, name_len);
1278   memcpy (rd_tmp, rd_ser, rd_ser_len);
1279
1280   GNUNET_free (pkey_enc);
1281
1282   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
1283
1284   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1285   do_transmit(h);
1286   return qe;
1287 }
1288
1289
1290 /**
1291  * Get a result for a particular key from the namestore.  The processor
1292  * will only be called once.  
1293  *
1294  * @param h handle to the namestore
1295  * @param zone zone to look up a record from
1296  * @param name name to look up
1297  * @param record_type desired record type, 0 for all
1298  * @param proc function to call on the matching records, or with
1299  *        NULL (rd_count == 0) if there are no matching records
1300  * @param proc_cls closure for proc
1301  * @return a handle that can be used to
1302  *         cancel
1303  */
1304 struct GNUNET_NAMESTORE_QueueEntry *
1305 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
1306                               const GNUNET_HashCode *zone,
1307                               const char *name,
1308                               uint32_t record_type,
1309                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1310 {
1311   struct GNUNET_NAMESTORE_QueueEntry *qe;
1312   struct PendingMessage *pe;
1313   size_t msg_size = 0;
1314   size_t name_len = 0;
1315   uint32_t rid = 0;
1316
1317   GNUNET_assert (NULL != h);
1318   GNUNET_assert (NULL != zone);
1319   GNUNET_assert (NULL != name);
1320
1321   name_len = strlen (name) + 1;
1322   if ((name_len == 0) || (name_len > 256))
1323   {
1324     GNUNET_break (0);
1325     return NULL;
1326   }
1327
1328   rid = get_op_id(h);
1329   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1330   qe->nsh = h;
1331   qe->proc = proc;
1332   qe->proc_cls = proc_cls;
1333   qe->op_id = rid;
1334   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1335
1336   /* set msg_size*/
1337   msg_size = sizeof (struct LookupNameMessage) + name_len;
1338   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1339
1340   /* create msg here */
1341   struct LookupNameMessage * msg;
1342   pe->size = msg_size;
1343   pe->is_init = GNUNET_NO;
1344   msg = (struct LookupNameMessage *) &pe[1];
1345   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1346   msg->gns_header.header.size = htons (msg_size);
1347   msg->gns_header.r_id = htonl (rid);
1348   msg->record_type = htonl (record_type);
1349   msg->zone = *zone;
1350   msg->name_len = htonl (name_len);
1351   memcpy (&msg[1], name, name_len);
1352
1353   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1354
1355   /* transmit message */
1356   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1357   do_transmit(h);
1358
1359   return qe;
1360 }
1361
1362
1363 /**
1364  * Look for an existing PKEY delegation record for a given public key.
1365  * Returns at most one result to the processor.
1366  *
1367  * @param h handle to the namestore
1368  * @param zone hash of public key of the zone to look up in, never NULL
1369  * @param value_zone hash of the public key of the target zone (value), never NULL
1370  * @param proc function to call on the matching records, or with
1371  *        NULL (rd_count == 0) if there are no matching records
1372  * @param proc_cls closure for proc
1373  * @return a handle that can be used to
1374  *         cancel
1375  */
1376 struct GNUNET_NAMESTORE_QueueEntry *
1377 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
1378                                const GNUNET_HashCode *zone,
1379                                const GNUNET_HashCode *value_zone,
1380                                GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1381 {
1382   struct GNUNET_NAMESTORE_QueueEntry *qe;
1383   struct PendingMessage *pe;
1384   size_t msg_size = 0;
1385   uint32_t rid = 0;
1386
1387   GNUNET_assert (NULL != h);
1388   GNUNET_assert (NULL != zone);
1389   GNUNET_assert (NULL != value_zone);
1390
1391   rid = get_op_id(h);
1392   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1393   qe->nsh = h;
1394   qe->proc = proc;
1395   qe->proc_cls = proc_cls;
1396   qe->op_id = rid;
1397   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1398
1399   /* set msg_size*/
1400   msg_size = sizeof (struct ZoneToNameMessage);
1401   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1402
1403   /* create msg here */
1404   struct ZoneToNameMessage * msg;
1405   pe->size = msg_size;
1406   pe->is_init = GNUNET_NO;
1407   msg = (struct ZoneToNameMessage *) &pe[1];
1408   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1409   msg->gns_header.header.size = htons (msg_size);
1410   msg->gns_header.r_id = htonl (rid);
1411   msg->zone = *zone;
1412   msg->value_zone = *value_zone;
1413
1414   char * z_tmp = strdup (GNUNET_h2s (zone));
1415   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s' in zone `%s'\n",
1416       "NAMESTORE_ZONE_TO_NAME",
1417       z_tmp,
1418       GNUNET_h2s (value_zone));
1419   GNUNET_free (z_tmp);
1420
1421   /* transmit message */
1422   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1423   do_transmit(h);
1424
1425   return qe;
1426 }
1427
1428
1429
1430 /**
1431  * Starts a new zone iteration (used to periodically PUT all of our
1432  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1433  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1434  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1435  * immediately, and then again after
1436  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1437  *
1438  * @param h handle to the namestore
1439  * @param zone zone to access, NULL for all zones
1440  * @param must_have_flags flags that must be set for the record to be returned
1441  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1442  * @param proc function to call on each name from the zone; it
1443  *        will be called repeatedly with a value (if available)
1444  *        and always once at the end with a name of NULL.
1445  * @param proc_cls closure for proc
1446  * @return an iterator handle to use for iteration
1447  */
1448 struct GNUNET_NAMESTORE_ZoneIterator *
1449 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1450                                        const GNUNET_HashCode *zone,
1451                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1452                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1453                                        GNUNET_NAMESTORE_RecordProcessor proc,
1454                                        void *proc_cls)
1455 {
1456   struct GNUNET_NAMESTORE_ZoneIterator *it;
1457   struct PendingMessage *pe;
1458   size_t msg_size = 0;
1459   uint32_t rid = 0;
1460
1461   GNUNET_assert (NULL != h);
1462   GNUNET_assert (NULL != zone);
1463
1464   rid = get_op_id(h);
1465   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1466   it->h = h;
1467   it->proc = proc;
1468   it->proc_cls = proc;
1469   it->op_id = rid;
1470   it->zone = *zone;
1471   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1472
1473   /* set msg_size*/
1474   msg_size = sizeof (struct ZoneIterationStartMessage);
1475   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1476
1477   /* create msg here */
1478   struct ZoneIterationStartMessage * msg;
1479   pe->size = msg_size;
1480   pe->is_init = GNUNET_NO;
1481   msg = (struct ZoneIterationStartMessage *) &pe[1];
1482   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1483   msg->gns_header.header.size = htons (msg_size);
1484   msg->gns_header.r_id = htonl (rid);
1485   msg->zone = *zone;
1486   msg->must_have_flags = ntohs (must_have_flags);
1487   msg->must_not_have_flags = ntohs (must_not_have_flags);
1488
1489   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1490
1491   /* transmit message */
1492   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1493   do_transmit(h);
1494
1495   return it;
1496 }
1497
1498
1499 /**
1500  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1501  * for the next record.
1502  *
1503  * @param it the iterator
1504  */
1505 void
1506 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1507 {
1508   struct GNUNET_NAMESTORE_Handle *h;
1509   struct PendingMessage *pe;
1510   size_t msg_size = 0;
1511
1512   GNUNET_assert (NULL != it);
1513   h = it->h;
1514
1515   /* set msg_size*/
1516   msg_size = sizeof (struct ZoneIterationNextMessage);
1517   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1518
1519   /* create msg here */
1520   struct ZoneIterationNextMessage * msg;
1521   pe->size = msg_size;
1522   pe->is_init = GNUNET_NO;
1523   msg = (struct ZoneIterationNextMessage *) &pe[1];
1524   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1525   msg->gns_header.header.size = htons (msg_size);
1526   msg->gns_header.r_id = htonl (it->op_id);
1527
1528   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1529
1530   /* transmit message */
1531   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1532   do_transmit(h);
1533 }
1534
1535
1536 /**
1537  * Stops iteration and releases the namestore handle for further calls.
1538  *
1539  * @param it the iterator
1540  */
1541 void
1542 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1543 {
1544   GNUNET_assert (NULL != it);
1545   struct PendingMessage *pe;
1546   size_t msg_size = 0;
1547   struct GNUNET_NAMESTORE_Handle *h = it->h;
1548
1549   /* set msg_size*/
1550   msg_size = sizeof (struct ZoneIterationStopMessage);
1551   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1552
1553   /* create msg here */
1554   struct ZoneIterationStopMessage * msg;
1555   pe->size = msg_size;
1556   pe->is_init = GNUNET_NO;
1557   msg = (struct ZoneIterationStopMessage *) &pe[1];
1558   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1559   msg->gns_header.header.size = htons (msg_size);
1560   msg->gns_header.r_id = htonl (it->op_id);
1561
1562   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1563
1564   /* transmit message */
1565   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1566   do_transmit(h);
1567 }
1568
1569
1570 /**
1571  * Cancel a namestore operation.  The final callback from the
1572  * operation must not have been done yet.
1573  *
1574  * @param qe operation to cancel
1575  */
1576 void
1577 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1578 {
1579   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1580
1581   GNUNET_assert (qe != NULL);
1582
1583   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1584   GNUNET_free(qe);
1585
1586 }
1587
1588 /* end of namestore_api.c */