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