RECLAIM: fix cli
[oweals/gnunet.git] / src / reclaim / gnunet-service-reclaim_tickets.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2012-2015 GNUnet e.V.
4
5    GNUnet is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License,
8    or (at your 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    Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18    SPDX-License-Identifier: AGPL3.0-or-later
19    */
20
21 /**
22  * @author Martin Schanzenbach
23  * @file src/reclaim/gnunet-service-reclaim_tickets.c
24  * @brief reclaim tickets
25  *
26  */
27 #include "gnunet-service-reclaim_tickets.h"
28
29 struct ParallelLookup;
30
31 struct RECLAIM_TICKETS_ConsumeHandle {
32   /**
33    * Ticket
34    */
35   struct GNUNET_RECLAIM_Ticket ticket;
36
37   /**
38    * LookupRequest
39    */
40   struct GNUNET_GNS_LookupRequest *lookup_request;
41
42   /**
43    * Audience Key
44    */
45   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
46
47   /**
48    * Audience Key
49    */
50   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
51
52   /**
53    * Lookup DLL
54    */
55   struct ParallelLookup *parallel_lookups_head;
56
57   /**
58    * Lookup DLL
59    */
60   struct ParallelLookup *parallel_lookups_tail;
61
62   /**
63    * Kill task
64    */
65   struct GNUNET_SCHEDULER_Task *kill_task;
66
67   /**
68    * Attributes
69    */
70   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
71
72   /**
73    * Lookup time
74    */
75   struct GNUNET_TIME_Absolute lookup_start_time;
76
77   /**
78    * Callback
79    */
80   RECLAIM_TICKETS_ConsumeCallback cb;
81
82   /**
83    * Callbacl closure
84    */
85   void *cb_cls;
86 };
87
88 /**
89  * Handle for a parallel GNS lookup job
90  */
91 struct ParallelLookup {
92   /* DLL */
93   struct ParallelLookup *next;
94
95   /* DLL */
96   struct ParallelLookup *prev;
97
98   /* The GNS request */
99   struct GNUNET_GNS_LookupRequest *lookup_request;
100
101   /* The handle the return to */
102   struct RECLAIM_TICKETS_ConsumeHandle *handle;
103
104   /**
105    * Lookup time
106    */
107   struct GNUNET_TIME_Absolute lookup_start_time;
108
109   /* The label to look up */
110   char *label;
111 };
112
113
114 /**
115  * A reference to a ticket stored in GNS
116  */
117 struct TicketReference {
118   /**
119    * DLL
120    */
121   struct TicketReference *next;
122
123   /**
124    * DLL
125    */
126   struct TicketReference *prev;
127
128   /**
129    * Attributes
130    */
131   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
132
133   /**
134    * Tickets
135    */
136   struct GNUNET_RECLAIM_Ticket ticket;
137 };
138
139
140 /**
141  * Ticket issue request handle
142  */
143 struct TicketIssueHandle {
144   /**
145    * Attributes to issue
146    */
147   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
148
149   /**
150    * Issuer Key
151    */
152   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
153
154   /**
155    * Ticket to issue
156    */
157   struct GNUNET_RECLAIM_Ticket ticket;
158
159   /**
160    * QueueEntry
161    */
162   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
163
164   /**
165    * Ticket reference list
166    */
167   struct TicketReference *ticket_refs_head;
168
169   /**
170    * Ticket reference list
171    */
172   struct TicketReference *ticket_refs_tail;
173
174   /**
175    * Number of references
176    */
177   uint32_t ticket_ref_num;
178
179   /**
180    * Callback
181    */
182   RECLAIM_TICKETS_TicketResult cb;
183
184   /**
185    * Callback cls
186    */
187   void *cb_cls;
188 };
189
190 /**
191  * Ticket iterator
192  */
193 struct RECLAIM_TICKETS_Iterator {
194   /**
195    * Issuer Key
196    */
197   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
198
199   /**
200    * Issuer pubkey
201    */
202   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
203
204   /**
205    * Namestore queue entry
206    */
207   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
208
209   /**
210    * Iter callback
211    */
212   RECLAIM_TICKETS_TicketIter cb;
213
214   /**
215    * Iter cls
216    */
217   void *cb_cls;
218
219   /**
220    * Ticket reference list
221    */
222   struct TicketReference *tickets_head;
223
224   /**
225    * Ticket reference list
226    */
227   struct TicketReference *tickets_tail;
228 };
229
230 /* Namestore handle */
231 static struct GNUNET_NAMESTORE_Handle *nsh;
232
233 /* GNS handle */
234 static struct GNUNET_GNS_Handle *gns;
235
236 /* Handle to the statistics service */
237 static struct GNUNET_STATISTICS_Handle *stats;
238
239
240 /**
241  * Cleanup ticket consume handle
242  * @param cth the handle to clean up
243  */
244 static void cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
245 {
246   struct ParallelLookup *lu;
247   struct ParallelLookup *tmp;
248   if (NULL != cth->lookup_request)
249     GNUNET_GNS_lookup_cancel (cth->lookup_request);
250   for (lu = cth->parallel_lookups_head; NULL != lu;) {
251     GNUNET_GNS_lookup_cancel (lu->lookup_request);
252     GNUNET_free (lu->label);
253     tmp = lu->next;
254     GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
255                                  cth->parallel_lookups_tail, lu);
256     GNUNET_free (lu);
257     lu = tmp;
258   }
259
260   if (NULL != cth->attrs)
261     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (cth->attrs);
262   GNUNET_free (cth);
263 }
264
265
266 static void
267 process_parallel_lookup_result (void *cls, uint32_t rd_count,
268                                 const struct GNUNET_GNSRECORD_Data *rd)
269 {
270   struct ParallelLookup *parallel_lookup = cls;
271   struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle;
272   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le;
273   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parallel lookup finished (count=%u)\n",
274               rd_count);
275
276   GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
277                                cth->parallel_lookups_tail, parallel_lookup);
278   GNUNET_free (parallel_lookup->label);
279
280   GNUNET_STATISTICS_update (
281       stats, "attribute_lookup_time_total",
282       GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time)
283           .rel_value_us,
284       GNUNET_YES);
285   GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES);
286
287
288   GNUNET_free (parallel_lookup);
289   if (1 != rd_count)
290     GNUNET_break (0); // TODO
291   if (rd->record_type == GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR) {
292     attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
293     attr_le->claim =
294         GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size);
295     GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head, cth->attrs->list_tail,
296                                  attr_le);
297   }
298   if (NULL != cth->parallel_lookups_head)
299     return; // Wait for more
300   /* Else we are done */
301
302   GNUNET_SCHEDULER_cancel (cth->kill_task);
303   cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL);
304   cleanup_cth (cth);
305 }
306
307
308 static void abort_parallel_lookups (void *cls)
309 {
310   struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
311   struct ParallelLookup *lu;
312   struct ParallelLookup *tmp;
313
314   cth->kill_task = NULL;
315   for (lu = cth->parallel_lookups_head; NULL != lu;) {
316     GNUNET_GNS_lookup_cancel (lu->lookup_request);
317     GNUNET_free (lu->label);
318     tmp = lu->next;
319     GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
320                                  cth->parallel_lookups_tail, lu);
321     GNUNET_free (lu);
322     lu = tmp;
323   }
324   cth->cb (cth->cb_cls, NULL, NULL, GNUNET_SYSERR, "Aborted");
325 }
326
327
328 static void lookup_authz_cb (void *cls, uint32_t rd_count,
329                              const struct GNUNET_GNSRECORD_Data *rd)
330 {
331   struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
332   struct ParallelLookup *parallel_lookup;
333   char *lbl;
334
335   cth->lookup_request = NULL;
336
337   GNUNET_STATISTICS_update (
338       stats, "reclaim_authz_lookup_time_total",
339       GNUNET_TIME_absolute_get_duration (cth->lookup_start_time).rel_value_us,
340       GNUNET_YES);
341   GNUNET_STATISTICS_update (stats, "reclaim_authz_lookups_count", 1,
342                             GNUNET_YES);
343
344   for (int i = 0; i < rd_count; i++) {
345     lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
346     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attribute ref found %s\n", lbl);
347     parallel_lookup = GNUNET_new (struct ParallelLookup);
348     parallel_lookup->handle = cth;
349     parallel_lookup->label = lbl;
350     parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
351     parallel_lookup->lookup_request = GNUNET_GNS_lookup (
352         gns, lbl, &cth->ticket.identity, GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR,
353         GNUNET_GNS_LO_DEFAULT, &process_parallel_lookup_result,
354         parallel_lookup);
355     GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
356                                  cth->parallel_lookups_tail, parallel_lookup);
357   }
358   cth->kill_task = GNUNET_SCHEDULER_add_delayed (
359       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3),
360       &abort_parallel_lookups, cth);
361 }
362
363
364 struct RECLAIM_TICKETS_ConsumeHandle *
365 RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_EcdsaPrivateKey *id,
366                          const struct GNUNET_RECLAIM_Ticket *ticket,
367                          RECLAIM_TICKETS_ConsumeCallback cb, void *cb_cls)
368 {
369   struct RECLAIM_TICKETS_ConsumeHandle *cth;
370   char *label;
371   cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle);
372
373   cth->identity = *id;
374   GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub);
375   cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
376   cth->ticket = *ticket;
377   cth->cb = cb;
378   cth->cb_cls = cb_cls;
379   label =
380       GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd, sizeof (uint64_t));
381   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for AuthZ info under %s\n",
382               label);
383   cth->lookup_start_time = GNUNET_TIME_absolute_get ();
384   cth->lookup_request = GNUNET_GNS_lookup (
385       gns, label, &cth->ticket.identity, GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF,
386       GNUNET_GNS_LO_DEFAULT, &lookup_authz_cb, cth);
387   GNUNET_free (label);
388   return cth;
389 }
390
391 void RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
392 {
393   cleanup_cth (cth);
394   return;
395 }
396
397
398 /*******************************
399  * Ticket issue
400  *******************************/
401
402 /**
403  * Cleanup ticket consume handle
404  * @param handle the handle to clean up
405  */
406 static void cleanup_issue_handle (struct TicketIssueHandle *handle)
407 {
408   struct TicketReference *tr;
409   struct TicketReference *tr_tmp;
410   if (NULL != handle->attrs)
411     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
412   if (NULL != handle->ns_qe)
413     GNUNET_NAMESTORE_cancel (handle->ns_qe);
414   for (tr = handle->ticket_refs_head; NULL != tr;) {
415     if (NULL != tr->attrs)
416       GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
417     tr_tmp = tr;
418     tr = tr->next;
419     GNUNET_free (tr_tmp);
420   }
421   GNUNET_free (handle);
422 }
423
424
425 static void store_ticket_refs_cont (void *cls, int32_t success,
426                                     const char *emsg)
427 {
428   struct TicketIssueHandle *handle = cls;
429   handle->ns_qe = NULL;
430   if (GNUNET_OK != success) {
431     handle->cb (handle->cb_cls, NULL, GNUNET_SYSERR,
432                 "Error storing updated ticket refs in GNS");
433     cleanup_issue_handle (handle);
434     return;
435   }
436   handle->cb (handle->cb_cls, &handle->ticket, GNUNET_OK, NULL);
437   cleanup_issue_handle (handle);
438 }
439
440
441 static void update_ticket_refs (void *cls)
442 {
443   struct TicketIssueHandle *handle = cls;
444   struct GNUNET_GNSRECORD_Data refs_rd[handle->ticket_ref_num];
445   struct TicketReference *tr;
446
447   tr = handle->ticket_refs_head;
448   for (int i = 0; i < handle->ticket_ref_num; i++) {
449     refs_rd[i].data = &tr->ticket;
450     refs_rd[i].data_size = sizeof (struct GNUNET_RECLAIM_Ticket);
451     refs_rd[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
452     refs_rd[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF;
453     refs_rd[i].flags =
454         GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
455     tr = tr->next;
456   }
457
458   handle->ns_qe = GNUNET_NAMESTORE_records_store (
459       nsh, &handle->identity, GNUNET_GNS_EMPTY_LABEL_AT, handle->ticket_ref_num,
460       refs_rd, &store_ticket_refs_cont, handle);
461 }
462
463
464 static void ticket_lookup_cb (void *cls,
465                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
466                               const char *label, unsigned int rd_count,
467                               const struct GNUNET_GNSRECORD_Data *rd)
468 {
469   struct TicketIssueHandle *handle = cls;
470   struct TicketReference *tr;
471
472   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
473               "Received tickets from local namestore.\n");
474   handle->ns_qe = NULL;
475   for (int i = 0; i < rd_count; i++) {
476     if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
477       continue;
478     tr = GNUNET_new (struct TicketReference);
479     memcpy (&tr->ticket, rd[i].data, sizeof (struct GNUNET_RECLAIM_Ticket));
480     if (0 != memcmp (&tr->ticket.identity, &handle->ticket.identity,
481                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) {
482       // Not our ticket
483       GNUNET_free (tr);
484       continue;
485     }
486     GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
487                                  handle->ticket_refs_tail, tr);
488     handle->ticket_ref_num++;
489   }
490   tr = GNUNET_new (struct TicketReference);
491   tr->ticket = handle->ticket;
492   tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (handle->attrs);
493   GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
494                                handle->ticket_refs_tail, tr);
495   handle->ticket_ref_num++;
496   GNUNET_SCHEDULER_add_now (&update_ticket_refs, handle);
497 }
498
499
500 /**
501  * TODO maybe we should cleanup the ATTRREFS here?
502  */
503 static void ticket_lookup_error_cb (void *cls)
504 {
505   struct TicketIssueHandle *handle = cls;
506   handle->ns_qe = NULL;
507   handle->cb (handle->cb_cls, &handle->ticket, GNUNET_SYSERR,
508               "Error checking for ticketsin GNS\n");
509   cleanup_issue_handle (handle);
510 }
511
512 static void store_ticket_issue_cont (void *cls, int32_t success,
513                                      const char *emsg)
514 {
515   struct TicketIssueHandle *handle = cls;
516
517   handle->ns_qe = NULL;
518   if (GNUNET_SYSERR == success) {
519     handle->cb (handle->cb_cls, &handle->ticket, GNUNET_SYSERR,
520                 "Error storing AuthZ ticket in GNS");
521     return;
522   }
523   /* First, local references to tickets */
524   handle->ns_qe = GNUNET_NAMESTORE_records_lookup (
525       nsh, &handle->identity, GNUNET_GNS_EMPTY_LABEL_AT,
526       &ticket_lookup_error_cb, handle, &ticket_lookup_cb, handle);
527 }
528
529
530 static void issue_ticket (struct TicketIssueHandle *ih)
531 {
532   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
533   struct GNUNET_GNSRECORD_Data *attrs_record;
534   char *label;
535   size_t list_len = 0;
536   int i;
537
538   for (le = ih->attrs->list_head; NULL != le; le = le->next)
539     list_len++;
540
541   attrs_record =
542       GNUNET_malloc (list_len * sizeof (struct GNUNET_GNSRECORD_Data));
543   i = 0;
544   for (le = ih->attrs->list_head; NULL != le; le = le->next) {
545     attrs_record[i].data = &le->claim->id;
546     attrs_record[i].data_size = sizeof (le->claim->id);
547     attrs_record[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
548     attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF;
549     attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
550     i++;
551   }
552
553   label =
554       GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, sizeof (uint64_t));
555   // Publish record
556   ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &ih->identity, label,
557                                               list_len, attrs_record,
558                                               &store_ticket_issue_cont, ih);
559   GNUNET_free (attrs_record);
560   GNUNET_free (label);
561 }
562
563
564 void RECLAIM_TICKETS_issue (
565     const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
566     const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
567     const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
568     RECLAIM_TICKETS_TicketResult cb, void *cb_cls)
569 {
570   struct TicketIssueHandle *tih;
571   tih = GNUNET_new (struct TicketIssueHandle);
572   tih->cb = cb;
573   tih->cb_cls = cb_cls;
574   tih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
575   tih->identity = *identity;
576   GNUNET_CRYPTO_ecdsa_key_get_public (identity, &tih->ticket.identity);
577   tih->ticket.rnd =
578       GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
579   tih->ticket.audience = *audience;
580   issue_ticket (tih);
581 }
582
583 /************************************
584  * Ticket iteration
585  ************************************/
586
587 static void cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter)
588 {
589   struct TicketReference *tr;
590   struct TicketReference *tr_tmp;
591   if (NULL != iter->ns_qe)
592     GNUNET_NAMESTORE_cancel (iter->ns_qe);
593   for (tr = iter->tickets_head; NULL != tr;) {
594     if (NULL != tr->attrs)
595       GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
596     tr_tmp = tr;
597     tr = tr->next;
598     GNUNET_free (tr_tmp);
599   }
600   GNUNET_free (iter);
601 }
602
603 static void do_cleanup_iter (void *cls)
604 {
605   struct RECLAIM_TICKETS_Iterator *iter = cls;
606   cleanup_iter (iter);
607 }
608
609 /**
610  * Perform ticket iteration step
611  *
612  * @param ti ticket iterator to process
613  */
614 static void run_ticket_iteration_round (struct RECLAIM_TICKETS_Iterator *iter)
615 {
616   struct TicketReference *tr;
617   if (NULL == iter->tickets_head) {
618     // No more tickets
619     iter->cb (iter->cb_cls, NULL);
620     GNUNET_SCHEDULER_add_now (&do_cleanup_iter, iter);
621     return;
622   }
623   tr = iter->tickets_head;
624   GNUNET_CONTAINER_DLL_remove (iter->tickets_head, iter->tickets_tail, tr);
625   iter->cb (iter->cb_cls, &tr->ticket);
626   if (NULL != tr->attrs)
627     GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
628   GNUNET_free (tr);
629 }
630
631 static void
632 collect_tickets_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
633                     const char *label, unsigned int rd_count,
634                     const struct GNUNET_GNSRECORD_Data *rd)
635 {
636   struct RECLAIM_TICKETS_Iterator *iter = cls;
637   struct TicketReference *tr;
638   iter->ns_qe = NULL;
639
640   for (int i = 0; i < rd_count; i++) {
641     if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
642       continue;
643     tr = GNUNET_new (struct TicketReference);
644     memcpy (&tr->ticket, rd[i].data, sizeof (struct GNUNET_RECLAIM_Ticket));
645     if (0 != memcmp (&tr->ticket.identity, &iter->identity_pub,
646                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) {
647       // Not our ticket
648       GNUNET_free (tr);
649       continue;
650     }
651     GNUNET_CONTAINER_DLL_insert (iter->tickets_head, iter->tickets_tail, tr);
652   }
653   run_ticket_iteration_round (iter);
654 }
655
656 static void collect_tickets_error_cb (void *cls)
657 {
658   struct RECLAIM_TICKETS_Iterator *iter = cls;
659   iter->ns_qe = NULL;
660   iter->cb (iter->cb_cls, NULL);
661   cleanup_iter (iter);
662 }
663
664 void RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter)
665 {
666   run_ticket_iteration_round (iter);
667 }
668
669 void RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter)
670 {
671   cleanup_iter (iter);
672 }
673
674 struct RECLAIM_TICKETS_Iterator *RECLAIM_TICKETS_iteration_start (
675     const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
676     RECLAIM_TICKETS_TicketIter cb, void *cb_cls)
677 {
678   struct RECLAIM_TICKETS_Iterator *iter;
679
680   iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator);
681   iter->identity = *identity;
682   GNUNET_CRYPTO_ecdsa_key_get_public (identity, &iter->identity_pub);
683   iter->cb = cb;
684   iter->cb_cls = cb_cls;
685   iter->ns_qe = GNUNET_NAMESTORE_records_lookup (
686       nsh, identity, GNUNET_GNS_EMPTY_LABEL_AT, &collect_tickets_error_cb, iter,
687       &collect_tickets_cb, iter);
688   return iter;
689 }
690
691
692 int RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
693 {
694   // Connect to identity and namestore services
695   nsh = GNUNET_NAMESTORE_connect (c);
696   if (NULL == nsh) {
697     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
698                          "error connecting to namestore");
699     return GNUNET_SYSERR;
700   }
701   gns = GNUNET_GNS_connect (c);
702   if (NULL == gns) {
703     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
704     return GNUNET_SYSERR;
705   }
706   stats = GNUNET_STATISTICS_create ("reclaim", c);
707   return GNUNET_OK;
708 }
709
710 void RECLAIM_TICKETS_deinit (void)
711 {
712   if (NULL != nsh)
713     GNUNET_NAMESTORE_disconnect (nsh);
714   nsh = NULL;
715   if (NULL != gns)
716     GNUNET_GNS_disconnect (gns);
717   gns = NULL;
718   if (NULL != stats) {
719     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
720     stats = NULL;
721   }
722 }