- more changes
[oweals/gnunet.git] / src / namestore / namestore_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file namestore/namestore_api.c
23  * @brief API to access the NAMESTORE service
24  * @author Martin Schanzenbach
25  * @author Matthias Wachs
26  */
27
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_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   char * rd_tmp;
204   struct GNUNET_NAMESTORE_RecordData *rd = NULL;
205   struct GNUNET_CRYPTO_RsaSignature *signature = NULL;
206   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy;
207   struct GNUNET_TIME_Absolute expire;
208   size_t msg_len = 0;
209   size_t name_len = 0;
210   size_t rd_len = 0;
211   int contains_sig = GNUNET_NO;
212   int rd_count = 0;
213
214   rd_len = ntohs (msg->rd_len);
215   msg_len = ntohs (msg->header.size);
216   name_len = ntohs (msg->name_len);
217   contains_sig = ntohs (msg->contains_sig);
218   expire = GNUNET_TIME_absolute_ntoh(msg->expire);
219
220   if (msg_len != sizeof (struct LookupNameResponseMessage) +
221       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
222       name_len +
223       rd_len +
224       contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature))
225   {
226     GNUNET_break_op (0);
227     return;
228   }
229
230   zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
231   name = (char *) &zone_key[1];
232   rd_tmp = &name[name_len];
233   rd_count = GNUNET_NAMESTORE_records_deserialize(&rd, rd_tmp, rd_len);
234
235   /* reset values if values not contained */
236   if (contains_sig == GNUNET_NO)
237     signature = NULL;
238   else
239     signature = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[rd_len];
240   if (rd_count == 0)
241     rd = NULL;
242   if (name_len == 0)
243     name = NULL;
244
245   memset (&dummy, '0', sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
246   if (0 == memcmp (zone_key, &dummy, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
247       zone_key = NULL;
248
249   if (qe->proc != NULL)
250   {
251     qe->proc (qe->proc_cls, zone_key, expire, name, rd_count, rd, signature);
252   }
253
254   GNUNET_NAMESTORE_records_free(rd_count, rd);
255
256   /* Operation done, remove */
257   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
258   GNUNET_free (qe);
259 }
260
261
262 static void
263 handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
264                              struct RecordPutResponseMessage* msg,
265                              size_t size)
266 {
267   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
268               "RECORD_PUT_RESPONSE");
269
270   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
271   int res = GNUNET_OK;
272
273   if (ntohs (msg->op_result) == GNUNET_OK)
274   {
275     res = GNUNET_OK;
276     if (qe->cont != NULL)
277     {
278       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
279     }
280
281   }
282   else if (ntohs (msg->op_result) == GNUNET_NO)
283   {
284     res = GNUNET_SYSERR;
285     if (qe->cont != NULL)
286     {
287       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
288     }
289   }
290   else
291   {
292     GNUNET_break_op (0);
293     return;
294   }
295
296   /* Operation done, remove */
297   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
298
299   GNUNET_free (qe);
300 }
301
302
303 static void
304 handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
305                              struct RecordCreateResponseMessage* msg,
306                              size_t size)
307 {
308   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
309               "RECORD_CREATE_RESPONSE");
310
311   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
312   int res = GNUNET_OK;
313
314   if (ntohs (msg->op_result) == GNUNET_OK)
315   {
316     res = GNUNET_OK;
317     if (qe->cont != NULL)
318     {
319       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
320     }
321
322   }
323   else if (ntohs (msg->op_result) == GNUNET_NO)
324   {
325     res = GNUNET_SYSERR;
326     if (qe->cont != NULL)
327     {
328       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
329     }
330   }
331   else
332   {
333     GNUNET_break_op (0);
334     return;
335   }
336
337   /* Operation done, remove */
338   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
339
340   GNUNET_free (qe);
341 }
342
343
344 static void
345 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
346                           const struct GNUNET_MessageHeader *msg,
347                           int type, size_t size)
348 {
349
350   /* handle different message type */
351   switch (type) {
352     case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
353         if (size < sizeof (struct LookupNameResponseMessage))
354         {
355           GNUNET_break_op (0);
356           break;
357         }
358         handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size);
359       break;
360     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
361         if (size != sizeof (struct RecordPutResponseMessage))
362         {
363           GNUNET_break_op (0);
364           break;
365         }
366         handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size);
367       break;
368     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE:
369         if (size != sizeof (struct RecordCreateResponseMessage))
370         {
371           GNUNET_break_op (0);
372           break;
373         }
374         handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size);
375       break;
376     default:
377       GNUNET_break_op (0);
378       break;
379   }
380 }
381
382 static void
383 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
384                                 struct ZoneIterationResponseMessage *msg,
385                                 size_t size)
386 {
387   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
388               "ZONE_ITERATION_RESPONSE");
389
390
391   if (ze->proc != NULL)
392   {
393     // FIXME
394     ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL);
395   }
396 }
397
398
399 static void
400 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
401                         const struct GNUNET_MessageHeader *msg,
402                         int type, size_t size)
403 {
404
405   /* handle different message type */
406   switch (type) {
407     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
408         if (size < sizeof (struct ZoneIterationResponseMessage))
409         {
410           GNUNET_break_op (0);
411           break;
412         }
413         handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size);
414       break;
415     default:
416       GNUNET_break_op (0);
417       break;
418   }
419 }
420
421 /**
422  * Type of a function to call when we receive a message
423  * from the service.
424  *
425  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
426  * @param msg message received, NULL on timeout or fatal error
427  */
428 static void
429 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
430 {
431   struct GNUNET_NAMESTORE_Handle *h = cls;
432   struct GenericMessage * gm;
433   struct GNUNET_NAMESTORE_QueueEntry *qe;
434   struct GNUNET_NAMESTORE_ZoneIterator *ze;
435   uint16_t size;
436   uint16_t type;
437   uint32_t op_id = UINT32_MAX;
438
439   if (NULL == msg)
440   {
441     force_reconnect (h);
442     return;
443   }
444
445   size = ntohs (msg->size);
446   type = ntohs (msg->type);
447
448   if (size < sizeof (struct GenericMessage))
449   {
450     GNUNET_break_op (0);
451     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
452                            GNUNET_TIME_UNIT_FOREVER_REL);
453     return;
454   }
455
456   gm = (struct GenericMessage *) msg;
457   op_id = ntohl (gm->op_id);
458
459   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, op_id);
460
461   /* Find matching operation */
462   if (op_id > h->op_id)
463   {
464     /* No matching pending operation found */
465     GNUNET_break_op (0);
466     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
467                            GNUNET_TIME_UNIT_FOREVER_REL);
468     return;
469   }
470
471   /* Is it a record related operation ? */
472   for (qe = h->op_head; qe != NULL; qe = qe->next)
473   {
474     if (qe->op_id == op_id)
475       break;
476   }
477   if (qe != NULL)
478   {
479     manage_record_operations (qe, msg, type, size);
480   }
481
482   /* Is it a zone iteration operation ? */
483   for (ze = h->z_head; ze != NULL; ze = ze->next)
484   {
485     if (ze->op_id == op_id)
486       break;
487   }
488   if (ze != NULL)
489   {
490     manage_zone_operations (ze, msg, type, size);
491   }
492
493   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
494                          GNUNET_TIME_UNIT_FOREVER_REL);
495
496   if (GNUNET_YES == h->reconnect)
497     force_reconnect (h);
498
499 }
500
501
502 /**
503  * Transmit messages from the message queue to the service
504  * (if there are any, and if we are not already trying).
505  *
506  * @param h handle to use
507  */
508 static void
509 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
510
511
512 /**
513  * We can now transmit a message to NAMESTORE. Do it.
514  *
515  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
516  * @param size number of bytes we can transmit
517  * @param buf where to copy the messages
518  * @return number of bytes copied into buf
519  */
520 static size_t
521 transmit_message_to_namestore (void *cls, size_t size, void *buf)
522 {
523   struct GNUNET_NAMESTORE_Handle *h = cls;
524   struct PendingMessage *p;
525   size_t ret;
526   char *cbuf;
527
528   h->th = NULL;
529   if ((size == 0) || (buf == NULL))
530   {
531     force_reconnect (h);
532     return 0;
533   }
534   ret = 0;
535   cbuf = buf;
536   while ((NULL != (p = h->pending_head)) && (p->size <= size))
537   {
538     memcpy (&cbuf[ret], &p[1], p->size);
539     ret += p->size;
540     size -= p->size;
541     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
542     if (GNUNET_YES == p->is_init)
543       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
544                              GNUNET_TIME_UNIT_FOREVER_REL);
545     GNUNET_free (p);
546   }
547   do_transmit (h);
548   return ret;
549 }
550
551
552 /**
553  * Transmit messages from the message queue to the service
554  * (if there are any, and if we are not already trying).
555  *
556  * @param h handle to use
557  */
558 static void
559 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
560 {
561   struct PendingMessage *p;
562
563   if (NULL != h->th)
564     return;
565   if (NULL == (p = h->pending_head))
566     return;
567   if (NULL == h->client)
568     return;                     /* currently reconnecting */
569
570   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
571                                            GNUNET_TIME_UNIT_FOREVER_REL,
572                                            GNUNET_NO, &transmit_message_to_namestore,
573                                            h);
574 }
575
576
577 /**
578  * Reconnect to namestore service.
579  *
580  * @param h the handle to the namestore service
581  */
582 static void
583 reconnect (struct GNUNET_NAMESTORE_Handle *h)
584 {
585   struct PendingMessage *p;
586   struct StartMessage *init;
587
588   GNUNET_assert (NULL == h->client);
589   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
590   GNUNET_assert (NULL != h->client);
591
592   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
593   {
594     p = GNUNET_malloc (sizeof (struct PendingMessage) +
595                        sizeof (struct StartMessage));
596     p->size = sizeof (struct StartMessage);
597     p->is_init = GNUNET_YES;
598     init = (struct StartMessage *) &p[1];
599     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
600     init->header.size = htons (sizeof (struct StartMessage));
601     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
602   }
603   do_transmit (h);
604 }
605
606 /**
607  * Re-establish the connection to the service.
608  *
609  * @param cls handle to use to re-connect.
610  * @param tc scheduler context
611  */
612 static void
613 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
614 {
615   struct GNUNET_NAMESTORE_Handle *h = cls;
616
617   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
618   reconnect (h);
619 }
620
621
622 /**
623  * Disconnect from service and then reconnect.
624  *
625  * @param h our handle
626  */
627 static void
628 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
629 {
630   h->reconnect = GNUNET_NO;
631   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
632   h->client = NULL;
633   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
634                                     &reconnect_task,
635                                     h);
636 }
637
638 static uint32_t
639 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
640 {
641   uint32_t op_id = h->op_id;
642   h->op_id ++;
643   return op_id;
644 }
645
646 /**
647  * Initialize the connection with the NAMESTORE service.
648  *
649  * @param cfg configuration to use
650  * @return handle to the GNS service, or NULL on error
651  */
652 struct GNUNET_NAMESTORE_Handle *
653 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
654 {
655   struct GNUNET_NAMESTORE_Handle *h;
656
657   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
658   h->cfg = cfg;
659   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
660   h->op_id = 0;
661   return h;
662 }
663
664
665 /**
666  * Disconnect from the namestore service (and free associated
667  * resources).
668  *
669  * @param h handle to the namestore
670  * @param drop set to GNUNET_YES to delete all data in namestore (!)
671  */
672 void
673 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
674 {
675   struct PendingMessage *p;
676   struct GNUNET_NAMESTORE_QueueEntry *q;
677   struct GNUNET_NAMESTORE_ZoneIterator *z;
678
679   GNUNET_assert (h != NULL);
680
681   while (NULL != (p = h->pending_head))
682   {
683     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
684     GNUNET_free (p);
685   }
686
687   while (NULL != (q = h->op_head))
688   {
689     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
690     GNUNET_free (q);
691   }
692
693   while (NULL != (z = h->z_head))
694   {
695     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
696     GNUNET_free (z);
697   }
698
699   if (NULL != h->client)
700   {
701     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
702     h->client = NULL;
703   }
704   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
705   {
706     GNUNET_SCHEDULER_cancel (h->reconnect_task);
707     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
708   }
709   GNUNET_free(h);
710   h = NULL;
711 }
712
713
714 /**
715  * Store an item in the namestore.  If the item is already present,
716  * the expiration time is updated to the max of the existing time and
717  * the new time.  This API is used when we cache signatures from other
718  * authorities.
719  *
720  * @param h handle to the namestore
721  * @param zone_key public key of the zone
722  * @param name name that is being mapped (at most 255 characters long)
723  * @param expire when does the corresponding block in the DHT expire (until
724  *               when should we never do a DHT lookup for the same name again)?
725  * @param rd_count number of entries in 'rd' array
726  * @param rd array of records with data to store
727  * @param signature signature for all the records in the zone under the given name
728  * @param cont continuation to call when done
729  * @param cont_cls closure for cont
730  * @return handle to abort the request
731  */
732 struct GNUNET_NAMESTORE_QueueEntry *
733 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
734                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
735                              const char *name,
736                              struct GNUNET_TIME_Absolute expire,
737                              unsigned int rd_count,
738                              const struct GNUNET_NAMESTORE_RecordData *rd,
739                              const struct GNUNET_CRYPTO_RsaSignature *signature,
740                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
741                              void *cont_cls)
742 {
743   struct GNUNET_NAMESTORE_QueueEntry *qe;
744   struct PendingMessage *pe;
745
746   /* pointer to elements */
747   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp;
748   char * rd_tmp;
749   char * rd_ser;
750   char * name_tmp;
751
752   size_t msg_size = 0;
753   size_t name_len = strlen(name) + 1;
754   size_t rd_ser_len = 0;
755   uint32_t id = 0;
756
757   GNUNET_assert (NULL != h);
758   id = get_op_id(h);
759   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
760   qe->nsh = h;
761   qe->cont = cont;
762   qe->cont_cls = cont_cls;
763   qe->op_id = id;
764   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
765
766   /* set msg_size*/
767   rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, rd_count, rd);
768
769   struct RecordPutMessage * msg;
770   msg_size = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len  + rd_ser_len;
771
772   /* create msg here */
773   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
774   pe->size = msg_size;
775   pe->is_init = GNUNET_NO;
776   msg = (struct RecordPutMessage *) &pe[1];
777   zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
778   name_tmp = (char *) &zone_key_tmp[1];
779   rd_tmp = &name_tmp[name_len];
780
781   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
782   msg->header.size = htons (msg_size);
783   msg->op_id = htonl (id);
784   memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
785   msg->signature = *signature;
786   msg->name_len = htons (name_len);
787   memcpy (name_tmp, name, name_len);
788   msg->expire = GNUNET_TIME_absolute_hton (expire);
789   msg->rd_len = htons (rd_ser_len);
790
791   memcpy (rd_tmp, rd_ser, rd_ser_len);
792   GNUNET_free (rd_ser);
793
794   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
795
796   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
797   do_transmit(h);
798
799   return qe;
800 }
801
802
803 /**
804  * Check if a signature is valid.  This API is used by the GNS Block
805  * to validate signatures received from the network.
806  *
807  * @param public_key public key of the zone
808  * @param name name that is being mapped (at most 255 characters long)
809  * @param rd_count number of entries in 'rd' array
810  * @param rd array of records with data to store
811  * @param signature signature for all the records in the zone under the given name
812  * @return GNUNET_OK if the signature is valid
813  */
814 int
815 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
816                                    const char *name,
817                                    unsigned int rd_count,
818                                    const struct GNUNET_NAMESTORE_RecordData *rd,
819                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
820 {
821   return GNUNET_SYSERR;
822 }
823
824 /**
825  * Store an item in the namestore.  If the item is already present,
826  * the expiration time is updated to the max of the existing time and
827  * the new time.  This API is used by the authority of a zone.
828  *
829  * @param h handle to the namestore
830  * @param pkey private key of the zone
831  * @param name name that is being mapped (at most 255 characters long)
832  * @param rd record data to store
833  * @param cont continuation to call when done
834  * @param cont_cls closure for cont
835  * @return handle to abort the request
836  */
837 struct GNUNET_NAMESTORE_QueueEntry *
838 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
839                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
840                                 const char *name,
841                                 const struct GNUNET_NAMESTORE_RecordData *rd,
842                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
843                                 void *cont_cls)
844 {
845   struct GNUNET_NAMESTORE_QueueEntry *qe;
846   struct PendingMessage *pe;
847   char * name_tmp;
848   char * rd_tmp;
849   char * rd_ser;
850   size_t rd_ser_len = 0;
851   size_t msg_size = 0;
852   size_t name_len = 0;
853   uint32_t id = 0;
854
855   GNUNET_assert (NULL != h);
856
857   id = get_op_id(h);
858   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
859   qe->nsh = h;
860   qe->cont = cont;
861   qe->cont_cls = cont_cls;
862   qe->op_id = id;
863
864   /* set msg_size*/
865   rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd);
866   struct RecordCreateMessage * msg;
867   msg_size = sizeof (struct RecordCreateMessage) + name_len + rd_ser_len;
868
869   /* create msg here */
870   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
871   pe->size = msg_size;
872   pe->is_init = GNUNET_NO;
873   msg = (struct RecordCreateMessage *) &pe[1];
874
875   name_tmp = (char *) &msg[1];
876   rd_tmp = &name_tmp[name_len];
877
878   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
879   msg->header.size = htons (msg_size);
880   msg->op_id = htonl (id);
881   //msg->signature = *signature;
882   msg->name_len = htons (name_len);
883   memcpy (name_tmp, name, name_len);
884   memcpy (rd_tmp, rd_ser, rd_ser_len);
885   GNUNET_free (rd_ser);
886
887   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
888
889   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
890   do_transmit(h);
891   return qe;
892 }
893
894
895 /**
896  * Explicitly remove some content from the database.  The
897  * "cont"inuation will be called with status "GNUNET_OK" if content
898  * was removed, "GNUNET_NO" if no matching entry was found and
899  * "GNUNET_SYSERR" on all other types of errors.
900  * This API is used by the authority of a zone.
901  *
902  * @param h handle to the namestore
903  * @param pkey private key of the zone
904  * @param name name that is being mapped (at most 255 characters long)
905  * @param rd record data
906  * @param cont continuation to call when done
907  * @param cont_cls closure for cont
908  * @return handle to abort the request
909  */
910 struct GNUNET_NAMESTORE_QueueEntry *
911 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
912                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
913                                 const char *name,
914                                 const struct GNUNET_NAMESTORE_RecordData *rd,
915                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
916                                 void *cont_cls)
917 {
918   struct GNUNET_NAMESTORE_QueueEntry *qe;
919   struct PendingMessage *pe;
920   char * rd_tmp;
921   char * rd_ser;
922   char * name_tmp;
923   size_t rd_ser_len = 0;
924   size_t msg_size = 0;
925   size_t name_len = 0;
926   uint32_t id = 0;
927
928   GNUNET_assert (NULL != h);
929
930   id = get_op_id(h);
931   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
932   qe->nsh = h;
933   qe->cont = cont;
934   qe->cont_cls = cont_cls;
935   qe->op_id = id;
936
937   /* set msg_size*/
938   rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd);
939   struct RecordRemoveMessage * msg;
940   msg_size = sizeof (struct RecordRemoveMessage) + name_len + rd_ser_len;
941
942   /* create msg here */
943   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
944   pe->size = msg_size;
945   pe->is_init = GNUNET_NO;
946   msg = (struct RecordRemoveMessage *) &pe[1];
947
948   name_tmp = (char *) &msg[1];
949   rd_tmp = &name_tmp[name_len];
950
951   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
952   msg->header.size = htons (msg_size);
953   msg->op_id = htonl (id);
954   //msg->signature = *signature;
955   msg->name_len = htons (name_len);
956   memcpy (name_tmp, name, name_len);
957   memcpy (rd_tmp, rd_ser, rd_ser_len);
958   GNUNET_free (rd_ser);
959
960   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
961
962   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
963   do_transmit(h);
964   return qe;
965 }
966
967
968 /**
969  * Get a result for a particular key from the namestore.  The processor
970  * will only be called once.  
971  *
972  * @param h handle to the namestore
973  * @param zone zone to look up a record from
974  * @param name name to look up
975  * @param record_type desired record type, 0 for all
976  * @param proc function to call on the matching records, or with
977  *        NULL (rd_count == 0) if there are no matching records
978  * @param proc_cls closure for proc
979  * @return a handle that can be used to
980  *         cancel
981  */
982 struct GNUNET_NAMESTORE_QueueEntry *
983 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
984                               const GNUNET_HashCode *zone,
985                               const char *name,
986                               uint32_t record_type,
987                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
988 {
989   struct GNUNET_NAMESTORE_QueueEntry *qe;
990   struct PendingMessage *pe;
991   size_t msg_size = 0;
992   size_t name_len = 0;
993   uint32_t id = 0;
994
995   GNUNET_assert (NULL != h);
996   GNUNET_assert (NULL != zone);
997   GNUNET_assert (NULL != name);
998
999   name_len = strlen (name) + 1;
1000   if ((name_len == 0) || (name_len > 256))
1001   {
1002     GNUNET_break (0);
1003     return NULL;
1004   }
1005
1006   id = get_op_id(h);
1007   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1008   qe->nsh = h;
1009   qe->proc = proc;
1010   qe->proc_cls = proc_cls;
1011   qe->op_id = id;
1012   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1013
1014   /* set msg_size*/
1015   msg_size = sizeof (struct LookupNameMessage) + name_len;
1016   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1017
1018   /* create msg here */
1019   struct LookupNameMessage * msg;
1020   pe->size = msg_size;
1021   pe->is_init = GNUNET_NO;
1022   msg = (struct LookupNameMessage *) &pe[1];
1023   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1024   msg->header.size = htons (msg_size);
1025   msg->op_id = htonl (id);
1026   msg->record_type = htonl (record_type);
1027   msg->zone = *zone;
1028   msg->name_len = htonl (name_len);
1029   memcpy (&msg[1], name, name_len);
1030
1031   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1032
1033   /* transmit message */
1034   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1035   do_transmit(h);
1036
1037   return qe;
1038 }
1039
1040
1041
1042 /**
1043  * Starts a new zone iteration (used to periodically PUT all of our
1044  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1045  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1046  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1047  * immediately, and then again after
1048  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1049  *
1050  * @param h handle to the namestore
1051  * @param zone zone to access, NULL for all zones
1052  * @param must_have_flags flags that must be set for the record to be returned
1053  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1054  * @param proc function to call on each name from the zone; it
1055  *        will be called repeatedly with a value (if available)
1056  *        and always once at the end with a name of NULL.
1057  * @param proc_cls closure for proc
1058  * @return an iterator handle to use for iteration
1059  */
1060 struct GNUNET_NAMESTORE_ZoneIterator *
1061 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1062                                        const GNUNET_HashCode *zone,
1063                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1064                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1065                                        GNUNET_NAMESTORE_RecordProcessor proc,
1066                                        void *proc_cls)
1067 {
1068   struct GNUNET_NAMESTORE_ZoneIterator *it;
1069   struct PendingMessage *pe;
1070   size_t msg_size = 0;
1071   uint32_t id = 0;
1072
1073   GNUNET_assert (NULL != h);
1074   GNUNET_assert (NULL != zone);
1075
1076   id = get_op_id(h);
1077   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1078   it->h = h;
1079   it->proc = proc;
1080   it->proc_cls = proc;
1081   it->op_id = id;
1082   it->zone = *zone;
1083   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1084
1085   /* set msg_size*/
1086   msg_size = sizeof (struct ZoneIterationStartMessage);
1087   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1088
1089   /* create msg here */
1090   struct ZoneIterationStartMessage * msg;
1091   pe->size = msg_size;
1092   pe->is_init = GNUNET_NO;
1093   msg = (struct ZoneIterationStartMessage *) &pe[1];
1094   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1095   msg->header.size = htons (msg_size);
1096   msg->op_id = htonl (id);
1097   msg->zone = *zone;
1098   msg->must_have_flags = ntohs (must_have_flags);
1099   msg->must_not_have_flags = ntohs (must_not_have_flags);
1100
1101   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1102
1103   /* transmit message */
1104   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1105   do_transmit(h);
1106
1107   return it;
1108 }
1109
1110
1111 /**
1112  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1113  * for the next record.
1114  *
1115  * @param it the iterator
1116  */
1117 void
1118 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1119 {
1120   struct GNUNET_NAMESTORE_Handle *h;
1121   struct PendingMessage *pe;
1122   size_t msg_size = 0;
1123
1124   GNUNET_assert (NULL != it);
1125   h = it->h;
1126
1127   /* set msg_size*/
1128   msg_size = sizeof (struct ZoneIterationNextMessage);
1129   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1130
1131   /* create msg here */
1132   struct ZoneIterationNextMessage * msg;
1133   pe->size = msg_size;
1134   pe->is_init = GNUNET_NO;
1135   msg = (struct ZoneIterationNextMessage *) &pe[1];
1136   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1137   msg->header.size = htons (msg_size);
1138   msg->op_id = htonl (it->op_id);
1139
1140   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1141
1142   /* transmit message */
1143   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1144   do_transmit(h);
1145 }
1146
1147
1148 /**
1149  * Stops iteration and releases the namestore handle for further calls.
1150  *
1151  * @param it the iterator
1152  */
1153 void
1154 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1155 {
1156   GNUNET_assert (NULL != it);
1157   struct PendingMessage *pe;
1158   size_t msg_size = 0;
1159   struct GNUNET_NAMESTORE_Handle *h = it->h;
1160
1161   /* set msg_size*/
1162   msg_size = sizeof (struct ZoneIterationStopMessage);
1163   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1164
1165   /* create msg here */
1166   struct ZoneIterationStopMessage * msg;
1167   pe->size = msg_size;
1168   pe->is_init = GNUNET_NO;
1169   msg = (struct ZoneIterationStopMessage *) &pe[1];
1170   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1171   msg->header.size = htons (msg_size);
1172   msg->op_id = htonl (it->op_id);
1173
1174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1175
1176   /* transmit message */
1177   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1178   do_transmit(h);
1179 }
1180
1181
1182 /**
1183  * Cancel a namestore operation.  The final callback from the
1184  * operation must not have been done yet.
1185  *
1186  * @param qe operation to cancel
1187  */
1188 void
1189 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1190 {
1191   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1192
1193   GNUNET_assert (qe != NULL);
1194
1195   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1196   GNUNET_free(qe);
1197
1198 }
1199
1200 /* end of namestore_api.c */