- using de/serialization functionality
[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   char * rd_tmp;
743   char * rd_ser;
744   char * name_tmp;
745
746   size_t msg_size = 0;
747   size_t name_len = strlen(name) + 1;
748   size_t rd_ser_len = 0;
749   uint32_t id = 0;
750
751   GNUNET_assert (NULL != h);
752   id = get_op_id(h);
753   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
754   qe->nsh = h;
755   qe->cont = cont;
756   qe->cont_cls = cont_cls;
757   qe->op_id = id;
758   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
759
760   /* set msg_size*/
761   rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, rd_count, rd);
762
763   struct RecordPutMessage * msg;
764   msg_size = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len  + rd_ser_len;
765
766   /* create msg here */
767   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
768   pe->size = msg_size;
769   pe->is_init = GNUNET_NO;
770   msg = (struct RecordPutMessage *) &pe[1];
771   zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
772   name_tmp = (char *) &zone_key_tmp[1];
773   rd_tmp = &name_tmp[name_len];
774
775   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
776   msg->header.size = htons (msg_size);
777   msg->op_id = htonl (id);
778   memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
779   msg->signature = *signature;
780   msg->name_len = htons (name_len);
781   memcpy (name_tmp, name, name_len);
782   msg->expire = GNUNET_TIME_absolute_hton (expire);
783   msg->rd_len = htons (rd_ser_len);
784
785   memcpy (rd_tmp, rd_ser, rd_ser_len);
786   GNUNET_free (rd_ser);
787
788   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
789
790   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
791   do_transmit(h);
792
793   return qe;
794 }
795
796
797 /**
798  * Check if a signature is valid.  This API is used by the GNS Block
799  * to validate signatures received from the network.
800  *
801  * @param public_key public key of the zone
802  * @param name name that is being mapped (at most 255 characters long)
803  * @param rd_count number of entries in 'rd' array
804  * @param rd array of records with data to store
805  * @param signature signature for all the records in the zone under the given name
806  * @return GNUNET_OK if the signature is valid
807  */
808 int
809 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
810                                    const char *name,
811                                    unsigned int rd_count,
812                                    const struct GNUNET_NAMESTORE_RecordData *rd,
813                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
814 {
815   return GNUNET_SYSERR;
816 }
817
818 /**
819  * Store an item in the namestore.  If the item is already present,
820  * the expiration time is updated to the max of the existing time and
821  * the new time.  This API is used by the authority of a zone.
822  *
823  * @param h handle to the namestore
824  * @param pkey private key of the zone
825  * @param name name that is being mapped (at most 255 characters long)
826  * @param rd record data to store
827  * @param cont continuation to call when done
828  * @param cont_cls closure for cont
829  * @return handle to abort the request
830  */
831 struct GNUNET_NAMESTORE_QueueEntry *
832 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
833                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
834                                 const char *name,
835                                 const struct GNUNET_NAMESTORE_RecordData *rd,
836                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
837                                 void *cont_cls)
838 {
839   struct GNUNET_NAMESTORE_QueueEntry *qe;
840   struct PendingMessage *pe;
841   char * name_tmp;
842   char * rd_tmp;
843   char * rd_ser;
844   size_t rd_ser_len = 0;
845   size_t msg_size = 0;
846   size_t name_len = 0;
847   uint32_t id = 0;
848
849   GNUNET_assert (NULL != h);
850
851   id = get_op_id(h);
852   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
853   qe->nsh = h;
854   qe->cont = cont;
855   qe->cont_cls = cont_cls;
856   qe->op_id = id;
857
858   /* set msg_size*/
859   rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd);
860   struct RecordCreateMessage * msg;
861   msg_size = sizeof (struct RecordCreateMessage) + name_len + rd_ser_len;
862
863   /* create msg here */
864   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
865   pe->size = msg_size;
866   pe->is_init = GNUNET_NO;
867   msg = (struct RecordCreateMessage *) &pe[1];
868
869   name_tmp = (char *) &msg[1];
870   rd_tmp = &name_tmp[name_len];
871
872   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
873   msg->header.size = htons (msg_size);
874   msg->op_id = htonl (id);
875   //msg->signature = *signature;
876   msg->name_len = htons (name_len);
877   memcpy (name_tmp, name, name_len);
878   memcpy (rd_tmp, rd_ser, rd_ser_len);
879   GNUNET_free (rd_ser);
880
881   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
882
883   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
884   do_transmit(h);
885   return qe;
886 }
887
888
889 /**
890  * Explicitly remove some content from the database.  The
891  * "cont"inuation will be called with status "GNUNET_OK" if content
892  * was removed, "GNUNET_NO" if no matching entry was found and
893  * "GNUNET_SYSERR" on all other types of errors.
894  * This API is used by the authority of a zone.
895  *
896  * @param h handle to the namestore
897  * @param pkey private key of the zone
898  * @param name name that is being mapped (at most 255 characters long)
899  * @param rd record data
900  * @param cont continuation to call when done
901  * @param cont_cls closure for cont
902  * @return handle to abort the request
903  */
904 struct GNUNET_NAMESTORE_QueueEntry *
905 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
906                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
907                                 const char *name,
908                                 const struct GNUNET_NAMESTORE_RecordData *rd,
909                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
910                                 void *cont_cls)
911 {
912   struct GNUNET_NAMESTORE_QueueEntry *qe;
913   struct PendingMessage *pe;
914   char * rd_tmp;
915   char * rd_ser;
916   char * name_tmp;
917   size_t rd_ser_len = 0;
918   size_t msg_size = 0;
919   size_t name_len = 0;
920   uint32_t id = 0;
921
922   GNUNET_assert (NULL != h);
923
924   id = get_op_id(h);
925   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
926   qe->nsh = h;
927   qe->cont = cont;
928   qe->cont_cls = cont_cls;
929   qe->op_id = id;
930
931   /* set msg_size*/
932   rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd);
933   struct RecordRemoveMessage * msg;
934   msg_size = sizeof (struct RecordRemoveMessage) + name_len + rd_ser_len;
935
936   /* create msg here */
937   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
938   pe->size = msg_size;
939   pe->is_init = GNUNET_NO;
940   msg = (struct RecordRemoveMessage *) &pe[1];
941
942   name_tmp = (char *) &msg[1];
943   rd_tmp = &name_tmp[name_len];
944
945   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
946   msg->header.size = htons (msg_size);
947   msg->op_id = htonl (id);
948   //msg->signature = *signature;
949   msg->name_len = htons (name_len);
950   memcpy (name_tmp, name, name_len);
951   memcpy (rd_tmp, rd_ser, rd_ser_len);
952   GNUNET_free (rd_ser);
953
954   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
955
956   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
957   do_transmit(h);
958   return qe;
959 }
960
961
962 /**
963  * Get a result for a particular key from the namestore.  The processor
964  * will only be called once.  
965  *
966  * @param h handle to the namestore
967  * @param zone zone to look up a record from
968  * @param name name to look up
969  * @param record_type desired record type, 0 for all
970  * @param proc function to call on the matching records, or with
971  *        NULL (rd_count == 0) if there are no matching records
972  * @param proc_cls closure for proc
973  * @return a handle that can be used to
974  *         cancel
975  */
976 struct GNUNET_NAMESTORE_QueueEntry *
977 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
978                               const GNUNET_HashCode *zone,
979                               const char *name,
980                               uint32_t record_type,
981                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
982 {
983   struct GNUNET_NAMESTORE_QueueEntry *qe;
984   struct PendingMessage *pe;
985   size_t msg_size = 0;
986   size_t name_len = 0;
987   uint32_t id = 0;
988
989   GNUNET_assert (NULL != h);
990   GNUNET_assert (NULL != zone);
991   GNUNET_assert (NULL != name);
992
993   name_len = strlen (name) + 1;
994   if ((name_len == 0) || (name_len > 256))
995   {
996     GNUNET_break (0);
997     return NULL;
998   }
999
1000   id = get_op_id(h);
1001   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1002   qe->nsh = h;
1003   qe->proc = proc;
1004   qe->proc_cls = proc_cls;
1005   qe->op_id = id;
1006   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1007
1008   /* set msg_size*/
1009   msg_size = sizeof (struct LookupNameMessage) + name_len;
1010   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1011
1012   /* create msg here */
1013   struct LookupNameMessage * msg;
1014   pe->size = msg_size;
1015   pe->is_init = GNUNET_NO;
1016   msg = (struct LookupNameMessage *) &pe[1];
1017   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1018   msg->header.size = htons (msg_size);
1019   msg->op_id = htonl (id);
1020   msg->record_type = htonl (record_type);
1021   msg->zone = *zone;
1022   msg->name_len = htonl (name_len);
1023   memcpy (&msg[1], name, name_len);
1024
1025   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1026
1027   /* transmit message */
1028   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1029   do_transmit(h);
1030
1031   return qe;
1032 }
1033
1034
1035
1036 /**
1037  * Starts a new zone iteration (used to periodically PUT all of our
1038  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1039  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1040  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1041  * immediately, and then again after
1042  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1043  *
1044  * @param h handle to the namestore
1045  * @param zone zone to access, NULL for all zones
1046  * @param must_have_flags flags that must be set for the record to be returned
1047  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1048  * @param proc function to call on each name from the zone; it
1049  *        will be called repeatedly with a value (if available)
1050  *        and always once at the end with a name of NULL.
1051  * @param proc_cls closure for proc
1052  * @return an iterator handle to use for iteration
1053  */
1054 struct GNUNET_NAMESTORE_ZoneIterator *
1055 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1056                                        const GNUNET_HashCode *zone,
1057                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1058                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1059                                        GNUNET_NAMESTORE_RecordProcessor proc,
1060                                        void *proc_cls)
1061 {
1062   struct GNUNET_NAMESTORE_ZoneIterator *it;
1063   struct PendingMessage *pe;
1064   size_t msg_size = 0;
1065   uint32_t id = 0;
1066
1067   GNUNET_assert (NULL != h);
1068   GNUNET_assert (NULL != zone);
1069
1070   id = get_op_id(h);
1071   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1072   it->h = h;
1073   it->proc = proc;
1074   it->proc_cls = proc;
1075   it->op_id = id;
1076   it->zone = *zone;
1077   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1078
1079   /* set msg_size*/
1080   msg_size = sizeof (struct ZoneIterationStartMessage);
1081   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1082
1083   /* create msg here */
1084   struct ZoneIterationStartMessage * msg;
1085   pe->size = msg_size;
1086   pe->is_init = GNUNET_NO;
1087   msg = (struct ZoneIterationStartMessage *) &pe[1];
1088   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1089   msg->header.size = htons (msg_size);
1090   msg->op_id = htonl (id);
1091   msg->zone = *zone;
1092   msg->must_have_flags = ntohs (must_have_flags);
1093   msg->must_not_have_flags = ntohs (must_not_have_flags);
1094
1095   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1096
1097   /* transmit message */
1098   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1099   do_transmit(h);
1100
1101   return it;
1102 }
1103
1104
1105 /**
1106  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1107  * for the next record.
1108  *
1109  * @param it the iterator
1110  */
1111 void
1112 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1113 {
1114   struct GNUNET_NAMESTORE_Handle *h;
1115   struct PendingMessage *pe;
1116   size_t msg_size = 0;
1117
1118   GNUNET_assert (NULL != it);
1119   h = it->h;
1120
1121   /* set msg_size*/
1122   msg_size = sizeof (struct ZoneIterationNextMessage);
1123   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1124
1125   /* create msg here */
1126   struct ZoneIterationNextMessage * msg;
1127   pe->size = msg_size;
1128   pe->is_init = GNUNET_NO;
1129   msg = (struct ZoneIterationNextMessage *) &pe[1];
1130   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1131   msg->header.size = htons (msg_size);
1132   msg->op_id = htonl (it->op_id);
1133
1134   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1135
1136   /* transmit message */
1137   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1138   do_transmit(h);
1139 }
1140
1141
1142 /**
1143  * Stops iteration and releases the namestore handle for further calls.
1144  *
1145  * @param it the iterator
1146  */
1147 void
1148 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1149 {
1150   GNUNET_assert (NULL != it);
1151   struct PendingMessage *pe;
1152   size_t msg_size = 0;
1153   struct GNUNET_NAMESTORE_Handle *h = it->h;
1154
1155   /* set msg_size*/
1156   msg_size = sizeof (struct ZoneIterationStopMessage);
1157   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1158
1159   /* create msg here */
1160   struct ZoneIterationStopMessage * msg;
1161   pe->size = msg_size;
1162   pe->is_init = GNUNET_NO;
1163   msg = (struct ZoneIterationStopMessage *) &pe[1];
1164   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1165   msg->header.size = htons (msg_size);
1166   msg->op_id = htonl (it->op_id);
1167
1168   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1169
1170   /* transmit message */
1171   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1172   do_transmit(h);
1173 }
1174
1175
1176 /**
1177  * Cancel a namestore operation.  The final callback from the
1178  * operation must not have been done yet.
1179  *
1180  * @param qe operation to cancel
1181  */
1182 void
1183 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1184 {
1185   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1186
1187   GNUNET_assert (qe != NULL);
1188
1189   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1190   GNUNET_free(qe);
1191
1192 }
1193
1194 /* end of namestore_api.c */