-fix
[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   if (ze->proc != NULL)
386   {
387     // FIXME
388     ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL);
389   }
390 }
391
392
393 static void
394 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
395                         const struct GNUNET_MessageHeader *msg,
396                         int type, size_t size)
397 {
398
399   /* handle different message type */
400   switch (type) {
401     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
402         if (size < sizeof (struct ZoneIterationResponseMessage))
403         {
404           GNUNET_break_op (0);
405           break;
406         }
407         handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size);
408       break;
409     default:
410       GNUNET_break_op (0);
411       break;
412   }
413 }
414
415 /**
416  * Type of a function to call when we receive a message
417  * from the service.
418  *
419  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
420  * @param msg message received, NULL on timeout or fatal error
421  */
422 static void
423 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
424 {
425   struct GNUNET_NAMESTORE_Handle *h = cls;
426   struct GenericMessage * gm;
427   struct GNUNET_NAMESTORE_QueueEntry *qe;
428   struct GNUNET_NAMESTORE_ZoneIterator *ze;
429   uint16_t size;
430   uint16_t type;
431   uint32_t op_id = UINT32_MAX;
432
433   if (NULL == msg)
434   {
435     force_reconnect (h);
436     return;
437   }
438
439   size = ntohs (msg->size);
440   type = ntohs (msg->type);
441
442   if (size < sizeof (struct GenericMessage))
443   {
444     GNUNET_break_op (0);
445     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
446                            GNUNET_TIME_UNIT_FOREVER_REL);
447     return;
448   }
449
450   gm = (struct GenericMessage *) msg;
451   op_id = ntohl (gm->op_id);
452
453   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, op_id);
454
455   /* Find matching operation */
456   if (op_id > h->op_id)
457   {
458     /* No matching pending operation found */
459     GNUNET_break_op (0);
460     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
461                            GNUNET_TIME_UNIT_FOREVER_REL);
462     return;
463   }
464
465   /* Is it a record related operation ? */
466   for (qe = h->op_head; qe != NULL; qe = qe->next)
467   {
468     if (qe->op_id == op_id)
469       break;
470   }
471   if (qe != NULL)
472   {
473     manage_record_operations (qe, msg, type, size);
474   }
475
476   /* Is it a zone iteration operation ? */
477   for (ze = h->z_head; ze != NULL; ze = ze->next)
478   {
479     if (ze->op_id == op_id)
480       break;
481   }
482   if (ze != NULL)
483   {
484     manage_zone_operations (ze, msg, type, size);
485   }
486
487   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
488                          GNUNET_TIME_UNIT_FOREVER_REL);
489
490   if (GNUNET_YES == h->reconnect)
491     force_reconnect (h);
492
493 }
494
495
496 /**
497  * Transmit messages from the message queue to the service
498  * (if there are any, and if we are not already trying).
499  *
500  * @param h handle to use
501  */
502 static void
503 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
504
505
506 /**
507  * We can now transmit a message to NAMESTORE. Do it.
508  *
509  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
510  * @param size number of bytes we can transmit
511  * @param buf where to copy the messages
512  * @return number of bytes copied into buf
513  */
514 static size_t
515 transmit_message_to_namestore (void *cls, size_t size, void *buf)
516 {
517   struct GNUNET_NAMESTORE_Handle *h = cls;
518   struct PendingMessage *p;
519   size_t ret;
520   char *cbuf;
521
522   h->th = NULL;
523   if ((size == 0) || (buf == NULL))
524   {
525     force_reconnect (h);
526     return 0;
527   }
528   ret = 0;
529   cbuf = buf;
530   while ((NULL != (p = h->pending_head)) && (p->size <= size))
531   {
532     memcpy (&cbuf[ret], &p[1], p->size);
533     ret += p->size;
534     size -= p->size;
535     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
536     if (GNUNET_YES == p->is_init)
537       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
538                              GNUNET_TIME_UNIT_FOREVER_REL);
539     GNUNET_free (p);
540   }
541   do_transmit (h);
542   return ret;
543 }
544
545
546 /**
547  * Transmit messages from the message queue to the service
548  * (if there are any, and if we are not already trying).
549  *
550  * @param h handle to use
551  */
552 static void
553 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
554 {
555   struct PendingMessage *p;
556
557   if (NULL != h->th)
558     return;
559   if (NULL == (p = h->pending_head))
560     return;
561   if (NULL == h->client)
562     return;                     /* currently reconnecting */
563
564   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
565                                            GNUNET_TIME_UNIT_FOREVER_REL,
566                                            GNUNET_NO, &transmit_message_to_namestore,
567                                            h);
568 }
569
570
571 /**
572  * Reconnect to namestore service.
573  *
574  * @param h the handle to the namestore service
575  */
576 static void
577 reconnect (struct GNUNET_NAMESTORE_Handle *h)
578 {
579   struct PendingMessage *p;
580   struct StartMessage *init;
581
582   GNUNET_assert (NULL == h->client);
583   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
584   GNUNET_assert (NULL != h->client);
585
586   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
587   {
588     p = GNUNET_malloc (sizeof (struct PendingMessage) +
589                        sizeof (struct StartMessage));
590     p->size = sizeof (struct StartMessage);
591     p->is_init = GNUNET_YES;
592     init = (struct StartMessage *) &p[1];
593     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
594     init->header.size = htons (sizeof (struct StartMessage));
595     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
596   }
597   do_transmit (h);
598 }
599
600 /**
601  * Re-establish the connection to the service.
602  *
603  * @param cls handle to use to re-connect.
604  * @param tc scheduler context
605  */
606 static void
607 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
608 {
609   struct GNUNET_NAMESTORE_Handle *h = cls;
610
611   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
612   reconnect (h);
613 }
614
615
616 /**
617  * Disconnect from service and then reconnect.
618  *
619  * @param h our handle
620  */
621 static void
622 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
623 {
624   h->reconnect = GNUNET_NO;
625   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
626   h->client = NULL;
627   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
628                                     &reconnect_task,
629                                     h);
630 }
631
632 static uint32_t
633 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
634 {
635   uint32_t op_id = h->op_id;
636   h->op_id ++;
637   return op_id;
638 }
639
640 /**
641  * Initialize the connection with the NAMESTORE service.
642  *
643  * @param cfg configuration to use
644  * @return handle to the GNS service, or NULL on error
645  */
646 struct GNUNET_NAMESTORE_Handle *
647 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
648 {
649   struct GNUNET_NAMESTORE_Handle *h;
650
651   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
652   h->cfg = cfg;
653   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
654   h->op_id = 0;
655   return h;
656 }
657
658
659 /**
660  * Disconnect from the namestore service (and free associated
661  * resources).
662  *
663  * @param h handle to the namestore
664  * @param drop set to GNUNET_YES to delete all data in namestore (!)
665  */
666 void
667 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
668 {
669   struct PendingMessage *p;
670   struct GNUNET_NAMESTORE_QueueEntry *q;
671   struct GNUNET_NAMESTORE_ZoneIterator *z;
672
673   GNUNET_assert (h != NULL);
674
675   while (NULL != (p = h->pending_head))
676   {
677     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
678     GNUNET_free (p);
679   }
680
681   while (NULL != (q = h->op_head))
682   {
683     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
684     GNUNET_free (q);
685   }
686
687   while (NULL != (z = h->z_head))
688   {
689     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
690     GNUNET_free (z);
691   }
692
693   if (NULL != h->client)
694   {
695     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
696     h->client = NULL;
697   }
698   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
699   {
700     GNUNET_SCHEDULER_cancel (h->reconnect_task);
701     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
702   }
703   GNUNET_free(h);
704   h = NULL;
705 }
706
707
708 /**
709  * Store an item in the namestore.  If the item is already present,
710  * the expiration time is updated to the max of the existing time and
711  * the new time.  This API is used when we cache signatures from other
712  * authorities.
713  *
714  * @param h handle to the namestore
715  * @param zone_key public key of the zone
716  * @param name name that is being mapped (at most 255 characters long)
717  * @param expire when does the corresponding block in the DHT expire (until
718  *               when should we never do a DHT lookup for the same name again)?
719  * @param rd_count number of entries in 'rd' array
720  * @param rd array of records with data to store
721  * @param signature signature for all the records in the zone under the given name
722  * @param cont continuation to call when done
723  * @param cont_cls closure for cont
724  * @return handle to abort the request
725  */
726 struct GNUNET_NAMESTORE_QueueEntry *
727 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
728                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
729                              const char *name,
730                              struct GNUNET_TIME_Absolute expire,
731                              unsigned int rd_count,
732                              const struct GNUNET_NAMESTORE_RecordData *rd,
733                              const struct GNUNET_CRYPTO_RsaSignature *signature,
734                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
735                              void *cont_cls)
736 {
737   struct GNUNET_NAMESTORE_QueueEntry *qe;
738   struct PendingMessage *pe;
739
740   /* pointer to elements */
741   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp;
742   struct GNUNET_NAMESTORE_RecordData *rd_tmp;
743   char * name_tmp;
744
745   size_t msg_size = 0;
746   size_t name_len = strlen(name) + 1;
747   uint32_t id = 0;
748
749   GNUNET_assert (NULL != h);
750   id = get_op_id(h);
751   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
752   qe->nsh = h;
753   qe->cont = cont;
754   qe->cont_cls = cont_cls;
755   qe->op_id = id;
756   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
757
758   /* set msg_size*/
759   struct RecordPutMessage * msg;
760   msg_size = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len  + rd_count * (sizeof (struct GNUNET_NAMESTORE_RecordData));
761
762   /* create msg here */
763   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
764   pe->size = msg_size;
765   pe->is_init = GNUNET_NO;
766   msg = (struct RecordPutMessage *) &pe[1];
767   zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
768   name_tmp = (char *) &zone_key_tmp[1];
769   rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len];
770
771   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
772   msg->header.size = htons (msg_size);
773   msg->op_id = htonl (id);
774   memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
775   msg->signature = *signature;
776   msg->name_len = htons (name_len);
777   memcpy (name_tmp, name, name_len);
778   msg->expire = GNUNET_TIME_absolute_hton (expire);
779   msg->rd_count = htonl(rd_count);
780   memcpy (rd_tmp, rd, rd_count * (sizeof (struct GNUNET_NAMESTORE_RecordData)));
781
782   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
783
784   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
785   do_transmit(h);
786
787   return qe;
788 }
789
790
791 /**
792  * Check if a signature is valid.  This API is used by the GNS Block
793  * to validate signatures received from the network.
794  *
795  * @param public_key public key of the zone
796  * @param name name that is being mapped (at most 255 characters long)
797  * @param rd_count number of entries in 'rd' array
798  * @param rd array of records with data to store
799  * @param signature signature for all the records in the zone under the given name
800  * @return GNUNET_OK if the signature is valid
801  */
802 int
803 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
804                                    const char *name,
805                                    unsigned int rd_count,
806                                    const struct GNUNET_NAMESTORE_RecordData *rd,
807                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
808 {
809   return GNUNET_SYSERR;
810 }
811
812 /**
813  * Store an item in the namestore.  If the item is already present,
814  * the expiration time is updated to the max of the existing time and
815  * the new time.  This API is used by the authority of a zone.
816  *
817  * @param h handle to the namestore
818  * @param pkey private key of the zone
819  * @param name name that is being mapped (at most 255 characters long)
820  * @param rd record data to store
821  * @param cont continuation to call when done
822  * @param cont_cls closure for cont
823  * @return handle to abort the request
824  */
825 struct GNUNET_NAMESTORE_QueueEntry *
826 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
827                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
828                                 const char *name,
829                                 const struct GNUNET_NAMESTORE_RecordData *rd,
830                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
831                                 void *cont_cls)
832 {
833   struct GNUNET_NAMESTORE_QueueEntry *qe;
834   struct PendingMessage *pe;
835   struct GNUNET_NAMESTORE_RecordData * rd_tmp;
836   char * name_tmp;
837   size_t msg_size = 0;
838   size_t name_len = 0;
839   uint32_t id = 0;
840
841   GNUNET_assert (NULL != h);
842
843   id = get_op_id(h);
844   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
845   qe->nsh = h;
846   qe->cont = cont;
847   qe->cont_cls = cont_cls;
848   qe->op_id = id;
849
850   /* set msg_size*/
851   struct RecordCreateMessage * msg;
852   msg_size = sizeof (struct RecordCreateMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData);
853
854   /* create msg here */
855   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
856   pe->size = msg_size;
857   pe->is_init = GNUNET_NO;
858   msg = (struct RecordCreateMessage *) &pe[1];
859
860   name_tmp = (char *) &msg[1];
861   rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len];
862
863   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
864   msg->header.size = htons (msg_size);
865   msg->op_id = htonl (id);
866   //msg->signature = *signature;
867   msg->name_len = htons (name_len);
868   memcpy (name_tmp, name, name_len);
869   memcpy (rd_tmp, rd, sizeof (struct GNUNET_NAMESTORE_RecordData));
870
871   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
872
873   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
874   do_transmit(h);
875   return qe;
876 }
877
878
879 /**
880  * Explicitly remove some content from the database.  The
881  * "cont"inuation will be called with status "GNUNET_OK" if content
882  * was removed, "GNUNET_NO" if no matching entry was found and
883  * "GNUNET_SYSERR" on all other types of errors.
884  * This API is used by the authority of a zone.
885  *
886  * @param h handle to the namestore
887  * @param pkey private key of the zone
888  * @param name name that is being mapped (at most 255 characters long)
889  * @param rd record data
890  * @param cont continuation to call when done
891  * @param cont_cls closure for cont
892  * @return handle to abort the request
893  */
894 struct GNUNET_NAMESTORE_QueueEntry *
895 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
896                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
897                                 const char *name,
898                                 const struct GNUNET_NAMESTORE_RecordData *rd,
899                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
900                                 void *cont_cls)
901 {
902   struct GNUNET_NAMESTORE_QueueEntry *qe;
903   struct PendingMessage *pe;
904   struct GNUNET_NAMESTORE_RecordData * rd_tmp;
905   char * name_tmp;
906   size_t msg_size = 0;
907   size_t name_len = 0;
908   uint32_t id = 0;
909
910   GNUNET_assert (NULL != h);
911
912   id = get_op_id(h);
913   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
914   qe->nsh = h;
915   qe->cont = cont;
916   qe->cont_cls = cont_cls;
917   qe->op_id = id;
918
919   /* set msg_size*/
920   struct RecordRemoveMessage * msg;
921   msg_size = sizeof (struct RecordRemoveMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData);
922
923   /* create msg here */
924   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
925   pe->size = msg_size;
926   pe->is_init = GNUNET_NO;
927   msg = (struct RecordRemoveMessage *) &pe[1];
928
929   name_tmp = (char *) &msg[1];
930   rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len];
931
932   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
933   msg->header.size = htons (msg_size);
934   msg->op_id = htonl (id);
935   //msg->signature = *signature;
936   msg->name_len = htons (name_len);
937   memcpy (name_tmp, name, name_len);
938   memcpy (rd_tmp, rd, sizeof (struct GNUNET_NAMESTORE_RecordData));
939
940   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
941
942   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
943   do_transmit(h);
944   return qe;
945 }
946
947
948 /**
949  * Get a result for a particular key from the namestore.  The processor
950  * will only be called once.  
951  *
952  * @param h handle to the namestore
953  * @param zone zone to look up a record from
954  * @param name name to look up
955  * @param record_type desired record type, 0 for all
956  * @param proc function to call on the matching records, or with
957  *        NULL (rd_count == 0) if there are no matching records
958  * @param proc_cls closure for proc
959  * @return a handle that can be used to
960  *         cancel
961  */
962 struct GNUNET_NAMESTORE_QueueEntry *
963 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
964                               const GNUNET_HashCode *zone,
965                               const char *name,
966                               uint32_t record_type,
967                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
968 {
969   struct GNUNET_NAMESTORE_QueueEntry *qe;
970   struct PendingMessage *pe;
971   size_t msg_size = 0;
972   size_t name_len = 0;
973   uint32_t id = 0;
974
975   GNUNET_assert (NULL != h);
976   GNUNET_assert (NULL != zone);
977   GNUNET_assert (NULL != name);
978
979   name_len = strlen (name) + 1;
980   if ((name_len == 0) || (name_len > 256))
981   {
982     GNUNET_break (0);
983     return NULL;
984   }
985
986   id = get_op_id(h);
987   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
988   qe->nsh = h;
989   qe->proc = proc;
990   qe->proc_cls = proc_cls;
991   qe->op_id = id;
992   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
993
994   /* set msg_size*/
995   msg_size = sizeof (struct LookupNameMessage) + name_len;
996   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
997
998   /* create msg here */
999   struct LookupNameMessage * msg;
1000   pe->size = msg_size;
1001   pe->is_init = GNUNET_NO;
1002   msg = (struct LookupNameMessage *) &pe[1];
1003   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1004   msg->header.size = htons (msg_size);
1005   msg->op_id = htonl (id);
1006   msg->record_type = htonl (record_type);
1007   msg->zone = *zone;
1008   msg->name_len = htonl (name_len);
1009   memcpy (&msg[1], name, name_len);
1010
1011   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1012
1013   /* transmit message */
1014   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1015   do_transmit(h);
1016
1017   return qe;
1018 }
1019
1020
1021
1022 /**
1023  * Starts a new zone iteration (used to periodically PUT all of our
1024  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1025  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1026  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1027  * immediately, and then again after
1028  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1029  *
1030  * @param h handle to the namestore
1031  * @param zone zone to access, NULL for all zones
1032  * @param must_have_flags flags that must be set for the record to be returned
1033  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1034  * @param proc function to call on each name from the zone; it
1035  *        will be called repeatedly with a value (if available)
1036  *        and always once at the end with a name of NULL.
1037  * @param proc_cls closure for proc
1038  * @return an iterator handle to use for iteration
1039  */
1040 struct GNUNET_NAMESTORE_ZoneIterator *
1041 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1042                                        const GNUNET_HashCode *zone,
1043                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1044                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1045                                        GNUNET_NAMESTORE_RecordProcessor proc,
1046                                        void *proc_cls)
1047 {
1048   struct GNUNET_NAMESTORE_ZoneIterator *it;
1049   struct PendingMessage *pe;
1050   size_t msg_size = 0;
1051   uint32_t id = 0;
1052
1053   GNUNET_assert (NULL != h);
1054   GNUNET_assert (NULL != zone);
1055
1056   id = get_op_id(h);
1057   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1058   it->h = h;
1059   it->proc = proc;
1060   it->proc_cls = proc;
1061   it->op_id = id;
1062   it->zone = *zone;
1063   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1064
1065   /* set msg_size*/
1066   msg_size = sizeof (struct ZoneIterationStartMessage);
1067   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1068
1069   /* create msg here */
1070   struct ZoneIterationStartMessage * msg;
1071   pe->size = msg_size;
1072   pe->is_init = GNUNET_NO;
1073   msg = (struct ZoneIterationStartMessage *) &pe[1];
1074   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1075   msg->header.size = htons (msg_size);
1076   msg->op_id = htonl (id);
1077   msg->zone = *zone;
1078   msg->must_have_flags = ntohs (must_have_flags);
1079   msg->must_not_have_flags = ntohs (must_not_have_flags);
1080
1081   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1082
1083   /* transmit message */
1084   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1085   do_transmit(h);
1086
1087   return it;
1088 }
1089
1090
1091 /**
1092  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1093  * for the next record.
1094  *
1095  * @param it the iterator
1096  */
1097 void
1098 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1099 {
1100   struct GNUNET_NAMESTORE_Handle *h;
1101   struct PendingMessage *pe;
1102   size_t msg_size = 0;
1103
1104   GNUNET_assert (NULL != it);
1105   h = it->h;
1106
1107   /* set msg_size*/
1108   msg_size = sizeof (struct ZoneIterationNextMessage);
1109   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1110
1111   /* create msg here */
1112   struct ZoneIterationNextMessage * msg;
1113   pe->size = msg_size;
1114   pe->is_init = GNUNET_NO;
1115   msg = (struct ZoneIterationNextMessage *) &pe[1];
1116   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1117   msg->header.size = htons (msg_size);
1118   msg->op_id = htonl (it->op_id);
1119
1120   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1121
1122   /* transmit message */
1123   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1124   do_transmit(h);
1125 }
1126
1127
1128 /**
1129  * Stops iteration and releases the namestore handle for further calls.
1130  *
1131  * @param it the iterator
1132  */
1133 void
1134 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1135 {
1136   GNUNET_assert (NULL != it);
1137   struct PendingMessage *pe;
1138   size_t msg_size = 0;
1139   struct GNUNET_NAMESTORE_Handle *h = it->h;
1140
1141   /* set msg_size*/
1142   msg_size = sizeof (struct ZoneIterationStopMessage);
1143   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1144
1145   /* create msg here */
1146   struct ZoneIterationStopMessage * msg;
1147   pe->size = msg_size;
1148   pe->is_init = GNUNET_NO;
1149   msg = (struct ZoneIterationStopMessage *) &pe[1];
1150   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1151   msg->header.size = htons (msg_size);
1152   msg->op_id = htonl (it->op_id);
1153
1154   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1155
1156   /* transmit message */
1157   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1158   do_transmit(h);
1159 }
1160
1161
1162 /**
1163  * Cancel a namestore operation.  The final callback from the
1164  * operation must not have been done yet.
1165  *
1166  * @param qe operation to cancel
1167  */
1168 void
1169 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1170 {
1171   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1172
1173   GNUNET_assert (qe != NULL);
1174
1175   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1176   GNUNET_free(qe);
1177
1178 }
1179
1180 /* end of namestore_api.c */