2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @author Martin Schanzenbach
23 * @file src/reclaim/gnunet-service-reclaim_tickets.c
24 * @brief reclaim tickets
27 #include "gnunet-service-reclaim_tickets.h"
29 struct ParallelLookup;
31 struct RECLAIM_TICKETS_ConsumeHandle {
35 struct GNUNET_RECLAIM_Ticket ticket;
40 struct GNUNET_GNS_LookupRequest *lookup_request;
45 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
50 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
55 struct ParallelLookup *parallel_lookups_head;
60 struct ParallelLookup *parallel_lookups_tail;
65 struct GNUNET_SCHEDULER_Task *kill_task;
70 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
75 struct GNUNET_TIME_Absolute lookup_start_time;
80 RECLAIM_TICKETS_ConsumeCallback cb;
89 * Handle for a parallel GNS lookup job
91 struct ParallelLookup {
93 struct ParallelLookup *next;
96 struct ParallelLookup *prev;
99 struct GNUNET_GNS_LookupRequest *lookup_request;
101 /* The handle the return to */
102 struct RECLAIM_TICKETS_ConsumeHandle *handle;
107 struct GNUNET_TIME_Absolute lookup_start_time;
109 /* The label to look up */
115 * A reference to a ticket stored in GNS
117 struct TicketReference {
121 struct TicketReference *next;
126 struct TicketReference *prev;
131 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
136 struct GNUNET_RECLAIM_Ticket ticket;
141 * Ticket issue request handle
143 struct TicketIssueHandle {
145 * Attributes to issue
147 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
152 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
157 struct GNUNET_RECLAIM_Ticket ticket;
162 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
165 * Ticket reference list
167 struct TicketReference *ticket_refs_head;
170 * Ticket reference list
172 struct TicketReference *ticket_refs_tail;
175 * Number of references
177 uint32_t ticket_ref_num;
182 RECLAIM_TICKETS_TicketResult cb;
193 struct RECLAIM_TICKETS_Iterator {
197 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
202 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
205 * Namestore queue entry
207 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
212 RECLAIM_TICKETS_TicketIter cb;
220 * Ticket reference list
222 struct TicketReference *tickets_head;
225 * Ticket reference list
227 struct TicketReference *tickets_tail;
230 /* Namestore handle */
231 static struct GNUNET_NAMESTORE_Handle *nsh;
234 static struct GNUNET_GNS_Handle *gns;
236 /* Handle to the statistics service */
237 static struct GNUNET_STATISTICS_Handle *stats;
239 static int create_sym_key_from_ecdh (
240 const struct GNUNET_HashCode *new_key_hash,
241 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
242 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
244 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
246 GNUNET_CRYPTO_hash_to_enc (new_key_hash, &new_key_hash_str);
247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n",
248 (char *)&new_key_hash_str);
249 static const char ctx_key[] = "gnuid-aes-ctx-key";
250 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
251 new_key_hash, sizeof (struct GNUNET_HashCode), ctx_key,
252 strlen (ctx_key), NULL, 0);
253 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
255 iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
256 new_key_hash, sizeof (struct GNUNET_HashCode), ctx_iv, strlen (ctx_iv),
263 * Cleanup ticket consume handle
264 * @param cth the handle to clean up
266 static void cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
268 struct ParallelLookup *lu;
269 struct ParallelLookup *tmp;
270 if (NULL != cth->lookup_request)
271 GNUNET_GNS_lookup_cancel (cth->lookup_request);
272 for (lu = cth->parallel_lookups_head; NULL != lu;) {
273 GNUNET_GNS_lookup_cancel (lu->lookup_request);
274 GNUNET_free (lu->label);
276 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
277 cth->parallel_lookups_tail, lu);
282 if (NULL != cth->attrs)
283 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (cth->attrs);
289 process_parallel_lookup_result (void *cls, uint32_t rd_count,
290 const struct GNUNET_GNSRECORD_Data *rd)
292 struct ParallelLookup *parallel_lookup = cls;
293 struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle;
294 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le;
295 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parallel lookup finished (count=%u)\n",
298 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
299 cth->parallel_lookups_tail, parallel_lookup);
300 GNUNET_free (parallel_lookup->label);
302 GNUNET_STATISTICS_update (
303 stats, "attribute_lookup_time_total",
304 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time)
307 GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES);
310 GNUNET_free (parallel_lookup);
312 GNUNET_break (0); // TODO
313 if (rd->record_type == GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR) {
314 attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
316 GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size);
317 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head, cth->attrs->list_tail,
320 if (NULL != cth->parallel_lookups_head)
321 return; // Wait for more
322 /* Else we are done */
324 GNUNET_SCHEDULER_cancel (cth->kill_task);
325 cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL);
330 static void abort_parallel_lookups (void *cls)
332 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
333 struct ParallelLookup *lu;
334 struct ParallelLookup *tmp;
336 cth->kill_task = NULL;
337 for (lu = cth->parallel_lookups_head; NULL != lu;) {
338 GNUNET_GNS_lookup_cancel (lu->lookup_request);
339 GNUNET_free (lu->label);
341 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
342 cth->parallel_lookups_tail, lu);
346 cth->cb (cth->cb_cls, NULL, NULL, GNUNET_SYSERR, "Aborted");
350 static void lookup_authz_cb (void *cls, uint32_t rd_count,
351 const struct GNUNET_GNSRECORD_Data *rd)
353 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
354 struct GNUNET_HashCode new_key_hash;
355 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
356 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
357 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
358 struct ParallelLookup *parallel_lookup;
364 cth->lookup_request = NULL;
366 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Number of keys %d != 1.", rd_count);
367 cth->cb (cth->cb_cls, NULL, NULL, GNUNET_SYSERR, "Number of keys %d != 1.");
373 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
375 buf = GNUNET_malloc (rd->data_size -
376 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
378 // Calculate symmetric key from ecdh parameters
379 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (
380 &cth->identity, ecdh_key, &new_key_hash));
381 create_sym_key_from_ecdh (&new_key_hash, &enc_key, &enc_iv);
382 size = GNUNET_CRYPTO_symmetric_decrypt (
383 rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
384 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), &enc_key,
387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
388 "Decrypted bytes: %zd Expected bytes: %zd\n", size,
389 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
390 GNUNET_STATISTICS_update (
391 stats, "reclaim_authz_lookup_time_total",
392 GNUNET_TIME_absolute_get_duration (cth->lookup_start_time).rel_value_us,
394 GNUNET_STATISTICS_update (stats, "reclaim_authz_lookups_count", 1,
396 lbls = GNUNET_strdup (buf);
397 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attributes found %s\n", lbls);
399 for (attr_lbl = strtok (lbls, ","); NULL != attr_lbl;
400 attr_lbl = strtok (NULL, ",")) {
401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking up %s\n", attr_lbl);
402 parallel_lookup = GNUNET_new (struct ParallelLookup);
403 parallel_lookup->handle = cth;
404 parallel_lookup->label = GNUNET_strdup (attr_lbl);
405 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
406 parallel_lookup->lookup_request = GNUNET_GNS_lookup (
407 gns, attr_lbl, &cth->ticket.identity,
408 GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR, GNUNET_GNS_LO_DEFAULT,
409 &process_parallel_lookup_result, parallel_lookup);
410 GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
411 cth->parallel_lookups_tail, parallel_lookup);
415 cth->kill_task = GNUNET_SCHEDULER_add_delayed (
416 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3),
417 &abort_parallel_lookups, cth);
421 struct RECLAIM_TICKETS_ConsumeHandle *
422 RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_EcdsaPrivateKey *id,
423 const struct GNUNET_RECLAIM_Ticket *ticket,
424 RECLAIM_TICKETS_ConsumeCallback cb, void *cb_cls)
426 struct RECLAIM_TICKETS_ConsumeHandle *cth;
428 cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle);
431 GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub);
432 cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
433 cth->ticket = *ticket;
435 cth->cb_cls = cb_cls;
437 GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd, sizeof (uint64_t));
438 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for AuthZ info under %s\n",
440 cth->lookup_start_time = GNUNET_TIME_absolute_get ();
441 cth->lookup_request = GNUNET_GNS_lookup (
442 gns, label, &cth->ticket.identity, GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ,
443 GNUNET_GNS_LO_DEFAULT, &lookup_authz_cb, cth);
448 void RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
455 /*******************************
457 *******************************/
460 * Cleanup ticket consume handle
461 * @param handle the handle to clean up
463 static void cleanup_issue_handle (struct TicketIssueHandle *handle)
465 struct TicketReference *tr;
466 struct TicketReference *tr_tmp;
467 if (NULL != handle->attrs)
468 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
469 if (NULL != handle->ns_qe)
470 GNUNET_NAMESTORE_cancel (handle->ns_qe);
471 for (tr = handle->ticket_refs_head; NULL != tr;) {
472 if (NULL != tr->attrs)
473 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
476 GNUNET_free (tr_tmp);
478 GNUNET_free (handle);
482 static void store_ticket_refs_cont (void *cls, int32_t success,
485 struct TicketIssueHandle *handle = cls;
486 handle->ns_qe = NULL;
487 if (GNUNET_OK != success) {
488 handle->cb (handle->cb_cls, NULL, GNUNET_SYSERR,
489 "Error storing updated ticket refs in GNS");
490 cleanup_issue_handle (handle);
493 handle->cb (handle->cb_cls, &handle->ticket, GNUNET_OK, NULL);
494 cleanup_issue_handle (handle);
498 static void update_ticket_refs (void *cls)
500 struct TicketIssueHandle *handle = cls;
501 struct GNUNET_GNSRECORD_Data refs_rd[handle->ticket_ref_num];
502 struct TicketReference *tr;
506 tr = handle->ticket_refs_head;
507 for (int i = 0; i < handle->ticket_ref_num; i++) {
508 buf_size = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (tr->attrs);
509 buf_size += sizeof (struct GNUNET_RECLAIM_Ticket);
510 buf = GNUNET_malloc (buf_size);
511 memcpy (buf, &tr->ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
512 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
513 tr->attrs, buf + sizeof (struct GNUNET_RECLAIM_Ticket));
514 refs_rd[i].data = buf;
515 refs_rd[i].data_size = buf_size;
516 refs_rd[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
517 refs_rd[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF;
519 GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
523 handle->ns_qe = GNUNET_NAMESTORE_records_store (
524 nsh, &handle->identity, GNUNET_GNS_EMPTY_LABEL_AT, handle->ticket_ref_num,
525 refs_rd, &store_ticket_refs_cont, handle);
526 for (int i = 0; i < handle->ticket_ref_num; i++)
527 GNUNET_free ((char *)refs_rd[i].data);
531 static void ticket_lookup_cb (void *cls,
532 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
533 const char *label, unsigned int rd_count,
534 const struct GNUNET_GNSRECORD_Data *rd)
536 struct TicketIssueHandle *handle = cls;
537 struct TicketReference *tr;
538 const char *attr_data;
539 size_t attr_data_len;
540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
541 "Received tickets from local namestore.\n");
542 handle->ns_qe = NULL;
543 for (int i = 0; i < rd_count; i++) {
544 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
546 tr = GNUNET_new (struct TicketReference);
547 memcpy (&tr->ticket, rd[i].data, sizeof (struct GNUNET_RECLAIM_Ticket));
548 if (0 != memcmp (&tr->ticket.identity, &handle->ticket.identity,
549 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) {
554 attr_data = rd[i].data + sizeof (struct GNUNET_RECLAIM_Ticket);
555 attr_data_len = rd[i].data_size - sizeof (struct GNUNET_RECLAIM_Ticket);
557 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attr_data, attr_data_len);
558 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
559 handle->ticket_refs_tail, tr);
560 handle->ticket_ref_num++;
562 tr = GNUNET_new (struct TicketReference);
563 tr->ticket = handle->ticket;
564 tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (handle->attrs);
565 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
566 handle->ticket_refs_tail, tr);
567 handle->ticket_ref_num++;
568 GNUNET_SCHEDULER_add_now (&update_ticket_refs, handle);
571 static void ticket_lookup_error_cb (void *cls)
573 struct TicketIssueHandle *handle = cls;
574 handle->ns_qe = NULL;
575 handle->cb (handle->cb_cls, &handle->ticket, GNUNET_SYSERR,
576 "Error checking for ticketsin GNS\n");
577 cleanup_issue_handle (handle);
580 static void store_ticket_issue_cont (void *cls, int32_t success,
583 struct TicketIssueHandle *handle = cls;
585 handle->ns_qe = NULL;
586 if (GNUNET_SYSERR == success) {
587 handle->cb (handle->cb_cls, &handle->ticket, GNUNET_SYSERR,
588 "Error storing AuthZ ticket in GNS");
591 /* First, local references to tickets */
592 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (
593 nsh, &handle->identity, GNUNET_GNS_EMPTY_LABEL_AT,
594 &ticket_lookup_error_cb, handle, &ticket_lookup_cb, handle);
599 serialize_authz_record (const struct GNUNET_RECLAIM_Ticket *ticket,
600 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
601 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
604 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
605 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
606 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
607 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
608 struct GNUNET_HashCode new_key_hash;
616 GNUNET_assert (NULL != attrs->list_head);
618 for (le = attrs->list_head; NULL != le; le = le->next) {
619 attrs_str_len += 15 + 1; // TODO propery calculate
621 buf = GNUNET_malloc (attrs_str_len);
623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing attributes\n");
624 for (le = attrs->list_head; NULL != le; le = le->next) {
626 GNUNET_STRINGS_data_to_string_alloc (&le->claim->id, sizeof (uint64_t));
627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute to record: %s\n",
630 GNUNET_memcpy (write_ptr, label, strlen (label));
631 write_ptr[strlen (label)] = ',';
632 write_ptr += strlen (label) + 1;
636 write_ptr[0] = '\0'; // replace last , with a 0-terminator
637 // ECDH keypair E = eG
638 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create ();
639 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey, &ecdh_pubkey);
640 enc_keyinfo = GNUNET_malloc (attrs_str_len);
641 // Derived key K = H(eB)
642 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
645 create_sym_key_from_ecdh (&new_key_hash, &skey, &iv);
646 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf, attrs_str_len, &skey, &iv,
649 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + enc_size);
650 GNUNET_memcpy (*result, &ecdh_pubkey,
651 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
652 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
653 enc_keyinfo, enc_size);
654 GNUNET_free (enc_keyinfo);
656 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + enc_size;
660 static void issue_ticket (struct TicketIssueHandle *ih)
662 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
663 struct GNUNET_GNSRECORD_Data code_record[1];
664 char *authz_record_data;
665 size_t authz_record_len;
668 // TODO rename function
669 authz_record_len = serialize_authz_record (
670 &ih->ticket, ih->attrs, &ecdhe_privkey, &authz_record_data);
671 code_record[0].data = authz_record_data;
672 code_record[0].data_size = authz_record_len;
673 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
674 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ;
675 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
678 GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, sizeof (uint64_t));
680 ih->ns_qe = GNUNET_NAMESTORE_records_store (
681 nsh, &ih->identity, label, 1, code_record, &store_ticket_issue_cont, ih);
682 GNUNET_free (ecdhe_privkey);
684 GNUNET_free (authz_record_data);
688 void RECLAIM_TICKETS_issue (
689 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
690 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
691 const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
692 RECLAIM_TICKETS_TicketResult cb, void *cb_cls)
694 struct TicketIssueHandle *tih;
695 tih = GNUNET_new (struct TicketIssueHandle);
697 tih->cb_cls = cb_cls;
698 tih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
699 tih->identity = *identity;
700 GNUNET_CRYPTO_ecdsa_key_get_public (identity, &tih->ticket.identity);
702 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
703 tih->ticket.audience = *audience;
707 /************************************
709 ************************************/
711 static void cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter)
713 struct TicketReference *tr;
714 struct TicketReference *tr_tmp;
715 if (NULL != iter->ns_qe)
716 GNUNET_NAMESTORE_cancel (iter->ns_qe);
717 for (tr = iter->tickets_head; NULL != tr;) {
718 if (NULL != tr->attrs)
719 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
722 GNUNET_free (tr_tmp);
727 static void do_cleanup_iter (void *cls)
729 struct RECLAIM_TICKETS_Iterator *iter = cls;
734 * Perform ticket iteration step
736 * @param ti ticket iterator to process
738 static void run_ticket_iteration_round (struct RECLAIM_TICKETS_Iterator *iter)
740 struct TicketReference *tr;
741 if (NULL == iter->tickets_head) {
743 iter->cb (iter->cb_cls, NULL);
744 GNUNET_SCHEDULER_add_now (&do_cleanup_iter, iter);
747 tr = iter->tickets_head;
748 GNUNET_CONTAINER_DLL_remove (iter->tickets_head, iter->tickets_tail, tr);
749 iter->cb (iter->cb_cls, &tr->ticket);
750 if (NULL != tr->attrs)
751 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
756 collect_tickets_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
757 const char *label, unsigned int rd_count,
758 const struct GNUNET_GNSRECORD_Data *rd)
760 struct RECLAIM_TICKETS_Iterator *iter = cls;
761 struct TicketReference *tr;
762 size_t attr_data_len;
763 const char *attr_data;
766 for (int i = 0; i < rd_count; i++) {
767 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
769 tr = GNUNET_new (struct TicketReference);
770 memcpy (&tr->ticket, rd[i].data, sizeof (struct GNUNET_RECLAIM_Ticket));
771 if (0 != memcmp (&tr->ticket.identity, &iter->identity_pub,
772 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) {
777 attr_data = rd[i].data + sizeof (struct GNUNET_RECLAIM_Ticket);
778 attr_data_len = rd[i].data_size - sizeof (struct GNUNET_RECLAIM_Ticket);
780 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attr_data, attr_data_len);
781 GNUNET_CONTAINER_DLL_insert (iter->tickets_head, iter->tickets_tail, tr);
783 run_ticket_iteration_round (iter);
786 static void collect_tickets_error_cb (void *cls)
788 struct RECLAIM_TICKETS_Iterator *iter = cls;
790 iter->cb (iter->cb_cls, NULL);
794 void RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter)
796 run_ticket_iteration_round (iter);
799 void RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter)
804 struct RECLAIM_TICKETS_Iterator *RECLAIM_TICKETS_iteration_start (
805 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
806 RECLAIM_TICKETS_TicketIter cb, void *cb_cls)
808 struct RECLAIM_TICKETS_Iterator *iter;
810 iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator);
811 iter->identity = *identity;
812 GNUNET_CRYPTO_ecdsa_key_get_public (identity, &iter->identity_pub);
814 iter->cb_cls = cb_cls;
815 iter->ns_qe = GNUNET_NAMESTORE_records_lookup (
816 nsh, identity, GNUNET_GNS_EMPTY_LABEL_AT, &collect_tickets_error_cb, iter,
817 &collect_tickets_cb, iter);
822 int RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
824 // Connect to identity and namestore services
825 nsh = GNUNET_NAMESTORE_connect (c);
827 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
828 "error connecting to namestore");
829 return GNUNET_SYSERR;
831 gns = GNUNET_GNS_connect (c);
833 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
834 return GNUNET_SYSERR;
836 stats = GNUNET_STATISTICS_create ("reclaim", c);
840 void RECLAIM_TICKETS_deinit (void)
843 GNUNET_NAMESTORE_disconnect (nsh);
846 GNUNET_GNS_disconnect (gns);
849 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);