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
21 * @author Martin Schanzenbach
22 * @file src/reclaim/gnunet-service-reclaim.c
23 * @brief reclaim Service
27 #include "gnunet_util_lib.h"
28 #include "gnunet-service-reclaim_tickets.h"
29 #include "gnunet_constants.h"
30 #include "gnunet_gnsrecord_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_reclaim_attribute_lib.h"
33 #include "gnunet_reclaim_service.h"
34 #include "gnunet_signatures.h"
41 static struct GNUNET_NAMESTORE_Handle *nsh;
46 static struct GNUNET_SCHEDULER_Task *timeout_task;
51 static const struct GNUNET_CONFIGURATION_Handle *cfg;
59 * A ticket iteration operation.
61 struct TicketIteration
66 struct TicketIteration *next;
71 struct TicketIteration *prev;
74 * Client which intiated this zone iteration
76 struct IdpClient *client;
79 * The operation id fot the iteration in the response for the client
86 struct RECLAIM_TICKETS_Iterator *iter;
91 * An attribute iteration operation.
93 struct AttributeIterator
96 * Next element in the DLL
98 struct AttributeIterator *next;
101 * Previous element in the DLL
103 struct AttributeIterator *prev;
106 * IDP client which intiated this zone iteration
108 struct IdpClient *client;
111 * Key of the zone we are iterating over.
113 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
118 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
121 * The operation id fot the zone iteration in the response for the client
135 struct IdpClient *prev;
140 struct IdpClient *next;
145 struct GNUNET_SERVICE_Client *client;
148 * Message queue for transmission to @e client
150 struct GNUNET_MQ_Handle *mq;
154 * Attribute iteration operations in
155 * progress initiated by this client
157 struct AttributeIterator *attr_iter_head;
161 * Attribute iteration operations
162 * in progress initiated by this client
164 struct AttributeIterator *attr_iter_tail;
167 * Head of DLL of ticket iteration ops
169 struct TicketIteration *ticket_iter_head;
172 * Tail of DLL of ticket iteration ops
174 struct TicketIteration *ticket_iter_tail;
177 * Head of DLL of ticket revocation ops
179 struct TicketRevocationOperation *revoke_op_head;
182 * Tail of DLL of ticket revocation ops
184 struct TicketRevocationOperation *revoke_op_tail;
187 * Head of DLL of ticket issue ops
189 struct TicketIssueOperation *issue_op_head;
192 * Tail of DLL of ticket issue ops
194 struct TicketIssueOperation *issue_op_tail;
197 * Head of DLL of ticket consume ops
199 struct ConsumeTicketOperation *consume_op_head;
202 * Tail of DLL of ticket consume ops
204 struct ConsumeTicketOperation *consume_op_tail;
207 * Head of DLL of attribute store ops
209 struct AttributeStoreHandle *store_op_head;
212 * Tail of DLL of attribute store ops
214 struct AttributeStoreHandle *store_op_tail;
216 * Head of DLL of attribute delete ops
218 struct AttributeDeleteHandle *delete_op_head;
221 * Tail of DLL of attribute delete ops
223 struct AttributeDeleteHandle *delete_op_tail;
228 * Handle for attribute deletion request
230 struct AttributeDeleteHandle
235 struct AttributeDeleteHandle *next;
240 struct AttributeDeleteHandle *prev;
245 struct IdpClient *client;
250 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
256 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
261 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
264 * The attribute to delete
266 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
271 struct TicketRecordsEntry *tickets_to_update_head;
276 struct TicketRecordsEntry *tickets_to_update_tail;
291 * Handle for attribute store request
293 struct AttributeStoreHandle
298 struct AttributeStoreHandle *next;
303 struct AttributeStoreHandle *prev;
308 struct IdpClient *client;
313 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
318 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
323 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
326 * The attribute to store
328 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
331 * The attribute expiration interval
333 struct GNUNET_TIME_Relative exp;
343 * Handle for ticket consume request
345 struct ConsumeTicketOperation
350 struct ConsumeTicketOperation *next;
355 struct ConsumeTicketOperation *prev;
360 struct IdpClient *client;
368 * Ticket consume handle
370 struct RECLAIM_TICKETS_ConsumeHandle *ch;
375 * Ticket revocation request handle
377 struct TicketRevocationOperation
382 struct TicketRevocationOperation *prev;
387 struct TicketRevocationOperation *next;
392 struct IdpClient *client;
397 struct RECLAIM_TICKETS_RevokeHandle *rh;
407 * Ticket issue operation handle
409 struct TicketIssueOperation
414 struct TicketIssueOperation *prev;
419 struct TicketIssueOperation *next;
424 struct IdpClient *client;
436 static struct IdpClient *client_list_head = NULL;
441 static struct IdpClient *client_list_tail = NULL;
445 * Cleanup attribute delete handle
447 * @param adh the attribute to cleanup
450 cleanup_adh (struct AttributeDeleteHandle *adh)
452 struct TicketRecordsEntry *le;
454 if (NULL != adh->ns_it)
455 GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
456 if (NULL != adh->ns_qe)
457 GNUNET_NAMESTORE_cancel (adh->ns_qe);
458 if (NULL != adh->label)
459 GNUNET_free (adh->label);
460 if (NULL != adh->claim)
461 GNUNET_free (adh->claim);
462 while (NULL != (le = adh->tickets_to_update_head))
464 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
465 adh->tickets_to_update_tail,
467 if (NULL != le->label)
468 GNUNET_free (le->label);
469 if (NULL != le->data)
470 GNUNET_free (le->data);
478 * Cleanup attribute store handle
480 * @param handle handle to clean up
483 cleanup_as_handle (struct AttributeStoreHandle *ash)
485 if (NULL != ash->ns_qe)
486 GNUNET_NAMESTORE_cancel (ash->ns_qe);
487 if (NULL != ash->claim)
488 GNUNET_free (ash->claim);
496 * @param idp the client to clean up
499 cleanup_client (struct IdpClient *idp)
501 struct AttributeIterator *ai;
502 struct TicketIteration *ti;
503 struct TicketRevocationOperation *rop;
504 struct TicketIssueOperation *iss;
505 struct ConsumeTicketOperation *ct;
506 struct AttributeStoreHandle *as;
507 struct AttributeDeleteHandle *adh;
509 while (NULL != (iss = idp->issue_op_head))
511 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
514 while (NULL != (ct = idp->consume_op_head))
516 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
517 idp->consume_op_tail,
520 RECLAIM_TICKETS_consume_cancel (ct->ch);
523 while (NULL != (as = idp->store_op_head))
525 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
526 cleanup_as_handle (as);
528 while (NULL != (adh = idp->delete_op_head))
530 GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
534 while (NULL != (ai = idp->attr_iter_head))
536 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
539 while (NULL != (rop = idp->revoke_op_head))
541 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
543 RECLAIM_TICKETS_revoke_cancel (rop->rh);
546 while (NULL != (ti = idp->ticket_iter_head))
548 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
549 idp->ticket_iter_tail,
551 if (NULL != ti->iter)
552 RECLAIM_TICKETS_iteration_stop (ti->iter);
565 struct IdpClient *cl;
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
569 while (NULL != (cl = client_list_head))
571 GNUNET_CONTAINER_DLL_remove (client_list_head,
576 RECLAIM_TICKETS_deinit ();
577 if (NULL != timeout_task)
578 GNUNET_SCHEDULER_cancel (timeout_task);
580 GNUNET_NAMESTORE_disconnect (nsh);
590 do_shutdown (void *cls)
592 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
598 * Sends a ticket result message to the client
600 * @param client the client to send to
601 * @param r_id the request message ID to reply to
602 * @param ticket the ticket to include (may be NULL)
603 * @param success the success status of the request
606 send_ticket_result (const struct IdpClient *client,
608 const struct GNUNET_RECLAIM_Ticket *ticket,
611 struct TicketResultMessage *irm;
612 struct GNUNET_MQ_Envelope *env;
614 env = GNUNET_MQ_msg (irm,
615 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
618 irm->ticket = *ticket;
620 // TODO add success member
621 irm->id = htonl (r_id);
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
623 GNUNET_MQ_send (client->mq, env);
628 * Issue ticket result
630 * @param cls out ticket issue operation handle
631 * @param ticket the issued ticket
632 * @param success issue success status (GNUNET_OK if successful)
633 * @param emsg error message (NULL of success is GNUNET_OK)
636 issue_ticket_result_cb (void *cls,
637 struct GNUNET_RECLAIM_Ticket *ticket,
641 struct TicketIssueOperation *tio = cls;
643 if (GNUNET_OK != success)
645 send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
646 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
647 tio->client->issue_op_tail,
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
653 send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
654 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
655 tio->client->issue_op_tail,
662 * Check issue ticket message
665 * @im message to check
666 * @return GNUNET_OK if message is ok
669 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
673 size = ntohs (im->header.size);
674 if (size <= sizeof(struct IssueTicketMessage))
677 return GNUNET_SYSERR;
684 * Handle ticket issue message
686 * @param cls our client
687 * @param im the message
690 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
692 struct TicketIssueOperation *tio;
693 struct IdpClient *idp = cls;
694 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
698 tio = GNUNET_new (struct TicketIssueOperation);
699 attrs_len = ntohs (im->attr_len);
700 attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *) &im[1],
702 tio->r_id = ntohl (im->id);
704 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
705 RECLAIM_TICKETS_issue (&im->identity,
708 &issue_ticket_result_cb,
710 GNUNET_SERVICE_client_continue (idp->client);
711 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
715 /**********************************************************
717 **********************************************************/
720 * Handles revocation result
722 * @param cls our revocation operation handle
723 * @param success revocation result (GNUNET_OK if successful)
726 revoke_result_cb (void *cls, int32_t success)
728 struct TicketRevocationOperation *rop = cls;
729 struct GNUNET_MQ_Envelope *env;
730 struct RevokeTicketResultMessage *trm;
732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
733 "Sending REVOKE_TICKET_RESULT message\n");
735 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
736 trm->id = htonl (rop->r_id);
737 trm->success = htonl (success);
738 GNUNET_MQ_send (rop->client->mq, env);
739 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
740 rop->client->revoke_op_tail,
747 * Check revocation message format
750 * @param im the message to check
751 * @return GNUNET_OK if message is ok
754 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
758 size = ntohs (im->header.size);
759 if (size != sizeof(struct RevokeTicketMessage))
762 return GNUNET_SYSERR;
769 * Handle a revocation message to a ticket.
771 * @param cls our client
772 * @param rm the message to handle
775 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
777 struct TicketRevocationOperation *rop;
778 struct IdpClient *idp = cls;
780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
781 rop = GNUNET_new (struct TicketRevocationOperation);
782 rop->r_id = ntohl (rm->id);
784 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
786 = RECLAIM_TICKETS_revoke (&rm->ticket, &rm->identity, &revoke_result_cb,
788 GNUNET_SERVICE_client_continue (idp->client);
793 * Handle a ticket consume result
795 * @param cls our consume ticket operation handle
796 * @param identity the attribute authority
797 * @param attrs the attribute/claim list
798 * @param success GNUNET_OK if successful
799 * @param emsg error message (NULL if success=GNUNET_OK)
802 consume_result_cb (void *cls,
803 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
804 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
808 struct ConsumeTicketOperation *cop = cls;
809 struct ConsumeTicketResultMessage *crm;
810 struct GNUNET_MQ_Envelope *env;
814 if (GNUNET_OK != success)
816 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
818 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
820 "Sending CONSUME_TICKET_RESULT message\n");
821 env = GNUNET_MQ_msg_extra (crm,
823 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
824 crm->id = htonl (cop->r_id);
825 crm->attrs_len = htons (attrs_len);
826 crm->identity = *identity;
827 crm->result = htonl (success);
828 data_tmp = (char *) &crm[1];
829 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
830 GNUNET_MQ_send (cop->client->mq, env);
831 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
832 cop->client->consume_op_tail,
839 * Check a consume ticket message
842 * @param cm the message to handle
845 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
849 size = ntohs (cm->header.size);
850 if (size != sizeof(struct ConsumeTicketMessage))
853 return GNUNET_SYSERR;
860 * Handle a consume ticket message
862 * @param cls our client handle
863 * @cm the message to handle
866 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
868 struct ConsumeTicketOperation *cop;
869 struct IdpClient *idp = cls;
871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
872 cop = GNUNET_new (struct ConsumeTicketOperation);
873 cop->r_id = ntohl (cm->id);
876 = RECLAIM_TICKETS_consume (&cm->identity, &cm->ticket, &consume_result_cb,
878 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
879 GNUNET_SERVICE_client_continue (idp->client);
883 /*****************************************
885 *****************************************/
889 * Attribute store result handler
891 * @param cls our attribute store handle
892 * @param success GNUNET_OK if successful
893 * @param emsg error message (NULL if success=GNUNET_OK)
896 attr_store_cont (void *cls, int32_t success, const char *emsg)
898 struct AttributeStoreHandle *ash = cls;
899 struct GNUNET_MQ_Envelope *env;
900 struct SuccessResultMessage *acr_msg;
903 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
904 ash->client->store_op_tail,
907 if (GNUNET_SYSERR == success)
909 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
910 "Failed to store attribute %s\n",
912 cleanup_as_handle (ash);
913 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
918 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
919 acr_msg->id = htonl (ash->r_id);
920 acr_msg->op_result = htonl (GNUNET_OK);
921 GNUNET_MQ_send (ash->client->mq, env);
922 cleanup_as_handle (ash);
927 * Add a new attribute
929 * @param cls the AttributeStoreHandle
932 attr_store_task (void *cls)
934 struct AttributeStoreHandle *ash = cls;
935 struct GNUNET_GNSRECORD_Data rd[1];
940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
941 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
942 buf = GNUNET_malloc (buf_size);
943 // Give the ash a new id if unset
944 if (0 == ash->claim->id)
946 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
947 GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
949 = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof(uint64_t));
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
952 rd[0].data_size = buf_size;
954 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
955 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
956 rd[0].expiration_time = ash->exp.rel_value_us;
957 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
970 * Check an attribute store message
973 * @param sam the message to check
976 check_attribute_store_message (void *cls,
977 const struct AttributeStoreMessage *sam)
981 size = ntohs (sam->header.size);
982 if (size <= sizeof(struct AttributeStoreMessage))
985 return GNUNET_SYSERR;
992 * Handle an attribute store message
994 * @param cls our client
995 * @param sam the message to handle
998 handle_attribute_store_message (void *cls,
999 const struct AttributeStoreMessage *sam)
1001 struct AttributeStoreHandle *ash;
1002 struct IdpClient *idp = cls;
1005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1007 data_len = ntohs (sam->attr_len);
1009 ash = GNUNET_new (struct AttributeStoreHandle);
1010 ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &sam[1],
1013 ash->r_id = ntohl (sam->id);
1014 ash->identity = sam->identity;
1015 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1016 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1018 GNUNET_SERVICE_client_continue (idp->client);
1020 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1021 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1026 * Send a deletion success response
1028 * @param adh our attribute deletion handle
1029 * @param success the success status
1032 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1034 struct GNUNET_MQ_Envelope *env;
1035 struct SuccessResultMessage *acr_msg;
1037 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1038 adh->client->delete_op_tail,
1041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1042 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1043 acr_msg->id = htonl (adh->r_id);
1044 acr_msg->op_result = htonl (success);
1045 GNUNET_MQ_send (adh->client->mq, env);
1050 * Namestore iteration within attribute deletion.
1051 * We need to reissue tickets with the deleted attribute removed.
1053 * @param cls our attribute deletion handle
1054 * @param zone the private key of the ticket issuer
1055 * @param label the label of the record
1056 * @param rd_count number of records
1057 * @param rd record data
1060 ticket_iter (void *cls,
1061 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1063 unsigned int rd_count,
1064 const struct GNUNET_GNSRECORD_Data *rd)
1066 struct AttributeDeleteHandle *adh = cls;
1067 struct TicketRecordsEntry *le;
1068 int has_changed = GNUNET_NO;
1070 for (int i = 0; i < rd_count; i++)
1072 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
1074 if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t)))
1076 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1077 "Attribute to delete found (%s)\n",
1079 has_changed = GNUNET_YES;
1082 if (GNUNET_YES == has_changed)
1084 le = GNUNET_new (struct TicketRecordsEntry);
1085 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1086 le->data = GNUNET_malloc (le->data_size);
1087 le->rd_count = rd_count;
1088 le->label = GNUNET_strdup (label);
1089 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1090 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1091 adh->tickets_to_update_tail,
1094 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1099 * Recursion prototype for function
1100 * @param cls our deletion handle
1103 update_tickets (void *cls);
1107 * Callback called when a ticket was updated
1109 * @param cls our attribute deletion handle
1110 * @param success GNUNET_OK if successful
1111 * @param emsg error message (NULL if success=GNUNET_OK)
1114 ticket_updated (void *cls, int32_t success, const char *emsg)
1116 struct AttributeDeleteHandle *adh = cls;
1119 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1124 * Update tickets: Remove shared attribute which has just been deleted.
1125 * This method is called recursively until all tickets are processed.
1126 * Eventually, the updated tickets are stored using ``update_tickets''.
1128 * @param cls our attribute deletion handle
1131 update_tickets (void *cls)
1133 struct AttributeDeleteHandle *adh = cls;
1134 struct TicketRecordsEntry *le;
1136 if (NULL == adh->tickets_to_update_head)
1138 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1139 "Finished updatding tickets, success\n");
1140 send_delete_response (adh, GNUNET_OK);
1144 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1146 adh->tickets_to_update_head->label);
1147 le = adh->tickets_to_update_head;
1148 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1149 adh->tickets_to_update_tail,
1151 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1152 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1153 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1159 "Unable to deserialize record data!\n");
1160 send_delete_response (adh, GNUNET_SYSERR);
1165 for (int i = 0; i < le->rd_count; i++)
1167 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1168 && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t))))
1173 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1180 GNUNET_free (le->label);
1181 GNUNET_free (le->data);
1187 * Done collecting affected tickets, start updating.
1189 * @param cls our attribute deletion handle
1192 ticket_iter_fin (void *cls)
1194 struct AttributeDeleteHandle *adh = cls;
1197 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1202 * Error collecting affected tickets. Abort.
1204 * @param cls our attribute deletion handle
1207 ticket_iter_err (void *cls)
1209 struct AttributeDeleteHandle *adh = cls;
1212 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1213 "Namestore error on delete %s\n",
1215 send_delete_response (adh, GNUNET_SYSERR);
1221 * Start processing tickets which may still contain reference to deleted
1224 * @param cls attribute deletion handle
1227 start_ticket_update (void *cls)
1229 struct AttributeDeleteHandle *adh = cls;
1231 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1243 * Attribute deleted callback
1245 * @param cls our handle
1246 * @param success success status
1247 * @param emsg error message (NULL if success=GNUNET_OK)
1250 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1252 struct AttributeDeleteHandle *adh = cls;
1255 if (GNUNET_SYSERR == success)
1257 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1258 "Error deleting attribute %s\n",
1260 send_delete_response (adh, GNUNET_SYSERR);
1264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1265 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1270 * Check attribute delete message format
1273 * @dam message to check
1276 check_attribute_delete_message (void *cls,
1277 const struct AttributeDeleteMessage *dam)
1281 size = ntohs (dam->header.size);
1282 if (size <= sizeof(struct AttributeDeleteMessage))
1285 return GNUNET_SYSERR;
1292 * Handle attribute deletion
1294 * @param cls our client
1295 * @param dam deletion message
1298 handle_attribute_delete_message (void *cls,
1299 const struct AttributeDeleteMessage *dam)
1301 struct AttributeDeleteHandle *adh;
1302 struct IdpClient *idp = cls;
1305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1307 data_len = ntohs (dam->attr_len);
1309 adh = GNUNET_new (struct AttributeDeleteHandle);
1310 adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &dam[1],
1313 adh->r_id = ntohl (dam->id);
1314 adh->identity = dam->identity;
1316 = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof(uint64_t));
1317 GNUNET_SERVICE_client_continue (idp->client);
1319 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1320 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1330 /*************************************************
1331 * Attrubute iteration
1332 *************************************************/
1336 * Done iterating over attributes
1338 * @param cls our iterator handle
1341 attr_iter_finished (void *cls)
1343 struct AttributeIterator *ai = cls;
1344 struct GNUNET_MQ_Envelope *env;
1345 struct AttributeResultMessage *arm;
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1348 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1349 arm->id = htonl (ai->request_id);
1350 arm->attr_len = htons (0);
1351 GNUNET_MQ_send (ai->client->mq, env);
1352 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1353 ai->client->attr_iter_tail,
1360 * Error iterating over attributes. Abort.
1362 * @param cls our attribute iteration handle
1365 attr_iter_error (void *cls)
1367 struct AttributeIterator *ai = cls;
1369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1370 attr_iter_finished (ai);
1375 * Got record. Return if it is an attribute.
1377 * @param cls our attribute iterator
1378 * @param zone zone we are iterating
1379 * @param label label of the records
1380 * @param rd_count record count
1384 attr_iter_cb (void *cls,
1385 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1387 unsigned int rd_count,
1388 const struct GNUNET_GNSRECORD_Data *rd)
1390 struct AttributeIterator *ai = cls;
1391 struct AttributeResultMessage *arm;
1392 struct GNUNET_MQ_Envelope *env;
1397 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1401 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type)
1403 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1408 env = GNUNET_MQ_msg_extra (arm,
1410 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1411 arm->id = htonl (ai->request_id);
1412 arm->attr_len = htons (rd->data_size);
1413 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1414 data_tmp = (char *) &arm[1];
1415 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1416 GNUNET_MQ_send (ai->client->mq, env);
1421 * Iterate over zone to get attributes
1423 * @param cls our client
1424 * @param ais_msg the iteration message to start
1427 handle_iteration_start (void *cls,
1428 const struct AttributeIterationStartMessage *ais_msg)
1430 struct IdpClient *idp = cls;
1431 struct AttributeIterator *ai;
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1434 "Received ATTRIBUTE_ITERATION_START message\n");
1435 ai = GNUNET_new (struct AttributeIterator);
1436 ai->request_id = ntohl (ais_msg->id);
1438 ai->identity = ais_msg->identity;
1440 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1441 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1447 &attr_iter_finished,
1449 GNUNET_SERVICE_client_continue (idp->client);
1454 * Handle iteration stop message from client
1456 * @param cls the client
1457 * @param ais_msg the stop message
1460 handle_iteration_stop (void *cls,
1461 const struct AttributeIterationStopMessage *ais_msg)
1463 struct IdpClient *idp = cls;
1464 struct AttributeIterator *ai;
1467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1468 "Received `%s' message\n",
1469 "ATTRIBUTE_ITERATION_STOP");
1470 rid = ntohl (ais_msg->id);
1471 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1472 if (ai->request_id == rid)
1477 GNUNET_SERVICE_client_drop (idp->client);
1480 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1482 GNUNET_SERVICE_client_continue (idp->client);
1487 * Client requests next attribute from iterator
1489 * @param cls the client
1490 * @param ais_msg the message
1493 handle_iteration_next (void *cls,
1494 const struct AttributeIterationNextMessage *ais_msg)
1496 struct IdpClient *idp = cls;
1497 struct AttributeIterator *ai;
1500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1501 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1502 rid = ntohl (ais_msg->id);
1503 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1504 if (ai->request_id == rid)
1509 GNUNET_SERVICE_client_drop (idp->client);
1512 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1513 GNUNET_SERVICE_client_continue (idp->client);
1517 /******************************************************
1519 ******************************************************/
1522 * Got a ticket. Return to client
1524 * @param cls our ticket iterator
1525 * @param ticket the ticket
1528 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1530 struct TicketIteration *ti = cls;
1531 struct GNUNET_MQ_Envelope *env;
1532 struct TicketResultMessage *trm;
1534 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1537 /* send empty response to indicate end of list */
1538 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1539 ti->client->ticket_iter_tail,
1544 trm->ticket = *ticket;
1546 trm->id = htonl (ti->r_id);
1547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
1548 GNUNET_MQ_send (ti->client->mq, env);
1555 * Client requests a ticket iteration
1557 * @param cls the client
1558 * @param tis_msg the iteration request message
1561 handle_ticket_iteration_start (
1563 const struct TicketIterationStartMessage *tis_msg)
1565 struct IdpClient *client = cls;
1566 struct TicketIteration *ti;
1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1569 "Received TICKET_ITERATION_START message\n");
1570 ti = GNUNET_new (struct TicketIteration);
1571 ti->r_id = ntohl (tis_msg->id);
1572 ti->client = client;
1574 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1575 client->ticket_iter_tail,
1578 = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1579 GNUNET_SERVICE_client_continue (client->client);
1584 * Client has had enough tickets
1586 * @param cls the client
1587 * @param tis_msg the stop message
1590 handle_ticket_iteration_stop (void *cls,
1591 const struct TicketIterationStopMessage *tis_msg)
1593 struct IdpClient *client = cls;
1594 struct TicketIteration *ti;
1597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1598 "Received `%s' message\n",
1599 "TICKET_ITERATION_STOP");
1600 rid = ntohl (tis_msg->id);
1601 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1602 if (ti->r_id == rid)
1607 GNUNET_SERVICE_client_drop (client->client);
1610 RECLAIM_TICKETS_iteration_stop (ti->iter);
1611 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1612 client->ticket_iter_tail,
1615 GNUNET_SERVICE_client_continue (client->client);
1620 * Client requests next result.
1622 * @param cls the client
1623 * @param tis_msg the message
1626 handle_ticket_iteration_next (void *cls,
1627 const struct TicketIterationNextMessage *tis_msg)
1629 struct IdpClient *client = cls;
1630 struct TicketIteration *ti;
1633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1634 "Received TICKET_ITERATION_NEXT message\n");
1635 rid = ntohl (tis_msg->id);
1636 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1637 if (ti->r_id == rid)
1642 GNUNET_SERVICE_client_drop (client->client);
1645 RECLAIM_TICKETS_iteration_next (ti->iter);
1646 GNUNET_SERVICE_client_continue (client->client);
1651 * Main function that will be run
1653 * @param cls closure
1654 * @param c the configuration used
1655 * @param server the service handle
1659 const struct GNUNET_CONFIGURATION_Handle *c,
1660 struct GNUNET_SERVICE_Handle *server)
1664 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
1666 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1667 "Unable to initialize TICKETS subsystem.\n");
1668 GNUNET_SCHEDULER_shutdown ();
1671 // Connect to identity and namestore services
1672 nsh = GNUNET_NAMESTORE_connect (cfg);
1675 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1676 "error connecting to namestore");
1679 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1684 * Called whenever a client is disconnected.
1686 * @param cls closure
1687 * @param client identification of the client
1688 * @param app_ctx @a client
1691 client_disconnect_cb (void *cls,
1692 struct GNUNET_SERVICE_Client *client,
1695 struct IdpClient *idp = app_ctx;
1697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1698 GNUNET_CONTAINER_DLL_remove (client_list_head,
1701 cleanup_client (idp);
1706 * Add a client to our list of active clients.
1709 * @param client client to add
1710 * @param mq message queue for @a client
1711 * @return internal namestore client structure for this client
1714 client_connect_cb (void *cls,
1715 struct GNUNET_SERVICE_Client *client,
1716 struct GNUNET_MQ_Handle *mq)
1718 struct IdpClient *idp;
1720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1721 idp = GNUNET_new (struct IdpClient);
1722 idp->client = client;
1724 GNUNET_CONTAINER_DLL_insert (client_list_head,
1732 * Define "main" method using service macro.
1734 GNUNET_SERVICE_MAIN (
1736 GNUNET_SERVICE_OPTION_NONE,
1739 &client_disconnect_cb,
1741 GNUNET_MQ_hd_var_size (attribute_store_message,
1742 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1743 struct AttributeStoreMessage,
1745 GNUNET_MQ_hd_var_size (attribute_delete_message,
1746 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1747 struct AttributeDeleteMessage,
1749 GNUNET_MQ_hd_fixed_size (
1751 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1752 struct AttributeIterationStartMessage,
1754 GNUNET_MQ_hd_fixed_size (iteration_next,
1755 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1756 struct AttributeIterationNextMessage,
1758 GNUNET_MQ_hd_fixed_size (iteration_stop,
1759 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1760 struct AttributeIterationStopMessage,
1762 GNUNET_MQ_hd_var_size (issue_ticket_message,
1763 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1764 struct IssueTicketMessage,
1766 GNUNET_MQ_hd_var_size (consume_ticket_message,
1767 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1768 struct ConsumeTicketMessage,
1770 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1771 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1772 struct TicketIterationStartMessage,
1774 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1775 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1776 struct TicketIterationNextMessage,
1778 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1779 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1780 struct TicketIterationStopMessage,
1782 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1783 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1784 struct RevokeTicketMessage,
1786 GNUNET_MQ_handler_end ());
1787 /* end of gnunet-service-reclaim.c */