- more code
[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_constants.h"
31 #include "gnunet_arm_service.h"
32 #include "gnunet_namestore_service.h"
33 #include "namestore.h"
34 #define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
35
36 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
37
38 /**
39  * A QueueEntry.
40  */
41 struct GNUNET_NAMESTORE_QueueEntry
42 {
43   struct GNUNET_NAMESTORE_QueueEntry *next;
44   struct GNUNET_NAMESTORE_QueueEntry *prev;
45
46   struct GNUNET_NAMESTORE_Handle *nsh;
47
48   uint32_t op_id;
49
50   GNUNET_NAMESTORE_ContinuationWithStatus cont;
51   void *cont_cls;
52
53   GNUNET_NAMESTORE_RecordProcessor proc;
54   void *proc_cls;
55
56   char *data; /*stub data pointer*/
57 };
58
59
60 /**
61  * Zone iterator
62  */
63 struct GNUNET_NAMESTORE_ZoneIterator
64 {
65   struct GNUNET_NAMESTORE_ZoneIterator *next;
66   struct GNUNET_NAMESTORE_ZoneIterator *prev;
67
68   uint32_t op_id;
69
70   struct GNUNET_NAMESTORE_Handle *h;
71   GNUNET_NAMESTORE_RecordProcessor proc;
72   void* proc_cls;
73   GNUNET_HashCode zone;
74   uint32_t no_flags;
75   uint32_t flags;
76 };
77
78
79 /**
80  * Message in linked list we should send to the service.  The
81  * actual binary message follows this struct.
82  */
83 struct PendingMessage
84 {
85
86   /**
87    * Kept in a DLL.
88    */
89   struct PendingMessage *next;
90
91   /**
92    * Kept in a DLL.
93    */
94   struct PendingMessage *prev;
95
96   /**
97    * Size of the message.
98    */
99   size_t size;
100
101   /**
102    * Is this the 'START' message?
103    */
104   int is_init;
105 };
106
107
108 /**
109  * Connection to the NAMESTORE service.
110  */
111 struct GNUNET_NAMESTORE_Handle
112 {
113
114   /**
115    * Configuration to use.
116    */
117   const struct GNUNET_CONFIGURATION_Handle *cfg;
118
119   /**
120    * Socket (if available).
121    */
122   struct GNUNET_CLIENT_Connection *client;
123
124   /**
125    * Currently pending transmission request (or NULL).
126    */
127   struct GNUNET_CLIENT_TransmitHandle *th;
128
129   /**
130    * Reconnect task
131    */
132   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
133
134   /**
135    * Pending messages to send to the service
136    */
137
138   struct PendingMessage * pending_head;
139   struct PendingMessage * pending_tail;
140
141   /**
142    * Should we reconnect to service due to some serious error?
143    */
144   int reconnect;
145
146
147   /**
148    * Pending namestore queue entries
149    */
150   struct GNUNET_NAMESTORE_QueueEntry * op_head;
151   struct GNUNET_NAMESTORE_QueueEntry * op_tail;
152
153   uint32_t op_id;
154
155   /**
156    * Pending namestore zone iterator entries
157    */
158   struct GNUNET_NAMESTORE_ZoneIterator * z_head;
159   struct GNUNET_NAMESTORE_ZoneIterator * z_tail;
160 };
161
162 struct GNUNET_NAMESTORE_SimpleRecord
163 {
164   /**
165    * DLL
166    */
167   struct GNUNET_NAMESTORE_SimpleRecord *next;
168
169   /**
170    * DLL
171    */
172   struct GNUNET_NAMESTORE_SimpleRecord *prev;
173   
174   const char *name;
175   const GNUNET_HashCode *zone;
176   uint32_t record_type;
177   struct GNUNET_TIME_Absolute expiration;
178   enum GNUNET_NAMESTORE_RecordFlags flags;
179   size_t data_size;
180   const void *data;
181 };
182
183
184 /**
185  * Disconnect from service and then reconnect.
186  *
187  * @param h our handle
188  */
189 static void
190 force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
191
192 static void
193 handle_lookup_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
194                              struct LookupNameResponseMessage * msg,
195                              size_t size)
196 {
197   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
198               "LOOKUP_NAME_RESPONSE");
199
200   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
201   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
202   char *name;
203   struct GNUNET_NAMESTORE_RecordData *rd = NULL;
204   struct GNUNET_CRYPTO_RsaSignature *signature = NULL;
205   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy;
206   struct GNUNET_TIME_Absolute expire;
207   unsigned int rd_count = 0;
208   size_t msg_len = 0;
209   size_t name_len = 0;
210   int contains_sig = GNUNET_NO;
211
212   rd_count = ntohl (msg->rc_count);
213   msg_len = ntohs (msg->header.size);
214   name_len = ntohs (msg->name_len);
215   contains_sig = ntohs (msg->contains_sig);
216   expire = GNUNET_TIME_absolute_ntoh(msg->expire);
217
218   if (msg_len != sizeof (struct LookupNameResponseMessage) +
219       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
220       name_len +
221       rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData) +
222       contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature))
223   {
224     GNUNET_break_op (0);
225     return;
226   }
227
228   zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
229   name = (char *) &zone_key[1];
230   rd = (struct GNUNET_NAMESTORE_RecordData *) &name[name_len];
231
232   /* reset values if values not contained */
233   if (contains_sig == GNUNET_NO)
234     signature = NULL;
235   else
236     signature = (struct GNUNET_CRYPTO_RsaSignature *) &rd[rd_count];
237   if (rd_count == 0)
238     rd = NULL;
239   if (name_len == 0)
240     name = NULL;
241
242   memset (&dummy, '0', sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
243   if (0 == memcmp (zone_key, &dummy, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
244       zone_key = NULL;
245
246   if (qe->proc != NULL)
247   {
248     qe->proc (qe->proc_cls, zone_key, expire, name, rd_count, rd, signature);
249   }
250   /* Operation done, remove */
251   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
252   GNUNET_free (qe);
253 }
254
255
256 static void
257 handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
258                              struct RecordPutResponseMessage* msg,
259                              size_t size)
260 {
261   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
262               "RECORD_PUT_RESPONSE");
263
264   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
265   int res = GNUNET_OK;
266
267   if (ntohs (msg->op_result) == GNUNET_OK)
268   {
269     res = GNUNET_OK;
270     if (qe->cont != NULL)
271     {
272       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
273     }
274
275   }
276   else if (ntohs (msg->op_result) == GNUNET_NO)
277   {
278     res = GNUNET_SYSERR;
279     if (qe->cont != NULL)
280     {
281       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
282     }
283   }
284   else
285   {
286     GNUNET_break_op (0);
287     return;
288   }
289
290   /* Operation done, remove */
291   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
292
293   GNUNET_free (qe);
294 }
295
296
297 static void
298 handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
299                              struct RecordCreateResponseMessage* msg,
300                              size_t size)
301 {
302   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
303               "RECORD_CREATE_RESPONSE");
304
305   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
306   int res = GNUNET_OK;
307
308   if (ntohs (msg->op_result) == GNUNET_OK)
309   {
310     res = GNUNET_OK;
311     if (qe->cont != NULL)
312     {
313       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
314     }
315
316   }
317   else if (ntohs (msg->op_result) == GNUNET_NO)
318   {
319     res = GNUNET_SYSERR;
320     if (qe->cont != NULL)
321     {
322       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
323     }
324   }
325   else
326   {
327     GNUNET_break_op (0);
328     return;
329   }
330
331   /* Operation done, remove */
332   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
333
334   GNUNET_free (qe);
335 }
336
337
338 static void
339 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
340                           const struct GNUNET_MessageHeader *msg,
341                           int type, size_t size)
342 {
343
344   /* handle different message type */
345   switch (type) {
346     case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
347         if (size < sizeof (struct LookupNameResponseMessage))
348         {
349           GNUNET_break_op (0);
350           break;
351         }
352         handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size);
353       break;
354     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
355         if (size != sizeof (struct RecordPutResponseMessage))
356         {
357           GNUNET_break_op (0);
358           break;
359         }
360         handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size);
361       break;
362     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE:
363         if (size != sizeof (struct RecordCreateResponseMessage))
364         {
365           GNUNET_break_op (0);
366           break;
367         }
368         handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size);
369       break;
370     default:
371       GNUNET_break_op (0);
372       break;
373   }
374 }
375
376 static void
377 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
378                                 struct ZoneIterationResponseMessage *msg,
379                                 size_t size)
380 {
381   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
382               "ZONE_ITERATION_RESPONSE");
383 }
384
385
386 static void
387 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
388                         const struct GNUNET_MessageHeader *msg,
389                         int type, size_t size)
390 {
391
392   /* handle different message type */
393   switch (type) {
394     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
395         if (size < sizeof (struct ZoneIterationResponseMessage))
396         {
397           GNUNET_break_op (0);
398           break;
399         }
400         handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size);
401       break;
402     default:
403       GNUNET_break_op (0);
404       break;
405   }
406 }
407
408 /**
409  * Type of a function to call when we receive a message
410  * from the service.
411  *
412  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
413  * @param msg message received, NULL on timeout or fatal error
414  */
415 static void
416 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
417 {
418   struct GNUNET_NAMESTORE_Handle *h = cls;
419   struct GenericMessage * gm;
420   struct GNUNET_NAMESTORE_QueueEntry *qe;
421   struct GNUNET_NAMESTORE_ZoneIterator *ze;
422   uint16_t size;
423   uint16_t type;
424   uint32_t op_id = UINT32_MAX;
425
426   if (NULL == msg)
427   {
428     force_reconnect (h);
429     return;
430   }
431
432   size = ntohs (msg->size);
433   type = ntohs (msg->type);
434
435   if (size < sizeof (struct GenericMessage))
436   {
437     GNUNET_break_op (0);
438     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
439                            GNUNET_TIME_UNIT_FOREVER_REL);
440     return;
441   }
442
443   gm = (struct GenericMessage *) msg;
444   op_id = ntohl (gm->op_id);
445
446   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, op_id);
447
448   /* Find matching operation */
449   if (op_id > h->op_id)
450   {
451     /* No matching pending operation found */
452     GNUNET_break_op (0);
453     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
454                            GNUNET_TIME_UNIT_FOREVER_REL);
455     return;
456   }
457
458   /* Is it a record related operation ? */
459   for (qe = h->op_head; qe != NULL; qe = qe->next)
460   {
461     if (qe->op_id == op_id)
462       break;
463   }
464   if (qe != NULL)
465   {
466     manage_record_operations (qe, msg, type, size);
467   }
468
469   /* Is it a zone iteration operation ? */
470   for (ze = h->z_head; ze != NULL; ze = ze->next)
471   {
472     if (ze->op_id == op_id)
473       break;
474   }
475   if (ze != NULL)
476   {
477     manage_zone_operations (ze, msg, type, size);
478   }
479
480   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
481                          GNUNET_TIME_UNIT_FOREVER_REL);
482
483   if (GNUNET_YES == h->reconnect)
484     force_reconnect (h);
485
486 }
487
488
489 /**
490  * Transmit messages from the message queue to the service
491  * (if there are any, and if we are not already trying).
492  *
493  * @param h handle to use
494  */
495 static void
496 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
497
498
499 /**
500  * We can now transmit a message to NAMESTORE. Do it.
501  *
502  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
503  * @param size number of bytes we can transmit
504  * @param buf where to copy the messages
505  * @return number of bytes copied into buf
506  */
507 static size_t
508 transmit_message_to_namestore (void *cls, size_t size, void *buf)
509 {
510   struct GNUNET_NAMESTORE_Handle *h = cls;
511   struct PendingMessage *p;
512   size_t ret;
513   char *cbuf;
514
515   h->th = NULL;
516   if ((size == 0) || (buf == NULL))
517   {
518     force_reconnect (h);
519     return 0;
520   }
521   ret = 0;
522   cbuf = buf;
523   while ((NULL != (p = h->pending_head)) && (p->size <= size))
524   {
525     memcpy (&cbuf[ret], &p[1], p->size);
526     ret += p->size;
527     size -= p->size;
528     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
529     if (GNUNET_YES == p->is_init)
530       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
531                              GNUNET_TIME_UNIT_FOREVER_REL);
532     GNUNET_free (p);
533   }
534   do_transmit (h);
535   return ret;
536 }
537
538
539 /**
540  * Transmit messages from the message queue to the service
541  * (if there are any, and if we are not already trying).
542  *
543  * @param h handle to use
544  */
545 static void
546 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
547 {
548   struct PendingMessage *p;
549
550   if (NULL != h->th)
551     return;
552   if (NULL == (p = h->pending_head))
553     return;
554   if (NULL == h->client)
555     return;                     /* currently reconnecting */
556
557   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
558                                            GNUNET_TIME_UNIT_FOREVER_REL,
559                                            GNUNET_NO, &transmit_message_to_namestore,
560                                            h);
561 }
562
563
564 /**
565  * Reconnect to namestore service.
566  *
567  * @param h the handle to the namestore service
568  */
569 static void
570 reconnect (struct GNUNET_NAMESTORE_Handle *h)
571 {
572   struct PendingMessage *p;
573   struct StartMessage *init;
574
575   GNUNET_assert (NULL == h->client);
576   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
577   GNUNET_assert (NULL != h->client);
578
579   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
580   {
581     p = GNUNET_malloc (sizeof (struct PendingMessage) +
582                        sizeof (struct StartMessage));
583     p->size = sizeof (struct StartMessage);
584     p->is_init = GNUNET_YES;
585     init = (struct StartMessage *) &p[1];
586     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
587     init->header.size = htons (sizeof (struct StartMessage));
588     GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, p);
589   }
590   do_transmit (h);
591 }
592
593 /**
594  * Re-establish the connection to the service.
595  *
596  * @param cls handle to use to re-connect.
597  * @param tc scheduler context
598  */
599 static void
600 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
601 {
602   struct GNUNET_NAMESTORE_Handle *h = cls;
603
604   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
605   reconnect (h);
606 }
607
608
609 /**
610  * Disconnect from service and then reconnect.
611  *
612  * @param h our handle
613  */
614 static void
615 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
616 {
617   h->reconnect = GNUNET_NO;
618   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
619   h->client = NULL;
620   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
621                                     &reconnect_task,
622                                     h);
623 }
624
625 static uint32_t
626 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
627 {
628   uint32_t op_id = h->op_id;
629   h->op_id ++;
630   return op_id;
631 }
632
633 /**
634  * Initialize the connection with the NAMESTORE service.
635  *
636  * @param cfg configuration to use
637  * @return handle to the GNS service, or NULL on error
638  */
639 struct GNUNET_NAMESTORE_Handle *
640 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
641 {
642   struct GNUNET_NAMESTORE_Handle *h;
643
644   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
645   h->cfg = cfg;
646   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
647   h->op_id = 0;
648   return h;
649 }
650
651
652 /**
653  * Disconnect from the namestore service (and free associated
654  * resources).
655  *
656  * @param h handle to the namestore
657  * @param drop set to GNUNET_YES to delete all data in namestore (!)
658  */
659 void
660 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
661 {
662   struct PendingMessage *p;
663   struct GNUNET_NAMESTORE_QueueEntry *q;
664   struct GNUNET_NAMESTORE_ZoneIterator *z;
665
666   GNUNET_assert (h != NULL);
667
668   while (NULL != (p = h->pending_head))
669   {
670     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
671     GNUNET_free (p);
672   }
673
674   while (NULL != (q = h->op_head))
675   {
676     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
677     GNUNET_free (q);
678   }
679
680   while (NULL != (z = h->z_head))
681   {
682     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
683     GNUNET_free (z);
684   }
685
686   if (NULL != h->client)
687   {
688     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
689     h->client = NULL;
690   }
691   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
692   {
693     GNUNET_SCHEDULER_cancel (h->reconnect_task);
694     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
695   }
696   GNUNET_free(h);
697   h = NULL;
698 }
699
700
701 /**
702  * Store an item in the namestore.  If the item is already present,
703  * the expiration time is updated to the max of the existing time and
704  * the new time.  This API is used when we cache signatures from other
705  * authorities.
706  *
707  * @param h handle to the namestore
708  * @param zone_key public key of the zone
709  * @param name name that is being mapped (at most 255 characters long)
710  * @param expire when does the corresponding block in the DHT expire (until
711  *               when should we never do a DHT lookup for the same name again)?
712  * @param rd_count number of entries in 'rd' array
713  * @param rd array of records with data to store
714  * @param signature signature for all the records in the zone under the given name
715  * @param cont continuation to call when done
716  * @param cont_cls closure for cont
717  * @return handle to abort the request
718  */
719 struct GNUNET_NAMESTORE_QueueEntry *
720 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
721                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
722                              const char *name,
723                              struct GNUNET_TIME_Absolute expire,
724                              unsigned int rd_count,
725                              const struct GNUNET_NAMESTORE_RecordData *rd,
726                              const struct GNUNET_CRYPTO_RsaSignature *signature,
727                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
728                              void *cont_cls)
729 {
730   struct GNUNET_NAMESTORE_QueueEntry *qe;
731   struct PendingMessage *pe;
732
733   /* pointer to elements */
734   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp;
735   struct GNUNET_NAMESTORE_RecordData *rd_tmp;
736   char * name_tmp;
737
738   size_t msg_size = 0;
739   size_t name_len = strlen(name) + 1;
740   uint32_t id = 0;
741
742   GNUNET_assert (NULL != h);
743   id = get_op_id(h);
744   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
745   qe->nsh = h;
746   qe->cont = cont;
747   qe->cont_cls = cont_cls;
748   qe->op_id = id;
749   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
750
751   /* set msg_size*/
752   struct RecordPutMessage * msg;
753   msg_size = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len  + rd_count * (sizeof (struct GNUNET_NAMESTORE_RecordData));
754
755   /* create msg here */
756   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
757   pe->size = msg_size;
758   pe->is_init = GNUNET_NO;
759   msg = (struct RecordPutMessage *) &pe[1];
760   zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
761   name_tmp = (char *) &zone_key_tmp[1];
762   rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len];
763
764   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
765   msg->header.size = htons (msg_size);
766   msg->op_id = htonl (id);
767   memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
768   msg->signature = *signature;
769   msg->name_len = htons (name_len);
770   memcpy (name_tmp, name, name_len);
771   msg->expire = GNUNET_TIME_absolute_hton (expire);
772   msg->rd_count = htonl(rd_count);
773   memcpy (rd_tmp, rd, rd_count * (sizeof (struct GNUNET_NAMESTORE_RecordData)));
774
775   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
776
777   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
778   do_transmit(h);
779
780   return qe;
781 }
782
783
784 /**
785  * Check if a signature is valid.  This API is used by the GNS Block
786  * to validate signatures received from the network.
787  *
788  * @param public_key public key of the zone
789  * @param name name that is being mapped (at most 255 characters long)
790  * @param rd_count number of entries in 'rd' array
791  * @param rd array of records with data to store
792  * @param signature signature for all the records in the zone under the given name
793  * @return GNUNET_OK if the signature is valid
794  */
795 int
796 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
797                                    const char *name,
798                                    unsigned int rd_count,
799                                    const struct GNUNET_NAMESTORE_RecordData *rd,
800                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
801 {
802   return GNUNET_SYSERR;
803 }
804
805 /**
806  * Store an item in the namestore.  If the item is already present,
807  * the expiration time is updated to the max of the existing time and
808  * the new time.  This API is used by the authority of a zone.
809  *
810  * @param h handle to the namestore
811  * @param pkey private key of the zone
812  * @param name name that is being mapped (at most 255 characters long)
813  * @param rd record data to store
814  * @param cont continuation to call when done
815  * @param cont_cls closure for cont
816  * @return handle to abort the request
817  */
818 struct GNUNET_NAMESTORE_QueueEntry *
819 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
820                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
821                                 const char *name,
822                                 const struct GNUNET_NAMESTORE_RecordData *rd,
823                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
824                                 void *cont_cls)
825 {
826   struct GNUNET_NAMESTORE_QueueEntry *qe;
827   struct PendingMessage *pe;
828   struct GNUNET_NAMESTORE_RecordData * rd_tmp;
829   char * name_tmp;
830   size_t msg_size = 0;
831   size_t name_len = 0;
832   uint32_t id = 0;
833
834   GNUNET_assert (NULL != h);
835
836   id = get_op_id(h);
837   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
838   qe->nsh = h;
839   qe->cont = cont;
840   qe->cont_cls = cont_cls;
841   qe->op_id = id;
842
843   /* set msg_size*/
844   struct RecordCreateMessage * msg;
845   msg_size = sizeof (struct RecordCreateMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData);
846
847   /* create msg here */
848   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
849   pe->size = msg_size;
850   pe->is_init = GNUNET_NO;
851   msg = (struct RecordCreateMessage *) &pe[1];
852
853   name_tmp = (char *) &msg[1];
854   rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len];
855
856   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
857   msg->header.size = htons (msg_size);
858   msg->op_id = htonl (id);
859   //msg->signature = *signature;
860   msg->name_len = htons (name_len);
861   memcpy (name_tmp, name, name_len);
862   memcpy (rd_tmp, rd, sizeof (struct GNUNET_NAMESTORE_RecordData));
863
864   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
865
866   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
867   do_transmit(h);
868   return qe;
869 }
870
871
872 /**
873  * Explicitly remove some content from the database.  The
874  * "cont"inuation will be called with status "GNUNET_OK" if content
875  * was removed, "GNUNET_NO" if no matching entry was found and
876  * "GNUNET_SYSERR" on all other types of errors.
877  * This API is used by the authority of a zone.
878  *
879  * @param h handle to the namestore
880  * @param pkey private key of the zone
881  * @param name name that is being mapped (at most 255 characters long)
882  * @param rd record data
883  * @param cont continuation to call when done
884  * @param cont_cls closure for cont
885  * @return handle to abort the request
886  */
887 struct GNUNET_NAMESTORE_QueueEntry *
888 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
889                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
890                                 const char *name,
891                                 const struct GNUNET_NAMESTORE_RecordData *rd,
892                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
893                                 void *cont_cls)
894 {
895   struct GNUNET_NAMESTORE_QueueEntry *qe;
896   struct PendingMessage *pe;
897   struct GNUNET_NAMESTORE_RecordData * rd_tmp;
898   char * name_tmp;
899   size_t msg_size = 0;
900   size_t name_len = 0;
901   uint32_t id = 0;
902
903   GNUNET_assert (NULL != h);
904
905   id = get_op_id(h);
906   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
907   qe->nsh = h;
908   qe->cont = cont;
909   qe->cont_cls = cont_cls;
910   qe->op_id = id;
911
912   /* set msg_size*/
913   struct RecordRemoveMessage * msg;
914   msg_size = sizeof (struct RecordRemoveMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData);
915
916   /* create msg here */
917   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
918   pe->size = msg_size;
919   pe->is_init = GNUNET_NO;
920   msg = (struct RecordRemoveMessage *) &pe[1];
921
922   name_tmp = (char *) &msg[1];
923   rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len];
924
925   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
926   msg->header.size = htons (msg_size);
927   msg->op_id = htonl (id);
928   //msg->signature = *signature;
929   msg->name_len = htons (name_len);
930   memcpy (name_tmp, name, name_len);
931   memcpy (rd_tmp, rd, sizeof (struct GNUNET_NAMESTORE_RecordData));
932
933   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
934
935   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
936   do_transmit(h);
937   return qe;
938 }
939
940
941 /**
942  * Get a result for a particular key from the namestore.  The processor
943  * will only be called once.  
944  *
945  * @param h handle to the namestore
946  * @param zone zone to look up a record from
947  * @param name name to look up
948  * @param record_type desired record type, 0 for all
949  * @param proc function to call on the matching records, or with
950  *        NULL (rd_count == 0) if there are no matching records
951  * @param proc_cls closure for proc
952  * @return a handle that can be used to
953  *         cancel
954  */
955 struct GNUNET_NAMESTORE_QueueEntry *
956 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
957                               const GNUNET_HashCode *zone,
958                               const char *name,
959                               uint32_t record_type,
960                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
961 {
962   struct GNUNET_NAMESTORE_QueueEntry *qe;
963   struct PendingMessage *pe;
964   size_t msg_size = 0;
965   size_t name_len = 0;
966   uint32_t id = 0;
967
968   GNUNET_assert (NULL != h);
969   GNUNET_assert (NULL != zone);
970   GNUNET_assert (NULL != name);
971
972   name_len = strlen (name) + 1;
973   if ((name_len == 0) || (name_len > 256))
974   {
975     GNUNET_break (0);
976     return NULL;
977   }
978
979   id = get_op_id(h);
980   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
981   qe->nsh = h;
982   qe->proc = proc;
983   qe->proc_cls = proc_cls;
984   qe->op_id = id;
985   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
986
987   /* set msg_size*/
988   msg_size = sizeof (struct LookupNameMessage) + name_len;
989   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
990
991   /* create msg here */
992   struct LookupNameMessage * msg;
993   pe->size = msg_size;
994   pe->is_init = GNUNET_NO;
995   msg = (struct LookupNameMessage *) &pe[1];
996   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
997   msg->header.size = htons (msg_size);
998   msg->op_id = htonl (id);
999   msg->record_type = htonl (record_type);
1000   msg->zone = *zone;
1001   msg->name_len = htonl (name_len);
1002   memcpy (&msg[1], name, name_len);
1003
1004   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1005
1006   /* transmit message */
1007   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1008   do_transmit(h);
1009
1010   return qe;
1011 }
1012
1013
1014
1015 /**
1016  * Starts a new zone iteration (used to periodically PUT all of our
1017  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1018  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1019  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1020  * immediately, and then again after
1021  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1022  *
1023  * @param h handle to the namestore
1024  * @param zone zone to access, NULL for all zones
1025  * @param must_have_flags flags that must be set for the record to be returned
1026  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1027  * @param proc function to call on each name from the zone; it
1028  *        will be called repeatedly with a value (if available)
1029  *        and always once at the end with a name of NULL.
1030  * @param proc_cls closure for proc
1031  * @return an iterator handle to use for iteration
1032  */
1033 struct GNUNET_NAMESTORE_ZoneIterator *
1034 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1035                                        const GNUNET_HashCode *zone,
1036                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1037                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1038                                        GNUNET_NAMESTORE_RecordProcessor proc,
1039                                        void *proc_cls)
1040 {
1041   struct GNUNET_NAMESTORE_ZoneIterator *it;
1042   struct PendingMessage *pe;
1043   size_t msg_size = 0;
1044   uint32_t id = 0;
1045
1046   GNUNET_assert (NULL != h);
1047   GNUNET_assert (NULL != zone);
1048
1049   id = get_op_id(h);
1050   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1051   it->h = h;
1052   it->proc = proc;
1053   it->proc_cls = proc;
1054   it->op_id = id;
1055   it->zone = *zone;
1056   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1057
1058   /* set msg_size*/
1059   msg_size = sizeof (struct ZoneIterationStartMessage);
1060   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1061
1062   /* create msg here */
1063   struct ZoneIterationStartMessage * msg;
1064   pe->size = msg_size;
1065   pe->is_init = GNUNET_NO;
1066   msg = (struct ZoneIterationStartMessage *) &pe[1];
1067   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1068   msg->header.size = htons (msg_size);
1069   msg->op_id = htonl (id);
1070   msg->zone = *zone;
1071   msg->must_have_flags = ntohs (must_have_flags);
1072   msg->must_not_have_flags = ntohs (must_not_have_flags);
1073
1074   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1075
1076   /* transmit message */
1077   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1078   do_transmit(h);
1079
1080   return it;
1081 }
1082
1083
1084 /**
1085  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1086  * for the next record.
1087  *
1088  * @param it the iterator
1089  */
1090 void
1091 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1092 {
1093   struct GNUNET_NAMESTORE_Handle *h;
1094   struct PendingMessage *pe;
1095   size_t msg_size = 0;
1096
1097   GNUNET_assert (NULL != it);
1098   h = it->h;
1099
1100   /* set msg_size*/
1101   msg_size = sizeof (struct ZoneIterationNextMessage);
1102   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1103
1104   /* create msg here */
1105   struct ZoneIterationNextMessage * msg;
1106   pe->size = msg_size;
1107   pe->is_init = GNUNET_NO;
1108   msg = (struct ZoneIterationNextMessage *) &pe[1];
1109   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1110   msg->header.size = htons (msg_size);
1111   msg->op_id = htonl (it->op_id);
1112
1113   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1114
1115   /* transmit message */
1116   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1117   do_transmit(h);
1118 }
1119
1120
1121 /**
1122  * Stops iteration and releases the namestore handle for further calls.
1123  *
1124  * @param it the iterator
1125  */
1126 void
1127 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1128 {
1129   GNUNET_assert (NULL != it);
1130   struct PendingMessage *pe;
1131   size_t msg_size = 0;
1132   struct GNUNET_NAMESTORE_Handle *h = it->h;
1133
1134   /* set msg_size*/
1135   msg_size = sizeof (struct ZoneIterationNextMessage);
1136   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1137
1138   /* create msg here */
1139   struct LookupNameMessage * msg;
1140   pe->size = msg_size;
1141   pe->is_init = GNUNET_NO;
1142   msg = (struct LookupNameMessage *) &pe[1];
1143   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1144   msg->header.size = htons (msg_size);
1145   msg->op_id = htonl (it->op_id);
1146
1147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1148
1149   /* transmit message */
1150   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1151   do_transmit(h);
1152 }
1153
1154
1155 /**
1156  * Cancel a namestore operation.  The final callback from the
1157  * operation must not have been done yet.
1158  *
1159  * @param qe operation to cancel
1160  */
1161 void
1162 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1163 {
1164   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1165
1166   GNUNET_assert (qe != NULL);
1167
1168   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1169   GNUNET_free(qe);
1170
1171 }
1172
1173 /* end of namestore_api.c */