- fixes
[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_crypto_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_arm_service.h"
33 #include "gnunet_signatures.h"
34 #include "gnunet_namestore_service.h"
35 #include "namestore.h"
36
37 #define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
38
39 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
40
41 /**
42  * A QueueEntry.
43  */
44 struct GNUNET_NAMESTORE_QueueEntry
45 {
46   struct GNUNET_NAMESTORE_QueueEntry *next;
47   struct GNUNET_NAMESTORE_QueueEntry *prev;
48
49   struct GNUNET_NAMESTORE_Handle *nsh;
50
51   uint32_t op_id;
52
53   GNUNET_NAMESTORE_ContinuationWithStatus cont;
54   void *cont_cls;
55
56   GNUNET_NAMESTORE_RecordProcessor proc;
57   void *proc_cls;
58
59   char *data; /*stub data pointer*/
60 };
61
62
63 /**
64  * Zone iterator
65  */
66 struct GNUNET_NAMESTORE_ZoneIterator
67 {
68   struct GNUNET_NAMESTORE_ZoneIterator *next;
69   struct GNUNET_NAMESTORE_ZoneIterator *prev;
70
71   uint32_t op_id;
72
73   struct GNUNET_NAMESTORE_Handle *h;
74   GNUNET_NAMESTORE_RecordProcessor proc;
75   void* proc_cls;
76   GNUNET_HashCode zone;
77   uint32_t no_flags;
78   uint32_t flags;
79 };
80
81
82 /**
83  * Message in linked list we should send to the service.  The
84  * actual binary message follows this struct.
85  */
86 struct PendingMessage
87 {
88
89   /**
90    * Kept in a DLL.
91    */
92   struct PendingMessage *next;
93
94   /**
95    * Kept in a DLL.
96    */
97   struct PendingMessage *prev;
98
99   /**
100    * Size of the message.
101    */
102   size_t size;
103
104   /**
105    * Is this the 'START' message?
106    */
107   int is_init;
108 };
109
110
111 /**
112  * Connection to the NAMESTORE service.
113  */
114 struct GNUNET_NAMESTORE_Handle
115 {
116
117   /**
118    * Configuration to use.
119    */
120   const struct GNUNET_CONFIGURATION_Handle *cfg;
121
122   /**
123    * Socket (if available).
124    */
125   struct GNUNET_CLIENT_Connection *client;
126
127   /**
128    * Currently pending transmission request (or NULL).
129    */
130   struct GNUNET_CLIENT_TransmitHandle *th;
131
132   /**
133    * Reconnect task
134    */
135   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
136
137   /**
138    * Pending messages to send to the service
139    */
140
141   struct PendingMessage * pending_head;
142   struct PendingMessage * pending_tail;
143
144   /**
145    * Should we reconnect to service due to some serious error?
146    */
147   int reconnect;
148
149
150   /**
151    * Pending namestore queue entries
152    */
153   struct GNUNET_NAMESTORE_QueueEntry * op_head;
154   struct GNUNET_NAMESTORE_QueueEntry * op_tail;
155
156   uint32_t op_id;
157
158   /**
159    * Pending namestore zone iterator entries
160    */
161   struct GNUNET_NAMESTORE_ZoneIterator * z_head;
162   struct GNUNET_NAMESTORE_ZoneIterator * z_tail;
163 };
164
165 struct GNUNET_NAMESTORE_SimpleRecord
166 {
167   /**
168    * DLL
169    */
170   struct GNUNET_NAMESTORE_SimpleRecord *next;
171
172   /**
173    * DLL
174    */
175   struct GNUNET_NAMESTORE_SimpleRecord *prev;
176   
177   const char *name;
178   const GNUNET_HashCode *zone;
179   uint32_t record_type;
180   struct GNUNET_TIME_Absolute expiration;
181   enum GNUNET_NAMESTORE_RecordFlags flags;
182   size_t data_size;
183   const void *data;
184 };
185
186
187 /**
188  * Disconnect from service and then reconnect.
189  *
190  * @param h our handle
191  */
192 static void
193 force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
194
195 static void
196 handle_lookup_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
197                              struct LookupNameResponseMessage * msg,
198                              size_t size)
199 {
200   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
201               "LOOKUP_NAME_RESPONSE");
202
203   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
204   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
205   char *name;
206   char * rd_tmp;
207
208   struct GNUNET_CRYPTO_RsaSignature *signature = NULL;
209   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy;
210   struct GNUNET_TIME_Absolute expire;
211   size_t exp_msg_len;
212   size_t msg_len = 0;
213   size_t name_len = 0;
214   size_t rd_len = 0;
215   int contains_sig = GNUNET_NO;
216   int rd_count = 0;
217
218   rd_len = ntohs (msg->rd_len);
219   rd_count = ntohs (msg->rd_count);
220   msg_len = ntohs (msg->gns_header.header.size);
221   name_len = ntohs (msg->name_len);
222   contains_sig = ntohs (msg->contains_sig);
223   expire = GNUNET_TIME_absolute_ntoh(msg->expire);
224
225   exp_msg_len = sizeof (struct LookupNameResponseMessage) +
226       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
227       name_len +
228       rd_len +
229       contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
230
231   if (msg_len != exp_msg_len)
232   {
233     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message size describes with `%u' bytes but calculated size is %u bytes \n",
234                 msg_len, exp_msg_len);
235     GNUNET_break_op (0);
236     return;
237   }
238
239   zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1];
240   name = (char *) &zone_key[1];
241   rd_tmp = &name[name_len];
242
243   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
244   GNUNET_NAMESTORE_records_deserialize(rd_len, rd_tmp, rd_count, rd);
245
246   /* reset values if values not contained */
247   if (contains_sig == GNUNET_NO)
248     signature = NULL;
249   else
250     signature = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[rd_len];
251   if (name_len == 0)
252     name = NULL;
253
254   memset (&dummy, '0', sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
255   if (0 == memcmp (zone_key, &dummy, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
256       zone_key = NULL;
257
258   if (qe->proc != NULL)
259   {
260     qe->proc (qe->proc_cls, zone_key, expire, name, rd_count, (rd_count > 0) ? rd : NULL, signature);
261   }
262
263   /* Operation done, remove */
264   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
265   GNUNET_free (qe);
266 }
267
268
269 static void
270 handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
271                              struct RecordPutResponseMessage* msg,
272                              size_t size)
273 {
274   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
275               "RECORD_PUT_RESPONSE");
276
277   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
278   int res = GNUNET_OK;
279
280   if (ntohs (msg->op_result) == GNUNET_OK)
281   {
282     res = GNUNET_OK;
283     if (qe->cont != NULL)
284     {
285       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
286     }
287
288   }
289   else if (ntohs (msg->op_result) == GNUNET_NO)
290   {
291     res = GNUNET_SYSERR;
292     if (qe->cont != NULL)
293     {
294       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
295     }
296   }
297   else
298   {
299     GNUNET_break_op (0);
300     return;
301   }
302
303   /* Operation done, remove */
304   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
305
306   GNUNET_free (qe);
307 }
308
309
310 static void
311 handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
312                              struct RecordCreateResponseMessage* msg,
313                              size_t size)
314 {
315   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
316               "RECORD_CREATE_RESPONSE");
317
318   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
319   int res = GNUNET_OK;
320
321   if (ntohs (msg->op_result) == GNUNET_OK)
322   {
323     res = GNUNET_OK;
324     if (qe->cont != NULL)
325     {
326       qe->cont (qe->cont_cls, res, _("Namestore added record successfully"));
327     }
328
329   }
330   else if (ntohs (msg->op_result) == GNUNET_NO)
331   {
332     res = GNUNET_SYSERR;
333     if (qe->cont != NULL)
334     {
335       qe->cont (qe->cont_cls, res, _("Namestore failed to add record"));
336     }
337   }
338   else
339   {
340     GNUNET_break_op (0);
341     return;
342   }
343
344   /* Operation done, remove */
345   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
346
347   GNUNET_free (qe);
348 }
349
350
351 static void
352 handle_record_remove_response (struct GNUNET_NAMESTORE_QueueEntry *qe,
353                              struct RecordRemoveResponseMessage* msg,
354                              size_t size)
355 {
356   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
357               "RECORD_REMOVE_RESPONSE");
358
359   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
360   int res = ntohs (msg->op_result);
361
362   /**
363    *  result:
364    *  0 : successful
365    *  1 : No records for entry
366    *  2 : Could not find record to remove
367    *  3 : Failed to create new signature
368    *  4 : Failed to put new set of records in database
369    */
370   switch (res) {
371     case 0:
372       if (qe->cont != NULL)
373       {
374         qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore removed record successfully"));
375       }
376
377       break;
378     case 1:
379       if (qe->cont != NULL)
380       {
381         qe->cont (qe->cont_cls, GNUNET_NO, _("No records for entry"));
382       }
383
384       break;
385     case 2:
386       if (qe->cont != NULL)
387       {
388         qe->cont (qe->cont_cls, GNUNET_NO, _("Could not find record to remove"));
389       }
390
391       break;
392     case 3:
393       if (qe->cont != NULL)
394       {
395         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to create new signature"));
396       }
397
398       break;
399     case 4:
400       if (qe->cont != NULL)
401       {
402         qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to put new set of records in database"));
403       }
404       break;
405     default:
406         GNUNET_break_op (0);
407       break;
408   }
409
410   /* Operation done, remove */
411   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
412
413   GNUNET_free (qe);
414 }
415
416
417 static void
418 manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe,
419                           const struct GNUNET_MessageHeader *msg,
420                           int type, size_t size)
421 {
422
423   /* handle different message type */
424   switch (type) {
425     case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE:
426         if (size < sizeof (struct LookupNameResponseMessage))
427         {
428           GNUNET_break_op (0);
429           break;
430         }
431         handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size);
432       break;
433     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE:
434         if (size != sizeof (struct RecordPutResponseMessage))
435         {
436           GNUNET_break_op (0);
437           break;
438         }
439         handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size);
440       break;
441     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE:
442         if (size != sizeof (struct RecordCreateResponseMessage))
443         {
444           GNUNET_break_op (0);
445           break;
446         }
447         handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size);
448       break;
449     case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE:
450         if (size != sizeof (struct RecordRemoveResponseMessage))
451         {
452           GNUNET_break_op (0);
453           break;
454         }
455         handle_record_remove_response (qe, (struct RecordRemoveResponseMessage *) msg, size);
456       break;
457     default:
458       GNUNET_break_op (0);
459       break;
460   }
461 }
462
463 static void
464 handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze,
465                                 struct ZoneIterationResponseMessage *msg,
466                                 size_t size)
467 {
468   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n",
469               "ZONE_ITERATION_RESPONSE");
470
471
472   if (ze->proc != NULL)
473   {
474     // FIXME
475     ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL);
476   }
477 }
478
479
480 static void
481 manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze,
482                         const struct GNUNET_MessageHeader *msg,
483                         int type, size_t size)
484 {
485
486   /* handle different message type */
487   switch (type) {
488     case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE:
489         if (size < sizeof (struct ZoneIterationResponseMessage))
490         {
491           GNUNET_break_op (0);
492           break;
493         }
494         handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size);
495       break;
496     default:
497       GNUNET_break_op (0);
498       break;
499   }
500 }
501
502 /**
503  * Type of a function to call when we receive a message
504  * from the service.
505  *
506  * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
507  * @param msg message received, NULL on timeout or fatal error
508  */
509 static void
510 process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
511 {
512   struct GNUNET_NAMESTORE_Handle *h = cls;
513   struct GNUNET_NAMESTORE_Header * gm;
514   struct GNUNET_NAMESTORE_QueueEntry *qe;
515   struct GNUNET_NAMESTORE_ZoneIterator *ze;
516   uint16_t size;
517   uint16_t type;
518   uint32_t r_id = UINT32_MAX;
519
520   if (NULL == msg)
521   {
522     force_reconnect (h);
523     return;
524   }
525
526   size = ntohs (msg->size);
527   type = ntohs (msg->type);
528
529   if (size < sizeof (struct GNUNET_NAMESTORE_Header))
530   {
531     GNUNET_break_op (0);
532     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
533                            GNUNET_TIME_UNIT_FOREVER_REL);
534     return;
535   }
536
537   gm = (struct GNUNET_NAMESTORE_Header *) msg;
538   r_id = ntohl (gm->r_id);
539
540   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, r_id);
541
542   /* Find matching operation */
543   if (r_id > h->op_id)
544   {
545     /* No matching pending operation found */
546     GNUNET_break_op (0);
547     GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
548                            GNUNET_TIME_UNIT_FOREVER_REL);
549     return;
550   }
551
552   /* Is it a record related operation ? */
553   for (qe = h->op_head; qe != NULL; qe = qe->next)
554   {
555     if (qe->op_id == r_id)
556       break;
557   }
558   if (qe != NULL)
559   {
560     manage_record_operations (qe, msg, type, size);
561   }
562
563   /* Is it a zone iteration operation ? */
564   for (ze = h->z_head; ze != NULL; ze = ze->next)
565   {
566     if (ze->op_id == r_id)
567       break;
568   }
569   if (ze != NULL)
570   {
571     manage_zone_operations (ze, msg, type, size);
572   }
573
574   GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
575                          GNUNET_TIME_UNIT_FOREVER_REL);
576
577   if (GNUNET_YES == h->reconnect)
578     force_reconnect (h);
579
580 }
581
582
583 /**
584  * Transmit messages from the message queue to the service
585  * (if there are any, and if we are not already trying).
586  *
587  * @param h handle to use
588  */
589 static void
590 do_transmit (struct GNUNET_NAMESTORE_Handle *h);
591
592
593 /**
594  * We can now transmit a message to NAMESTORE. Do it.
595  *
596  * @param cls the 'struct GNUNET_NAMESTORE_Handle'
597  * @param size number of bytes we can transmit
598  * @param buf where to copy the messages
599  * @return number of bytes copied into buf
600  */
601 static size_t
602 transmit_message_to_namestore (void *cls, size_t size, void *buf)
603 {
604   struct GNUNET_NAMESTORE_Handle *h = cls;
605   struct PendingMessage *p;
606   size_t ret;
607   char *cbuf;
608
609   h->th = NULL;
610   if ((size == 0) || (buf == NULL))
611   {
612     force_reconnect (h);
613     return 0;
614   }
615   ret = 0;
616   cbuf = buf;
617   while ((NULL != (p = h->pending_head)) && (p->size <= size))
618   {
619     memcpy (&cbuf[ret], &p[1], p->size);
620     ret += p->size;
621     size -= p->size;
622     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
623     if (GNUNET_YES == p->is_init)
624       GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
625                              GNUNET_TIME_UNIT_FOREVER_REL);
626     GNUNET_free (p);
627   }
628   do_transmit (h);
629   return ret;
630 }
631
632
633 /**
634  * Transmit messages from the message queue to the service
635  * (if there are any, and if we are not already trying).
636  *
637  * @param h handle to use
638  */
639 static void
640 do_transmit (struct GNUNET_NAMESTORE_Handle *h)
641 {
642   struct PendingMessage *p;
643
644   if (NULL != h->th)
645     return;
646   if (NULL == (p = h->pending_head))
647     return;
648   if (NULL == h->client)
649     return;                     /* currently reconnecting */
650
651   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size,
652                                            GNUNET_TIME_UNIT_FOREVER_REL,
653                                            GNUNET_NO, &transmit_message_to_namestore,
654                                            h);
655 }
656
657
658 /**
659  * Reconnect to namestore service.
660  *
661  * @param h the handle to the namestore service
662  */
663 static void
664 reconnect (struct GNUNET_NAMESTORE_Handle *h)
665 {
666   struct PendingMessage *p;
667   struct StartMessage *init;
668
669   GNUNET_assert (NULL == h->client);
670   h->client = GNUNET_CLIENT_connect ("namestore", h->cfg);
671   GNUNET_assert (NULL != h->client);
672
673   if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init))
674   {
675     p = GNUNET_malloc (sizeof (struct PendingMessage) +
676                        sizeof (struct StartMessage));
677     p->size = sizeof (struct StartMessage);
678     p->is_init = GNUNET_YES;
679     init = (struct StartMessage *) &p[1];
680     init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
681     init->header.size = htons (sizeof (struct StartMessage));
682     GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p);
683   }
684   do_transmit (h);
685 }
686
687 /**
688  * Re-establish the connection to the service.
689  *
690  * @param cls handle to use to re-connect.
691  * @param tc scheduler context
692  */
693 static void
694 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
695 {
696   struct GNUNET_NAMESTORE_Handle *h = cls;
697
698   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
699   reconnect (h);
700 }
701
702
703 /**
704  * Disconnect from service and then reconnect.
705  *
706  * @param h our handle
707  */
708 static void
709 force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
710 {
711   h->reconnect = GNUNET_NO;
712   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
713   h->client = NULL;
714   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
715                                     &reconnect_task,
716                                     h);
717 }
718
719 static uint32_t
720 get_op_id (struct GNUNET_NAMESTORE_Handle *h)
721 {
722   uint32_t op_id = h->op_id;
723   h->op_id ++;
724   return op_id;
725 }
726
727 /**
728  * Initialize the connection with the NAMESTORE service.
729  *
730  * @param cfg configuration to use
731  * @return handle to the GNS service, or NULL on error
732  */
733 struct GNUNET_NAMESTORE_Handle *
734 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
735 {
736   struct GNUNET_NAMESTORE_Handle *h;
737
738   h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
739   h->cfg = cfg;
740   h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h);
741   h->op_id = 0;
742   return h;
743 }
744
745
746 /**
747  * Disconnect from the namestore service (and free associated
748  * resources).
749  *
750  * @param h handle to the namestore
751  * @param drop set to GNUNET_YES to delete all data in namestore (!)
752  */
753 void
754 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop)
755 {
756   struct PendingMessage *p;
757   struct GNUNET_NAMESTORE_QueueEntry *q;
758   struct GNUNET_NAMESTORE_ZoneIterator *z;
759
760   GNUNET_assert (h != NULL);
761
762   while (NULL != (p = h->pending_head))
763   {
764     GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
765     GNUNET_free (p);
766   }
767
768   while (NULL != (q = h->op_head))
769   {
770     GNUNET_break (0);
771     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
772     GNUNET_free (q);
773   }
774
775   while (NULL != (z = h->z_head))
776   {
777     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
778     GNUNET_free (z);
779   }
780
781   if (NULL != h->client)
782   {
783     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
784     h->client = NULL;
785   }
786   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
787   {
788     GNUNET_SCHEDULER_cancel (h->reconnect_task);
789     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
790   }
791   GNUNET_free(h);
792   h = NULL;
793 }
794
795
796 /**
797  * Store an item in the namestore.  If the item is already present,
798  * the expiration time is updated to the max of the existing time and
799  * the new time.  This API is used when we cache signatures from other
800  * authorities.
801  *
802  * @param h handle to the namestore
803  * @param zone_key public key of the zone
804  * @param name name that is being mapped (at most 255 characters long)
805  * @param expire when does the corresponding block in the DHT expire (until
806  *               when should we never do a DHT lookup for the same name again)?
807  * @param rd_count number of entries in 'rd' array
808  * @param rd array of records with data to store
809  * @param signature signature for all the records in the zone under the given name
810  * @param cont continuation to call when done
811  * @param cont_cls closure for cont
812  * @return handle to abort the request
813  */
814 struct GNUNET_NAMESTORE_QueueEntry *
815 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
816                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
817                              const char *name,
818                              struct GNUNET_TIME_Absolute expire,
819                              unsigned int rd_count,
820                              const struct GNUNET_NAMESTORE_RecordData *rd,
821                              const struct GNUNET_CRYPTO_RsaSignature *signature,
822                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
823                              void *cont_cls)
824 {
825   struct GNUNET_NAMESTORE_QueueEntry *qe;
826   struct PendingMessage *pe;
827
828   /* pointer to elements */
829   char * zone_key_tmp;
830   char * rd_tmp;
831   char * name_tmp;
832
833   size_t msg_size = 0;
834   size_t name_len = 0;
835   size_t rd_ser_len = 0;
836   size_t pubkey_len = 0;
837   uint32_t rid = 0;
838
839   GNUNET_assert (NULL != h);
840   GNUNET_assert (NULL != zone_key);
841   GNUNET_assert (NULL != name);
842   GNUNET_assert (NULL != rd);
843   GNUNET_assert (NULL != signature);
844
845   name_len = strlen(name) + 1;
846   if (name_len > 256)
847   {
848     GNUNET_break (0);
849     return NULL;
850   }
851
852   rid = get_op_id(h);
853   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
854   qe->nsh = h;
855   qe->cont = cont;
856   qe->cont_cls = cont_cls;
857   qe->op_id = rid;
858   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
859
860   /* set msg_size*/
861   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
862   char rd_ser[rd_ser_len];
863   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
864
865   pubkey_len = sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded);
866   struct RecordPutMessage * msg;
867   msg_size = sizeof (struct RecordPutMessage) + pubkey_len + name_len  + rd_ser_len;
868
869   /* create msg here */
870   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
871   pe->size = msg_size;
872   pe->is_init = GNUNET_NO;
873   msg = (struct RecordPutMessage *) &pe[1];
874   zone_key_tmp = (char *) &msg[1];
875   name_tmp = (char *) &zone_key_tmp[pubkey_len];
876   rd_tmp = &name_tmp[name_len];
877
878   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
879   msg->gns_header.header.size = htons (msg_size);
880   msg->gns_header.r_id = htonl (rid);
881   msg->key_len = htons (pubkey_len);
882   memcpy (zone_key_tmp, zone_key, pubkey_len);
883   msg->signature = *signature;
884   msg->name_len = htons (name_len);
885   memcpy (name_tmp, name, name_len);
886   msg->expire = GNUNET_TIME_absolute_hton (expire);
887   msg->rd_len = htons (rd_ser_len);
888   msg->rd_count = htons (rd_count);
889
890   memcpy (rd_tmp, rd_ser, rd_ser_len);
891
892   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
893
894   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
895   do_transmit(h);
896
897   return qe;
898 }
899
900
901 /**
902  * Check if a signature is valid.  This API is used by the GNS Block
903  * to validate signatures received from the network.
904  *
905  * @param public_key public key of the zone
906  * @param name name that is being mapped (at most 255 characters long)
907  * @param rd_count number of entries in 'rd' array
908  * @param rd array of records with data to store
909  * @param signature signature for all the records in the zone under the given name
910  * @return GNUNET_OK if the signature is valid
911  */
912 int
913 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
914                                    const char *name,
915                                    unsigned int rd_count,
916                                    const struct GNUNET_NAMESTORE_RecordData *rd,
917                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
918 {
919   int res = GNUNET_SYSERR;
920   size_t rd_ser_len = 0;
921   size_t name_len = 0;
922   char * name_tmp;
923   char * rd_tmp;
924   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
925
926   GNUNET_assert (public_key != NULL);
927   GNUNET_assert (name != NULL);
928   GNUNET_assert (signature != NULL);
929
930   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
931   char rd_ser[rd_ser_len];
932   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
933
934   name_len = strlen (name) + 1;
935
936   sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + rd_ser_len + name_len);
937   sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len);
938   sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
939   name_tmp = (char *) &sig_purpose[1];
940   rd_tmp = &name_tmp[name_len];
941   memcpy (name_tmp, name, name_len);
942   memcpy (rd_tmp, rd_ser, rd_ser_len);
943
944   res = GNUNET_CRYPTO_rsa_verify(GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key);
945
946   GNUNET_free (sig_purpose);
947
948   return res;
949 }
950
951 /**
952  * Store an item in the namestore.  If the item is already present,
953  * the expiration time is updated to the max of the existing time and
954  * the new time.  This API is used by the authority of a zone.
955  *
956  * @param h handle to the namestore
957  * @param pkey private key of the zone
958  * @param name name that is being mapped (at most 255 characters long)
959  * @param rd record data to store
960  * @param cont continuation to call when done
961  * @param cont_cls closure for cont
962  * @return handle to abort the request
963  */
964 struct GNUNET_NAMESTORE_QueueEntry *
965 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
966                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
967                                 const char *name,
968                                 const struct GNUNET_NAMESTORE_RecordData *rd,
969                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
970                                 void *cont_cls)
971 {
972   struct GNUNET_NAMESTORE_QueueEntry *qe;
973   struct PendingMessage *pe;
974   char * name_tmp;
975   char * pkey_tmp;
976   char * rd_tmp;
977   size_t rd_ser_len = 0;
978   size_t msg_size = 0;
979   size_t name_len = 0;
980   size_t key_len = 0;
981   uint32_t rid = 0;
982
983   GNUNET_assert (NULL != h);
984   GNUNET_assert (NULL != pkey);
985   GNUNET_assert (NULL != name);
986   GNUNET_assert (NULL != rd);
987
988   name_len = strlen(name) + 1;
989   if (name_len > 256)
990   {
991     GNUNET_break (0);
992     return NULL;
993   }
994
995   rid = get_op_id(h);
996   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
997   qe->nsh = h;
998   qe->cont = cont;
999   qe->cont_cls = cont_cls;
1000   qe->op_id = rid;
1001   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1002
1003   /* set msg_size*/
1004   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1005   GNUNET_assert (pkey_enc != NULL);
1006   key_len = ntohs (pkey_enc->len);
1007
1008   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1009   char rd_ser[rd_ser_len];
1010   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1011
1012   struct RecordCreateMessage * msg;
1013   msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1014
1015   /* create msg here */
1016   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1017   pe->size = msg_size;
1018   pe->is_init = GNUNET_NO;
1019   msg = (struct RecordCreateMessage *) &pe[1];
1020
1021   pkey_tmp = (char *) &msg[1];
1022   name_tmp = &pkey_tmp[key_len];
1023   rd_tmp = &name_tmp[name_len];
1024
1025   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
1026   msg->gns_header.header.size = htons (msg_size);
1027   msg->gns_header.r_id = htonl (rid);
1028   msg->name_len = htons (name_len);
1029   msg->rd_count = htons (1);
1030   msg->rd_len = htons (rd_ser_len);
1031   msg->pkey_len = htons (key_len);
1032   memcpy (pkey_tmp, pkey_enc, key_len);
1033   memcpy (name_tmp, name, name_len);
1034   memcpy (rd_tmp, rd_ser, rd_ser_len);
1035   GNUNET_free (pkey_enc);
1036
1037   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
1038
1039   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1040   do_transmit(h);
1041   return qe;
1042 }
1043
1044
1045 /**
1046  * Explicitly remove some content from the database.  The
1047  * "cont"inuation will be called with status "GNUNET_OK" if content
1048  * was removed, "GNUNET_NO" if no matching entry was found and
1049  * "GNUNET_SYSERR" on all other types of errors.
1050  * This API is used by the authority of a zone.
1051  *
1052  * @param h handle to the namestore
1053  * @param pkey private key of the zone
1054  * @param name name that is being mapped (at most 255 characters long)
1055  * @param rd record data
1056  * @param cont continuation to call when done
1057  * @param cont_cls closure for cont
1058  * @return handle to abort the request
1059  */
1060 struct GNUNET_NAMESTORE_QueueEntry *
1061 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
1062                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1063                                 const char *name,
1064                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1065                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1066                                 void *cont_cls)
1067 {
1068   struct GNUNET_NAMESTORE_QueueEntry *qe;
1069   struct PendingMessage *pe;
1070   char *pkey_tmp;
1071   char *rd_tmp;
1072   char *name_tmp;
1073   size_t rd_ser_len = 0;
1074   size_t msg_size = 0;
1075   size_t name_len = 0;
1076   size_t key_len = 0;
1077   uint32_t rid = 0;
1078
1079   GNUNET_assert (NULL != h);
1080
1081   rid = get_op_id(h);
1082   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1083   qe->nsh = h;
1084   qe->cont = cont;
1085   qe->cont_cls = cont_cls;
1086   qe->op_id = rid;
1087   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1088
1089   /* set msg_size*/
1090   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1091   GNUNET_assert (pkey_enc != NULL);
1092   key_len = ntohs (pkey_enc->len);
1093
1094   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1095   char rd_ser[rd_ser_len];
1096   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1097
1098   name_len = strlen (name) + 1;
1099
1100   struct RecordRemoveMessage * msg;
1101   msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1102
1103   /* create msg here */
1104   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1105   pe->size = msg_size;
1106   pe->is_init = GNUNET_NO;
1107   msg = (struct RecordRemoveMessage *) &pe[1];
1108
1109   pkey_tmp = (char *) &msg[1];
1110   name_tmp = &pkey_tmp[key_len];
1111   rd_tmp = &name_tmp[name_len];
1112
1113   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
1114   msg->gns_header.header.size = htons (msg_size);
1115   msg->gns_header.r_id = htonl (rid);
1116   msg->name_len = htons (name_len);
1117   msg->rd_len = htons (rd_ser_len);
1118   msg->rd_count = htons (1);
1119   msg->key_len = htons (key_len);
1120   memcpy (pkey_tmp, pkey_enc, key_len);
1121   memcpy (name_tmp, name, name_len);
1122   memcpy (rd_tmp, rd_ser, rd_ser_len);
1123
1124   GNUNET_free (pkey_enc);
1125
1126   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
1127
1128   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1129   do_transmit(h);
1130   return qe;
1131 }
1132
1133
1134 /**
1135  * Get a result for a particular key from the namestore.  The processor
1136  * will only be called once.  
1137  *
1138  * @param h handle to the namestore
1139  * @param zone zone to look up a record from
1140  * @param name name to look up
1141  * @param record_type desired record type, 0 for all
1142  * @param proc function to call on the matching records, or with
1143  *        NULL (rd_count == 0) if there are no matching records
1144  * @param proc_cls closure for proc
1145  * @return a handle that can be used to
1146  *         cancel
1147  */
1148 struct GNUNET_NAMESTORE_QueueEntry *
1149 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
1150                               const GNUNET_HashCode *zone,
1151                               const char *name,
1152                               uint32_t record_type,
1153                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1154 {
1155   struct GNUNET_NAMESTORE_QueueEntry *qe;
1156   struct PendingMessage *pe;
1157   size_t msg_size = 0;
1158   size_t name_len = 0;
1159   uint32_t rid = 0;
1160
1161   GNUNET_assert (NULL != h);
1162   GNUNET_assert (NULL != zone);
1163   GNUNET_assert (NULL != name);
1164
1165   name_len = strlen (name) + 1;
1166   if ((name_len == 0) || (name_len > 256))
1167   {
1168     GNUNET_break (0);
1169     return NULL;
1170   }
1171
1172   rid = get_op_id(h);
1173   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1174   qe->nsh = h;
1175   qe->proc = proc;
1176   qe->proc_cls = proc_cls;
1177   qe->op_id = rid;
1178   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1179
1180   /* set msg_size*/
1181   msg_size = sizeof (struct LookupNameMessage) + name_len;
1182   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1183
1184   /* create msg here */
1185   struct LookupNameMessage * msg;
1186   pe->size = msg_size;
1187   pe->is_init = GNUNET_NO;
1188   msg = (struct LookupNameMessage *) &pe[1];
1189   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1190   msg->gns_header.header.size = htons (msg_size);
1191   msg->gns_header.r_id = htonl (rid);
1192   msg->record_type = htonl (record_type);
1193   msg->zone = *zone;
1194   msg->name_len = htonl (name_len);
1195   memcpy (&msg[1], name, name_len);
1196
1197   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1198
1199   /* transmit message */
1200   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1201   do_transmit(h);
1202
1203   return qe;
1204 }
1205
1206
1207
1208 /**
1209  * Starts a new zone iteration (used to periodically PUT all of our
1210  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1211  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1212  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1213  * immediately, and then again after
1214  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1215  *
1216  * @param h handle to the namestore
1217  * @param zone zone to access, NULL for all zones
1218  * @param must_have_flags flags that must be set for the record to be returned
1219  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1220  * @param proc function to call on each name from the zone; it
1221  *        will be called repeatedly with a value (if available)
1222  *        and always once at the end with a name of NULL.
1223  * @param proc_cls closure for proc
1224  * @return an iterator handle to use for iteration
1225  */
1226 struct GNUNET_NAMESTORE_ZoneIterator *
1227 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1228                                        const GNUNET_HashCode *zone,
1229                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1230                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1231                                        GNUNET_NAMESTORE_RecordProcessor proc,
1232                                        void *proc_cls)
1233 {
1234   struct GNUNET_NAMESTORE_ZoneIterator *it;
1235   struct PendingMessage *pe;
1236   size_t msg_size = 0;
1237   uint32_t rid = 0;
1238
1239   GNUNET_assert (NULL != h);
1240   GNUNET_assert (NULL != zone);
1241
1242   rid = get_op_id(h);
1243   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1244   it->h = h;
1245   it->proc = proc;
1246   it->proc_cls = proc;
1247   it->op_id = rid;
1248   it->zone = *zone;
1249   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1250
1251   /* set msg_size*/
1252   msg_size = sizeof (struct ZoneIterationStartMessage);
1253   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1254
1255   /* create msg here */
1256   struct ZoneIterationStartMessage * msg;
1257   pe->size = msg_size;
1258   pe->is_init = GNUNET_NO;
1259   msg = (struct ZoneIterationStartMessage *) &pe[1];
1260   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1261   msg->gns_header.header.size = htons (msg_size);
1262   msg->gns_header.r_id = htonl (rid);
1263   msg->zone = *zone;
1264   msg->must_have_flags = ntohs (must_have_flags);
1265   msg->must_not_have_flags = ntohs (must_not_have_flags);
1266
1267   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1268
1269   /* transmit message */
1270   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1271   do_transmit(h);
1272
1273   return it;
1274 }
1275
1276
1277 /**
1278  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1279  * for the next record.
1280  *
1281  * @param it the iterator
1282  */
1283 void
1284 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1285 {
1286   struct GNUNET_NAMESTORE_Handle *h;
1287   struct PendingMessage *pe;
1288   size_t msg_size = 0;
1289
1290   GNUNET_assert (NULL != it);
1291   h = it->h;
1292
1293   /* set msg_size*/
1294   msg_size = sizeof (struct ZoneIterationNextMessage);
1295   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1296
1297   /* create msg here */
1298   struct ZoneIterationNextMessage * msg;
1299   pe->size = msg_size;
1300   pe->is_init = GNUNET_NO;
1301   msg = (struct ZoneIterationNextMessage *) &pe[1];
1302   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1303   msg->gns_header.header.size = htons (msg_size);
1304   msg->gns_header.r_id = htonl (it->op_id);
1305
1306   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1307
1308   /* transmit message */
1309   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1310   do_transmit(h);
1311 }
1312
1313
1314 /**
1315  * Stops iteration and releases the namestore handle for further calls.
1316  *
1317  * @param it the iterator
1318  */
1319 void
1320 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1321 {
1322   GNUNET_assert (NULL != it);
1323   struct PendingMessage *pe;
1324   size_t msg_size = 0;
1325   struct GNUNET_NAMESTORE_Handle *h = it->h;
1326
1327   /* set msg_size*/
1328   msg_size = sizeof (struct ZoneIterationStopMessage);
1329   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1330
1331   /* create msg here */
1332   struct ZoneIterationStopMessage * msg;
1333   pe->size = msg_size;
1334   pe->is_init = GNUNET_NO;
1335   msg = (struct ZoneIterationStopMessage *) &pe[1];
1336   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1337   msg->gns_header.header.size = htons (msg_size);
1338   msg->gns_header.r_id = htonl (it->op_id);
1339
1340   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1341
1342   /* transmit message */
1343   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1344   do_transmit(h);
1345 }
1346
1347
1348 /**
1349  * Cancel a namestore operation.  The final callback from the
1350  * operation must not have been done yet.
1351  *
1352  * @param qe operation to cancel
1353  */
1354 void
1355 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1356 {
1357   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1358
1359   GNUNET_assert (qe != NULL);
1360
1361   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1362   GNUNET_free(qe);
1363
1364 }
1365
1366 /* end of namestore_api.c */