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
29 #include "gnunet-service-reclaim_tickets.h"
31 struct ParallelLookup;
33 struct RECLAIM_TICKETS_ConsumeHandle {
37 struct GNUNET_RECLAIM_Ticket ticket;
42 struct GNUNET_GNS_LookupRequest *lookup_request;
47 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
52 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
57 struct ParallelLookup *parallel_lookups_head;
62 struct ParallelLookup *parallel_lookups_tail;
67 struct GNUNET_SCHEDULER_Task *kill_task;
72 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
77 struct GNUNET_TIME_Absolute lookup_start_time;
82 RECLAIM_TICKETS_ConsumeCallback cb;
91 * Handle for a parallel GNS lookup job
93 struct ParallelLookup {
95 struct ParallelLookup *next;
98 struct ParallelLookup *prev;
100 /* The GNS request */
101 struct GNUNET_GNS_LookupRequest *lookup_request;
103 /* The handle the return to */
104 struct RECLAIM_TICKETS_ConsumeHandle *handle;
109 struct GNUNET_TIME_Absolute lookup_start_time;
111 /* The label to look up */
117 * A reference to a ticket stored in GNS
119 struct TicketReference {
123 struct TicketReference *next;
128 struct TicketReference *prev;
133 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
138 struct GNUNET_RECLAIM_Ticket ticket;
143 * Ticket issue request handle
145 struct TicketIssueHandle {
147 * Attributes to issue
149 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
154 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
159 struct GNUNET_RECLAIM_Ticket ticket;
164 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
167 * Ticket reference list
169 struct TicketReference *ticket_refs_head;
172 * Ticket reference list
174 struct TicketReference *ticket_refs_tail;
177 * Number of references
179 uint32_t ticket_ref_num;
184 RECLAIM_TICKETS_TicketResult cb;
195 struct RECLAIM_TICKETS_Iterator {
199 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
204 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
207 * Namestore queue entry
209 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
214 RECLAIM_TICKETS_TicketIter cb;
222 * Ticket reference list
224 struct TicketReference *tickets_head;
227 * Ticket reference list
229 struct TicketReference *tickets_tail;
233 struct RevokedAttributeEntry {
237 struct RevokedAttributeEntry *next;
242 struct RevokedAttributeEntry *prev;
245 * Old ID of the attribute
250 * New ID of the attribute
256 struct TicketRecordsEntry {
260 struct TicketRecordsEntry *next;
265 struct TicketRecordsEntry *prev;
270 unsigned int rd_count;
289 * Ticket revocation request handle
291 struct RECLAIM_TICKETS_RevokeHandle {
295 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
300 RECLAIM_TICKETS_RevokeCallback cb;
310 struct GNUNET_RECLAIM_Ticket ticket;
315 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
320 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
325 struct RevokedAttributeEntry *attrs_head;
330 struct RevokedAttributeEntry *attrs_tail;
333 * Current attribute to move
335 struct RevokedAttributeEntry *move_attr;
338 * Number of attributes in ticket
340 unsigned int ticket_attrs;
345 struct TicketRecordsEntry *tickets_to_update_head;
350 struct TicketRecordsEntry *tickets_to_update_tail;
354 /* Namestore handle */
355 static struct GNUNET_NAMESTORE_Handle *nsh;
358 static struct GNUNET_GNS_Handle *gns;
360 /* Handle to the statistics service */
361 static struct GNUNET_STATISTICS_Handle *stats;
364 move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rh);
367 move_attrs_cont (void *cls)
369 move_attrs ((struct RECLAIM_TICKETS_RevokeHandle *)cls);
373 * Cleanup revoke handle
375 * @param rh the ticket revocation handle
378 cleanup_rvk (struct RECLAIM_TICKETS_RevokeHandle *rh)
380 struct RevokedAttributeEntry *ae;
381 struct TicketRecordsEntry *le;
382 if (NULL != rh->ns_qe)
383 GNUNET_NAMESTORE_cancel (rh->ns_qe);
384 if (NULL != rh->ns_it)
385 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
386 while (NULL != (ae = rh->attrs_head)) {
387 GNUNET_CONTAINER_DLL_remove (rh->attrs_head, rh->attrs_tail, ae);
390 while (NULL != (le = rh->tickets_to_update_head)) {
391 GNUNET_CONTAINER_DLL_remove (rh->tickets_to_update_head,
392 rh->tickets_to_update_head, le);
393 if (NULL != le->data)
394 GNUNET_free (le->data);
395 if (NULL != le->label)
396 GNUNET_free (le->label);
403 del_attr_finished (void *cls, int32_t success, const char *emsg)
405 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
407 if (GNUNET_SYSERR == success) {
408 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error removing attribute: %s\n",
410 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Continuing\n");
415 rvk->move_attr = rvk->move_attr->next;
416 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
420 move_attr_finished (void *cls, int32_t success, const char *emsg)
422 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
425 if (GNUNET_SYSERR == success) {
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error moving attribute: %s\n", emsg);
427 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
431 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
433 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Removing attribute %s\n", label);
434 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &rvk->identity, label, 0,
435 NULL, &del_attr_finished, rvk);
440 rvk_move_attr_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
441 const char *label, unsigned int rd_count,
442 const struct GNUNET_GNSRECORD_Data *rd)
444 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
445 struct RevokedAttributeEntry *le;
449 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
450 "The attribute %s no longer exists!\n", label);
452 rvk->move_attr = le->next;
453 GNUNET_CONTAINER_DLL_remove (rvk->attrs_head, rvk->attrs_tail, le);
455 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
458 /** find a new place for this attribute **/
459 rvk->move_attr->new_id =
460 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
461 new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
463 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute %s\n", new_label);
464 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &rvk->identity, new_label,
465 1, rd, &move_attr_finished, rvk);
466 GNUNET_free (new_label);
471 rvk_ticket_update (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
472 const char *label, unsigned int rd_count,
473 const struct GNUNET_GNSRECORD_Data *rd)
475 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
476 struct TicketRecordsEntry *le;
477 struct RevokedAttributeEntry *ae;
478 int has_changed = GNUNET_NO;
480 /** Let everything point to the old record **/
481 for (int i = 0; i < rd_count; i++) {
482 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
484 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next) {
485 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof (uint64_t)))
487 has_changed = GNUNET_YES;
490 if (GNUNET_YES == has_changed)
493 if (GNUNET_YES == has_changed) {
494 le = GNUNET_new (struct TicketRecordsEntry);
495 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
496 le->data = GNUNET_malloc (le->data_size);
497 le->rd_count = rd_count;
498 le->label = GNUNET_strdup (label);
499 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
500 GNUNET_CONTAINER_DLL_insert (rvk->tickets_to_update_head,
501 rvk->tickets_to_update_tail, le);
503 GNUNET_NAMESTORE_zone_iterator_next (rvk->ns_it, 1);
508 process_tickets (void *cls);
512 ticket_processed (void *cls, int32_t success, const char *emsg)
514 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
516 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
520 process_tickets (void *cls)
522 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
523 struct TicketRecordsEntry *le;
524 struct RevokedAttributeEntry *ae;
525 if (NULL == rvk->tickets_to_update_head) {
526 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
527 "Finished updatding tickets, success\n");
528 rvk->cb (rvk->cb_cls, GNUNET_OK);
532 le = rvk->tickets_to_update_head;
533 GNUNET_CONTAINER_DLL_remove (rvk->tickets_to_update_head,
534 rvk->tickets_to_update_tail, le);
535 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
536 GNUNET_GNSRECORD_records_deserialize (le->data_size, le->data, le->rd_count,
538 for (int i = 0; i < le->rd_count; i++) {
539 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
541 for (ae = rvk->attrs_head; NULL != ae; ae = ae->next) {
542 if (0 != memcmp (rd[i].data, &ae->old_id, sizeof (uint64_t)))
544 rd[i].data = &ae->new_id;
547 rvk->ns_qe = GNUNET_NAMESTORE_records_store (
548 nsh, &rvk->identity, le->label, le->rd_count, rd, &ticket_processed, rvk);
549 GNUNET_free (le->label);
550 GNUNET_free (le->data);
555 rvk_ticket_update_finished (void *cls)
557 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
559 GNUNET_SCHEDULER_add_now (&process_tickets, rvk);
564 rvk_ns_iter_err (void *cls)
566 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
568 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
569 "Namestore error on revocation (id=%" PRIu64 "\n",
570 rvk->move_attr->old_id);
571 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
577 rvk_ns_err (void *cls)
579 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
581 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
582 "Namestore error on revocation (id=%" PRIu64 "\n",
583 rvk->move_attr->old_id);
584 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
590 move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk)
594 if (NULL == rvk->move_attr) {
595 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Finished moving attributes\n");
596 rvk->ns_it = GNUNET_NAMESTORE_zone_iteration_start (
597 nsh, &rvk->identity, &rvk_ns_iter_err, rvk, &rvk_ticket_update, rvk,
598 &rvk_ticket_update_finished, rvk);
601 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
603 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Moving attribute %s\n", label);
605 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (
606 nsh, &rvk->identity, label, &rvk_ns_err, rvk, &rvk_move_attr_cb, rvk);
612 remove_ticket_cont (void *cls, int32_t success, const char *emsg)
614 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
616 if (GNUNET_SYSERR == success) {
617 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
618 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted ticket\n");
623 if (0 == rvk->ticket_attrs) {
624 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
625 "No attributes to move... strange\n");
626 rvk->cb (rvk->cb_cls, GNUNET_OK);
630 rvk->move_attr = rvk->attrs_head;
636 revoke_attrs_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
637 const char *label, unsigned int rd_count,
638 const struct GNUNET_GNSRECORD_Data *rd)
641 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
642 struct RevokedAttributeEntry *le;
644 for (int i = 0; i < rd_count; i++) {
645 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
647 le = GNUNET_new (struct RevokedAttributeEntry);
648 le->old_id = *((uint64_t *)rd[i].data);
649 GNUNET_CONTAINER_DLL_insert (rvk->attrs_head, rvk->attrs_tail, le);
653 /** Now, remove ticket **/
654 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &rvk->identity, label, 0,
655 NULL, &remove_ticket_cont, rvk);
660 rvk_attrs_err_cb (void *cls)
662 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
663 rvk->cb (rvk->cb_cls, GNUNET_SYSERR);
668 struct RECLAIM_TICKETS_RevokeHandle *
669 RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket,
670 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
671 RECLAIM_TICKETS_RevokeCallback cb, void *cb_cls)
673 struct RECLAIM_TICKETS_RevokeHandle *rvk;
676 rvk = GNUNET_new (struct RECLAIM_TICKETS_RevokeHandle);
678 rvk->cb_cls = cb_cls;
679 rvk->identity = *identity;
680 rvk->ticket = *ticket;
681 GNUNET_CRYPTO_ecdsa_key_get_public (&rvk->identity, &rvk->ticket.identity);
682 /** Get shared attributes **/
683 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, sizeof (uint64_t));
685 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (
686 nsh, identity, label, &rvk_attrs_err_cb, rvk, &revoke_attrs_cb, rvk);
692 RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh)
696 /*******************************
698 *******************************/
701 * Cleanup ticket consume handle
702 * @param cth the handle to clean up
705 cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
707 struct ParallelLookup *lu;
708 struct ParallelLookup *tmp;
709 if (NULL != cth->lookup_request)
710 GNUNET_GNS_lookup_cancel (cth->lookup_request);
711 for (lu = cth->parallel_lookups_head; NULL != lu;) {
712 GNUNET_GNS_lookup_cancel (lu->lookup_request);
713 GNUNET_free (lu->label);
715 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
716 cth->parallel_lookups_tail, lu);
721 if (NULL != cth->attrs)
722 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (cth->attrs);
728 process_parallel_lookup_result (void *cls, uint32_t rd_count,
729 const struct GNUNET_GNSRECORD_Data *rd)
731 struct ParallelLookup *parallel_lookup = cls;
732 struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle;
733 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le;
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parallel lookup finished (count=%u)\n",
737 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
738 cth->parallel_lookups_tail, parallel_lookup);
739 GNUNET_free (parallel_lookup->label);
741 GNUNET_STATISTICS_update (
742 stats, "attribute_lookup_time_total",
743 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time)
746 GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES);
749 GNUNET_free (parallel_lookup);
751 GNUNET_break (0); // TODO
752 if (rd->record_type == GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR) {
753 attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
755 GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size);
756 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head, cth->attrs->list_tail,
759 if (NULL != cth->parallel_lookups_head)
760 return; // Wait for more
761 /* Else we are done */
763 GNUNET_SCHEDULER_cancel (cth->kill_task);
764 cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL);
770 abort_parallel_lookups (void *cls)
772 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
773 struct ParallelLookup *lu;
774 struct ParallelLookup *tmp;
776 cth->kill_task = NULL;
777 for (lu = cth->parallel_lookups_head; NULL != lu;) {
778 GNUNET_GNS_lookup_cancel (lu->lookup_request);
779 GNUNET_free (lu->label);
781 GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head,
782 cth->parallel_lookups_tail, lu);
786 cth->cb (cth->cb_cls, NULL, NULL, GNUNET_SYSERR, "Aborted");
791 lookup_authz_cb (void *cls, uint32_t rd_count,
792 const struct GNUNET_GNSRECORD_Data *rd)
794 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
795 struct ParallelLookup *parallel_lookup;
798 cth->lookup_request = NULL;
800 GNUNET_STATISTICS_update (
801 stats, "reclaim_authz_lookup_time_total",
802 GNUNET_TIME_absolute_get_duration (cth->lookup_start_time).rel_value_us,
804 GNUNET_STATISTICS_update (stats, "reclaim_authz_lookups_count", 1,
807 for (int i = 0; i < rd_count; i++) {
808 lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attribute ref found %s\n", lbl);
810 parallel_lookup = GNUNET_new (struct ParallelLookup);
811 parallel_lookup->handle = cth;
812 parallel_lookup->label = lbl;
813 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
814 parallel_lookup->lookup_request = GNUNET_GNS_lookup (
815 gns, lbl, &cth->ticket.identity, GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR,
816 GNUNET_GNS_LO_DEFAULT, &process_parallel_lookup_result,
818 GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
819 cth->parallel_lookups_tail, parallel_lookup);
821 cth->kill_task = GNUNET_SCHEDULER_add_delayed (
822 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3),
823 &abort_parallel_lookups, cth);
827 struct RECLAIM_TICKETS_ConsumeHandle *
828 RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_EcdsaPrivateKey *id,
829 const struct GNUNET_RECLAIM_Ticket *ticket,
830 RECLAIM_TICKETS_ConsumeCallback cb, void *cb_cls)
832 struct RECLAIM_TICKETS_ConsumeHandle *cth;
834 cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle);
837 GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub);
838 cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
839 cth->ticket = *ticket;
841 cth->cb_cls = cb_cls;
843 GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd, sizeof (uint64_t));
844 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for AuthZ info under %s\n",
846 cth->lookup_start_time = GNUNET_TIME_absolute_get ();
847 cth->lookup_request = GNUNET_GNS_lookup (
848 gns, label, &cth->ticket.identity, GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF,
849 GNUNET_GNS_LO_DEFAULT, &lookup_authz_cb, cth);
855 RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
862 /*******************************
864 *******************************/
867 * Cleanup ticket consume handle
868 * @param handle the handle to clean up
871 cleanup_issue_handle (struct TicketIssueHandle *handle)
873 struct TicketReference *tr;
874 struct TicketReference *tr_tmp;
875 if (NULL != handle->attrs)
876 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
877 if (NULL != handle->ns_qe)
878 GNUNET_NAMESTORE_cancel (handle->ns_qe);
879 for (tr = handle->ticket_refs_head; NULL != tr;) {
880 if (NULL != tr->attrs)
881 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
884 GNUNET_free (tr_tmp);
886 GNUNET_free (handle);
891 store_ticket_refs_cont (void *cls, int32_t success, const char *emsg)
893 struct TicketIssueHandle *handle = cls;
894 handle->ns_qe = NULL;
895 if (GNUNET_OK != success) {
896 handle->cb (handle->cb_cls, NULL, GNUNET_SYSERR,
897 "Error storing updated ticket refs in GNS");
898 cleanup_issue_handle (handle);
901 handle->cb (handle->cb_cls, &handle->ticket, GNUNET_OK, NULL);
902 cleanup_issue_handle (handle);
907 update_ticket_refs (void *cls)
909 struct TicketIssueHandle *handle = cls;
910 struct GNUNET_GNSRECORD_Data refs_rd[handle->ticket_ref_num];
911 struct TicketReference *tr;
913 tr = handle->ticket_refs_head;
914 for (int i = 0; i < handle->ticket_ref_num; i++) {
915 refs_rd[i].data = &tr->ticket;
916 refs_rd[i].data_size = sizeof (struct GNUNET_RECLAIM_Ticket);
917 refs_rd[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
918 refs_rd[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF;
920 GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
924 handle->ns_qe = GNUNET_NAMESTORE_records_store (
925 nsh, &handle->identity, GNUNET_GNS_EMPTY_LABEL_AT, handle->ticket_ref_num,
926 refs_rd, &store_ticket_refs_cont, handle);
931 ticket_lookup_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
932 const char *label, unsigned int rd_count,
933 const struct GNUNET_GNSRECORD_Data *rd)
935 struct TicketIssueHandle *handle = cls;
936 struct TicketReference *tr;
938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
939 "Received tickets from local namestore.\n");
940 handle->ns_qe = NULL;
941 for (int i = 0; i < rd_count; i++) {
942 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
944 tr = GNUNET_new (struct TicketReference);
945 memcpy (&tr->ticket, rd[i].data, sizeof (struct GNUNET_RECLAIM_Ticket));
946 if (0 != memcmp (&tr->ticket.identity, &handle->ticket.identity,
947 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) {
952 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
953 handle->ticket_refs_tail, tr);
954 handle->ticket_ref_num++;
956 tr = GNUNET_new (struct TicketReference);
957 tr->ticket = handle->ticket;
958 tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (handle->attrs);
959 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
960 handle->ticket_refs_tail, tr);
961 handle->ticket_ref_num++;
962 GNUNET_SCHEDULER_add_now (&update_ticket_refs, handle);
967 * TODO maybe we should cleanup the ATTRREFS here?
970 ticket_lookup_error_cb (void *cls)
972 struct TicketIssueHandle *handle = cls;
973 handle->ns_qe = NULL;
974 handle->cb (handle->cb_cls, &handle->ticket, GNUNET_SYSERR,
975 "Error checking for ticketsin GNS\n");
976 cleanup_issue_handle (handle);
980 store_ticket_issue_cont (void *cls, int32_t success, const char *emsg)
982 struct TicketIssueHandle *handle = cls;
984 handle->ns_qe = NULL;
985 if (GNUNET_SYSERR == success) {
986 handle->cb (handle->cb_cls, &handle->ticket, GNUNET_SYSERR,
987 "Error storing AuthZ ticket in GNS");
990 /* First, local references to tickets */
991 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (
992 nsh, &handle->identity, GNUNET_GNS_EMPTY_LABEL_AT,
993 &ticket_lookup_error_cb, handle, &ticket_lookup_cb, handle);
998 issue_ticket (struct TicketIssueHandle *ih)
1000 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
1001 struct GNUNET_GNSRECORD_Data *attrs_record;
1003 size_t list_len = 0;
1006 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1010 GNUNET_malloc (list_len * sizeof (struct GNUNET_GNSRECORD_Data));
1012 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
1013 attrs_record[i].data = &le->claim->id;
1014 attrs_record[i].data_size = sizeof (le->claim->id);
1015 attrs_record[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1016 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF;
1017 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1022 GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, sizeof (uint64_t));
1024 ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &ih->identity, label,
1025 list_len, attrs_record,
1026 &store_ticket_issue_cont, ih);
1027 GNUNET_free (attrs_record);
1028 GNUNET_free (label);
1033 RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1034 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
1035 const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
1036 RECLAIM_TICKETS_TicketResult cb, void *cb_cls)
1038 struct TicketIssueHandle *tih;
1039 tih = GNUNET_new (struct TicketIssueHandle);
1041 tih->cb_cls = cb_cls;
1042 tih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
1043 tih->identity = *identity;
1044 GNUNET_CRYPTO_ecdsa_key_get_public (identity, &tih->ticket.identity);
1046 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1047 tih->ticket.audience = *audience;
1051 /************************************
1053 ************************************/
1056 cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter)
1058 struct TicketReference *tr;
1059 struct TicketReference *tr_tmp;
1060 if (NULL != iter->ns_qe)
1061 GNUNET_NAMESTORE_cancel (iter->ns_qe);
1062 for (tr = iter->tickets_head; NULL != tr;) {
1063 if (NULL != tr->attrs)
1064 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
1067 GNUNET_free (tr_tmp);
1073 do_cleanup_iter (void *cls)
1075 struct RECLAIM_TICKETS_Iterator *iter = cls;
1076 cleanup_iter (iter);
1080 * Perform ticket iteration step
1082 * @param ti ticket iterator to process
1085 run_ticket_iteration_round (struct RECLAIM_TICKETS_Iterator *iter)
1087 struct TicketReference *tr;
1088 if (NULL == iter->tickets_head) {
1090 iter->cb (iter->cb_cls, NULL);
1091 GNUNET_SCHEDULER_add_now (&do_cleanup_iter, iter);
1094 tr = iter->tickets_head;
1095 GNUNET_CONTAINER_DLL_remove (iter->tickets_head, iter->tickets_tail, tr);
1096 iter->cb (iter->cb_cls, &tr->ticket);
1097 if (NULL != tr->attrs)
1098 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
1103 collect_tickets_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1104 const char *label, unsigned int rd_count,
1105 const struct GNUNET_GNSRECORD_Data *rd)
1107 struct RECLAIM_TICKETS_Iterator *iter = cls;
1108 struct TicketReference *tr;
1111 for (int i = 0; i < rd_count; i++) {
1112 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
1114 tr = GNUNET_new (struct TicketReference);
1115 memcpy (&tr->ticket, rd[i].data, sizeof (struct GNUNET_RECLAIM_Ticket));
1116 if (0 != memcmp (&tr->ticket.identity, &iter->identity_pub,
1117 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) {
1122 GNUNET_CONTAINER_DLL_insert (iter->tickets_head, iter->tickets_tail, tr);
1124 run_ticket_iteration_round (iter);
1128 collect_tickets_error_cb (void *cls)
1130 struct RECLAIM_TICKETS_Iterator *iter = cls;
1132 iter->cb (iter->cb_cls, NULL);
1133 cleanup_iter (iter);
1137 RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter)
1139 run_ticket_iteration_round (iter);
1143 RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter)
1145 cleanup_iter (iter);
1148 struct RECLAIM_TICKETS_Iterator *
1149 RECLAIM_TICKETS_iteration_start (
1150 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1151 RECLAIM_TICKETS_TicketIter cb, void *cb_cls)
1153 struct RECLAIM_TICKETS_Iterator *iter;
1155 iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator);
1156 iter->identity = *identity;
1157 GNUNET_CRYPTO_ecdsa_key_get_public (identity, &iter->identity_pub);
1159 iter->cb_cls = cb_cls;
1160 iter->ns_qe = GNUNET_NAMESTORE_records_lookup (
1161 nsh, identity, GNUNET_GNS_EMPTY_LABEL_AT, &collect_tickets_error_cb, iter,
1162 &collect_tickets_cb, iter);
1168 RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
1170 // Connect to identity and namestore services
1171 nsh = GNUNET_NAMESTORE_connect (c);
1173 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1174 "error connecting to namestore");
1175 return GNUNET_SYSERR;
1177 gns = GNUNET_GNS_connect (c);
1179 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1180 return GNUNET_SYSERR;
1182 stats = GNUNET_STATISTICS_create ("reclaim", c);
1187 RECLAIM_TICKETS_deinit (void)
1190 GNUNET_NAMESTORE_disconnect (nsh);
1193 GNUNET_GNS_disconnect (gns);
1195 if (NULL != stats) {
1196 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);