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