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