- put record
[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
289   /* Operation done, remove */
290   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
291
292   GNUNET_free (qe);
293 }
294
295
296 /**
297  * Type of a function to call when we receive a message
298  * from the service.
299  *
300  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
301  * @param msg message received, NULL on timeout or fatal error
302  */
303 static void
304 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
305 {
306   struct GNUNET_NAMESTORE_Handle *h = cls;
307   struct GenericMessage * gm;
308   struct GNUNET_NAMESTORE_QueueEntry *qe;
309   uint16_t size;
310   uint16_t type;
311   uint32_t op_id = UINT32_MAX;
312
313   if (NULL == msg)
314   {
315     force_reconnect (h);
316     return;
317   }
318
319   size = ntohs (msg->size);
320   type = ntohs (msg->type);
321
322   if (size < sizeof (struct GenericMessage))
323   {
324     GNUNET_break_op (0);
325     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
326                            GNUNET_TIME_UNIT_FOREVER_REL);
327     return;
328   }
329
330   gm = (struct GenericMessage *) msg;
331   op_id = ntohl (gm->op_id);
332
333   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, op_id);
334
335   /* Find matching operation */
336   if (op_id > h->op_id)
337   {
338     /* No matching pending operation found */
339     GNUNET_break_op (0);
340     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
341                            GNUNET_TIME_UNIT_FOREVER_REL);
342     return;
343   }
344   for (qe = h->op_head; qe != NULL; qe = qe->next)
345   {
346     if (qe->op_id == op_id)
347       break;
348   }
349   if (qe == NULL)
350   {
351     /* No matching pending operation found */
352     GNUNET_break_op (0);
353     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
354                            GNUNET_TIME_UNIT_FOREVER_REL);
355     return;
356   }
357
358   /* handle different message type */
359   switch (type) {
360     case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
361         if (size < sizeof (struct LookupNameResponseMessage))
362         {
363           GNUNET_break_op (0);
364           break;
365         }
366         handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size);
367       break;
368     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
369         if (size != sizeof (struct RecordPutResponseMessage))
370         {
371           GNUNET_break_op (0);
372           break;
373         }
374         handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size);
375       break;
376     default:
377       GNUNET_break_op (0);
378       break;
379   }
380
381   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
382                          GNUNET_TIME_UNIT_FOREVER_REL);
383
384   if (GNUNET_YES == h->reconnect)
385     force_reconnect (h);
386 }
387
388
389 /**
390  * Transmit messages from the message queue to the service
391  * (if there are any, and if we are not already trying).
392  *
393  * @param h handle to use
394  */
395 static void
396 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
397
398
399 /**
400  * We can now transmit a message to NAMESTORE. Do it.
401  *
402  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
403  * @param size number of bytes we can transmit
404  * @param buf where to copy the messages
405  * @return number of bytes copied into buf
406  */
407 static size_t
408 transmit_message_to_namestore (void *cls, size_t size, void *buf)
409 {
410   struct GNUNET_NAMESTORE_Handle *h = cls;
411   struct PendingMessage *p;
412   size_t ret;
413   char *cbuf;
414
415   h->th = NULL;
416   if ((size == 0) || (buf == NULL))
417   {
418     force_reconnect (h);
419     return 0;
420   }
421   ret = 0;
422   cbuf = buf;
423   while ((NULL != (p = h->pending_head)) && (p->size <= size))
424   {
425     memcpy (&cbuf[ret], &p[1], p->size);
426     ret += p->size;
427     size -= p->size;
428     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
429     if (GNUNET_YES == p->is_init)
430       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
431                              GNUNET_TIME_UNIT_FOREVER_REL);
432     GNUNET_free (p);
433   }
434   do_transmit (h);
435   return ret;
436 }
437
438
439 /**
440  * Transmit messages from the message queue to the service
441  * (if there are any, and if we are not already trying).
442  *
443  * @param h handle to use
444  */
445 static void
446 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
447 {
448   struct PendingMessage *p;
449
450   if (NULL != h->th)
451     return;
452   if (NULL == (p = h->pending_head))
453     return;
454   if (NULL == h->client)
455     return;                     /* currently reconnecting */
456
457   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
458                                            GNUNET_TIME_UNIT_FOREVER_REL,
459                                            GNUNET_NO, &transmit_message_to_namestore,
460                                            h);
461 }
462
463
464 /**
465  * Reconnect to namestore service.
466  *
467  * @param h the handle to the namestore service
468  */
469 static void
470 reconnect (struct GNUNET_NAMESTORE_Handle *h)
471 {
472   struct PendingMessage *p;
473   struct StartMessage *init;
474
475   GNUNET_assert (NULL == h->client);
476   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
477   GNUNET_assert (NULL != h->client);
478
479   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
480   {
481     p = GNUNET_malloc (sizeof (struct PendingMessage) +
482                        sizeof (struct StartMessage));
483     p->size = sizeof (struct StartMessage);
484     p->is_init = GNUNET_YES;
485     init = (struct StartMessage *) &p[1];
486     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
487     init->header.size = htons (sizeof (struct StartMessage));
488     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
489   }
490   do_transmit (h);
491 }
492
493 /**
494  * Re-establish the connection to the service.
495  *
496  * @param cls handle to use to re-connect.
497  * @param tc scheduler context
498  */
499 static void
500 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
501 {
502   struct GNUNET_NAMESTORE_Handle *h = cls;
503
504   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
505   reconnect (h);
506 }
507
508
509 /**
510  * Disconnect from service and then reconnect.
511  *
512  * @param h our handle
513  */
514 static void
515 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
516 {
517   h->reconnect = GNUNET_NO;
518   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
519   h->client = NULL;
520   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
521                                     &reconnect_task,
522                                     h);
523 }
524
525 static uint32_t
526 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
527 {
528   uint32_t op_id = h->op_id;
529   h->op_id ++;
530   return op_id;
531 }
532
533 /**
534  * Initialize the connection with the NAMESTORE service.
535  *
536  * @param cfg configuration to use
537  * @return handle to the GNS service, or NULL on error
538  */
539 struct GNUNET_NAMESTORE_Handle *
540 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
541 {
542   struct GNUNET_NAMESTORE_Handle *h;
543
544   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
545   h->cfg = cfg;
546   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
547   h->op_id = 0;
548   return h;
549 }
550
551
552 void
553 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
554 {
555   struct PendingMessage *p;
556   struct GNUNET_NAMESTORE_QueueEntry *q;
557   struct GNUNET_NAMESTORE_ZoneIterator *z;
558
559   GNUNET_assert (h != NULL);
560
561   while (NULL != (p = h->pending_head))
562   {
563     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
564     GNUNET_free (p);
565   }
566
567   while (NULL != (q = h->op_head))
568   {
569     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
570     GNUNET_free (q);
571   }
572
573   while (NULL != (z = h->z_head))
574   {
575     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
576     GNUNET_free (z);
577   }
578
579   if (NULL != h->client)
580   {
581     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
582     h->client = NULL;
583   }
584   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
585   {
586     GNUNET_SCHEDULER_cancel (h->reconnect_task);
587     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
588   }
589   GNUNET_free(h);
590   h = NULL;
591 }
592
593
594 /**
595  * Store an item in the namestore.  If the item is already present,
596  * the expiration time is updated to the max of the existing time and
597  * the new time.  This API is used when we cache signatures from other
598  * authorities.
599  *
600  * @param h handle to the namestore
601  * @param zone_key public key of the zone
602  * @param name name that is being mapped (at most 255 characters long)
603  * @param expire when does the corresponding block in the DHT expire (until
604  *               when should we never do a DHT lookup for the same name again)?
605  * @param rd_count number of entries in 'rd' array
606  * @param rd array of records with data to store
607  * @param signature signature for all the records in the zone under the given name
608  * @param cont continuation to call when done
609  * @param cont_cls closure for cont
610  * @return handle to abort the request
611  */
612 struct GNUNET_NAMESTORE_QueueEntry *
613 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
614                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
615                              const char *name,
616                              struct GNUNET_TIME_Absolute expire,
617                              unsigned int rd_count,
618                              const struct GNUNET_NAMESTORE_RecordData *rd,
619                              const struct GNUNET_CRYPTO_RsaSignature *signature,
620                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
621                              void *cont_cls)
622 {
623   struct GNUNET_NAMESTORE_QueueEntry *qe;
624   struct PendingMessage *pe;
625
626   /* pointer to elements */
627   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp;
628   struct GNUNET_NAMESTORE_RecordData *rd_tmp;
629   char * name_tmp;
630
631   size_t msg_size = 0;
632   size_t name_len = strlen(name) + 1;
633   uint32_t id = 0;
634
635   GNUNET_assert (NULL != h);
636   id = get_op_id(h);
637   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
638   qe->nsh = h;
639   qe->cont = cont;
640   qe->cont_cls = cont_cls;
641   qe->op_id = id;
642   GNUNET_CONTAINER_DLL_insert(h->op_head, h->op_tail, qe);
643
644   /* set msg_size*/
645   struct RecordPutMessage * msg;
646   msg_size = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len  + rd_count * (sizeof (struct GNUNET_NAMESTORE_RecordData));
647
648   /* create msg here */
649   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
650   pe->size = msg_size;
651   pe->is_init = GNUNET_NO;
652   msg = (struct RecordPutMessage *) &pe[1];
653   zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
654   name_tmp = (char *) &zone_key_tmp[1];
655   rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len];
656
657   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
658   msg->header.size = htons (msg_size);
659   msg->op_id = htonl (id);
660   memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
661   msg->signature = *signature;
662   msg->name_len = htons (name_len);
663   memcpy (name_tmp, name, name_len);
664   msg->expire = GNUNET_TIME_absolute_hton (expire);
665   msg->rd_count = htonl(rd_count);
666   memcpy (rd_tmp, rd, rd_count * (sizeof (struct GNUNET_NAMESTORE_RecordData)));
667
668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
669
670   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CALC: %u %u %u %u\n",
671       sizeof (struct RecordPutMessage),
672       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
673       name_len,
674       rd_count * (sizeof (struct GNUNET_NAMESTORE_RecordData)));
675
676   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
677   do_transmit(h);
678
679   return qe;
680 }
681
682
683 /**
684  * Check if a signature is valid.  This API is used by the GNS Block
685  * to validate signatures received from the network.
686  *
687  * @param public_key public key of the zone
688  * @param name name that is being mapped (at most 255 characters long)
689  * @param rd_count number of entries in 'rd' array
690  * @param rd array of records with data to store
691  * @param signature signature for all the records in the zone under the given name
692  * @return GNUNET_OK if the signature is valid
693  */
694 int
695 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
696                                    const char *name,
697                                    unsigned int rd_count,
698                                    const struct GNUNET_NAMESTORE_RecordData *rd,
699                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
700 {
701   return GNUNET_SYSERR;
702 }
703
704 /**
705  * Store an item in the namestore.  If the item is already present,
706  * the expiration time is updated to the max of the existing time and
707  * the new time.  This API is used by the authority of a zone.
708  *
709  * @param h handle to the namestore
710  * @param pkey private key of the zone
711  * @param name name that is being mapped (at most 255 characters long)
712  * @param rd record data to store
713  * @param cont continuation to call when done
714  * @param cont_cls closure for cont
715  * @return handle to abort the request
716  */
717 struct GNUNET_NAMESTORE_QueueEntry *
718 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
719                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
720                                 const char *name,
721                                 const struct GNUNET_NAMESTORE_RecordData *rd,
722                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
723                                 void *cont_cls)
724 {
725   struct GNUNET_NAMESTORE_QueueEntry *qe;
726   struct PendingMessage *pe;
727   size_t msg_size = 0;
728
729   GNUNET_assert (NULL != h);
730
731   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
732   qe->nsh = h;
733   qe->cont = cont;
734   qe->cont_cls = cont_cls;
735   get_op_id(h);
736
737   /* set msg_size*/
738   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
739
740   /* create msg here */
741
742   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
743   do_transmit(h);
744   return qe;
745 }
746
747
748 /**
749  * Explicitly remove some content from the database.  The
750  * "cont"inuation will be called with status "GNUNET_OK" if content
751  * was removed, "GNUNET_NO" if no matching entry was found and
752  * "GNUNET_SYSERR" on all other types of errors.
753  * This API is used by the authority of a zone.
754  *
755  * @param h handle to the namestore
756  * @param pkey private key of the zone
757  * @param name name that is being mapped (at most 255 characters long)
758  * @param rd record data
759  * @param cont continuation to call when done
760  * @param cont_cls closure for cont
761  * @return handle to abort the request
762  */
763 struct GNUNET_NAMESTORE_QueueEntry *
764 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
765                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
766                                 const char *name,
767                                 const struct GNUNET_NAMESTORE_RecordData *rd,
768                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
769                                 void *cont_cls)
770 {
771   struct GNUNET_NAMESTORE_QueueEntry *qe;
772   struct PendingMessage *pe;
773   size_t msg_size = 0;
774
775   GNUNET_assert (NULL != h);
776
777   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
778   qe->nsh = h;
779   qe->cont = cont;
780   qe->cont_cls = cont_cls;
781   get_op_id(h);
782
783   /* set msg_size*/
784   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
785
786   /* create msg here */
787
788   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
789   do_transmit(h);
790
791 #if 0
792   struct GNUNET_NAMESTORE_SimpleRecord *iter;
793   for (iter=h->records_head; iter != NULL; iter=iter->next)
794   {
795     if (strcmp ( iter->name, name ) &&
796         iter->record_type == record_type &&
797         GNUNET_CRYPTO_hash_cmp (iter->zone, zone))
798       break;
799   }
800   if (iter)
801     GNUNET_CONTAINER_DLL_remove(h->records_head,
802                                 h->records_tail,
803                                 iter);
804 #endif
805   return qe;
806 }
807
808
809 /**
810  * Get a result for a particular key from the namestore.  The processor
811  * will only be called once.  
812  *
813  * @param h handle to the namestore
814  * @param zone zone to look up a record from
815  * @param name name to look up
816  * @param record_type desired record type, 0 for all
817  * @param proc function to call on the matching records, or with
818  *        NULL (rd_count == 0) if there are no matching records
819  * @param proc_cls closure for proc
820  * @return a handle that can be used to
821  *         cancel
822  */
823 struct GNUNET_NAMESTORE_QueueEntry *
824 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
825                               const GNUNET_HashCode *zone,
826                               const char *name,
827                               uint32_t record_type,
828                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
829 {
830   struct GNUNET_NAMESTORE_QueueEntry *qe;
831   struct PendingMessage *pe;
832   size_t msg_size = 0;
833   size_t name_len = 0;
834   uint32_t id = 0;
835
836   GNUNET_assert (NULL != h);
837   GNUNET_assert (NULL != zone);
838   GNUNET_assert (NULL != name);
839
840   name_len = strlen (name) + 1;
841   if ((name_len == 0) || (name_len > 256))
842   {
843     GNUNET_break (0);
844     return NULL;
845   }
846
847   id = get_op_id(h);
848   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
849   qe->nsh = h;
850   qe->proc = proc;
851   qe->proc_cls = proc_cls;
852   qe->op_id = id;
853   GNUNET_CONTAINER_DLL_insert(h->op_head, h->op_tail, qe);
854
855   /* set msg_size*/
856   msg_size = sizeof (struct LookupNameMessage) + name_len;
857   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
858
859   /* create msg here */
860   struct LookupNameMessage * msg;
861   pe->size = msg_size;
862   pe->is_init = GNUNET_NO;
863   msg = (struct LookupNameMessage *) &pe[1];
864   msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
865   msg->header.size = htons (msg_size);
866   msg->op_id = htonl (id);
867   msg->record_type = htonl (record_type);
868   msg->zone = *zone;
869   msg->name_len = htonl (name_len);
870   memcpy (&msg[1], name, name_len);
871
872   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
873
874   /* transmit message */
875   GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, pe);
876   do_transmit(h);
877
878   return qe;
879 }
880
881
882
883 /**
884  * Starts a new zone iteration (used to periodically PUT all of our
885  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
886  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
887  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
888  * immediately, and then again after
889  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
890  *
891  * @param h handle to the namestore
892  * @param zone zone to access, NULL for all zones
893  * @param must_have_flags flags that must be set for the record to be returned
894  * @param must_not_have_flags flags that must NOT be set for the record to be returned
895  * @param proc function to call on each name from the zone; it
896  *        will be called repeatedly with a value (if available)
897  *        and always once at the end with a name of NULL.
898  * @param proc_cls closure for proc
899  * @return an iterator handle to use for iteration
900  */
901 struct GNUNET_NAMESTORE_ZoneIterator *
902 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
903                                        const GNUNET_HashCode *zone,
904                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
905                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
906                                        GNUNET_NAMESTORE_RecordProcessor proc,
907                                        void *proc_cls)
908 {
909   struct GNUNET_NAMESTORE_ZoneIterator *it;
910
911   GNUNET_assert (h != NULL);
912
913   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
914   it->h = h;
915   it->proc = proc;
916   it->proc_cls = proc;
917   GNUNET_CONTAINER_DLL_insert(h->z_head, h->z_tail, it);
918
919   return it;
920 }
921
922
923 /**
924  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
925  * for the next record.
926  *
927  * @param it the iterator
928  */
929 void
930 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
931 {
932
933 }
934
935
936 /**
937  * Stops iteration and releases the namestore handle for further calls.
938  *
939  * @param it the iterator
940  */
941 void
942 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
943 {
944   struct GNUNET_NAMESTORE_Handle * h;
945   GNUNET_assert (it != NULL);
946
947   h = it->h;
948   GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, it);
949   GNUNET_free (it);
950
951 }
952
953
954 /**
955  * Cancel a namestore operation.  The final callback from the
956  * operation must not have been done yet.
957  *
958  * @param qe operation to cancel
959  */
960 void
961 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
962 {
963   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
964
965   GNUNET_assert (qe != NULL);
966
967   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
968   GNUNET_free(qe);
969
970 }
971
972 /* end of namestore_api.c */