- more changes: sign & verify working and tested
[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_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
771     GNUNET_free (q);
772   }
773
774   while (NULL != (z = h->z_head))
775   {
776     GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
777     GNUNET_free (z);
778   }
779
780   if (NULL != h->client)
781   {
782     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
783     h->client = NULL;
784   }
785   if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task)
786   {
787     GNUNET_SCHEDULER_cancel (h->reconnect_task);
788     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
789   }
790   GNUNET_free(h);
791   h = NULL;
792 }
793
794
795 /**
796  * Store an item in the namestore.  If the item is already present,
797  * the expiration time is updated to the max of the existing time and
798  * the new time.  This API is used when we cache signatures from other
799  * authorities.
800  *
801  * @param h handle to the namestore
802  * @param zone_key public key of the zone
803  * @param name name that is being mapped (at most 255 characters long)
804  * @param expire when does the corresponding block in the DHT expire (until
805  *               when should we never do a DHT lookup for the same name again)?
806  * @param rd_count number of entries in 'rd' array
807  * @param rd array of records with data to store
808  * @param signature signature for all the records in the zone under the given name
809  * @param cont continuation to call when done
810  * @param cont_cls closure for cont
811  * @return handle to abort the request
812  */
813 struct GNUNET_NAMESTORE_QueueEntry *
814 GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
815                              const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
816                              const char *name,
817                              struct GNUNET_TIME_Absolute expire,
818                              unsigned int rd_count,
819                              const struct GNUNET_NAMESTORE_RecordData *rd,
820                              const struct GNUNET_CRYPTO_RsaSignature *signature,
821                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
822                              void *cont_cls)
823 {
824   struct GNUNET_NAMESTORE_QueueEntry *qe;
825   struct PendingMessage *pe;
826
827   /* pointer to elements */
828   char * zone_key_tmp;
829   char * rd_tmp;
830   char * name_tmp;
831
832   size_t msg_size = 0;
833   size_t name_len = 0;
834   size_t rd_ser_len = 0;
835   size_t pubkey_len = 0;
836   uint32_t rid = 0;
837
838   GNUNET_assert (NULL != h);
839   GNUNET_assert (NULL != zone_key);
840   GNUNET_assert (NULL != name);
841   GNUNET_assert (NULL != rd);
842   GNUNET_assert (NULL != signature);
843
844   name_len = strlen(name) + 1;
845   if (name_len > 256)
846   {
847     GNUNET_break (0);
848     return NULL;
849   }
850
851   rid = get_op_id(h);
852   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
853   qe->nsh = h;
854   qe->cont = cont;
855   qe->cont_cls = cont_cls;
856   qe->op_id = rid;
857   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
858
859   /* set msg_size*/
860   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
861   char rd_ser[rd_ser_len];
862   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
863
864   pubkey_len = sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded);
865   struct RecordPutMessage * msg;
866   msg_size = sizeof (struct RecordPutMessage) + pubkey_len + name_len  + rd_ser_len;
867
868   /* create msg here */
869   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
870   pe->size = msg_size;
871   pe->is_init = GNUNET_NO;
872   msg = (struct RecordPutMessage *) &pe[1];
873   zone_key_tmp = (char *) &msg[1];
874   name_tmp = (char *) &zone_key_tmp[pubkey_len];
875   rd_tmp = &name_tmp[name_len];
876
877   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
878   msg->gns_header.header.size = htons (msg_size);
879   msg->gns_header.r_id = htonl (rid);
880   msg->key_len = htons (pubkey_len);
881   memcpy (zone_key_tmp, zone_key, pubkey_len);
882   msg->signature = *signature;
883   msg->name_len = htons (name_len);
884   memcpy (name_tmp, name, name_len);
885   msg->expire = GNUNET_TIME_absolute_hton (expire);
886   msg->rd_len = htons (rd_ser_len);
887   msg->rd_count = htons (rd_count);
888
889   memcpy (rd_tmp, rd_ser, rd_ser_len);
890
891   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);
892
893   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
894   do_transmit(h);
895
896   return qe;
897 }
898
899
900 /**
901  * Check if a signature is valid.  This API is used by the GNS Block
902  * to validate signatures received from the network.
903  *
904  * @param public_key public key of the zone
905  * @param name name that is being mapped (at most 255 characters long)
906  * @param rd_count number of entries in 'rd' array
907  * @param rd array of records with data to store
908  * @param signature signature for all the records in the zone under the given name
909  * @return GNUNET_OK if the signature is valid
910  */
911 int
912 GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
913                                    const char *name,
914                                    unsigned int rd_count,
915                                    const struct GNUNET_NAMESTORE_RecordData *rd,
916                                    const struct GNUNET_CRYPTO_RsaSignature *signature)
917 {
918   int res = GNUNET_SYSERR;
919   size_t rd_ser_len = 0;
920   size_t name_len = 0;
921   char * name_tmp;
922   char * rd_tmp;
923   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
924
925   GNUNET_assert (public_key != NULL);
926   GNUNET_assert (name != NULL);
927   GNUNET_assert (signature != NULL);
928
929   rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
930   char rd_ser[rd_ser_len];
931   GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
932
933   name_len = strlen (name) + 1;
934
935   sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + rd_ser_len + name_len);
936   sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len);
937   sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
938   name_tmp = (char *) &sig_purpose[1];
939   rd_tmp = &name_tmp[name_len];
940   memcpy (name_tmp, name, name_len);
941   memcpy (rd_tmp, rd_ser, rd_ser_len);
942
943   res = GNUNET_CRYPTO_rsa_verify(GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key);
944
945   GNUNET_free (sig_purpose);
946
947   return res;
948 }
949
950 /**
951  * Store an item in the namestore.  If the item is already present,
952  * the expiration time is updated to the max of the existing time and
953  * the new time.  This API is used by the authority of a zone.
954  *
955  * @param h handle to the namestore
956  * @param pkey private key of the zone
957  * @param name name that is being mapped (at most 255 characters long)
958  * @param rd record data to store
959  * @param cont continuation to call when done
960  * @param cont_cls closure for cont
961  * @return handle to abort the request
962  */
963 struct GNUNET_NAMESTORE_QueueEntry *
964 GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
965                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
966                                 const char *name,
967                                 const struct GNUNET_NAMESTORE_RecordData *rd,
968                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
969                                 void *cont_cls)
970 {
971   struct GNUNET_NAMESTORE_QueueEntry *qe;
972   struct PendingMessage *pe;
973   char * name_tmp;
974   char * pkey_tmp;
975   char * rd_tmp;
976   size_t rd_ser_len = 0;
977   size_t msg_size = 0;
978   size_t name_len = 0;
979   size_t key_len = 0;
980   uint32_t rid = 0;
981
982   GNUNET_assert (NULL != h);
983   GNUNET_assert (NULL != pkey);
984   GNUNET_assert (NULL != name);
985   GNUNET_assert (NULL != rd);
986
987   name_len = strlen(name) + 1;
988   if (name_len > 256)
989   {
990     GNUNET_break (0);
991     return NULL;
992   }
993
994   rid = get_op_id(h);
995   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
996   qe->nsh = h;
997   qe->cont = cont;
998   qe->cont_cls = cont_cls;
999   qe->op_id = rid;
1000   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1001
1002   /* set msg_size*/
1003   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1004   GNUNET_assert (pkey_enc != NULL);
1005   key_len = ntohs (pkey_enc->len);
1006
1007   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1008   char rd_ser[rd_ser_len];
1009   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1010
1011   struct RecordCreateMessage * msg;
1012   msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1013
1014   /* create msg here */
1015   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1016   pe->size = msg_size;
1017   pe->is_init = GNUNET_NO;
1018   msg = (struct RecordCreateMessage *) &pe[1];
1019
1020   pkey_tmp = (char *) &msg[1];
1021   name_tmp = &pkey_tmp[key_len];
1022   rd_tmp = &name_tmp[name_len];
1023
1024   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
1025   msg->gns_header.header.size = htons (msg_size);
1026   msg->gns_header.r_id = htonl (rid);
1027   msg->name_len = htons (name_len);
1028   msg->rd_count = htons (1);
1029   msg->rd_len = htons (rd_ser_len);
1030   msg->pkey_len = htons (key_len);
1031   memcpy (pkey_tmp, pkey_enc, key_len);
1032   memcpy (name_tmp, name, name_len);
1033   memcpy (rd_tmp, rd_ser, rd_ser_len);
1034   GNUNET_free (pkey_enc);
1035
1036   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);
1037
1038   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1039   do_transmit(h);
1040   return qe;
1041 }
1042
1043
1044 /**
1045  * Explicitly remove some content from the database.  The
1046  * "cont"inuation will be called with status "GNUNET_OK" if content
1047  * was removed, "GNUNET_NO" if no matching entry was found and
1048  * "GNUNET_SYSERR" on all other types of errors.
1049  * This API is used by the authority of a zone.
1050  *
1051  * @param h handle to the namestore
1052  * @param pkey private key of the zone
1053  * @param name name that is being mapped (at most 255 characters long)
1054  * @param rd record data
1055  * @param cont continuation to call when done
1056  * @param cont_cls closure for cont
1057  * @return handle to abort the request
1058  */
1059 struct GNUNET_NAMESTORE_QueueEntry *
1060 GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
1061                                 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
1062                                 const char *name,
1063                                 const struct GNUNET_NAMESTORE_RecordData *rd,
1064                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1065                                 void *cont_cls)
1066 {
1067   struct GNUNET_NAMESTORE_QueueEntry *qe;
1068   struct PendingMessage *pe;
1069   char *pkey_tmp;
1070   char *rd_tmp;
1071   char *name_tmp;
1072   size_t rd_ser_len = 0;
1073   size_t msg_size = 0;
1074   size_t name_len = 0;
1075   size_t key_len = 0;
1076   uint32_t rid = 0;
1077
1078   GNUNET_assert (NULL != h);
1079
1080   rid = get_op_id(h);
1081   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1082   qe->nsh = h;
1083   qe->cont = cont;
1084   qe->cont_cls = cont_cls;
1085   qe->op_id = rid;
1086   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1087
1088   /* set msg_size*/
1089   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
1090   GNUNET_assert (pkey_enc != NULL);
1091   key_len = ntohs (pkey_enc->len);
1092
1093   rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
1094   char rd_ser[rd_ser_len];
1095   GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);
1096
1097   name_len = strlen (name) + 1;
1098
1099   struct RecordRemoveMessage * msg;
1100   msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1101
1102   /* create msg here */
1103   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1104   pe->size = msg_size;
1105   pe->is_init = GNUNET_NO;
1106   msg = (struct RecordRemoveMessage *) &pe[1];
1107
1108   pkey_tmp = (char *) &msg[1];
1109   name_tmp = &pkey_tmp[key_len];
1110   rd_tmp = &name_tmp[name_len];
1111
1112   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE);
1113   msg->gns_header.header.size = htons (msg_size);
1114   msg->gns_header.r_id = htonl (rid);
1115   msg->name_len = htons (name_len);
1116   msg->rd_len = htons (rd_ser_len);
1117   msg->rd_count = htons (1);
1118   msg->key_len = htons (key_len);
1119   memcpy (pkey_tmp, pkey_enc, key_len);
1120   memcpy (name_tmp, name, name_len);
1121   memcpy (rd_tmp, rd_ser, rd_ser_len);
1122
1123   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size);
1124
1125   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1126   do_transmit(h);
1127   return qe;
1128 }
1129
1130
1131 /**
1132  * Get a result for a particular key from the namestore.  The processor
1133  * will only be called once.  
1134  *
1135  * @param h handle to the namestore
1136  * @param zone zone to look up a record from
1137  * @param name name to look up
1138  * @param record_type desired record type, 0 for all
1139  * @param proc function to call on the matching records, or with
1140  *        NULL (rd_count == 0) if there are no matching records
1141  * @param proc_cls closure for proc
1142  * @return a handle that can be used to
1143  *         cancel
1144  */
1145 struct GNUNET_NAMESTORE_QueueEntry *
1146 GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
1147                               const GNUNET_HashCode *zone,
1148                               const char *name,
1149                               uint32_t record_type,
1150                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
1151 {
1152   struct GNUNET_NAMESTORE_QueueEntry *qe;
1153   struct PendingMessage *pe;
1154   size_t msg_size = 0;
1155   size_t name_len = 0;
1156   uint32_t rid = 0;
1157
1158   GNUNET_assert (NULL != h);
1159   GNUNET_assert (NULL != zone);
1160   GNUNET_assert (NULL != name);
1161
1162   name_len = strlen (name) + 1;
1163   if ((name_len == 0) || (name_len > 256))
1164   {
1165     GNUNET_break (0);
1166     return NULL;
1167   }
1168
1169   rid = get_op_id(h);
1170   qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
1171   qe->nsh = h;
1172   qe->proc = proc;
1173   qe->proc_cls = proc_cls;
1174   qe->op_id = rid;
1175   GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);
1176
1177   /* set msg_size*/
1178   msg_size = sizeof (struct LookupNameMessage) + name_len;
1179   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1180
1181   /* create msg here */
1182   struct LookupNameMessage * msg;
1183   pe->size = msg_size;
1184   pe->is_init = GNUNET_NO;
1185   msg = (struct LookupNameMessage *) &pe[1];
1186   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
1187   msg->gns_header.header.size = htons (msg_size);
1188   msg->gns_header.r_id = htonl (rid);
1189   msg->record_type = htonl (record_type);
1190   msg->zone = *zone;
1191   msg->name_len = htonl (name_len);
1192   memcpy (&msg[1], name, name_len);
1193
1194   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);
1195
1196   /* transmit message */
1197   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1198   do_transmit(h);
1199
1200   return qe;
1201 }
1202
1203
1204
1205 /**
1206  * Starts a new zone iteration (used to periodically PUT all of our
1207  * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle
1208  * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and
1209  * GNUNET_NAMESTORE_zone_iteration_stop.  "proc" will be called once
1210  * immediately, and then again after
1211  * "GNUNET_NAMESTORE_zone_iterator_next" is invoked.
1212  *
1213  * @param h handle to the namestore
1214  * @param zone zone to access, NULL for all zones
1215  * @param must_have_flags flags that must be set for the record to be returned
1216  * @param must_not_have_flags flags that must NOT be set for the record to be returned
1217  * @param proc function to call on each name from the zone; it
1218  *        will be called repeatedly with a value (if available)
1219  *        and always once at the end with a name of NULL.
1220  * @param proc_cls closure for proc
1221  * @return an iterator handle to use for iteration
1222  */
1223 struct GNUNET_NAMESTORE_ZoneIterator *
1224 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
1225                                        const GNUNET_HashCode *zone,
1226                                        enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
1227                                        enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
1228                                        GNUNET_NAMESTORE_RecordProcessor proc,
1229                                        void *proc_cls)
1230 {
1231   struct GNUNET_NAMESTORE_ZoneIterator *it;
1232   struct PendingMessage *pe;
1233   size_t msg_size = 0;
1234   uint32_t rid = 0;
1235
1236   GNUNET_assert (NULL != h);
1237   GNUNET_assert (NULL != zone);
1238
1239   rid = get_op_id(h);
1240   it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator));
1241   it->h = h;
1242   it->proc = proc;
1243   it->proc_cls = proc;
1244   it->op_id = rid;
1245   it->zone = *zone;
1246   GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it);
1247
1248   /* set msg_size*/
1249   msg_size = sizeof (struct ZoneIterationStartMessage);
1250   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1251
1252   /* create msg here */
1253   struct ZoneIterationStartMessage * msg;
1254   pe->size = msg_size;
1255   pe->is_init = GNUNET_NO;
1256   msg = (struct ZoneIterationStartMessage *) &pe[1];
1257   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1258   msg->gns_header.header.size = htons (msg_size);
1259   msg->gns_header.r_id = htonl (rid);
1260   msg->zone = *zone;
1261   msg->must_have_flags = ntohs (must_have_flags);
1262   msg->must_not_have_flags = ntohs (must_not_have_flags);
1263
1264   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone));
1265
1266   /* transmit message */
1267   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1268   do_transmit(h);
1269
1270   return it;
1271 }
1272
1273
1274 /**
1275  * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start
1276  * for the next record.
1277  *
1278  * @param it the iterator
1279  */
1280 void
1281 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
1282 {
1283   struct GNUNET_NAMESTORE_Handle *h;
1284   struct PendingMessage *pe;
1285   size_t msg_size = 0;
1286
1287   GNUNET_assert (NULL != it);
1288   h = it->h;
1289
1290   /* set msg_size*/
1291   msg_size = sizeof (struct ZoneIterationNextMessage);
1292   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1293
1294   /* create msg here */
1295   struct ZoneIterationNextMessage * msg;
1296   pe->size = msg_size;
1297   pe->is_init = GNUNET_NO;
1298   msg = (struct ZoneIterationNextMessage *) &pe[1];
1299   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1300   msg->gns_header.header.size = htons (msg_size);
1301   msg->gns_header.r_id = htonl (it->op_id);
1302
1303   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone));
1304
1305   /* transmit message */
1306   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1307   do_transmit(h);
1308 }
1309
1310
1311 /**
1312  * Stops iteration and releases the namestore handle for further calls.
1313  *
1314  * @param it the iterator
1315  */
1316 void
1317 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1318 {
1319   GNUNET_assert (NULL != it);
1320   struct PendingMessage *pe;
1321   size_t msg_size = 0;
1322   struct GNUNET_NAMESTORE_Handle *h = it->h;
1323
1324   /* set msg_size*/
1325   msg_size = sizeof (struct ZoneIterationStopMessage);
1326   pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
1327
1328   /* create msg here */
1329   struct ZoneIterationStopMessage * msg;
1330   pe->size = msg_size;
1331   pe->is_init = GNUNET_NO;
1332   msg = (struct ZoneIterationStopMessage *) &pe[1];
1333   msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1334   msg->gns_header.header.size = htons (msg_size);
1335   msg->gns_header.r_id = htonl (it->op_id);
1336
1337   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone));
1338
1339   /* transmit message */
1340   GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
1341   do_transmit(h);
1342 }
1343
1344
1345 /**
1346  * Cancel a namestore operation.  The final callback from the
1347  * operation must not have been done yet.
1348  *
1349  * @param qe operation to cancel
1350  */
1351 void
1352 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1353 {
1354   struct GNUNET_NAMESTORE_Handle *h = qe->nsh;
1355
1356   GNUNET_assert (qe != NULL);
1357
1358   GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe);
1359   GNUNET_free(qe);
1360
1361 }
1362
1363 /* end of namestore_api.c */